Changeset 27431 in webkit


Ignore:
Timestamp:
Nov 4, 2007 4:09:54 PM (16 years ago)
Author:
timothy@apple.com
Message:

Reviewed by Adam.

Bug 15834: There are many subtle bugs in the Styles pane of the Web Inspector
http://bugs.webkit.org/show_bug.cgi?id=15834

  • Broke up DocumentPanel and added three SidebarPane sub-classes.
  • Fixed many Style pane bugs, including:
    • Poor handling of duplicate properties in the same rule. Some of this can't be fixed since we can't only get the "winning" value for duplicate properties. So we should only show one entry per unique property name.
    • Computed style does not show font shorthand sub-properties if 'font' was used.
    • Property priority was broken, the wrong properties were crossed out.
    • The 'border' shorthand shows null for the shorthand value.
    • Shorthands didn't show their priority (e.g. !important).
    • HSL and HTML hex colors didn't have preview swatch blocks.
    • Code refactoring, making it easier to reuse for console.log later.
  • page/inspector/DocumentPanel.js: Move sidebar pane code to three seperate classes in new files.
  • page/inspector/MetricsSidebarPane.js: Added.
  • page/inspector/Panel.js: Remove an InspectorController.log() call.
  • page/inspector/PropertiesSection.js: Add the section to the TreeOutline. So TreeElements can access properties on their section.
  • page/inspector/PropertiesSidebarPane.js: Added.
  • page/inspector/SidebarPane.js: Remove the explicit asignment of the onexpand and oncollapse to null. These were hiding prototypes.
  • page/inspector/StylesSidebarPane.js: Added.
  • page/inspector/inspector.html: Include the new script files.
  • page/inspector/treeoutline.js: If a null representedObject is passed in just use a empty object.
Location:
trunk/WebCore
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r27427 r27431  
     12007-11-04  Timothy Hatcher  <timothy@apple.com>
     2
     3        Reviewed by Adam.
     4
     5        Bug 15834: There are many subtle bugs in the Styles pane of the Web Inspector
     6        http://bugs.webkit.org/show_bug.cgi?id=15834
     7
     8        - Broke up DocumentPanel and added three SidebarPane sub-classes.
     9        - Fixed many Style pane bugs, including:
     10          * Poor handling of duplicate properties in the same rule. Some of this can't be
     11            fixed since we can't only get the "winning" value for duplicate properties.
     12            So we should only show one entry per unique property name.
     13          * Computed style does not show font shorthand sub-properties if 'font' was used.
     14          * Property priority was broken, the wrong properties were crossed out.
     15          * The 'border' shorthand shows null for the shorthand value.
     16          * Shorthands didn't show their priority (e.g. !important).
     17          * HSL and HTML hex colors didn't have preview swatch blocks.
     18          * Code refactoring, making it easier to reuse for console.log later.
     19
     20        * page/inspector/DocumentPanel.js: Move sidebar pane code to three seperate
     21          classes in new files.
     22        * page/inspector/MetricsSidebarPane.js: Added.
     23        * page/inspector/Panel.js: Remove an InspectorController.log() call.
     24        * page/inspector/PropertiesSection.js: Add the section to the TreeOutline.
     25          So TreeElements can access properties on their section.
     26        * page/inspector/PropertiesSidebarPane.js: Added.
     27        * page/inspector/SidebarPane.js: Remove the explicit asignment of the
     28          onexpand and oncollapse to null. These were hiding prototypes.
     29        * page/inspector/StylesSidebarPane.js: Added.
     30        * page/inspector/inspector.html: Include the new script files.
     31        * page/inspector/treeoutline.js: If a null representedObject is passed
     32          in just use a empty object.
     33
    1342007-11-04  David D. Kilzer  <ddkilzer@webkit.org>
    235
  • trunk/WebCore/page/inspector/DocumentPanel.js

    r27171 r27431  
    5656
    5757    domView.sidebarPanes = {};
    58     domView.sidebarPanes.styles = new WebInspector.SidebarPane("Styles");
    59     domView.sidebarPanes.metrics = new WebInspector.SidebarPane("Metrics");
    60     domView.sidebarPanes.properties = new WebInspector.SidebarPane("Properties");
     58    domView.sidebarPanes.styles = new WebInspector.StylesSidebarPane();
     59    domView.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
     60    domView.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
    6161
    6262    var panel = this;
     
    106106            return;
    107107        var element = this.views.dom.treeOutline.selectedTreeElement;
    108         element.updateSelection(element);
     108        element.updateSelection();
    109109    },
    110110
     
    182182        var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.rootDOMNode) : this.rootDOMNode.firstChild);
    183183        while (node) {
    184             var item = new WebInspector.DOMNodeTreeElement(node);
    185             this.views.dom.treeOutline.appendChild(item);
     184            this.views.dom.treeOutline.appendChild(new WebInspector.DOMNodeTreeElement(node));
    186185            node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
    187186        }
     
    313312    updateStyles: function()
    314313    {
    315         if (!this.views.dom.sidebarPanes.styles.expanded)
    316             return;
    317         if (!this.views.dom.sidebarPanes.styles.needsUpdate)
    318             return;
    319 
    320         this.views.dom.sidebarPanes.styles.needsUpdate = false;
    321 
    322         var stylesBody = this.views.dom.sidebarPanes.styles.bodyElement;
    323 
    324         stylesBody.removeChildren();
    325         this.views.dom.sidebarPanes.styles.sections = [];
    326 
    327         if (!this.focusedDOMNode)
    328             return;
    329 
    330         var styleNode = this.focusedDOMNode;
    331         if (styleNode.nodeType === Node.TEXT_NODE && styleNode.parentNode)
    332             styleNode = styleNode.parentNode;
    333 
    334         var styleRules = [];
    335         var styleProperties = [];
    336 
    337         if (styleNode.nodeType === Node.ELEMENT_NODE) {
    338             var propertyCount = [];
    339 
    340             var computedStyle = styleNode.ownerDocument.defaultView.getComputedStyle(styleNode);
    341             if (computedStyle && computedStyle.length)
    342                 styleRules.push({ isComputedStyle: true, selectorText: "Computed Style", style: computedStyle });
    343 
    344             var styleNodeName = styleNode.nodeName.toLowerCase();
    345             for (var i = 0; i < styleNode.attributes.length; ++i) {
    346                 var attr = styleNode.attributes[i];
    347                 if (attr.style) {
    348                     var attrStyle = { attrName: attr.name, style: attr.style };
    349                     attrStyle.subtitle = "element\u2019s \u201C" + attr.name + "\u201D attribute";
    350                     attrStyle.selectorText = styleNodeName + "[" + attr.name;
    351                     if (attr.value.length)
    352                         attrStyle.selectorText += "=" + attr.value;
    353                     attrStyle.selectorText += "]";
    354                     styleRules.push(attrStyle);
    355                 }
    356             }
    357 
    358             if (styleNode.style && styleNode.style.length) {
    359                 var inlineStyle = { selectorText: "Inline Style Attribute", style: styleNode.style };
    360                 inlineStyle.subtitle = "element\u2019s \u201Cstyle\u201D attribute";
    361                 styleRules.push(inlineStyle);
    362             }
    363 
    364             var matchedStyleRules = styleNode.ownerDocument.defaultView.getMatchedCSSRules(styleNode, "", !Preferences.showUserAgentStyles);
    365             if (matchedStyleRules) {
    366                 for (var i = matchedStyleRules.length - 1; i >= 0; --i)
    367                     styleRules.push(matchedStyleRules[i]);
    368             }
    369 
    370             var priorityUsed = false;
    371             var usedProperties = {};
    372             var shorthandProperties = {};
    373             for (var i = 0; i < styleRules.length; ++i) {
    374                 styleProperties[i] = [];
    375 
    376                 var style = styleRules[i].style;
    377                 var styleShorthandLookup = [];
    378                 for (var j = 0; j < style.length; ++j) {
    379                     var prop = null;
    380                     var name = style[j];
    381                     var shorthand = style.getPropertyShorthand(name);
    382                     if (!shorthand && styleRules[i].isComputedStyle)
    383                         shorthand = shorthandProperties[name];
    384 
    385                     if (shorthand) {
    386                         prop = styleShorthandLookup[shorthand];
    387                         shorthandProperties[name] = shorthand;
    388                     }
    389 
    390                     if (!priorityUsed && style.getPropertyPriority(name).length)
    391                         priorityUsed = true;
    392 
    393                     if (prop) {
    394                         prop.subProperties.push(name);
    395                     } else {
    396                         prop = { style: style, subProperties: [name], unusedProperties: [], name: (shorthand ? shorthand : name) };
    397                         styleProperties[i].push(prop);
    398 
    399                         if (shorthand) {
    400                             styleShorthandLookup[shorthand] = prop;
    401                             if (!styleRules[i].isComputedStyle) {
    402                                 if (!propertyCount[shorthand]) {
    403                                     propertyCount[shorthand] = 1;
    404                                 } else {
    405                                     prop.unusedProperties[shorthand] = true;
    406                                     propertyCount[shorthand]++;
    407                                 }
    408                             }
    409                         }
    410                     }
    411 
    412                     if (styleRules[i].isComputedStyle)
    413                         continue;
    414 
    415                     usedProperties[name] = true;
    416                     if (shorthand)
    417                         usedProperties[shorthand] = true;
    418 
    419                     if (!propertyCount[name]) {
    420                         propertyCount[name] = 1;
    421                     } else {
    422                         prop.unusedProperties[name] = true;
    423                         propertyCount[name]++;
    424                     }
    425                 }
    426             }
    427 
    428             if (priorityUsed) {
    429                 // walk the properties again and account for !important
    430                 var priorityCount = [];
    431                 for (var i = 0; i < styleRules.length; ++i) {
    432                     if (styleRules[i].isComputedStyle)
    433                         continue;
    434                     var style = styleRules[i].style;
    435                     for (var j = 0; j < styleProperties[i].length; ++j) {
    436                         var prop = styleProperties[i][j];
    437                         for (var k = 0; k < prop.subProperties.length; ++k) {
    438                             var name = prop.subProperties[k];
    439                             if (style.getPropertyPriority(name).length) {
    440                                 if (!priorityCount[name]) {
    441                                     if (prop.unusedProperties[name])
    442                                         prop.unusedProperties[name] = false;
    443                                     priorityCount[name] = 1;
    444                                 } else {
    445                                     priorityCount[name]++;
    446                                 }
    447                             } else if (priorityCount[name]) {
    448                                 prop.unusedProperties[name] = true;
    449                             }
    450                         }
    451                     }
    452                 }
    453             }
    454 
    455             var styleRulesLength = styleRules.length;
    456             for (var i = 0; i < styleRulesLength; ++i) {
    457                 var selectorText = styleRules[i].selectorText;
    458 
    459                 var section = new WebInspector.PropertiesSection(selectorText);
    460                 section.expanded = true;
    461 
    462                 if (styleRules[i].isComputedStyle) {
    463                     if (Preferences.showInheritedComputedStyleProperties)
    464                         section.element.addStyleClass("show-inherited");
    465 
    466                     var showInheritedLabel = document.createElement("label");
    467                     var showInheritedInput = document.createElement("input");
    468                     showInheritedInput.type = "checkbox";
    469                     showInheritedInput.checked = Preferences.showInheritedComputedStyleProperties;
    470 
    471                     var computedStyleSection = section;
    472                     var showInheritedToggleFunction = function(event) {
    473                         Preferences.showInheritedComputedStyleProperties = showInheritedInput.checked;
    474                         if (Preferences.showInheritedComputedStyleProperties)
    475                             computedStyleSection.element.addStyleClass("show-inherited");
    476                         else
    477                             computedStyleSection.element.removeStyleClass("show-inherited");
    478                         event.stopPropagation();
    479                     };
    480 
    481                     showInheritedLabel.addEventListener("click", showInheritedToggleFunction, false);
    482 
    483                     showInheritedLabel.appendChild(showInheritedInput);
    484                     showInheritedLabel.appendChild(document.createTextNode("Show implicit properties"));
    485                     section.subtitleElement.appendChild(showInheritedLabel);
    486                 } else {
    487                     var sheet;
    488                     var file = false;
    489                     if (styleRules[i].subtitle)
    490                         sheet = styleRules[i].subtitle;
    491                     else if (styleRules[i].parentStyleSheet && styleRules[i].parentStyleSheet.href) {
    492                         var url = styleRules[i].parentStyleSheet.href;
    493                         sheet = WebInspector.linkifyURL(url, url.trimURL(WebInspector.mainResource.domain).escapeHTML());
    494                         file = true;
    495                     } else if (styleRules[i].parentStyleSheet && !styleRules[i].parentStyleSheet.ownerNode)
    496                         sheet = "user agent stylesheet";
    497                     else
    498                         sheet = "inline stylesheet";
    499 
    500                     if (file)
    501                         section.subtitleElement.addStyleClass("file");
    502 
    503                     section.subtitle = sheet;
    504                 }
    505 
    506                 stylesBody.appendChild(section.element);
    507                 this.views.dom.sidebarPanes.styles.sections.push(section);
    508 
    509                 var properties = styleProperties[i];
    510                 var isComputedStyle = styleRules[i].isComputedStyle;
    511 
    512                 for (var j = 0; j < properties.length; ++j) {
    513                     var prop = properties[j];
    514 
    515                     var propTreeElement = new WebInspector.StylePropertyTreeElement(prop, isComputedStyle, usedProperties);
    516                     section.propertiesTreeOutline.appendChild(propTreeElement);
    517                 }
    518             }
    519         } else {
    520             // can't style this node
    521         }
     314        var stylesSidebarPane = this.views.dom.sidebarPanes.styles;
     315        if (!stylesSidebarPane.expanded || !stylesSidebarPane.needsUpdate)
     316            return;
     317
     318        stylesSidebarPane.update(this.focusedDOMNode);
     319        stylesSidebarPane.needsUpdate = false;
    522320    },
    523321
    524322    updateMetrics: function()
    525323    {
    526         if (!this.views.dom.sidebarPanes.metrics.expanded)
    527             return;
    528         if (!this.views.dom.sidebarPanes.metrics.needsUpdate)
    529             return;
    530 
    531         this.views.dom.sidebarPanes.metrics.needsUpdate = false;
    532 
    533         var metricsBody = this.views.dom.sidebarPanes.metrics.bodyElement;
    534 
    535         metricsBody.removeChildren();
    536 
    537         if (!this.focusedDOMNode)
    538             return;
    539 
    540         var style;
    541         if (this.focusedDOMNode.nodeType === Node.ELEMENT_NODE)
    542             style = this.focusedDOMNode.ownerDocument.defaultView.getComputedStyle(this.focusedDOMNode);
    543         if (!style)
    544             return;
    545 
    546         var metricsElement = document.createElement("div");
    547         metricsElement.className = "metrics";
    548 
    549         function boxPartValue(style, name, suffix)
    550         {
    551             var value = style.getPropertyValue(name + suffix);
    552             if (value === "" || value === "0px")
    553                 value = "\u2012";
    554             return value.replace(/px$/, "");
    555         }
    556 
    557         // Display types for which margin is ignored.
    558         var noMarginDisplayType = {
    559             "table-cell": true,
    560             "table-column": true,
    561             "table-column-group": true,
    562             "table-footer-group": true,
    563             "table-header-group": true,
    564             "table-row": true,
    565             "table-row-group": true
    566         };
    567 
    568         // Display types for which padding is ignored.
    569         var noPaddingDisplayType = {
    570             "table-column": true,
    571             "table-column-group": true,
    572             "table-footer-group": true,
    573             "table-header-group": true,
    574             "table-row": true,
    575             "table-row-group": true
    576         };
    577 
    578         var boxes = ["content", "padding", "border", "margin"];
    579         var previousBox;
    580         for (var i = 0; i < boxes.length; ++i) {
    581             var name = boxes[i];
    582 
    583             if (name === "margin" && noMarginDisplayType[style.display])
    584                 continue;
    585             if (name === "padding" && noPaddingDisplayType[style.display])
    586                 continue;
    587 
    588             var boxElement = document.createElement("div");
    589             boxElement.className = name;
    590 
    591             if (boxes[i] === "content") {
    592                 var width = style.width.replace(/px$/, "");
    593                 var height = style.height.replace(/px$/, "");
    594                 boxElement.textContent = width + " \u00D7 " + height;
    595             } else {
    596                 var suffix = boxes[i] === "border" ? "-width" : "";
    597 
    598                 var labelElement = document.createElement("div");
    599                 labelElement.className = "label";
    600                 labelElement.textContent = name;
    601                 boxElement.appendChild(labelElement);
    602 
    603                 var topElement = document.createElement("div");
    604                 topElement.className = "top";
    605                 topElement.textContent = boxPartValue(style, name + "-top", suffix);
    606                 boxElement.appendChild(topElement);
    607 
    608                 var leftElement = document.createElement("div");
    609                 leftElement.className = "left";
    610                 leftElement.textContent = boxPartValue(style, name + "-left", suffix);
    611                 boxElement.appendChild(leftElement);
    612 
    613                 if (previousBox)
    614                     boxElement.appendChild(previousBox);
    615 
    616                 var rightElement = document.createElement("div");
    617                 rightElement.className = "right";
    618                 rightElement.textContent = boxPartValue(style, name + "-right", suffix);
    619                 boxElement.appendChild(rightElement);
    620 
    621                 var bottomElement = document.createElement("div");
    622                 bottomElement.className = "bottom";
    623                 bottomElement.textContent = boxPartValue(style, name + "-bottom", suffix);
    624                 boxElement.appendChild(bottomElement);
    625             }
    626 
    627             previousBox = boxElement;
    628         }
    629 
    630         metricsElement.appendChild(previousBox);
    631         metricsBody.appendChild(metricsElement);
     324        var metricsSidebarPane = this.views.dom.sidebarPanes.metrics;
     325        if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
     326            return;
     327
     328        metricsSidebarPane.update(this.focusedDOMNode);
     329        metricsSidebarPane.needsUpdate = false;
    632330    },
    633331
    634332    updateProperties: function()
    635333    {
    636         if (!this.views.dom.sidebarPanes.properties.expanded)
    637             return;
    638         if (!this.views.dom.sidebarPanes.properties.needsUpdate)
    639             return;
    640 
    641         this.views.dom.sidebarPanes.properties.needsUpdate = false;
    642 
    643         var propertiesBody = this.views.dom.sidebarPanes.properties.bodyElement;
    644 
    645         propertiesBody.removeChildren();
    646         this.views.dom.sidebarPanes.properties.sections = [];
    647 
    648         if (!this.focusedDOMNode)
    649             return;
    650 
    651         for (var prototype = this.focusedDOMNode; prototype; prototype = prototype.__proto__) {
    652             var hasChildren = false;
    653             for (var prop in prototype) {
    654                 if (prop === "__treeElementIdentifier")
    655                     continue;
    656                 if (!prototype.hasOwnProperty(prop))
    657                     continue;
    658 
    659                 hasChildren = true;
    660                 break;
    661             }
    662 
    663             if (!hasChildren)
    664                 continue;
    665 
    666             var title = Object.describe(prototype);
    667             var subtitle;
    668             if (title.match(/Prototype$/)) {
    669                 title = title.replace(/Prototype$/, "");
    670                 subtitle = "Prototype";
    671             }
    672 
    673             var section = new WebInspector.PropertiesSection(title, subtitle);
    674             section.onpopulate = WebInspector.DOMPropertiesSection.onpopulate(prototype);
    675 
    676             propertiesBody.appendChild(section.element);
    677             this.views.dom.sidebarPanes.properties.sections.push(section);
    678         }
     334        var propertiesSidebarPane = this.views.dom.sidebarPanes.properties;
     335        if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
     336            return;
     337
     338        propertiesSidebarPane.update(this.focusedDOMNode);
     339        propertiesSidebarPane.needsUpdate = false;
    679340    },
    680341
     
    722383WebInspector.DocumentPanel.prototype.__proto__ = WebInspector.SourcePanel.prototype;
    723384
    724 WebInspector.DOMPropertiesSection = function()
    725 {
    726     // FIXME: Perhaps this should be a real subclass someday
    727 }
    728 
    729 WebInspector.DOMPropertiesSection.onpopulate = function(prototype)
    730 {
    731     return function(section) {
    732         var properties = Object.sortedProperties(prototype);
    733         for (var i = 0; i < properties.length; ++i) {
    734             var name = properties[i];
    735             if (!prototype.hasOwnProperty(name))
    736                 continue;
    737             if (name === "__treeElementIdentifier")
    738                 continue;
    739             var item = new WebInspector.DOMPropertyTreeElement(name, prototype);
    740             section.propertiesTreeOutline.appendChild(item);
    741         }
    742     }
    743 }
    744 
    745385WebInspector.DOMNodeTreeElement = function(node)
    746386{
    747387    var hasChildren = (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
    748 
    749388    var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
    750     var title = titleInfo.title;
    751     hasChildren = titleInfo.hasChildren;
    752 
    753     var item = new TreeElement(title, node, hasChildren);
    754     item.updateSelection = WebInspector.DOMNodeTreeElement.updateSelection;
    755     item.onpopulate = WebInspector.DOMNodeTreeElement.populate;
    756     item.onexpand = WebInspector.DOMNodeTreeElement.expanded;
    757     item.oncollapse = WebInspector.DOMNodeTreeElement.collapsed;
    758     item.onselect = WebInspector.DOMNodeTreeElement.selected;
    759     item.onreveal = WebInspector.DOMNodeTreeElement.revealed;
    760     item.ondblclick = WebInspector.DOMNodeTreeElement.doubleClicked;
    761     if (hasChildren)
    762         item.whitespaceIgnored = Preferences.ignoreWhitespace;
    763     return item;
     389
     390    if (titleInfo.hasChildren)
     391        this.whitespaceIgnored = Preferences.ignoreWhitespace;
     392
     393    TreeElement.call(this, titleInfo.title, node, titleInfo.hasChildren);
    764394}
    765395
    766 WebInspector.DOMNodeTreeElement.updateSelection = function(element)
    767 {
    768     if (!element || !element._listItemNode)
    769         return;
    770 
    771     if (!element.selectionElement) {
    772         element.selectionElement = document.createElement("div");
    773         element.selectionElement.className = "selection selected";
    774         element._listItemNode.insertBefore(element.selectionElement, element._listItemNode.firstChild);
    775     }
    776 
    777     element.selectionElement.style.height = element._listItemNode.offsetHeight + "px";
    778 }
    779 
    780 WebInspector.DOMNodeTreeElement.populate = function(element)
    781 {
    782     if (element.children.length || element.whitespaceIgnored !== Preferences.ignoreWhitespace)
    783         return;
    784 
    785     element.removeChildren();
    786     element.whitespaceIgnored = Preferences.ignoreWhitespace;
    787 
    788     var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(element.representedObject) : element.representedObject.firstChild);
    789     while (node) {
    790         var item = new WebInspector.DOMNodeTreeElement(node);
    791         element.appendChild(item);
    792         node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
    793     }
    794 
    795     if (element.representedObject.nodeType == Node.ELEMENT_NODE) {
    796         var title = "<span class=\"webkit-html-tag close\">&lt;/" + element.representedObject.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
    797         var item = new TreeElement(title, element.representedObject, false);
    798         item.selectable = false;
    799         element.appendChild(item);
     396WebInspector.DOMNodeTreeElement.prototype = {
     397    updateSelection: function()
     398    {
     399        if (!this._listItemNode)
     400            return;
     401
     402        if (!this.selectionElement) {
     403            this.selectionElement = document.createElement("div");
     404            this.selectionElement.className = "selection selected";
     405            this._listItemNode.insertBefore(this.selectionElement, this._listItemNode.firstChild);
     406        }
     407
     408        this.selectionElement.style.height = this._listItemNode.offsetHeight + "px";
     409    },
     410
     411    onpopulate: function()
     412    {
     413        if (this.children.length || this.whitespaceIgnored !== Preferences.ignoreWhitespace)
     414            return;
     415
     416        this.removeChildren();
     417        this.whitespaceIgnored = Preferences.ignoreWhitespace;
     418
     419        var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.representedObject) : this.representedObject.firstChild);
     420        while (node) {
     421            this.appendChild(new WebInspector.DOMNodeTreeElement(node));
     422            node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
     423        }
     424
     425        if (this.representedObject.nodeType == Node.ELEMENT_NODE) {
     426            var title = "<span class=\"webkit-html-tag close\">&lt;/" + this.representedObject.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
     427            var item = new TreeElement(title, this.representedObject, false);
     428            item.selectable = false;
     429            this.appendChild(item);
     430        }
     431    },
     432
     433    onexpand: function()
     434    {
     435        this.treeOutline.panel.updateTreeSelection();
     436    },
     437
     438    oncollapse: function()
     439    {
     440        this.treeOutline.panel.updateTreeSelection();
     441    },
     442
     443    onreveal: function()
     444    {
     445        if (!this._listItemNode || !this.treeOutline || !this.treeOutline._childrenListNode)
     446            return;
     447        var parent = this.treeOutline.panel.views.dom.treeContentElement;
     448        parent.scrollToElement(this._listItemNode);
     449    },
     450
     451    onselect: function()
     452    {
     453        this.treeOutline.panel.focusedDOMNode = this.representedObject;
     454
     455        // Call updateSelection twice to make sure the height is correct,
     456        // the first time might have a bad height because we are in a weird tree state
     457        this.updateSelection();
     458
     459        var element = this;
     460        setTimeout(function() { element.updateSelection() }, 0);
     461    },
     462
     463    ondblclick: function()
     464    {
     465        var panel = this.treeOutline.panel;
     466        panel.rootDOMNode = this.representedObject.parentNode;
     467        panel.focusedDOMNode = this.representedObject;
    800468    }
    801469}
    802470
    803 WebInspector.DOMNodeTreeElement.expanded = function(element)
    804 {
    805     element.treeOutline.panel.updateTreeSelection();
    806 }
    807 
    808 WebInspector.DOMNodeTreeElement.collapsed = function(element)
    809 {
    810     element.treeOutline.panel.updateTreeSelection();
    811 }
    812 
    813 WebInspector.DOMNodeTreeElement.revealed = function(element)
    814 {
    815     if (!element._listItemNode || !element.treeOutline || !element.treeOutline._childrenListNode)
    816         return;
    817     var parent = element.treeOutline.panel.views.dom.treeContentElement;
    818     parent.scrollToElement(element._listItemNode);
    819 }
    820 
    821 WebInspector.DOMNodeTreeElement.selected = function(element)
    822 {
    823     var panel = element.treeOutline.panel;
    824     panel.focusedDOMNode = element.representedObject;
    825 
    826     // Call updateSelection twice to make sure the height is correct,
    827     // the first time might have a bad height because we are in a weird tree state
    828     element.updateSelection(element);
    829     setTimeout(function() { element.updateSelection(element) }, 0);
    830 }
    831 
    832 WebInspector.DOMNodeTreeElement.doubleClicked = function(element)
    833 {
    834     var panel = element.treeOutline.panel;
    835     panel.rootDOMNode = element.representedObject.parentNode;
    836     panel.focusedDOMNode = element.representedObject;
    837 }
    838 
    839 WebInspector.StylePropertyTreeElement = function(prop, computedStyle, usedProperties)
    840 {
    841     var overloadCount = 0;
    842     var priority;
    843     if (prop.subProperties && prop.subProperties.length > 1) {
    844         for (var i = 0; i < prop.subProperties.length; ++i) {
    845             var name = prop.subProperties[i];
    846             if (!priority)
    847                 priority = prop.style.getPropertyPriority(name);
    848             if (prop.unusedProperties[name])
    849                 overloadCount++;
    850         }
    851     }
    852 
    853     if (!priority)
    854         priority = prop.style.getPropertyPriority(prop.name);
    855 
    856     var overloaded = (prop.unusedProperties[prop.name] || overloadCount === prop.subProperties.length);
    857     var title = WebInspector.StylePropertyTreeElement.createTitle(prop.name, prop.style, overloaded, priority, computedStyle, usedProperties);
    858 
    859     var item = new TreeElement(title, prop, (prop.subProperties && prop.subProperties.length > 1));
    860     item.computedStyle = computedStyle;
    861     item.onpopulate = WebInspector.StylePropertyTreeElement.populate;
    862     return item;
    863 }
    864 
    865 WebInspector.StylePropertyTreeElement.createTitle = function(name, style, overloaded, priority, computed, usedProperties)
    866 {
    867     // "Nicknames" for some common values that are easier to read.
    868     var valueNickname = {
    869         "rgb(0, 0, 0)": "black",
    870         "rgb(255, 255, 255)": "white",
    871         "rgba(0, 0, 0, 0)": "transparent"
    872     };
    873 
    874     var alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
    875 
    876     var value = style.getPropertyValue(name);
    877 
    878     var textValue = value;
    879     if (value) {
    880         var urls = value.match(/url\([^)]+\)/);
    881         if (urls) {
    882             for (var i = 0; i < urls.length; ++i) {
    883                 var url = urls[i].substring(4, urls[i].length - 1);
    884                 textValue = textValue.replace(urls[i], "url(" + WebInspector.linkifyURL(url) + ")");
    885             }
    886         } else {
    887             if (value in valueNickname)
    888                 textValue = valueNickname[value];
    889             textValue = textValue.escapeHTML();
    890         }
    891     }
    892 
    893     var classes = [];
    894     if (!computed && (style.isPropertyImplicit(name) || value == "initial"))
    895         classes.push("implicit");
    896     if (computed && !usedProperties[name] && !alwaysShowComputedProperties[name])
    897         classes.push("inherited");
    898     if (overloaded)
    899         classes.push("overloaded");
    900 
    901     var title = "";
    902     if (classes.length)
    903         title += "<span class=\"" + classes.join(" ") + "\">";
    904 
    905     title += "<span class=\"name\">" + name.escapeHTML() + "</span>: ";
    906     title += "<span class=\"value\">" + textValue;
    907     if (priority && priority.length)
    908         title += " !" + priority;
    909     title += "</span>;";
    910 
    911     if (value) {
    912         // FIXME: this dosen't catch keyword based colors like black and white
    913         var colors = value.match(/(rgb\([0-9]+,\s?[0-9]+,\s?[0-9]+\))|(rgba\([0-9]+,\s?[0-9]+,\s?[0-9]+,\s?[0-9]+\))/g);
    914         if (colors) {
    915             var colorsLength = colors.length;
    916             for (var i = 0; i < colorsLength; ++i)
    917                 title += "<span class=\"swatch\" style=\"background-color: " + colors[i] + "\"></span>";
    918         }
    919     }
    920 
    921     if (classes.length)
    922         title += "</span>";
    923 
    924     return title;
    925 }
    926 
    927 WebInspector.StylePropertyTreeElement.populate = function(element)
    928 {
    929     if (element.children.length)
    930         return;
    931 
    932     var prop = element.representedObject;
    933     if (prop.subProperties && prop.subProperties.length > 1) {
    934         for (var i = 0; i < prop.subProperties.length; ++i) {
    935             var name = prop.subProperties[i];
    936             var overloaded = (prop.unusedProperties[prop.name] || prop.unusedProperties[name]);
    937             var priority = prop.style.getPropertyPriority(name);
    938             var title = WebInspector.StylePropertyTreeElement.createTitle(name, prop.style, overloaded, priority, element.computedStyle);
    939             var subitem = new TreeElement(title, {}, false);
    940             element.appendChild(subitem);
    941         }
    942     }
    943 }
    944 
    945 WebInspector.DOMPropertyTreeElement = function(name, object)
    946 {
    947     var title = "<span class=\"name\">" + name.escapeHTML() + "</span>: ";
    948     title += "<span class=\"value\">" + Object.describe(object[name], true).escapeHTML() + "</span>";
    949 
    950     var hasChildren = false;
    951     var type = typeof object[name];
    952     if (object[name] && (type === "object" || type === "function")) {
    953         for (value in object[name]) {
    954             hasChildren = true;
    955             break;
    956         }
    957     }
    958 
    959     var representedObj = { object: object, name: name };
    960     var item = new TreeElement(title, representedObj, hasChildren);
    961     item.onpopulate = WebInspector.DOMPropertyTreeElement.populate;
    962     return item;
    963 }
    964 
    965 WebInspector.DOMPropertyTreeElement.populate = function(element)
    966 {
    967     if (element.children.length)
    968         return;
    969 
    970     var parent = element.representedObject.object[element.representedObject.name];
    971     var properties = Object.sortedProperties(parent);
    972     for (var i = 0; i < properties.length; ++i) {
    973         if (properties[i] === "__treeElementIdentifier")
    974             continue;
    975         var item = new WebInspector.DOMPropertyTreeElement(properties[i], parent);
    976         element.appendChild(item);
    977     }
    978 }
     471WebInspector.DOMNodeTreeElement.prototype.__proto__ = TreeElement.prototype;
  • trunk/WebCore/page/inspector/Panel.js

    r26933 r27431  
    135135    set currentView(x)
    136136    {
    137         InspectorController.log(x);
    138137        if (typeof x === "string" || x instanceof String)
    139138            x = this.views[x];
  • trunk/WebCore/page/inspector/PropertiesSection.js

    r26933 r27431  
    5050    this.propertiesElement.className = "properties";
    5151    this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
     52    this.propertiesTreeOutline.section = this;
    5253
    5354    this.element.appendChild(this.headerElement);
  • trunk/WebCore/page/inspector/SidebarPane.js

    r26933 r27431  
    4747    this.growbarVisible = false;
    4848    this.expanded = false;
    49     this.onexpand = null;
    50     this.oncollapse = null;
    5149}
    5250
  • trunk/WebCore/page/inspector/inspector.html

    r27141 r27431  
    3939    <script type="text/javascript" src="SidebarPane.js"></script>
    4040    <script type="text/javascript" src="PropertiesSection.js"></script>
     41    <script type="text/javascript" src="MetricsSidebarPane.js"></script>
     42    <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
     43    <script type="text/javascript" src="StylesSidebarPane.js"></script>
    4144    <script type="text/javascript" src="Panel.js"></script>
    4245    <script type="text/javascript" src="ResourcePanel.js"></script>
  • trunk/WebCore/page/inspector/treeoutline.js

    r26997 r27431  
    279279
    280280    for (var i = 0; i < ancestors.length; ++i) {
    281         item = this.findTreeElement(ancestors[i]);
    282         if (ancestors[i] !== representedObject && item.onpopulate)
     281        item = this.findTreeElement(ancestors[i], isAncestor, getParent);
     282        if (ancestors[i] !== representedObject && item && item.onpopulate)
    283283            item.onpopulate(item);
    284284    }
     
    379379{
    380380    this._title = title;
    381     this.representedObject = representedObject;
     381    this.representedObject = (representedObject || {});
    382382
    383383    if (this.representedObject.__treeElementIdentifier)
     
    394394    this.hasChildren = hasChildren;
    395395    this.children = [];
    396     this.onpopulate = null;
    397     this.onexpand = null;
    398     this.oncollapse = null;
    399     this.onreveal = null;
    400     this.onselect = null;
    401     this.ondeselect = null;
    402     this.ondblclick = null;
    403396    this.treeOutline = null;
    404397    this.parent = null;
Note: See TracChangeset for help on using the changeset viewer.