mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 971662 - part 2 - Highlight nodes matching style-editor selectors on mouseover; r=harth
This commit is contained in:
parent
556b135ea8
commit
582f6e4122
@ -33,6 +33,7 @@ const console = require("resource://gre/modules/devtools/Console.jsm").console;
|
||||
|
||||
const LOAD_ERROR = "error-load";
|
||||
const STYLE_EDITOR_TEMPLATE = "stylesheet";
|
||||
const SELECTOR_HIGHLIGHTER_TYPE = "SelectorHighlighter";
|
||||
const PREF_MEDIA_SIDEBAR = "devtools.styleeditor.showMediaSidebar";
|
||||
const PREF_SIDEBAR_WIDTH = "devtools.styleeditor.mediaSidebarWidth";
|
||||
const PREF_NAV_WIDTH = "devtools.styleeditor.navSidebarWidth";
|
||||
@ -111,18 +112,24 @@ StyleEditorUI.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Initiates the style editor ui creation and the inspector front to get
|
||||
* reference to the walker.
|
||||
* Initiates the style editor ui creation, the inspector front to get
|
||||
* reference to the walker and the selector highlighter if available
|
||||
*/
|
||||
initialize: function() {
|
||||
let toolbox = gDevTools.getToolbox(this._target);
|
||||
return toolbox.initInspector().then(() => {
|
||||
return Task.spawn(function*() {
|
||||
let toolbox = gDevTools.getToolbox(this._target);
|
||||
yield toolbox.initInspector();
|
||||
this._walker = toolbox.walker;
|
||||
}).then(() => {
|
||||
|
||||
let hUtils = toolbox.highlighterUtils;
|
||||
if (hUtils.hasCustomHighlighter(SELECTOR_HIGHLIGHTER_TYPE)) {
|
||||
this._highlighter =
|
||||
yield hUtils.getHighlighterByType(SELECTOR_HIGHLIGHTER_TYPE);
|
||||
}
|
||||
}.bind(this)).then(() => {
|
||||
this.createUI();
|
||||
this._debuggee.getStyleSheets().then((styleSheets) => {
|
||||
this._resetStyleSheetList(styleSheets);
|
||||
|
||||
this._resetStyleSheetList(styleSheets);
|
||||
this._target.on("will-navigate", this._clear);
|
||||
this._target.on("navigate", this._onNewDocument);
|
||||
});
|
||||
@ -292,8 +299,8 @@ StyleEditorUI.prototype = {
|
||||
file = savedFile;
|
||||
}
|
||||
|
||||
let editor =
|
||||
new StyleSheetEditor(styleSheet, this._window, file, isNew, this._walker);
|
||||
let editor = new StyleSheetEditor(styleSheet, this._window, file, isNew,
|
||||
this._walker, this._highlighter);
|
||||
|
||||
editor.on("property-change", this._summaryChange.bind(this, editor));
|
||||
editor.on("media-rules-changed", this._updateMediaList.bind(this, editor));
|
||||
@ -820,6 +827,11 @@ StyleEditorUI.prototype = {
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (this._highlighter) {
|
||||
this._highlighter.finalize();
|
||||
this._highlighter = null;
|
||||
}
|
||||
|
||||
this._clearStyleSheetEditors();
|
||||
|
||||
let sidebar = this._panelDoc.querySelector(".splitview-controller");
|
||||
|
@ -20,6 +20,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
Cu.import("resource:///modules/devtools/StyleEditorUtil.jsm");
|
||||
|
||||
@ -46,6 +47,10 @@ const MAX_CHECK_COUNT=10;
|
||||
// The classname used to show a line that is not used
|
||||
const UNUSED_CLASS = "cm-unused-line";
|
||||
|
||||
// How much time should the mouse be still before the selector at that position
|
||||
// gets highlighted?
|
||||
const SELECTOR_HIGHLIGHT_TIMEOUT = 500;
|
||||
|
||||
/**
|
||||
* StyleSheetEditor controls the editor linked to a particular StyleSheet
|
||||
* object.
|
||||
@ -65,8 +70,11 @@ const UNUSED_CLASS = "cm-unused-line";
|
||||
* Optional whether the sheet was created by the user
|
||||
* @param {Walker} walker
|
||||
* Optional walker used for selectors autocompletion
|
||||
* @param {CustomHighlighterFront} highlighter
|
||||
* Optional highlighter front for the SelectorHighligher used to
|
||||
* highlight selectors
|
||||
*/
|
||||
function StyleSheetEditor(styleSheet, win, file, isNew, walker) {
|
||||
function StyleSheetEditor(styleSheet, win, file, isNew, walker, highlighter) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.styleSheet = styleSheet;
|
||||
@ -75,6 +83,7 @@ function StyleSheetEditor(styleSheet, win, file, isNew, walker) {
|
||||
this._window = win;
|
||||
this._isNew = isNew;
|
||||
this.walker = walker;
|
||||
this.highlighter = highlighter;
|
||||
|
||||
this._state = { // state to use when inputElement attaches
|
||||
text: "",
|
||||
@ -99,6 +108,7 @@ function StyleSheetEditor(styleSheet, win, file, isNew, walker) {
|
||||
this.markLinkedFileBroken = this.markLinkedFileBroken.bind(this);
|
||||
this.saveToFile = this.saveToFile.bind(this);
|
||||
this.updateStyleSheet = this.updateStyleSheet.bind(this);
|
||||
this._onMouseMove = this._onMouseMove.bind(this);
|
||||
|
||||
this._focusOnSourceEditorReady = false;
|
||||
this.cssSheet.on("property-change", this._onPropertyChange);
|
||||
@ -377,6 +387,10 @@ StyleSheetEditor.prototype = {
|
||||
sourceEditor.setSelection(this._state.selection.start,
|
||||
this._state.selection.end);
|
||||
|
||||
if (this.highlighter && this.walker) {
|
||||
sourceEditor.container.addEventListener("mousemove", this._onMouseMove);
|
||||
}
|
||||
|
||||
this.emit("source-editor-load");
|
||||
});
|
||||
},
|
||||
@ -469,6 +483,52 @@ StyleSheetEditor.prototype = {
|
||||
this.styleSheet.update(this._state.text, transitionsEnabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle mousemove events, calling _highlightSelectorAt after a delay only
|
||||
* and reseting the delay everytime.
|
||||
*/
|
||||
_onMouseMove: function(e) {
|
||||
this.highlighter.hide();
|
||||
|
||||
if (this.mouseMoveTimeout) {
|
||||
this._window.clearTimeout(this.mouseMoveTimeout);
|
||||
this.mouseMoveTimeout = null;
|
||||
}
|
||||
|
||||
this.mouseMoveTimeout = this._window.setTimeout(() => {
|
||||
this._highlightSelectorAt(e.clientX, e.clientY);
|
||||
}, SELECTOR_HIGHLIGHT_TIMEOUT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight nodes matching the selector found at coordinates x,y in the
|
||||
* editor, if any.
|
||||
*
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
*/
|
||||
_highlightSelectorAt: Task.async(function*(x, y) {
|
||||
// Need to catch parsing exceptions as long as bug 1051900 isn't fixed
|
||||
let info;
|
||||
try {
|
||||
let pos = this.sourceEditor.getPositionFromCoords({left: x, top: y});
|
||||
info = this.sourceEditor.getInfoAt(pos);
|
||||
} catch (e) {}
|
||||
if (!info || info.state !== "selector") {
|
||||
return;
|
||||
}
|
||||
|
||||
let node = yield this.walker.getStyleSheetOwnerNode(this.styleSheet.actorID);
|
||||
yield this.highlighter.show(node, {
|
||||
selector: info.selector,
|
||||
hideInfoBar: true,
|
||||
showOnly: "border",
|
||||
region: "border"
|
||||
});
|
||||
|
||||
this.emit("node-highlighted");
|
||||
}),
|
||||
|
||||
/**
|
||||
* Save the editor contents into a file and set savedFile property.
|
||||
* A file picker UI will open if file is not set and editor is not headless.
|
||||
@ -639,6 +699,10 @@ StyleSheetEditor.prototype = {
|
||||
this._sourceEditor.off("dirty-change", this._onPropertyChange);
|
||||
this._sourceEditor.off("save", this.saveToFile);
|
||||
this._sourceEditor.off("change", this.updateStyleSheet);
|
||||
if (this.highlighter && this.walker && this._sourceEditor.container) {
|
||||
this._sourceEditor.container.removeEventListener("mousemove",
|
||||
this._onMouseMove);
|
||||
}
|
||||
this._sourceEditor.destroy();
|
||||
}
|
||||
this.cssSheet.off("property-change", this._onPropertyChange);
|
||||
|
@ -49,6 +49,7 @@ skip-if = os == "linux" || "mac" # bug 949355
|
||||
[browser_styleeditor_enabled.js]
|
||||
[browser_styleeditor_fetch-from-cache.js]
|
||||
[browser_styleeditor_filesave.js]
|
||||
[browser_styleeditor_highlight-selector.js]
|
||||
[browser_styleeditor_import.js]
|
||||
[browser_styleeditor_import_rule.js]
|
||||
[browser_styleeditor_init.js]
|
||||
|
@ -0,0 +1,48 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that hovering over a simple selector in the style-editor requests the
|
||||
// highlighting of the corresponding nodes
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf8," +
|
||||
"<style>div{color:red}</style><div>highlighter test</div>";
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
let {UI} = yield addTabAndOpenStyleEditors(1, null, TEST_URL);
|
||||
let editor = UI.editors[0];
|
||||
|
||||
// Mock the highlighter so we can locally assert that things happened
|
||||
// correctly instead of accessing the highlighter elements
|
||||
editor.highlighter = {
|
||||
isShown: false,
|
||||
options: null,
|
||||
|
||||
show: function(node, options) {
|
||||
this.isShown = true;
|
||||
this.options = options;
|
||||
return promise.resolve();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.isShown = false;
|
||||
}
|
||||
};
|
||||
|
||||
info("Expecting a node-highlighted event");
|
||||
let onHighlighted = editor.once("node-highlighted");
|
||||
|
||||
info("Simulate a mousemove event on the div selector");
|
||||
editor._onMouseMove({clientX: 40, clientY: 10});
|
||||
yield onHighlighted;
|
||||
|
||||
ok(editor.highlighter.isShown, "The highlighter is now shown");
|
||||
is(editor.highlighter.options.selector, "div", "The selector is correct");
|
||||
|
||||
info("Simulate a mousemove event elsewhere in the editor");
|
||||
editor._onMouseMove({clientX: 0, clientY: 0});
|
||||
|
||||
ok(!editor.highlighter.isShown, "The highlighter is now hidden");
|
||||
});
|
@ -31,11 +31,15 @@ const HIGHLIGHTER_PICKED_TIMER = 1000;
|
||||
const INFO_BAR_OFFSET = 5;
|
||||
// The minimum distance a line should be before it has an arrow marker-end
|
||||
const ARROW_LINE_MIN_DISTANCE = 10;
|
||||
// How many maximum nodes can be highlighted at the same time by the
|
||||
// SelectorHighlighter
|
||||
const MAX_HIGHLIGHTED_ELEMENTS = 100;
|
||||
|
||||
// All possible highlighter classes
|
||||
let HIGHLIGHTER_CLASSES = exports.HIGHLIGHTER_CLASSES = {
|
||||
"BoxModelHighlighter": BoxModelHighlighter,
|
||||
"CssTransformHighlighter": CssTransformHighlighter
|
||||
"CssTransformHighlighter": CssTransformHighlighter,
|
||||
"SelectorHighlighter": SelectorHighlighter
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1224,6 +1228,69 @@ CssTransformHighlighter.prototype = Heritage.extend(XULBasedHighlighter.prototyp
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The SelectorHighlighter runs a given selector through querySelectorAll on the
|
||||
* document of the provided context node and then uses the BoxModelHighlighter
|
||||
* to highlight the matching nodes
|
||||
*/
|
||||
function SelectorHighlighter(tabActor) {
|
||||
this.tabActor = tabActor;
|
||||
this._highlighters = [];
|
||||
}
|
||||
|
||||
SelectorHighlighter.prototype = {
|
||||
/**
|
||||
* Show BoxModelHighlighter on each node that matches that provided selector.
|
||||
* @param {DOMNode} node A context node that is used to get the document on
|
||||
* which querySelectorAll should be executed. This node will NOT be
|
||||
* highlighted.
|
||||
* @param {Object} options Should at least contain the 'selector' option, a
|
||||
* string that will be used in querySelectorAll. On top of this, all of the
|
||||
* valid options to BoxModelHighlighter.show are also valid here.
|
||||
*/
|
||||
show: function(node, options={}) {
|
||||
this.hide();
|
||||
|
||||
if (!isNodeValid(node) || !options.selector) {
|
||||
return;
|
||||
}
|
||||
|
||||
let nodes = [];
|
||||
try {
|
||||
nodes = [...node.ownerDocument.querySelectorAll(options.selector)];
|
||||
} catch (e) {}
|
||||
|
||||
delete options.selector;
|
||||
|
||||
let i = 0;
|
||||
for (let matchingNode of nodes) {
|
||||
if (i >= MAX_HIGHLIGHTED_ELEMENTS) {
|
||||
break;
|
||||
}
|
||||
|
||||
let highlighter = new BoxModelHighlighter(this.tabActor);
|
||||
if (options.fill) {
|
||||
highlighter.regionFill[options.region || "border"] = options.fill;
|
||||
}
|
||||
highlighter.show(matchingNode, options);
|
||||
this._highlighters.push(highlighter);
|
||||
i ++;
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
for (let highlighter of this._highlighters) {
|
||||
highlighter.destroy();
|
||||
}
|
||||
this._highlighters = [];
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.hide();
|
||||
this.tabActor = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The SimpleOutlineHighlighter is a class that has the same API than the
|
||||
* BoxModelHighlighter, but adds a pseudo-class on the target element itself
|
||||
|
@ -2346,6 +2346,29 @@ var WalkerActor = protocol.ActorClass({
|
||||
nodeFront: RetVal("nullable:disconnectedNode")
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Given an StyleSheetActor (identified by its ID), commonly used in the
|
||||
* style-editor, get its ownerNode and return the corresponding walker's
|
||||
* NodeActor
|
||||
*/
|
||||
getStyleSheetOwnerNode: method(function(styleSheetActorID) {
|
||||
let styleSheetActor = this.conn.getActor(styleSheetActorID);
|
||||
let ownerNode = styleSheetActor.ownerNode;
|
||||
|
||||
if (!styleSheetActor || !ownerNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.attachElement(ownerNode);
|
||||
}, {
|
||||
request: {
|
||||
styleSheetActorID: Arg(0, "string")
|
||||
},
|
||||
response: {
|
||||
ownerNode: RetVal("nullable:disconnectedNode")
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
@ -2487,6 +2510,14 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, {
|
||||
impl: "_getNodeActorFromObjectActor"
|
||||
}),
|
||||
|
||||
getStyleSheetOwnerNode: protocol.custom(function(styleSheetActorID) {
|
||||
return this._getStyleSheetOwnerNode(styleSheetActorID).then(response => {
|
||||
return response ? response.node : null;
|
||||
});
|
||||
}, {
|
||||
impl: "_getStyleSheetOwnerNode"
|
||||
}),
|
||||
|
||||
_releaseFront: function(node, force) {
|
||||
if (node.retained && !force) {
|
||||
node.reparent(null);
|
||||
|
@ -115,7 +115,8 @@ RootActor.prototype = {
|
||||
// (see server/actors/highlighter.js)
|
||||
customHighlighters: [
|
||||
"BoxModelHighlighter",
|
||||
"CssTransformHighlighter"
|
||||
"CssTransformHighlighter",
|
||||
"SelectorHighlighter"
|
||||
],
|
||||
// Whether the inspector actor implements the getImageDataFromURL
|
||||
// method that returns data-uris for image URLs. This is used for image
|
||||
|
@ -430,6 +430,8 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
return null;
|
||||
},
|
||||
|
||||
get ownerNode() this.rawSheet.ownerNode,
|
||||
|
||||
/**
|
||||
* URL of underlying stylesheet.
|
||||
*/
|
||||
@ -488,8 +490,7 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
return promise.resolve(rules);
|
||||
}
|
||||
|
||||
let ownerNode = this.rawSheet.ownerNode;
|
||||
if (!ownerNode) {
|
||||
if (!this.ownerNode) {
|
||||
return promise.resolve([]);
|
||||
}
|
||||
|
||||
@ -500,12 +501,12 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
let deferred = promise.defer();
|
||||
|
||||
let onSheetLoaded = (event) => {
|
||||
ownerNode.removeEventListener("load", onSheetLoaded, false);
|
||||
this.ownerNode.removeEventListener("load", onSheetLoaded, false);
|
||||
|
||||
deferred.resolve(this.rawSheet.cssRules);
|
||||
};
|
||||
|
||||
ownerNode.addEventListener("load", onSheetLoaded, false);
|
||||
this.ownerNode.addEventListener("load", onSheetLoaded, false);
|
||||
|
||||
// cache so we don't add many listeners if this is called multiple times.
|
||||
this._cssRules = deferred.promise;
|
||||
@ -526,13 +527,12 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
}
|
||||
|
||||
let docHref;
|
||||
let ownerNode = this.rawSheet.ownerNode;
|
||||
if (ownerNode) {
|
||||
if (ownerNode instanceof Ci.nsIDOMHTMLDocument) {
|
||||
docHref = ownerNode.location.href;
|
||||
if (this.ownerNode) {
|
||||
if (this.ownerNode instanceof Ci.nsIDOMHTMLDocument) {
|
||||
docHref = this.ownerNode.location.href;
|
||||
}
|
||||
else if (ownerNode.ownerDocument && ownerNode.ownerDocument.location) {
|
||||
docHref = ownerNode.ownerDocument.location.href;
|
||||
else if (this.ownerNode.ownerDocument && this.ownerNode.ownerDocument.location) {
|
||||
docHref = this.ownerNode.ownerDocument.location.href;
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
|
||||
if (!this.href) {
|
||||
// this is an inline <style> sheet
|
||||
let content = this.rawSheet.ownerNode.textContent;
|
||||
let content = this.ownerNode.textContent;
|
||||
this.text = content;
|
||||
return promise.resolve(content);
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ skip-if = buildapp == 'mulet'
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_highlighter-csstransform_03.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_highlighter-selector_01.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_highlighter-selector_02.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_inspector-changeattrs.html]
|
||||
[test_inspector-changevalue.html]
|
||||
[test_inspector-hide.html]
|
||||
|
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that the custom selector highlighter creates as many box-model highlighters
|
||||
as there are nodes that match the given selector
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Framerate actor test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-node">test node</div>
|
||||
<ul>
|
||||
<li class="item">item</li>
|
||||
<li class="item">item</li>
|
||||
<li class="item">item</li>
|
||||
<li class="item">item</li>
|
||||
<li class="item">item</li>
|
||||
</ul>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.onload = function() {
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
|
||||
const {InspectorFront} = devtools.require("devtools/server/actors/inspector");
|
||||
|
||||
const TEST_DATA = [{
|
||||
selector: "#test-node",
|
||||
containerCount: 1
|
||||
}, {
|
||||
selector: null,
|
||||
containerCount: 0,
|
||||
}, {
|
||||
selector: undefined,
|
||||
containerCount: 0,
|
||||
}, {
|
||||
selector: ".invalid-class",
|
||||
containerCount: 0
|
||||
}, {
|
||||
selector: ".item",
|
||||
containerCount: 5
|
||||
}, {
|
||||
selector: "#test-node, ul, .item",
|
||||
containerCount: 7
|
||||
}];
|
||||
|
||||
DebuggerServer.init(() => true);
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(() => {
|
||||
client.listTabs(response => {
|
||||
let form = response.tabs[response.selected];
|
||||
let front = InspectorFront(client, form);
|
||||
|
||||
Task.spawn(function*() {
|
||||
let walker = yield front.getWalker();
|
||||
let highlighter = yield front.getHighlighterByType("SelectorHighlighter");
|
||||
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser")
|
||||
.gBrowser.selectedBrowser;
|
||||
|
||||
// Remove left-over highlighter contains from previous tests
|
||||
for (let container of browser.parentNode
|
||||
.querySelectorAll(".highlighter-container")) {
|
||||
container.remove();
|
||||
}
|
||||
|
||||
// The node given to SelectorHighlighter's show method is only used to
|
||||
// know which document should matching nodes be searched in
|
||||
let node = document.body;
|
||||
|
||||
for (let {selector, containerCount} of TEST_DATA) {
|
||||
info("Showing the highlighter on " + selector + ". Expecting " +
|
||||
containerCount + " highlighter containers");
|
||||
|
||||
yield highlighter.show(walker.frontForRawNode(node), {selector});
|
||||
|
||||
let containers = browser.parentNode.querySelectorAll(
|
||||
".highlighter-container");
|
||||
is(containers.length, containerCount,
|
||||
"The correct number of box-model highlighers were created");
|
||||
yield highlighter.hide();
|
||||
}
|
||||
|
||||
yield highlighter.finalize();
|
||||
}).then(null, ok.bind(null, false)).then(() => {
|
||||
client.close(() => {
|
||||
DebuggerServer.destroy();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,100 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that the custom selector highlighter creates highlighters for nodes in the
|
||||
right frame
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Framerate actor test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="root-level-node"></div>
|
||||
<iframe src="data:text/html;charset=utf8,<div class='sub-level-node'></div>"></iframe>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.onload = function() {
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
|
||||
const {InspectorFront} = devtools.require("devtools/server/actors/inspector");
|
||||
|
||||
const TEST_DATA = [{
|
||||
contextNode: document.body,
|
||||
selector: ".root-level-node",
|
||||
containerCount: 1
|
||||
}, {
|
||||
contextNode: document.body,
|
||||
selector: ".sub-level-node",
|
||||
containerCount: 0
|
||||
}, {
|
||||
contextNode: document.querySelector("iframe").contentDocument.body,
|
||||
selector: ".root-level-node",
|
||||
containerCount: 0
|
||||
}, {
|
||||
contextNode: document.querySelector("iframe").contentDocument.body,
|
||||
selector: ".sub-level-node",
|
||||
containerCount: 1
|
||||
}];
|
||||
|
||||
DebuggerServer.init(() => true);
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect(() => {
|
||||
client.listTabs(response => {
|
||||
let form = response.tabs[response.selected];
|
||||
let front = InspectorFront(client, form);
|
||||
|
||||
Task.spawn(function*() {
|
||||
let walker = yield front.getWalker();
|
||||
let highlighter = yield front.getHighlighterByType("SelectorHighlighter");
|
||||
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser")
|
||||
.gBrowser.selectedBrowser;
|
||||
|
||||
// Remove left-over highlighter contains from previous tests
|
||||
for (let container of browser.parentNode
|
||||
.querySelectorAll(".highlighter-container")) {
|
||||
container.remove();
|
||||
}
|
||||
|
||||
for (let {contextNode, selector, containerCount} of TEST_DATA) {
|
||||
info("Showing the highlighter on " + selector + ". Expecting " +
|
||||
containerCount + " highlighter containers");
|
||||
|
||||
yield highlighter.show(walker.frontForRawNode(contextNode), {selector});
|
||||
|
||||
let containers = browser.parentNode.querySelectorAll(
|
||||
".highlighter-container");
|
||||
is(containers.length, containerCount,
|
||||
"The correct number of box-model highlighers were created");
|
||||
yield highlighter.hide();
|
||||
}
|
||||
|
||||
yield highlighter.finalize();
|
||||
}).then(null, ok.bind(null, false)).then(() => {
|
||||
client.close(() => {
|
||||
DebuggerServer.destroy();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user