Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 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 14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission. 15 * from this software without specific prior written permission.
16 * 16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 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 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 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 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28
29 /** 28 /**
30 * @constructor 29 * @unrestricted
31 * @extends {WebInspector.ElementsSidebarPane}
32 */ 30 */
33 WebInspector.MetricsSidebarPane = function() 31 WebInspector.MetricsSidebarPane = class extends WebInspector.ElementsSidebarPane {
34 { 32 constructor() {
35 WebInspector.ElementsSidebarPane.call(this); 33 super();
34 }
35
36 /**
37 * @override
38 * @protected
39 * @return {!Promise.<?>}
40 */
41 doUpdate() {
42 // "style" attribute might have changed. Update metrics unless they are bein g edited
43 // (if a CSS property is added, a StyleSheetChanged event is dispatched).
44 if (this._isEditingMetrics)
45 return Promise.resolve();
46
47 // FIXME: avoid updates of a collapsed pane.
48 var node = this.node();
49 var cssModel = this.cssModel();
50 if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {
51 this.element.removeChildren();
52 return Promise.resolve();
53 }
54
55 /**
56 * @param {?Map.<string, string>} style
57 * @this {WebInspector.MetricsSidebarPane}
58 */
59 function callback(style) {
60 if (!style || this.node() !== node)
61 return;
62 this._updateMetrics(style);
63 }
64 /**
65 * @param {?WebInspector.CSSModel.InlineStyleResult} inlineStyleResult
66 * @this {WebInspector.MetricsSidebarPane}
67 */
68 function inlineStyleCallback(inlineStyleResult) {
69 if (inlineStyleResult && this.node() === node)
70 this.inlineStyle = inlineStyleResult.inlineStyle;
71 }
72
73 var promises = [
74 cssModel.computedStylePromise(node.id).then(callback.bind(this)),
75 cssModel.inlineStylesPromise(node.id).then(inlineStyleCallback.bind(this))
76 ];
77 return Promise.all(promises);
78 }
79
80 /**
81 * @override
82 */
83 onCSSModelChanged() {
84 this.update();
85 }
86
87 /**
88 * @param {!Map.<string, string>} style
89 * @param {string} propertyName
90 * @return {number}
91 */
92 _getPropertyValueAsPx(style, propertyName) {
93 return Number(style.get(propertyName).replace(/px$/, '') || 0);
94 }
95
96 /**
97 * @param {!Map.<string, string>} computedStyle
98 * @param {string} componentName
99 */
100 _getBox(computedStyle, componentName) {
101 var suffix = componentName === 'border' ? '-width' : '';
102 var left = this._getPropertyValueAsPx(computedStyle, componentName + '-left' + suffix);
103 var top = this._getPropertyValueAsPx(computedStyle, componentName + '-top' + suffix);
104 var right = this._getPropertyValueAsPx(computedStyle, componentName + '-righ t' + suffix);
105 var bottom = this._getPropertyValueAsPx(computedStyle, componentName + '-bot tom' + suffix);
106 return {left: left, top: top, right: right, bottom: bottom};
107 }
108
109 /**
110 * @param {boolean} showHighlight
111 * @param {string} mode
112 * @param {!Event} event
113 */
114 _highlightDOMNode(showHighlight, mode, event) {
115 event.consume();
116 if (showHighlight && this.node()) {
117 if (this._highlightMode === mode)
118 return;
119 this._highlightMode = mode;
120 this.node().highlight(mode);
121 } else {
122 delete this._highlightMode;
123 WebInspector.DOMModel.hideDOMNodeHighlight();
124 }
125
126 for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) {
127 var element = this._boxElements[i];
128 if (!this.node() || mode === 'all' || element._name === mode)
129 element.style.backgroundColor = element._backgroundColor;
130 else
131 element.style.backgroundColor = '';
132 }
133 }
134
135 /**
136 * @param {!Map.<string, string>} style
137 */
138 _updateMetrics(style) {
139 // Updating with computed style.
140 var metricsElement = createElement('div');
141 metricsElement.className = 'metrics';
142 var self = this;
143
144 /**
145 * @param {!Map.<string, string>} style
146 * @param {string} name
147 * @param {string} side
148 * @param {string} suffix
149 * @this {WebInspector.MetricsSidebarPane}
150 */
151 function createBoxPartElement(style, name, side, suffix) {
152 var propertyName = (name !== 'position' ? name + '-' : '') + side + suffix ;
153 var value = style.get(propertyName);
154 if (value === '' || (name !== 'position' && value === '0px'))
155 value = '\u2012';
156 else if (name === 'position' && value === 'auto')
157 value = '\u2012';
158 value = value.replace(/px$/, '');
159 value = Number.toFixedIfFloating(value);
160
161 var element = createElement('div');
162 element.className = side;
163 element.textContent = value;
164 element.addEventListener('dblclick', this.startEditing.bind(this, element, name, propertyName, style), false);
165 return element;
166 }
167
168 /**
169 * @param {!Map.<string, string>} style
170 * @return {string}
171 */
172 function getContentAreaWidthPx(style) {
173 var width = style.get('width').replace(/px$/, '');
174 if (!isNaN(width) && style.get('box-sizing') === 'border-box') {
175 var borderBox = self._getBox(style, 'border');
176 var paddingBox = self._getBox(style, 'padding');
177
178 width = width - borderBox.left - borderBox.right - paddingBox.left - pad dingBox.right;
179 }
180
181 return Number.toFixedIfFloating(width.toString());
182 }
183
184 /**
185 * @param {!Map.<string, string>} style
186 * @return {string}
187 */
188 function getContentAreaHeightPx(style) {
189 var height = style.get('height').replace(/px$/, '');
190 if (!isNaN(height) && style.get('box-sizing') === 'border-box') {
191 var borderBox = self._getBox(style, 'border');
192 var paddingBox = self._getBox(style, 'padding');
193
194 height = height - borderBox.top - borderBox.bottom - paddingBox.top - pa ddingBox.bottom;
195 }
196
197 return Number.toFixedIfFloating(height.toString());
198 }
199
200 // Display types for which margin is ignored.
201 var noMarginDisplayType = {
202 'table-cell': true,
203 'table-column': true,
204 'table-column-group': true,
205 'table-footer-group': true,
206 'table-header-group': true,
207 'table-row': true,
208 'table-row-group': true
209 };
210
211 // Display types for which padding is ignored.
212 var noPaddingDisplayType = {
213 'table-column': true,
214 'table-column-group': true,
215 'table-footer-group': true,
216 'table-header-group': true,
217 'table-row': true,
218 'table-row-group': true
219 };
220
221 // Position types for which top, left, bottom and right are ignored.
222 var noPositionType = {'static': true};
223
224 var boxes = ['content', 'padding', 'border', 'margin', 'position'];
225 var boxColors = [
226 WebInspector.Color.PageHighlight.Content, WebInspector.Color.PageHighlight .Padding,
227 WebInspector.Color.PageHighlight.Border, WebInspector.Color.PageHighlight. Margin,
228 WebInspector.Color.fromRGBA([0, 0, 0, 0])
229 ];
230 var boxLabels = [
231 WebInspector.UIString('content'), WebInspector.UIString('padding'), WebIns pector.UIString('border'),
232 WebInspector.UIString('margin'), WebInspector.UIString('position')
233 ];
234 var previousBox = null;
235 this._boxElements = [];
236 for (var i = 0; i < boxes.length; ++i) {
237 var name = boxes[i];
238
239 if (name === 'margin' && noMarginDisplayType[style.get('display')])
240 continue;
241 if (name === 'padding' && noPaddingDisplayType[style.get('display')])
242 continue;
243 if (name === 'position' && noPositionType[style.get('position')])
244 continue;
245
246 var boxElement = createElement('div');
247 boxElement.className = name;
248 boxElement._backgroundColor = boxColors[i].asString(WebInspector.Color.For mat.RGBA);
249 boxElement._name = name;
250 boxElement.style.backgroundColor = boxElement._backgroundColor;
251 boxElement.addEventListener(
252 'mouseover', this._highlightDOMNode.bind(this, true, name === 'positio n' ? 'all' : name), false);
253 this._boxElements.push(boxElement);
254
255 if (name === 'content') {
256 var widthElement = createElement('span');
257 widthElement.textContent = getContentAreaWidthPx(style);
258 widthElement.addEventListener(
259 'dblclick', this.startEditing.bind(this, widthElement, 'width', 'wid th', style), false);
260
261 var heightElement = createElement('span');
262 heightElement.textContent = getContentAreaHeightPx(style);
263 heightElement.addEventListener(
264 'dblclick', this.startEditing.bind(this, heightElement, 'height', 'h eight', style), false);
265
266 boxElement.appendChild(widthElement);
267 boxElement.createTextChild(' \u00D7 ');
268 boxElement.appendChild(heightElement);
269 } else {
270 var suffix = (name === 'border' ? '-width' : '');
271
272 var labelElement = createElement('div');
273 labelElement.className = 'label';
274 labelElement.textContent = boxLabels[i];
275 boxElement.appendChild(labelElement);
276
277 boxElement.appendChild(createBoxPartElement.call(this, style, name, 'top ', suffix));
278 boxElement.appendChild(createElement('br'));
279 boxElement.appendChild(createBoxPartElement.call(this, style, name, 'lef t', suffix));
280
281 if (previousBox)
282 boxElement.appendChild(previousBox);
283
284 boxElement.appendChild(createBoxPartElement.call(this, style, name, 'rig ht', suffix));
285 boxElement.appendChild(createElement('br'));
286 boxElement.appendChild(createBoxPartElement.call(this, style, name, 'bot tom', suffix));
287 }
288
289 previousBox = boxElement;
290 }
291
292 metricsElement.appendChild(previousBox);
293 metricsElement.addEventListener('mouseover', this._highlightDOMNode.bind(thi s, false, 'all'), false);
294 this.element.removeChildren();
295 this.element.appendChild(metricsElement);
296 }
297
298 /**
299 * @param {!Element} targetElement
300 * @param {string} box
301 * @param {string} styleProperty
302 * @param {!Map.<string, string>} computedStyle
303 */
304 startEditing(targetElement, box, styleProperty, computedStyle) {
305 if (WebInspector.isBeingEdited(targetElement))
306 return;
307
308 var context = {box: box, styleProperty: styleProperty, computedStyle: comput edStyle};
309 var boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty);
310 context.keyDownHandler = boundKeyDown;
311 targetElement.addEventListener('keydown', boundKeyDown, false);
312
313 this._isEditingMetrics = true;
314
315 var config = new WebInspector.InplaceEditor.Config(
316 this._editingCommitted.bind(this), this.editingCancelled.bind(this), con text);
317 WebInspector.InplaceEditor.startEditing(targetElement, config);
318
319 targetElement.getComponentSelection().setBaseAndExtent(targetElement, 0, tar getElement, 1);
320 }
321
322 _handleKeyDown(context, styleProperty, event) {
323 var element = event.currentTarget;
324
325 /**
326 * @param {string} originalValue
327 * @param {string} replacementString
328 * @this {WebInspector.MetricsSidebarPane}
329 */
330 function finishHandler(originalValue, replacementString) {
331 this._applyUserInput(element, replacementString, originalValue, context, f alse);
332 }
333
334 /**
335 * @param {string} prefix
336 * @param {number} number
337 * @param {string} suffix
338 * @return {string}
339 */
340 function customNumberHandler(prefix, number, suffix) {
341 if (styleProperty !== 'margin' && number < 0)
342 number = 0;
343 return prefix + number + suffix;
344 }
345
346 WebInspector.handleElementValueModifications(
347 event, element, finishHandler.bind(this), undefined, customNumberHandler );
348 }
349
350 editingEnded(element, context) {
351 delete this.originalPropertyData;
352 delete this.previousPropertyDataCandidate;
353 element.removeEventListener('keydown', context.keyDownHandler, false);
354 delete this._isEditingMetrics;
355 }
356
357 editingCancelled(element, context) {
358 if ('originalPropertyData' in this && this.inlineStyle) {
359 if (!this.originalPropertyData) {
360 // An added property, remove the last property in the style.
361 var pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropert yIndex();
362 if (pastLastSourcePropertyIndex)
363 this.inlineStyle.allProperties[pastLastSourcePropertyIndex - 1].setTex t('', false);
364 } else
365 this.inlineStyle.allProperties[this.originalPropertyData.index].setText(
366 this.originalPropertyData.propertyText, false);
367 }
368 this.editingEnded(element, context);
369 this.update();
370 }
371
372 _applyUserInput(element, userInput, previousContent, context, commitEditor) {
373 if (!this.inlineStyle) {
374 // Element has no renderer.
375 return this.editingCancelled(element, context); // nothing changed, so ca ncel
376 }
377
378 if (commitEditor && userInput === previousContent)
379 return this.editingCancelled(element, context); // nothing changed, so ca ncel
380
381 if (context.box !== 'position' && (!userInput || userInput === '\u2012'))
382 userInput = '0px';
383 else if (context.box === 'position' && (!userInput || userInput === '\u2012' ))
384 userInput = 'auto';
385
386 userInput = userInput.toLowerCase();
387 // Append a "px" unit if the user input was just a number.
388 if (/^\d+$/.test(userInput))
389 userInput += 'px';
390
391 var styleProperty = context.styleProperty;
392 var computedStyle = context.computedStyle;
393
394 if (computedStyle.get('box-sizing') === 'border-box' && (styleProperty === ' width' || styleProperty === 'height')) {
395 if (!userInput.match(/px$/)) {
396 WebInspector.console.error(
397 'For elements with box-sizing: border-box, only absolute content are a dimensions can be applied');
398 return;
399 }
400
401 var borderBox = this._getBox(computedStyle, 'border');
402 var paddingBox = this._getBox(computedStyle, 'padding');
403 var userValuePx = Number(userInput.replace(/px$/, ''));
404 if (isNaN(userValuePx))
405 return;
406 if (styleProperty === 'width')
407 userValuePx += borderBox.left + borderBox.right + paddingBox.left + padd ingBox.right;
408 else
409 userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddi ngBox.bottom;
410
411 userInput = userValuePx + 'px';
412 }
413
414 this.previousPropertyDataCandidate = null;
415
416 var allProperties = this.inlineStyle.allProperties;
417 for (var i = 0; i < allProperties.length; ++i) {
418 var property = allProperties[i];
419 if (property.name !== context.styleProperty || !property.activeInStyle())
420 continue;
421
422 this.previousPropertyDataCandidate = property;
423 property.setValue(userInput, commitEditor, true, callback.bind(this));
424 return;
425 }
426
427 this.inlineStyle.appendProperty(context.styleProperty, userInput, callback.b ind(this));
428
429 /**
430 * @param {boolean} success
431 * @this {WebInspector.MetricsSidebarPane}
432 */
433 function callback(success) {
434 if (!success)
435 return;
436 if (!('originalPropertyData' in this))
437 this.originalPropertyData = this.previousPropertyDataCandidate;
438
439 if (typeof this._highlightMode !== 'undefined')
440 this.node().highlight(this._highlightMode);
441
442 if (commitEditor)
443 this.update();
444 }
445 }
446
447 _editingCommitted(element, userInput, previousContent, context) {
448 this.editingEnded(element, context);
449 this._applyUserInput(element, userInput, previousContent, context, true);
450 }
36 }; 451 };
37
38 WebInspector.MetricsSidebarPane.prototype = {
39 /**
40 * @override
41 * @protected
42 * @return {!Promise.<?>}
43 */
44 doUpdate: function()
45 {
46 // "style" attribute might have changed. Update metrics unless they are being edited
47 // (if a CSS property is added, a StyleSheetChanged event is dispatched) .
48 if (this._isEditingMetrics)
49 return Promise.resolve();
50
51 // FIXME: avoid updates of a collapsed pane.
52 var node = this.node();
53 var cssModel = this.cssModel();
54 if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {
55 this.element.removeChildren();
56 return Promise.resolve();
57 }
58
59 /**
60 * @param {?Map.<string, string>} style
61 * @this {WebInspector.MetricsSidebarPane}
62 */
63 function callback(style)
64 {
65 if (!style || this.node() !== node)
66 return;
67 this._updateMetrics(style);
68 }
69 /**
70 * @param {?WebInspector.CSSModel.InlineStyleResult} inlineStyleResult
71 * @this {WebInspector.MetricsSidebarPane}
72 */
73 function inlineStyleCallback(inlineStyleResult)
74 {
75 if (inlineStyleResult && this.node() === node)
76 this.inlineStyle = inlineStyleResult.inlineStyle;
77 }
78
79 var promises = [
80 cssModel.computedStylePromise(node.id).then(callback.bind(this)),
81 cssModel.inlineStylesPromise(node.id).then(inlineStyleCallback.bind( this))
82 ];
83 return Promise.all(promises);
84 },
85
86 /**
87 * @override
88 */
89 onCSSModelChanged: function()
90 {
91 this.update();
92 },
93
94 /**
95 * @param {!Map.<string, string>} style
96 * @param {string} propertyName
97 * @return {number}
98 */
99 _getPropertyValueAsPx: function(style, propertyName)
100 {
101 return Number(style.get(propertyName).replace(/px$/, "") || 0);
102 },
103
104 /**
105 * @param {!Map.<string, string>} computedStyle
106 * @param {string} componentName
107 */
108 _getBox: function(computedStyle, componentName)
109 {
110 var suffix = componentName === "border" ? "-width" : "";
111 var left = this._getPropertyValueAsPx(computedStyle, componentName + "-l eft" + suffix);
112 var top = this._getPropertyValueAsPx(computedStyle, componentName + "-to p" + suffix);
113 var right = this._getPropertyValueAsPx(computedStyle, componentName + "- right" + suffix);
114 var bottom = this._getPropertyValueAsPx(computedStyle, componentName + " -bottom" + suffix);
115 return { left: left, top: top, right: right, bottom: bottom };
116 },
117
118 /**
119 * @param {boolean} showHighlight
120 * @param {string} mode
121 * @param {!Event} event
122 */
123 _highlightDOMNode: function(showHighlight, mode, event)
124 {
125 event.consume();
126 if (showHighlight && this.node()) {
127 if (this._highlightMode === mode)
128 return;
129 this._highlightMode = mode;
130 this.node().highlight(mode);
131 } else {
132 delete this._highlightMode;
133 WebInspector.DOMModel.hideDOMNodeHighlight();
134 }
135
136 for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) {
137 var element = this._boxElements[i];
138 if (!this.node() || mode === "all" || element._name === mode)
139 element.style.backgroundColor = element._backgroundColor;
140 else
141 element.style.backgroundColor = "";
142 }
143 },
144
145 /**
146 * @param {!Map.<string, string>} style
147 */
148 _updateMetrics: function(style)
149 {
150 // Updating with computed style.
151 var metricsElement = createElement("div");
152 metricsElement.className = "metrics";
153 var self = this;
154
155 /**
156 * @param {!Map.<string, string>} style
157 * @param {string} name
158 * @param {string} side
159 * @param {string} suffix
160 * @this {WebInspector.MetricsSidebarPane}
161 */
162 function createBoxPartElement(style, name, side, suffix)
163 {
164 var propertyName = (name !== "position" ? name + "-" : "") + side + suffix;
165 var value = style.get(propertyName);
166 if (value === "" || (name !== "position" && value === "0px"))
167 value = "\u2012";
168 else if (name === "position" && value === "auto")
169 value = "\u2012";
170 value = value.replace(/px$/, "");
171 value = Number.toFixedIfFloating(value);
172
173 var element = createElement("div");
174 element.className = side;
175 element.textContent = value;
176 element.addEventListener("dblclick", this.startEditing.bind(this, el ement, name, propertyName, style), false);
177 return element;
178 }
179
180 /**
181 * @param {!Map.<string, string>} style
182 * @return {string}
183 */
184 function getContentAreaWidthPx(style)
185 {
186 var width = style.get("width").replace(/px$/, "");
187 if (!isNaN(width) && style.get("box-sizing") === "border-box") {
188 var borderBox = self._getBox(style, "border");
189 var paddingBox = self._getBox(style, "padding");
190
191 width = width - borderBox.left - borderBox.right - paddingBox.le ft - paddingBox.right;
192 }
193
194 return Number.toFixedIfFloating(width.toString());
195 }
196
197 /**
198 * @param {!Map.<string, string>} style
199 * @return {string}
200 */
201 function getContentAreaHeightPx(style)
202 {
203 var height = style.get("height").replace(/px$/, "");
204 if (!isNaN(height) && style.get("box-sizing") === "border-box") {
205 var borderBox = self._getBox(style, "border");
206 var paddingBox = self._getBox(style, "padding");
207
208 height = height - borderBox.top - borderBox.bottom - paddingBox. top - paddingBox.bottom;
209 }
210
211 return Number.toFixedIfFloating(height.toString());
212 }
213
214 // Display types for which margin is ignored.
215 var noMarginDisplayType = {
216 "table-cell": true,
217 "table-column": true,
218 "table-column-group": true,
219 "table-footer-group": true,
220 "table-header-group": true,
221 "table-row": true,
222 "table-row-group": true
223 };
224
225 // Display types for which padding is ignored.
226 var noPaddingDisplayType = {
227 "table-column": true,
228 "table-column-group": true,
229 "table-footer-group": true,
230 "table-header-group": true,
231 "table-row": true,
232 "table-row-group": true
233 };
234
235 // Position types for which top, left, bottom and right are ignored.
236 var noPositionType = {
237 "static": true
238 };
239
240 var boxes = ["content", "padding", "border", "margin", "position"];
241 var boxColors = [
242 WebInspector.Color.PageHighlight.Content,
243 WebInspector.Color.PageHighlight.Padding,
244 WebInspector.Color.PageHighlight.Border,
245 WebInspector.Color.PageHighlight.Margin,
246 WebInspector.Color.fromRGBA([0, 0, 0, 0])
247 ];
248 var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString ("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), W ebInspector.UIString("position")];
249 var previousBox = null;
250 this._boxElements = [];
251 for (var i = 0; i < boxes.length; ++i) {
252 var name = boxes[i];
253
254 if (name === "margin" && noMarginDisplayType[style.get("display")])
255 continue;
256 if (name === "padding" && noPaddingDisplayType[style.get("display")] )
257 continue;
258 if (name === "position" && noPositionType[style.get("position")])
259 continue;
260
261 var boxElement = createElement("div");
262 boxElement.className = name;
263 boxElement._backgroundColor = boxColors[i].asString(WebInspector.Col or.Format.RGBA);
264 boxElement._name = name;
265 boxElement.style.backgroundColor = boxElement._backgroundColor;
266 boxElement.addEventListener("mouseover", this._highlightDOMNode.bind (this, true, name === "position" ? "all" : name), false);
267 this._boxElements.push(boxElement);
268
269 if (name === "content") {
270 var widthElement = createElement("span");
271 widthElement.textContent = getContentAreaWidthPx(style);
272 widthElement.addEventListener("dblclick", this.startEditing.bind (this, widthElement, "width", "width", style), false);
273
274 var heightElement = createElement("span");
275 heightElement.textContent = getContentAreaHeightPx(style);
276 heightElement.addEventListener("dblclick", this.startEditing.bin d(this, heightElement, "height", "height", style), false);
277
278 boxElement.appendChild(widthElement);
279 boxElement.createTextChild(" \u00D7 ");
280 boxElement.appendChild(heightElement);
281 } else {
282 var suffix = (name === "border" ? "-width" : "");
283
284 var labelElement = createElement("div");
285 labelElement.className = "label";
286 labelElement.textContent = boxLabels[i];
287 boxElement.appendChild(labelElement);
288
289 boxElement.appendChild(createBoxPartElement.call(this, style, na me, "top", suffix));
290 boxElement.appendChild(createElement("br"));
291 boxElement.appendChild(createBoxPartElement.call(this, style, na me, "left", suffix));
292
293 if (previousBox)
294 boxElement.appendChild(previousBox);
295
296 boxElement.appendChild(createBoxPartElement.call(this, style, na me, "right", suffix));
297 boxElement.appendChild(createElement("br"));
298 boxElement.appendChild(createBoxPartElement.call(this, style, na me, "bottom", suffix));
299 }
300
301 previousBox = boxElement;
302 }
303
304 metricsElement.appendChild(previousBox);
305 metricsElement.addEventListener("mouseover", this._highlightDOMNode.bind (this, false, "all"), false);
306 this.element.removeChildren();
307 this.element.appendChild(metricsElement);
308 },
309
310 /**
311 * @param {!Element} targetElement
312 * @param {string} box
313 * @param {string} styleProperty
314 * @param {!Map.<string, string>} computedStyle
315 */
316 startEditing: function(targetElement, box, styleProperty, computedStyle)
317 {
318 if (WebInspector.isBeingEdited(targetElement))
319 return;
320
321 var context = { box: box, styleProperty: styleProperty, computedStyle: c omputedStyle };
322 var boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty );
323 context.keyDownHandler = boundKeyDown;
324 targetElement.addEventListener("keydown", boundKeyDown, false);
325
326 this._isEditingMetrics = true;
327
328 var config = new WebInspector.InplaceEditor.Config(this._editingCommitte d.bind(this), this.editingCancelled.bind(this), context);
329 WebInspector.InplaceEditor.startEditing(targetElement, config);
330
331 targetElement.getComponentSelection().setBaseAndExtent(targetElement, 0, targetElement, 1);
332 },
333
334 _handleKeyDown: function(context, styleProperty, event)
335 {
336 var element = event.currentTarget;
337
338 /**
339 * @param {string} originalValue
340 * @param {string} replacementString
341 * @this {WebInspector.MetricsSidebarPane}
342 */
343 function finishHandler(originalValue, replacementString)
344 {
345 this._applyUserInput(element, replacementString, originalValue, cont ext, false);
346 }
347
348 /**
349 * @param {string} prefix
350 * @param {number} number
351 * @param {string} suffix
352 * @return {string}
353 */
354 function customNumberHandler(prefix, number, suffix)
355 {
356 if (styleProperty !== "margin" && number < 0)
357 number = 0;
358 return prefix + number + suffix;
359 }
360
361 WebInspector.handleElementValueModifications(event, element, finishHandl er.bind(this), undefined, customNumberHandler);
362 },
363
364 editingEnded: function(element, context)
365 {
366 delete this.originalPropertyData;
367 delete this.previousPropertyDataCandidate;
368 element.removeEventListener("keydown", context.keyDownHandler, false);
369 delete this._isEditingMetrics;
370 },
371
372 editingCancelled: function(element, context)
373 {
374 if ("originalPropertyData" in this && this.inlineStyle) {
375 if (!this.originalPropertyData) {
376 // An added property, remove the last property in the style.
377 var pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourc ePropertyIndex();
378 if (pastLastSourcePropertyIndex)
379 this.inlineStyle.allProperties[pastLastSourcePropertyIndex - 1].setText("", false);
380 } else
381 this.inlineStyle.allProperties[this.originalPropertyData.index]. setText(this.originalPropertyData.propertyText, false);
382 }
383 this.editingEnded(element, context);
384 this.update();
385 },
386
387 _applyUserInput: function(element, userInput, previousContent, context, comm itEditor)
388 {
389 if (!this.inlineStyle) {
390 // Element has no renderer.
391 return this.editingCancelled(element, context); // nothing changed, so cancel
392 }
393
394 if (commitEditor && userInput === previousContent)
395 return this.editingCancelled(element, context); // nothing changed, so cancel
396
397 if (context.box !== "position" && (!userInput || userInput === "\u2012") )
398 userInput = "0px";
399 else if (context.box === "position" && (!userInput || userInput === "\u2 012"))
400 userInput = "auto";
401
402 userInput = userInput.toLowerCase();
403 // Append a "px" unit if the user input was just a number.
404 if (/^\d+$/.test(userInput))
405 userInput += "px";
406
407 var styleProperty = context.styleProperty;
408 var computedStyle = context.computedStyle;
409
410 if (computedStyle.get("box-sizing") === "border-box" && (styleProperty = == "width" || styleProperty === "height")) {
411 if (!userInput.match(/px$/)) {
412 WebInspector.console.error("For elements with box-sizing: border -box, only absolute content area dimensions can be applied");
413 return;
414 }
415
416 var borderBox = this._getBox(computedStyle, "border");
417 var paddingBox = this._getBox(computedStyle, "padding");
418 var userValuePx = Number(userInput.replace(/px$/, ""));
419 if (isNaN(userValuePx))
420 return;
421 if (styleProperty === "width")
422 userValuePx += borderBox.left + borderBox.right + paddingBox.lef t + paddingBox.right;
423 else
424 userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;
425
426 userInput = userValuePx + "px";
427 }
428
429 this.previousPropertyDataCandidate = null;
430
431 var allProperties = this.inlineStyle.allProperties;
432 for (var i = 0; i < allProperties.length; ++i) {
433 var property = allProperties[i];
434 if (property.name !== context.styleProperty || !property.activeInSty le())
435 continue;
436
437 this.previousPropertyDataCandidate = property;
438 property.setValue(userInput, commitEditor, true, callback.bind(this) );
439 return;
440 }
441
442 this.inlineStyle.appendProperty(context.styleProperty, userInput, callba ck.bind(this));
443
444 /**
445 * @param {boolean} success
446 * @this {WebInspector.MetricsSidebarPane}
447 */
448 function callback(success)
449 {
450 if (!success)
451 return;
452 if (!("originalPropertyData" in this))
453 this.originalPropertyData = this.previousPropertyDataCandidate;
454
455 if (typeof this._highlightMode !== "undefined")
456 this.node().highlight(this._highlightMode);
457
458 if (commitEditor)
459 this.update();
460 }
461 },
462
463 _editingCommitted: function(element, userInput, previousContent, context)
464 {
465 this.editingEnded(element, context);
466 this._applyUserInput(element, userInput, previousContent, context, true) ;
467 },
468
469 __proto__: WebInspector.ElementsSidebarPane.prototype
470 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698