1/* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29WebInspector.MetricsSidebarPane = function() 30{ 31 WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics")); 32 this._inlineStyleId = null; 33} 34 35WebInspector.MetricsSidebarPane.prototype = { 36 update: function(node) 37 { 38 var body = this.bodyElement; 39 40 body.removeChildren(); 41 42 if (node) 43 this.node = node; 44 else 45 node = this.node; 46 47 if (!node || !node.ownerDocument.defaultView) 48 return; 49 50 if (node.nodeType !== Node.ELEMENT_NODE) 51 return; 52 53 var self = this; 54 var callback = function(stylePayload) { 55 if (!stylePayload) 56 return; 57 var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload); 58 self._update(node, body, style); 59 }; 60 InspectorController.getComputedStyle(node, callback); 61 62 var inlineStyleCallback = function(stylePayload) { 63 if (!stylePayload) 64 return; 65 self._inlineStyleId = stylePayload.id; 66 }; 67 InspectorController.getInlineStyle(node, inlineStyleCallback); 68 }, 69 70 _update: function(node, body, style) 71 { 72 var metricsElement = document.createElement("div"); 73 metricsElement.className = "metrics"; 74 75 function createBoxPartElement(style, name, side, suffix) 76 { 77 var propertyName = (name !== "position" ? name + "-" : "") + side + suffix; 78 var value = style.getPropertyValue(propertyName); 79 if (value === "" || (name !== "position" && value === "0px")) 80 value = "\u2012"; 81 else if (name === "position" && value === "auto") 82 value = "\u2012"; 83 value = value.replace(/px$/, ""); 84 85 var element = document.createElement("div"); 86 element.className = side; 87 element.textContent = value; 88 element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName), false); 89 return element; 90 } 91 92 // Display types for which margin is ignored. 93 var noMarginDisplayType = { 94 "table-cell": true, 95 "table-column": true, 96 "table-column-group": true, 97 "table-footer-group": true, 98 "table-header-group": true, 99 "table-row": true, 100 "table-row-group": true 101 }; 102 103 // Display types for which padding is ignored. 104 var noPaddingDisplayType = { 105 "table-column": true, 106 "table-column-group": true, 107 "table-footer-group": true, 108 "table-header-group": true, 109 "table-row": true, 110 "table-row-group": true 111 }; 112 113 // Position types for which top, left, bottom and right are ignored. 114 var noPositionType = { 115 "static": true 116 }; 117 118 var boxes = ["content", "padding", "border", "margin", "position"]; 119 var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")]; 120 var previousBox; 121 for (var i = 0; i < boxes.length; ++i) { 122 var name = boxes[i]; 123 124 if (name === "margin" && noMarginDisplayType[style.display]) 125 continue; 126 if (name === "padding" && noPaddingDisplayType[style.display]) 127 continue; 128 if (name === "position" && noPositionType[style.position]) 129 continue; 130 131 var boxElement = document.createElement("div"); 132 boxElement.className = name; 133 134 if (name === "content") { 135 var width = style.width.replace(/px$/, ""); 136 var widthElement = document.createElement("span"); 137 widthElement.textContent = width; 138 widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false); 139 140 var height = style.height.replace(/px$/, ""); 141 var heightElement = document.createElement("span"); 142 heightElement.textContent = height; 143 heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false); 144 145 boxElement.appendChild(widthElement); 146 boxElement.appendChild(document.createTextNode(" \u00D7 ")); 147 boxElement.appendChild(heightElement); 148 } else { 149 var suffix = (name === "border" ? "-width" : ""); 150 151 var labelElement = document.createElement("div"); 152 labelElement.className = "label"; 153 labelElement.textContent = boxLabels[i]; 154 boxElement.appendChild(labelElement); 155 156 boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix)); 157 boxElement.appendChild(document.createElement("br")); 158 boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix)); 159 160 if (previousBox) 161 boxElement.appendChild(previousBox); 162 163 boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix)); 164 boxElement.appendChild(document.createElement("br")); 165 boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix)); 166 } 167 168 previousBox = boxElement; 169 } 170 171 metricsElement.appendChild(previousBox); 172 body.appendChild(metricsElement); 173 }, 174 175 startEditing: function(targetElement, box, styleProperty) 176 { 177 if (WebInspector.isBeingEdited(targetElement)) 178 return; 179 180 var context = { box: box, styleProperty: styleProperty }; 181 182 WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); 183 }, 184 185 editingCancelled: function(element, context) 186 { 187 this.update(); 188 }, 189 190 editingCommitted: function(element, userInput, previousContent, context) 191 { 192 if (userInput === previousContent) 193 return this.editingCancelled(element, context); // nothing changed, so cancel 194 195 if (context.box !== "position" && (!userInput || userInput === "\u2012")) 196 userInput = "0px"; 197 else if (context.box === "position" && (!userInput || userInput === "\u2012")) 198 userInput = "auto"; 199 200 // Append a "px" unit if the user input was just a number. 201 if (/^\d+$/.test(userInput)) 202 userInput += "px"; 203 204 var self = this; 205 var callback = function(success) { 206 if (!success) 207 return; 208 self.dispatchEventToListeners("metrics edited"); 209 self.update(); 210 }; 211 InspectorController.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback); 212 } 213} 214 215WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; 216