Bug 1333714 - update grid highlighter and layout panel on markupmutation;r=gl
MozReview-Commit-ID: 9TAUxqTiT4M
--- a/devtools/client/inspector/grids/grid-inspector.js
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -42,16 +42,17 @@ function GridInspector(inspector, window
this.walker = this.inspector.walker;
this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
this.setSelectedNode = this.setSelectedNode.bind(this);
this.updateGridPanel = this.updateGridPanel.bind(this);
this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
this.onHighlighterChange = this.onHighlighterChange.bind(this);
+ this.onMarkupMutation = this.onMarkupMutation.bind(this);
this.onSetGridOverlayColor = this.onSetGridOverlayColor.bind(this);
this.onShowBoxModelHighlighterForNode =
this.onShowBoxModelHighlighterForNode.bind(this);
this.onShowGridAreaHighlight = this.onShowGridAreaHighlight.bind(this);
this.onShowGridCellHighlight = this.onShowGridCellHighlight.bind(this);
this.onSidebarSelect = this.onSidebarSelect.bind(this);
this.onToggleGridHighlighter = this.onToggleGridHighlighter.bind(this);
this.onToggleShowGridLineNumbers = this.onToggleShowGridLineNumbers.bind(this);
@@ -81,28 +82,30 @@ GridInspector.prototype = {
this.inspector,
{
supportsCssColor4ColorFunction: () => false
}
);
this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
+ this.inspector.on("markupmutation", this.onMarkupMutation);
this.inspector.sidebar.on("select", this.onSidebarSelect);
this.onSidebarSelect();
}),
/**
* Destruction function called when the inspector is destroyed. Removes event listeners
* and cleans up references.
*/
destroy() {
this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
+ this.inspector.off("markupmutation", this.onMarkupMutation);
this.inspector.sidebar.off("select", this.onSidebarSelect);
this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
this.swatchColorPickerTooltip.destroy();
this.document = null;
this.highlighters = null;
this.inspector = null;
@@ -294,16 +297,24 @@ GridInspector.prototype = {
onHighlighterChange(event, nodeFront, options) {
let highlighted = event === "grid-highlighter-shown";
let { color } = options;
this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
this.store.dispatch(updateGridColor(nodeFront, color));
},
/**
+ * Handler for the "markupmutation" event fired by the inspector. On markup mutations,
+ * update the grid panel content.
+ */
+ onMarkupMutation() {
+ this.updateGridPanel();
+ },
+
+ /**
* Handler for a change in the grid overlay color picker for a grid container.
*
* @param {NodeFront} node
* The NodeFront of the grid container element for which the grid color is
* being updated.
* @param {String} color
* A hex string representing the color to use.
*/
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -81,16 +81,18 @@ const PORTRAIT_MODE_WIDTH = 700;
* to source-mapped files)
* - rule-view-refreshed
* Fired when the rule view updates to a new node
* - rule-view-sourcelinks-updated
* Fired when the stylesheet source links have been updated (when switching
* to source-mapped files)
*/
function Inspector(toolbox) {
+ EventEmitter.decorate(this);
+
this._toolbox = toolbox;
this._target = toolbox.target;
this.panelDoc = window.document;
this.panelWin = window;
this.panelWin.inspector = this;
this.highlighters = new HighlightersOverlay(this);
this.store = Store();
@@ -109,18 +111,16 @@ function Inspector(toolbox) {
this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
this._onMarkupFrameLoad = this._onMarkupFrameLoad.bind(this);
this.onPanelWindowResize = this.onPanelWindowResize.bind(this);
this.onSidebarShown = this.onSidebarShown.bind(this);
this.onSidebarHidden = this.onSidebarHidden.bind(this);
this._target.on("will-navigate", this._onBeforeNavigate);
this._detectingActorFeatures = this._detectActorFeatures();
-
- EventEmitter.decorate(this);
}
Inspector.prototype = {
/**
* open is effectively an asynchronous constructor
*/
init: Task.async(function* () {
// Localize all the nodes containing a data-localization attribute.
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -145,16 +145,17 @@ skip-if = os == "mac" # Bug 1245996 : cl
[browser_rules_edit-value-after-name_04.js]
[browser_rules_editable-field-focus_01.js]
[browser_rules_editable-field-focus_02.js]
[browser_rules_eyedropper.js]
[browser_rules_filtereditor-appears-on-swatch-click.js]
[browser_rules_filtereditor-commit-on-ENTER.js]
[browser_rules_filtereditor-revert-on-ESC.js]
skip-if = (os == "win" && debug) # bug 963492: win.
+[browser_rules_grid-highlighter-on-mutation.js]
[browser_rules_grid-highlighter-on-navigate.js]
[browser_rules_grid-highlighter-on-reload.js]
[browser_rules_grid-highlighter-restored-after-reload.js]
[browser_rules_grid-toggle_01.js]
[browser_rules_grid-toggle_01b.js]
[browser_rules_grid-toggle_02.js]
[browser_rules_grid-toggle_03.js]
[browser_rules_guessIndentation.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_grid-highlighter-on-mutation.js
@@ -0,0 +1,44 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that the grid highlighter is hidden when the highlighted grid container is
+// removed from the page.
+
+const TEST_URI = `
+ <style type='text/css'>
+ #grid {
+ display: grid;
+ }
+ </style>
+ <div id="grid">
+ <div id="cell1">cell1</div>
+ <div id="cell2">cell2</div>
+ </div>
+`;
+
+add_task(function* () {
+ yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+ let {inspector, view, testActor} = yield openRuleView();
+ let highlighters = view.highlighters;
+
+ yield selectNode("#grid", inspector);
+ let container = getRuleViewProperty(view, "#grid", "display").valueSpan;
+ let gridToggle = container.querySelector(".ruleview-grid");
+
+ info("Toggling ON the CSS grid highlighter from the rule-view.");
+ let onHighlighterShown = highlighters.once("grid-highlighter-shown");
+ gridToggle.click();
+ yield onHighlighterShown;
+ ok(highlighters.gridHighlighterShown, "CSS grid highlighter is shown.");
+
+ let onHighlighterHidden = highlighters.once("grid-highlighter-hidden");
+ info("Remove the #grid container in the content page");
+ testActor.eval(`
+ content.document.querySelector("#grid").remove();
+ `);
+ yield onHighlighterHidden;
+ ok(!highlighters.gridHighlighterShown, "CSS grid highlighter is hidden.");
+});
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -35,23 +35,25 @@ function HighlightersOverlay(inspector)
this.selectorHighlighterShown = null;
// Saved state to be restore on page navigation.
this.state = {
// Only the grid highlighter state is saved at the moment.
grid: {}
};
this.onClick = this.onClick.bind(this);
+ this.onMarkupMutation = this.onMarkupMutation.bind(this);
this.onMouseMove = this.onMouseMove.bind(this);
this.onMouseOut = this.onMouseOut.bind(this);
this.onWillNavigate = this.onWillNavigate.bind(this);
this.onNavigate = this.onNavigate.bind(this);
this._handleRejection = this._handleRejection.bind(this);
- // Add target events, not specific to a given view.
+ // Add inspector events, not specific to a given view.
+ this.inspector.on("markupmutation", this.onMarkupMutation);
this.inspector.target.on("navigate", this.onNavigate);
this.inspector.target.on("will-navigate", this.onWillNavigate);
EventEmitter.decorate(this);
}
HighlightersOverlay.prototype = {
get isRuleView() {
@@ -371,16 +373,40 @@ HighlightersOverlay.prototype = {
}
// Otherwise, hide the highlighter.
this._lastHovered = null;
this._hideHoveredHighlighter();
},
/**
+ * Handler function for "markupmutation" events. Hides the grid highlighter if the grid
+ * container is no longer in the DOM tree.
+ */
+ onMarkupMutation: Task.async(function* (evt, mutations) {
+ let hasInterestingMutation = mutations.some(mut => mut.type === "childList");
+ if (!hasInterestingMutation || !this.gridHighlighterShown) {
+ // Bail out if the mutations did not remove nodes, or if no grid highlighter is
+ // displayed.
+ return;
+ }
+
+ let nodeFront = this.gridHighlighterShown;
+
+ try {
+ let isInTree = yield this.inspector.walker.isInDOMTree(nodeFront);
+ if (!isInTree) {
+ this.hideGridHighlighter(nodeFront);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ }),
+
+ /**
* Restore saved highlighter state after navigate.
*/
onNavigate: Task.async(function* () {
try {
yield this.restoreState();
} catch (e) {
this._handleRejection(e);
}
@@ -405,17 +431,18 @@ HighlightersOverlay.prototype = {
destroy: function () {
for (let type in this.highlighters) {
if (this.highlighters[type]) {
this.highlighters[type].finalize();
this.highlighters[type] = null;
}
}
- // Remove target events.
+ // Remove inspector events.
+ this.inspector.off("markupmutation", this.onMarkupMutation);
this.inspector.target.off("navigate", this.onNavigate);
this.inspector.target.off("will-navigate", this.onWillNavigate);
this._lastHovered = null;
this.inspector = null;
this.highlighters = null;
this.highlighterUtils = null;