Index: Source/devtools/front_end/toolbox/MediaQueryInspector.js |
diff --git a/Source/devtools/front_end/toolbox/MediaQueryInspector.js b/Source/devtools/front_end/toolbox/MediaQueryInspector.js |
index 31e2cfcf6b420e23439ae1174169a85c48d1b5dc..ad473c81694ae0549569d3d7bfa6c22a58154c40 100644 |
--- a/Source/devtools/front_end/toolbox/MediaQueryInspector.js |
+++ b/Source/devtools/front_end/toolbox/MediaQueryInspector.js |
@@ -13,13 +13,15 @@ WebInspector.MediaQueryInspector = function() |
this.element.classList.add("media-inspector-view", "media-inspector-view-empty"); |
this.element.addEventListener("click", this._onMediaQueryClicked.bind(this), false); |
this.element.addEventListener("contextmenu", this._onContextMenu.bind(this), false); |
- this.element.addEventListener("webkitAnimationEnd", this._onAnimationEnd.bind(this), false); |
this._mediaThrottler = new WebInspector.Throttler(100); |
this._translateZero = 0; |
this._offset = 0; |
this._scale = 1; |
this._lastReportedCount = 0; |
+ this._highlightedModel = null; |
+ this._highlightDecorationVisible = false; |
+ this._availableSections = [false, false, false]; |
this._rulerDecorationLayer = document.createElementWithClass("div", "fill"); |
this._rulerDecorationLayer.classList.add("media-inspector-ruler-decoration"); |
@@ -41,9 +43,13 @@ WebInspector.MediaQueryInspector.Section = { |
WebInspector.MediaQueryInspector.Events = { |
HeightUpdated: "HeightUpdated", |
- CountUpdated: "CountUpdated" |
+ CountUpdated: "CountUpdated", |
+ HighlightDecorationUpdated: "HighlightDecorationUpdated" |
} |
+/** @typedef {!{value: number, section: number}} */ |
+WebInspector.MediaQueryInspector.Threshold; |
+ |
WebInspector.MediaQueryInspector.prototype = { |
/** |
* @param {!WebInspector.Target} target |
@@ -82,7 +88,7 @@ WebInspector.MediaQueryInspector.prototype = { |
}, |
/** |
- * @return {!Array.<number>} |
+ * @return {!Array.<!WebInspector.MediaQueryInspector.Threshold>} |
*/ |
_mediaQueryThresholds: function() |
{ |
@@ -92,11 +98,21 @@ WebInspector.MediaQueryInspector.prototype = { |
for (var i = 0; i < this._cachedQueryModels.length; ++i) { |
var model = this._cachedQueryModels[i]; |
if (model.minWidthExpression()) |
- thresholds.push(model.minWidthExpression().computedLength()); |
+ thresholds.push({value: model.minWidthExpression().computedLength(), section: model.section()}); |
if (model.maxWidthExpression()) |
- thresholds.push(model.maxWidthExpression().computedLength()); |
+ thresholds.push({value: model.maxWidthExpression().computedLength(), section: model.section()}); |
+ } |
+ /** |
+ * @param {!WebInspector.MediaQueryInspector.Threshold} threshold1 |
+ * @param {!WebInspector.MediaQueryInspector.Threshold} threshold2 |
+ * @return {number} |
+ */ |
+ function comparator(threshold1, threshold2) |
+ { |
+ return threshold1.value - threshold2.value; |
} |
- thresholds.sortNumbers(); |
+ |
+ thresholds.sort(comparator); |
return thresholds; |
}, |
@@ -105,32 +121,10 @@ WebInspector.MediaQueryInspector.prototype = { |
*/ |
_onRulerDecorationClicked: function(event) |
{ |
- var thresholdElement = event.target.enclosingNodeOrSelfWithClass("media-inspector-threshold-serif"); |
+ var thresholdElement = event.target.enclosingNodeOrSelfWithClass("media-inspector-threshold"); |
if (!thresholdElement) |
return; |
WebInspector.settings.showMediaQueryInspector.set(true); |
- var revealValue = thresholdElement._value; |
- for (var mediaQueryContainer = this.element.firstChild; mediaQueryContainer; mediaQueryContainer = mediaQueryContainer.nextSibling) { |
- var model = mediaQueryContainer._model; |
- if ((model.minWidthExpression() && Math.abs(model.minWidthExpression().computedLength() - revealValue) === 0) |
- || (model.maxWidthExpression() && Math.abs(model.maxWidthExpression().computedLength() - revealValue) === 0)) { |
- mediaQueryContainer.scrollIntoViewIfNeeded(false); |
- var hasRunningAnimation = mediaQueryContainer.classList.contains("media-inspector-marker-highlight-1") || mediaQueryContainer.classList.contains("media-inspector-marker-highlight-2"); |
- mediaQueryContainer.classList.toggle("media-inspector-marker-highlight-1"); |
- if (hasRunningAnimation) |
- mediaQueryContainer.classList.toggle("media-inspector-marker-highlight-2"); |
- return; |
- } |
- } |
- }, |
- |
- /** |
- * @param {!Event} event |
- */ |
- _onAnimationEnd: function(event) |
- { |
- event.target.classList.remove("media-inspector-marker-highlight-1"); |
- event.target.classList.remove("media-inspector-marker-highlight-2"); |
}, |
/** |
@@ -162,8 +156,8 @@ WebInspector.MediaQueryInspector.prototype = { |
*/ |
_onMediaQueryClicked: function(event) |
{ |
- var mediaQueryMarkerContainer = event.target.enclosingNodeOrSelfWithClass("media-inspector-marker-container"); |
- if (!mediaQueryMarkerContainer) |
+ var mediaQueryMarker = event.target.enclosingNodeOrSelfWithClass("media-inspector-marker"); |
+ if (!mediaQueryMarker) |
return; |
/** |
@@ -175,7 +169,7 @@ WebInspector.MediaQueryInspector.prototype = { |
WebInspector.overridesSupport.settings.emulateResolution.set(true); |
} |
- var model = mediaQueryMarkerContainer._model; |
+ var model = mediaQueryMarker._model; |
if (model.section() === WebInspector.MediaQueryInspector.Section.Max) { |
setWidth(model.maxWidthExpression().computedLength()); |
return; |
@@ -196,11 +190,11 @@ WebInspector.MediaQueryInspector.prototype = { |
*/ |
_onContextMenu: function(event) |
{ |
- var mediaQueryMarkerContainer = event.target.enclosingNodeOrSelfWithClass("media-inspector-marker-container"); |
- if (!mediaQueryMarkerContainer) |
+ var mediaQueryMarker = event.target.enclosingNodeOrSelfWithClass("media-inspector-marker"); |
+ if (!mediaQueryMarker) |
return; |
- var locations = mediaQueryMarkerContainer._locations; |
+ var locations = mediaQueryMarker._locations; |
var contextMenu = new WebInspector.ContextMenu(event); |
var subMenuItem = contextMenu.appendSubMenuItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in source code" : "Reveal In Source Code")); |
for (var i = 0; i < locations.length; ++i) { |
@@ -335,26 +329,83 @@ WebInspector.MediaQueryInspector.prototype = { |
if (!this.isShowing()) |
return; |
- var heightChanges = this.element.children.length !== markers.length; |
- |
+ var oldChildrenCount = this.element.children.length; |
var scrollTop = this.element.scrollTop; |
this.element.removeChildren(); |
+ |
+ for (var i = 0; i < this._availableSections.length; ++i) |
+ this._availableSections[i] = false; |
+ |
+ var container = null; |
for (var i = 0; i < markers.length; ++i) { |
+ if (!i || markers[i].model.section() !== markers[i - 1].model.section()) { |
+ container = this.element.createChild("div", "media-inspector-marker-container"); |
+ this._availableSections[markers[i].model.section()] = true; |
+ var handler = this._onMarkerContainerMouseMove.bind(this); |
+ container.addEventListener("mousemove", handler, false); |
+ container.addEventListener("mouseout", handler, false); |
+ } |
var marker = markers[i]; |
- var bar = this._createElementFromMediaQueryModel(marker.model); |
+ var bar = this._createElementFromMediaQueryModel(/** @type {!Element} */ (container), marker.model); |
bar._model = marker.model; |
bar._locations = marker.locations; |
bar.classList.toggle("media-inspector-marker-inactive", !marker.active); |
- |
- this.element.appendChild(bar); |
} |
this.element.scrollTop = scrollTop; |
this.element.classList.toggle("media-inspector-view-empty", !this.element.children.length); |
- if (heightChanges) |
+ if (this.element.children.length != oldChildrenCount) |
this.dispatchEventToListeners(WebInspector.MediaQueryInspector.Events.HeightUpdated); |
}, |
/** |
+ * @param {!Event} event |
+ */ |
+ _onMarkerContainerMouseMove: function(event) |
+ { |
+ var mediaQueryMarkerContainer = event.target.enclosingNodeOrSelfWithClass("media-inspector-marker-container"); |
+ if (!mediaQueryMarkerContainer) |
+ return; |
+ var children = mediaQueryMarkerContainer.children; |
+ if (!children.length) |
+ return; |
+ for (var i = children.length - 1; i >= 0; --i) { |
+ if (children[i].containsEventPoint(event)) { |
lushnikov
2014/09/03 14:30:41
can't we use relatedTarget/target instead of this
|
+ this._highlightMarkerInContainer(children[i], mediaQueryMarkerContainer); |
+ return; |
+ } |
+ } |
+ this._highlightMarkerInContainer(null, mediaQueryMarkerContainer); |
+ }, |
+ |
+ /** |
+ * @param {?Element} marker |
+ * @param {!Element} container |
+ */ |
+ _highlightMarkerInContainer: function(marker, container) |
+ { |
+ var children = container.children; |
+ var found = !marker; |
+ for (var i = children.length - 1; i >= 0; --i) { |
lushnikov
2014/09/03 14:30:41
Can we simply update z-index of a marker (if any),
|
+ if (found) { |
+ children[i].classList.remove("media-inspector-marker-highlight"); |
+ children[i].classList.remove("media-inspector-marker-under-highlighted"); |
+ } else if (children[i] === marker) { |
+ children[i].classList.add("media-inspector-marker-highlight"); |
+ children[i].classList.remove("media-inspector-marker-under-highlighted"); |
+ found = true; |
+ } else { |
+ children[i].classList.remove("media-inspector-marker-highlight"); |
+ children[i].classList.add("media-inspector-marker-under-highlighted"); |
+ } |
+ } |
+ var highlightedModel = marker ? marker._model : null; |
+ if (highlightedModel !== this._highlightedModel) { |
+ this._highlightedModel = highlightedModel; |
+ this._renderRulerDecorations(); |
+ } |
+ }, |
+ |
+ /** |
* @return {number} |
*/ |
_zoomFactor: function() |
@@ -362,17 +413,89 @@ WebInspector.MediaQueryInspector.prototype = { |
return WebInspector.zoomManager.zoomFactor() / this._scale; |
}, |
+ /** |
+ * @return {boolean} |
+ */ |
+ highlightDecorationVisible: function() |
+ { |
+ return this._highlightDecorationVisible; |
+ }, |
+ |
_renderRulerDecorations: function() |
{ |
+ var highlightDecorationVisible = this.isShowing() && !!this._highlightedModel; |
+ if (highlightDecorationVisible !== this._highlightDecorationVisible) { |
+ this._highlightDecorationVisible = highlightDecorationVisible; |
+ this.dispatchEventToListeners(WebInspector.MediaQueryInspector.Events.HighlightDecorationUpdated); |
+ } |
+ |
this._rulerDecorationLayer.removeChildren(); |
var zoomFactor = this._zoomFactor(); |
- var thresholds = this._mediaQueryThresholds(); |
- for (var i = 0; i < thresholds.length; ++i) { |
- var thresholdElement = this._rulerDecorationLayer.createChild("div", "media-inspector-threshold-serif"); |
- thresholdElement.title = thresholds[i] + "px"; |
- thresholdElement._value = thresholds[i]; |
- thresholdElement.style.left = (thresholds[i] - this._offset) / zoomFactor + "px"; |
+ if (this.isShowing()) { |
+ if (!this._highlightedModel) |
lushnikov
2014/09/03 14:30:41
Can we extract this if-branch in a separate method
dgozman
2014/09/04 15:34:32
This method is removed now.
|
+ return; |
+ |
+ const highlightStyleClassPerSection = [ |
+ "media-inspector-highlight-threshold-max", |
+ "media-inspector-highlight-threshold-min-max", |
+ "media-inspector-highlight-threshold-min" |
+ ]; |
+ const classPerRowCount = [ |
+ "media-inspector-highlight-threshold-one-row", |
+ "media-inspector-highlight-threshold-two-rows", |
+ "media-inspector-highlight-threshold-three-rows" |
+ ]; |
+ var section = this._highlightedModel.section(); |
+ var rowCount = 0; |
+ for (var i = section; i < highlightStyleClassPerSection.length; ++i) { |
+ if (this._availableSections[i]) |
lushnikov
2014/09/03 14:30:41
availableSections is used only here; lets compute
dgozman
2014/09/04 15:34:32
Done.
|
+ rowCount++; |
+ } |
+ |
+ if (this._highlightedModel.minWidthExpression()) { |
+ var valueInPixels = this._highlightedModel.minWidthExpression().computedLength(); |
+ var minThresholdElement = this._rulerDecorationLayer.createChild("div", "media-inspector-highlight-threshold"); |
+ minThresholdElement.classList.add(highlightStyleClassPerSection[section]); |
+ minThresholdElement.classList.add(classPerRowCount[rowCount - 1]); |
+ if (this._highlightedModel.maxWidthExpression()) { |
lushnikov
2014/09/03 14:30:41
curly braces are not needed
|
+ minThresholdElement.classList.add("media-inspector-highlight-threshold-left"); |
+ } else { |
+ minThresholdElement.classList.add("media-inspector-highlight-threshold-right"); |
+ } |
+ minThresholdElement.title = valueInPixels + "px"; |
+ minThresholdElement.style.left = (valueInPixels - this._offset) / zoomFactor + "px"; |
+ minThresholdElement.createChild("span", "media-inspector-highlight-threshold-label").textContent = valueInPixels + "px"; |
+ } |
+ |
+ if (this._highlightedModel.maxWidthExpression()) { |
lushnikov
2014/09/03 14:30:41
this if-statment look almost identical to the prev
|
+ var valueInPixels = this._highlightedModel.maxWidthExpression().computedLength(); |
+ var maxThresholdElement = this._rulerDecorationLayer.createChild("div", "media-inspector-highlight-threshold"); |
+ maxThresholdElement.classList.add(highlightStyleClassPerSection[section]); |
+ maxThresholdElement.classList.add(classPerRowCount[rowCount - 1]); |
+ if (this._highlightedModel.minWidthExpression()) { |
+ maxThresholdElement.classList.add("media-inspector-highlight-threshold-right"); |
+ } else { |
+ maxThresholdElement.classList.add("media-inspector-highlight-threshold-left"); |
+ } |
+ maxThresholdElement.title = valueInPixels + "px"; |
+ maxThresholdElement.style.left = (valueInPixels - this._offset) / zoomFactor + "px"; |
+ maxThresholdElement.createChild("span", "media-inspector-highlight-threshold-label").textContent = valueInPixels + "px"; |
+ } |
+ } else { |
+ const thresholdStyleClassPerSection = [ |
+ "media-inspector-threshold-max", |
+ "media-inspector-threshold-min-max", |
+ "media-inspector-threshold-min" |
+ ]; |
+ var thresholds = this._mediaQueryThresholds(); |
+ for (var i = 0; i < thresholds.length; ++i) { |
+ var thresholdElement = this._rulerDecorationLayer.createChild("div", "media-inspector-threshold"); |
+ thresholdElement.classList.add(thresholdStyleClassPerSection[thresholds[i].section]); |
+ thresholdElement.title = thresholds[i].value + "px"; |
+ thresholdElement._value = thresholds[i].value; |
+ thresholdElement.style.left = (thresholds[i].value - this._offset) / zoomFactor + "px"; |
+ } |
} |
}, |
@@ -381,51 +504,42 @@ WebInspector.MediaQueryInspector.prototype = { |
this._renderMediaQueries(); |
}, |
+ willHide: function() |
+ { |
+ window.setImmediate(this._renderRulerDecorations.bind(this)); |
lushnikov
2014/09/03 14:30:41
why do you use setImmediate here?
dgozman
2014/09/04 15:34:32
It was necessary to have isShowing return the righ
|
+ }, |
+ |
/** |
+ * @param {!Element} container |
* @param {!WebInspector.MediaQueryInspector.MediaQueryUIModel} model |
* @return {!Element} |
*/ |
- _createElementFromMediaQueryModel: function(model) |
+ _createElementFromMediaQueryModel: function(container, model) |
{ |
var zoomFactor = this._zoomFactor(); |
var minWidthValue = model.minWidthExpression() ? model.minWidthExpression().computedLength() : 0; |
const styleClassPerSection = [ |
- "media-inspector-marker-container-max-width", |
- "media-inspector-marker-container-min-max-width", |
- "media-inspector-marker-container-min-width" |
+ "media-inspector-marker-max-width", |
+ "media-inspector-marker-min-max-width", |
+ "media-inspector-marker-min-width" |
]; |
- var container = document.createElementWithClass("div", "media-inspector-marker-container hbox"); |
- container.classList.add(styleClassPerSection[model.section()]); |
- |
var markerElement = container.createChild("div", "media-inspector-marker"); |
var leftPixelValue = minWidthValue ? (minWidthValue - this._offset) / zoomFactor + this._translateZero : 0; |
markerElement.style.left = leftPixelValue + "px"; |
+ markerElement.classList.add(styleClassPerSection[model.section()]); |
var widthPixelValue = null; |
- if (model.maxWidthExpression() && model.minWidthExpression()) |
+ if (model.maxWidthExpression() && model.minWidthExpression()) { |
lushnikov
2014/09/03 14:30:41
curlies are not needed
dgozman
2014/09/04 15:34:32
Done.
|
widthPixelValue = (model.maxWidthExpression().computedLength() - minWidthValue) / zoomFactor; |
- else if (model.maxWidthExpression()) |
+ } else if (model.maxWidthExpression()) { |
lushnikov
2014/09/03 14:30:41
ditto
|
widthPixelValue = (model.maxWidthExpression().computedLength() - this._offset) / zoomFactor + this._translateZero; |
- else |
+ } else { |
lushnikov
2014/09/03 14:30:41
ditto
|
markerElement.style.right = "0"; |
+ } |
if (typeof widthPixelValue === "number") |
markerElement.style.width = widthPixelValue + "px"; |
- var maxLabelFiller = container.createChild("div", "media-inspector-max-label-filler"); |
- if (model.maxWidthExpression()) { |
- maxLabelFiller.style.maxWidth = Math.max(widthPixelValue + leftPixelValue, 0) + "px"; |
- var label = container.createChild("span", "media-inspector-marker-label media-inspector-max-label"); |
- label.textContent = model.maxWidthExpression().computedLength() + "px"; |
- } |
- |
- if (model.minWidthExpression()) { |
- var minLabelFiller = maxLabelFiller.createChild("div", "media-inspector-min-label-filler"); |
- minLabelFiller.style.maxWidth = Math.max(leftPixelValue, 0) + "px"; |
- var label = minLabelFiller.createChild("span", "media-inspector-marker-label media-inspector-min-label"); |
- label.textContent = model.minWidthExpression().computedLength() + "px"; |
- } |
- |
- return container; |
+ return markerElement; |
}, |
__proto__: WebInspector.View.prototype |
@@ -527,10 +641,10 @@ WebInspector.MediaQueryInspector.MediaQueryUIModel.prototype = { |
return myLocation.uiSourceCode.uri().compareTo(otherLocation.uiSourceCode.uri()) || myLocation.lineNumber - otherLocation.lineNumber || myLocation.columnNumber - otherLocation.columnNumber; |
} |
if (this.section() === WebInspector.MediaQueryInspector.Section.Max) |
- return this.maxWidthExpression().computedLength() - other.maxWidthExpression().computedLength(); |
+ return other.maxWidthExpression().computedLength() - this.maxWidthExpression().computedLength(); |
if (this.section() === WebInspector.MediaQueryInspector.Section.Min) |
return this.minWidthExpression().computedLength() - other.minWidthExpression().computedLength(); |
- return this.minWidthExpression().computedLength() - other.minWidthExpression().computedLength() || this.maxWidthExpression().computedLength() - other.maxWidthExpression().computedLength(); |
+ return this.minWidthExpression().computedLength() - other.minWidthExpression().computedLength() || other.maxWidthExpression().computedLength() - this.maxWidthExpression().computedLength(); |
}, |
/** |