зеркало из https://github.com/mozilla/gecko-dev.git
Bug 912915 - Implement a simple generic highlighter. r=jwalker
This commit is contained in:
Родитель
0a48e68b74
Коммит
a280f4502a
|
@ -1648,7 +1648,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
|||
|
||||
(function(module) {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LayoutHelpers",
|
||||
"resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
"resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
|
||||
// String used as an indication to generate default file name in the following
|
||||
// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
|
||||
|
|
|
@ -19,7 +19,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/VariablesView.jsm");
|
||||
|
|
|
@ -11,7 +11,7 @@ const ENSURE_SELECTION_VISIBLE_DELAY = 50; // ms
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let promise = require("sdk/core/promise");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
const {Cu, Cc, Ci} = require("chrome");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
@ -15,6 +15,19 @@ let EventEmitter = require("devtools/shared/event-emitter");
|
|||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
// add ":visited" and ":link" after bug 713106 is fixed
|
||||
|
||||
exports._forceBasic = {value: false};
|
||||
|
||||
exports.Highlighter = function Highlighter(aTarget, aInspector, aToolbox) {
|
||||
if (aTarget.isLocalTab && !exports._forceBasic.value) {
|
||||
return new LocalHighlighter(aTarget, aInspector, aToolbox);
|
||||
} else {
|
||||
return new BasicHighlighter(aTarget, aInspector, aToolbox);
|
||||
}
|
||||
}
|
||||
|
||||
exports.LocalHighlighter = LocalHighlighter;
|
||||
exports.BasicHighlighter = BasicHighlighter;
|
||||
|
||||
/**
|
||||
* A highlighter mechanism.
|
||||
*
|
||||
|
@ -71,7 +84,7 @@ const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
|||
* @param aInspector Inspector panel.
|
||||
* @param aToolbox The toolbox holding the inspector.
|
||||
*/
|
||||
function Highlighter(aTarget, aInspector, aToolbox)
|
||||
function LocalHighlighter(aTarget, aInspector, aToolbox)
|
||||
{
|
||||
this.target = aTarget;
|
||||
this.tab = aTarget.tab;
|
||||
|
@ -86,14 +99,12 @@ function Highlighter(aTarget, aInspector, aToolbox)
|
|||
this._init();
|
||||
}
|
||||
|
||||
exports.Highlighter = Highlighter;
|
||||
|
||||
Highlighter.prototype = {
|
||||
LocalHighlighter.prototype = {
|
||||
get selection() {
|
||||
return this.inspector.selection;
|
||||
},
|
||||
|
||||
_init: function Highlighter__init()
|
||||
_init: function LocalHighlighter__init()
|
||||
{
|
||||
this.toggleLockState = this.toggleLockState.bind(this);
|
||||
this.unlockAndFocus = this.unlockAndFocus.bind(this);
|
||||
|
@ -157,7 +168,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Destroy the nodes. Remove listeners.
|
||||
*/
|
||||
destroy: function Highlighter_destroy()
|
||||
destroy: function LocalHighlighter_destroy()
|
||||
{
|
||||
this.inspectButton.removeEventListener("command", this.unlockAndFocus);
|
||||
this.inspectButton = null;
|
||||
|
@ -195,7 +206,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Show the outline, and select a node.
|
||||
*/
|
||||
highlight: function Highlighter_highlight()
|
||||
highlight: function LocalHighlighter_highlight()
|
||||
{
|
||||
if (this.selection.reason != "highlighter") {
|
||||
this.lock();
|
||||
|
@ -225,7 +236,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Update the highlighter size and position.
|
||||
*/
|
||||
invalidateSize: function Highlighter_invalidateSize()
|
||||
invalidateSize: function LocalHighlighter_invalidateSize()
|
||||
{
|
||||
let canHiglightNode = this.selection.isNode() &&
|
||||
this.selection.isConnected() &&
|
||||
|
@ -333,7 +344,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Focus the browser before unlocking.
|
||||
*/
|
||||
unlockAndFocus: function Highlighter_unlockAndFocus() {
|
||||
unlockAndFocus: function LocalHighlighter_unlockAndFocus() {
|
||||
if (this.locked === false) return;
|
||||
this.chromeWin.focus();
|
||||
this.unlock();
|
||||
|
@ -342,7 +353,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Hide the infobar
|
||||
*/
|
||||
hideInfobar: function Highlighter_hideInfobar() {
|
||||
hideInfobar: function LocalHighlighter_hideInfobar() {
|
||||
this.nodeInfo.container.setAttribute("force-transitions", "true");
|
||||
this.nodeInfo.container.setAttribute("hidden", "true");
|
||||
},
|
||||
|
@ -350,7 +361,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Show the infobar
|
||||
*/
|
||||
showInfobar: function Highlighter_showInfobar() {
|
||||
showInfobar: function LocalHighlighter_showInfobar() {
|
||||
this.nodeInfo.container.removeAttribute("hidden");
|
||||
this.moveInfobar();
|
||||
this.nodeInfo.container.removeAttribute("force-transitions");
|
||||
|
@ -359,14 +370,14 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Hide the outline
|
||||
*/
|
||||
hideOutline: function Highlighter_hideOutline() {
|
||||
hideOutline: function LocalHighlighter_hideOutline() {
|
||||
this.outline.setAttribute("hidden", "true");
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the outline
|
||||
*/
|
||||
showOutline: function Highlighter_showOutline() {
|
||||
showOutline: function LocalHighlighter_showOutline() {
|
||||
if (this._highlighting)
|
||||
this.outline.removeAttribute("hidden");
|
||||
},
|
||||
|
@ -375,7 +386,7 @@ Highlighter.prototype = {
|
|||
* Build the node Infobar.
|
||||
*
|
||||
* <box class="highlighter-nodeinfobar-container">
|
||||
* <box class="Highlighter-nodeinfobar-arrow-top"/>
|
||||
* <box class="highlighter-nodeinfobar-arrow-top"/>
|
||||
* <hbox class="highlighter-nodeinfobar">
|
||||
* <toolbarbutton class="highlighter-nodeinfobar-button highlighter-nodeinfobar-inspectbutton"/>
|
||||
* <hbox class="highlighter-nodeinfobar-text">
|
||||
|
@ -386,13 +397,13 @@ Highlighter.prototype = {
|
|||
* </hbox>
|
||||
* <toolbarbutton class="highlighter-nodeinfobar-button highlighter-nodeinfobar-menu"/>
|
||||
* </hbox>
|
||||
* <box class="Highlighter-nodeinfobar-arrow-bottom"/>
|
||||
* <box class="highlighter-nodeinfobar-arrow-bottom"/>
|
||||
* </box>
|
||||
*
|
||||
* @param nsIDOMElement aParent
|
||||
* The container of the infobar.
|
||||
*/
|
||||
buildInfobar: function Highlighter_buildInfobar(aParent)
|
||||
buildInfobar: function LocalHighlighter_buildInfobar(aParent)
|
||||
{
|
||||
let container = this.chromeDoc.createElement("box");
|
||||
container.className = "highlighter-nodeinfobar-container";
|
||||
|
@ -489,7 +500,7 @@ Highlighter.prototype = {
|
|||
* @returns boolean
|
||||
* True if the rectangle was highlighted, false otherwise.
|
||||
*/
|
||||
highlightRectangle: function Highlighter_highlightRectangle(aRect)
|
||||
highlightRectangle: function LocalHighlighter_highlightRectangle(aRect)
|
||||
{
|
||||
if (!aRect) {
|
||||
this.unhighlight();
|
||||
|
@ -532,7 +543,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Clear the highlighter surface.
|
||||
*/
|
||||
unhighlight: function Highlighter_unhighlight()
|
||||
unhighlight: function LocalHighlighter_unhighlight()
|
||||
{
|
||||
this._highlighting = false;
|
||||
this.hideOutline();
|
||||
|
@ -541,7 +552,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Update node information (tagName#id.class)
|
||||
*/
|
||||
updateInfobar: function Highlighter_updateInfobar()
|
||||
updateInfobar: function LocalHighlighter_updateInfobar()
|
||||
{
|
||||
if (!this.selection.isElementNode()) {
|
||||
this.nodeInfo.tagNameLabel.textContent = "";
|
||||
|
@ -577,7 +588,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Move the Infobar to the right place in the highlighter.
|
||||
*/
|
||||
moveInfobar: function Highlighter_moveInfobar()
|
||||
moveInfobar: function LocalHighlighter_moveInfobar()
|
||||
{
|
||||
if (this._highlightRect) {
|
||||
let winHeight = this.win.innerHeight * this.zoom;
|
||||
|
@ -644,7 +655,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Store page zoom factor.
|
||||
*/
|
||||
computeZoomFactor: function Highlighter_computeZoomFactor() {
|
||||
computeZoomFactor: function LocalHighlighter_computeZoomFactor() {
|
||||
this.zoom =
|
||||
this.win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
|
@ -654,7 +665,7 @@ Highlighter.prototype = {
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
//// Event Handling
|
||||
|
||||
attachMouseListeners: function Highlighter_attachMouseListeners()
|
||||
attachMouseListeners: function LocalHighlighter_attachMouseListeners()
|
||||
{
|
||||
this.browser.addEventListener("mousemove", this, true);
|
||||
this.browser.addEventListener("click", this, true);
|
||||
|
@ -663,7 +674,7 @@ Highlighter.prototype = {
|
|||
this.browser.addEventListener("mouseup", this, true);
|
||||
},
|
||||
|
||||
detachMouseListeners: function Highlighter_detachMouseListeners()
|
||||
detachMouseListeners: function LocalHighlighter_detachMouseListeners()
|
||||
{
|
||||
this.browser.removeEventListener("mousemove", this, true);
|
||||
this.browser.removeEventListener("click", this, true);
|
||||
|
@ -672,14 +683,14 @@ Highlighter.prototype = {
|
|||
this.browser.removeEventListener("mouseup", this, true);
|
||||
},
|
||||
|
||||
attachPageListeners: function Highlighter_attachPageListeners()
|
||||
attachPageListeners: function LocalHighlighter_attachPageListeners()
|
||||
{
|
||||
this.browser.addEventListener("resize", this, true);
|
||||
this.browser.addEventListener("scroll", this, true);
|
||||
this.browser.addEventListener("MozAfterPaint", this, true);
|
||||
},
|
||||
|
||||
detachPageListeners: function Highlighter_detachPageListeners()
|
||||
detachPageListeners: function LocalHighlighter_detachPageListeners()
|
||||
{
|
||||
this.browser.removeEventListener("resize", this, true);
|
||||
this.browser.removeEventListener("scroll", this, true);
|
||||
|
@ -692,7 +703,7 @@ Highlighter.prototype = {
|
|||
* @param nsIDOMEvent aEvent
|
||||
* The DOM event object.
|
||||
*/
|
||||
handleEvent: function Highlighter_handleEvent(aEvent)
|
||||
handleEvent: function LocalHighlighter_handleEvent(aEvent)
|
||||
{
|
||||
switch (aEvent.type) {
|
||||
case "click":
|
||||
|
@ -723,7 +734,7 @@ Highlighter.prototype = {
|
|||
* Disable the CSS transitions for a short time to avoid laggy animations
|
||||
* during scrolling or resizing.
|
||||
*/
|
||||
brieflyDisableTransitions: function Highlighter_brieflyDisableTransitions()
|
||||
brieflyDisableTransitions: function LocalHighlighter_brieflyDisableTransitions()
|
||||
{
|
||||
if (this.transitionDisabler) {
|
||||
this.chromeWin.clearTimeout(this.transitionDisabler);
|
||||
|
@ -742,7 +753,7 @@ Highlighter.prototype = {
|
|||
/**
|
||||
* Don't listen to page events while inspecting with the mouse.
|
||||
*/
|
||||
brieflyIgnorePageEvents: function Highlighter_brieflyIgnorePageEvents()
|
||||
brieflyIgnorePageEvents: function LocalHighlighter_brieflyIgnorePageEvents()
|
||||
{
|
||||
// The goal is to keep smooth animations while inspecting.
|
||||
// CSS Transitions might be interrupted because of a MozAfterPaint
|
||||
|
@ -773,7 +784,7 @@ Highlighter.prototype = {
|
|||
* @param nsIDOMEvent aEvent
|
||||
* The DOM event.
|
||||
*/
|
||||
handleClick: function Highlighter_handleClick(aEvent)
|
||||
handleClick: function LocalHighlighter_handleClick(aEvent)
|
||||
{
|
||||
// Stop inspection when the user clicks on a node.
|
||||
if (aEvent.button == 0) {
|
||||
|
@ -791,7 +802,7 @@ Highlighter.prototype = {
|
|||
* @param nsiDOMEvent aEvent
|
||||
* The MouseEvent triggering the method.
|
||||
*/
|
||||
handleMouseMove: function Highlighter_handleMouseMove(aEvent)
|
||||
handleMouseMove: function LocalHighlighter_handleMouseMove(aEvent)
|
||||
{
|
||||
let doc = aEvent.target.ownerDocument;
|
||||
|
||||
|
@ -807,13 +818,58 @@ Highlighter.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
// BasicHighlighter. Doesn't implement any fancy features. Just change
|
||||
// the outline of the selected node. Works with remote target.
|
||||
|
||||
function BasicHighlighter(aTarget, aInspector)
|
||||
{
|
||||
this.walker = aInspector.walker;
|
||||
this.selection = aInspector.selection;
|
||||
this.highlight = this.highlight.bind(this);
|
||||
this.selection.on("new-node-front", this.highlight);
|
||||
EventEmitter.decorate(this);
|
||||
this.locked = true;
|
||||
}
|
||||
|
||||
BasicHighlighter.prototype = {
|
||||
destroy: function() {
|
||||
this.selection.off("new-node-front", this.highlight);
|
||||
this.walker = null;
|
||||
this.selection = null;
|
||||
},
|
||||
toggleLockState: function() {
|
||||
this.locked = !this.locked;
|
||||
if (this.locked) {
|
||||
this.walker.cancelPick();
|
||||
} else {
|
||||
this.emit("unlocked");
|
||||
this.walker.pick().then(
|
||||
(node) => this._onPick(node),
|
||||
() => this._onPick(null)
|
||||
);
|
||||
}
|
||||
},
|
||||
highlight: function() {
|
||||
this.walker.highlight(this.selection.nodeFront);
|
||||
},
|
||||
_onPick: function(node) {
|
||||
if (node) {
|
||||
this.selection.setNodeFront(node);
|
||||
}
|
||||
this.locked = true;
|
||||
this.emit("locked");
|
||||
},
|
||||
hide: function() {},
|
||||
show: function() {},
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils)
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Highlighter.prototype, "strings", function () {
|
||||
XPCOMUtils.defineLazyGetter(LocalHighlighter.prototype, "strings", function () {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/inspector.properties");
|
||||
});
|
||||
|
|
|
@ -82,20 +82,6 @@ InspectorPanel.prototype = {
|
|||
this.scheduleLayoutChange = this.scheduleLayoutChange.bind(this);
|
||||
this.browser.addEventListener("resize", this.scheduleLayoutChange, true);
|
||||
|
||||
this.highlighter = new Highlighter(this.target, this, this._toolbox);
|
||||
let button = this.panelDoc.getElementById("inspector-inspect-toolbutton");
|
||||
button.hidden = false;
|
||||
this.onLockStateChanged = function() {
|
||||
if (this.highlighter.locked) {
|
||||
button.removeAttribute("checked");
|
||||
this._toolbox.raise();
|
||||
} else {
|
||||
button.setAttribute("checked", "true");
|
||||
}
|
||||
}.bind(this);
|
||||
this.highlighter.on("locked", this.onLockStateChanged);
|
||||
this.highlighter.on("unlocked", this.onLockStateChanged);
|
||||
|
||||
// Show a warning when the debugger is paused.
|
||||
// We show the warning only when the inspector
|
||||
// is selected.
|
||||
|
@ -124,6 +110,19 @@ InspectorPanel.prototype = {
|
|||
this.updateDebuggerPausedWarning();
|
||||
}
|
||||
|
||||
this.highlighter = new Highlighter(this.target, this, this._toolbox);
|
||||
let button = this.panelDoc.getElementById("inspector-inspect-toolbutton");
|
||||
this.onLockStateChanged = function() {
|
||||
if (this.highlighter.locked) {
|
||||
button.removeAttribute("checked");
|
||||
this._toolbox.raise();
|
||||
} else {
|
||||
button.setAttribute("checked", "true");
|
||||
}
|
||||
}.bind(this);
|
||||
this.highlighter.on("locked", this.onLockStateChanged);
|
||||
this.highlighter.on("unlocked", this.onLockStateChanged);
|
||||
|
||||
this._initMarkup();
|
||||
this.isReady = false;
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||
tooltiptext="&inspector.selectButton.tooltip;"
|
||||
class="devtools-toolbarbutton"
|
||||
hidden="true"
|
||||
oncommand="inspector.highlighter.toggleLockState()"/>
|
||||
<arrowscrollbox id="inspector-breadcrumbs"
|
||||
class="breadcrumbs-widget-container"
|
||||
|
|
|
@ -41,5 +41,6 @@ MOCHITEST_BROWSER_FILES := \
|
|||
browser_inspector_select_last_selected.js \
|
||||
browser_inspector_select_last_selected.html \
|
||||
browser_inspector_select_last_selected2.html \
|
||||
browser_inspector_basic_highlighter.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
function test()
|
||||
{
|
||||
let inspector, doc;
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let {require} = devtools;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
doc = content.document;
|
||||
waitForFocus(setupTest, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<h1>foo<h1><h2>bar</h2>";
|
||||
|
||||
function setupTest()
|
||||
{
|
||||
let h = require("devtools/inspector/highlighter");
|
||||
h._forceBasic.value = true;
|
||||
openInspector(runTests);
|
||||
}
|
||||
|
||||
function runTests(aInspector)
|
||||
{
|
||||
inspector = aInspector;
|
||||
let h1 = doc.querySelector("h1");
|
||||
inspector.selection.once("new-node-front", () => executeSoon(testH1Selected));
|
||||
inspector.selection.setNode(h1);
|
||||
}
|
||||
|
||||
function testH1Selected() {
|
||||
let h1 = doc.querySelector("h1");
|
||||
let nodes = doc.querySelectorAll(":-moz-devtools-highlighted");
|
||||
is(nodes.length, 1, "only one node selected");
|
||||
is(nodes[0], h1, "h1 selected");
|
||||
inspector.selection.once("new-node-front", () => executeSoon(testNoNodeSelected));
|
||||
inspector.selection.setNode(null);
|
||||
}
|
||||
|
||||
function testNoNodeSelected() {
|
||||
ok(doc.querySelectorAll(":-moz-devtools-highlighted").length, 0, "no node selected");
|
||||
finishUp();
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
let h = require("devtools/inspector/highlighter");
|
||||
h._forceBasic.value = false;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ function test()
|
|||
parentNode.removeChild(node);
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
|
||||
|
||||
// Wait for the inspector to process the mutation
|
||||
|
|
|
@ -32,7 +32,7 @@ function test()
|
|||
iframe = null;
|
||||
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
|
||||
ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
|
||||
ok(!inspector.selection.isConnected(), "Selection considered as disconnected");
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ SimpleTest.registerCleanupFunction(() => {
|
|||
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
let LayoutHelpers = tempScope.LayoutHelpers;
|
||||
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ let EventEmitter = require("devtools/shared/event-emitter");
|
|||
let {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
|
||||
let promise = require("sdk/core/promise");
|
||||
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Templater.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
|
|
@ -26,7 +26,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource:///modules/source-editor.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource:///modules/devtools/scratchpad-manager.jsm");
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Tests that scrollIntoViewIfNeeded works properly.
|
||||
|
||||
let imported = {};
|
||||
Components.utils.import("resource:///modules/devtools/LayoutHelpers.jsm",
|
||||
Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm",
|
||||
imported);
|
||||
registerCleanupFunction(function () {
|
||||
imported = {};
|
||||
|
|
|
@ -10,7 +10,7 @@ let TiltUtils = devtools.require("devtools/tilt/tilt-utils");
|
|||
let {TiltVisualizer} = devtools.require("devtools/tilt/tilt-visualizer");
|
||||
|
||||
let tempScope = {};
|
||||
Components.utils.import("resource:///modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope);
|
||||
let LayoutHelpers = tempScope.LayoutHelpers;
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const {Cc, Ci, Cu} = require("chrome");
|
|||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
|
||||
const STACK_THICKNESS = 15;
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ const {LongStringActor, ShortLongString} = require("devtools/server/actors/strin
|
|||
const promise = require("sdk/core/promise");
|
||||
const object = require("sdk/util/object");
|
||||
const events = require("sdk/event/core");
|
||||
const {setTimeout, clearTimeout} = require('sdk/timers');
|
||||
const { Unknown } = require("sdk/platform/xpcom");
|
||||
const { Class } = require("sdk/core/heritage");
|
||||
const {PageStyleActor} = require("devtools/server/actors/styles");
|
||||
|
@ -66,9 +67,14 @@ const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
|||
|
||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
|
||||
const HELPER_SHEET = "." + HIDDEN_CLASS + " { visibility: hidden !important }";
|
||||
const HIGHLIGHTED_PSEUDO_CLASS = ":-moz-devtools-highlighted";
|
||||
const HIGHLIGHTED_TIMEOUT = 2000;
|
||||
|
||||
let HELPER_SHEET = ".__fx-devtools-hide-shortcut__ { visibility: hidden !important } ";
|
||||
HELPER_SHEET += ":-moz-devtools-highlighted { outline: 2px dashed #F06!important; outline-offset: -2px!important } ";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
|
||||
exports.register = function(handle) {
|
||||
handle.addTabActor(InspectorActor, "inspectorActor");
|
||||
|
@ -841,6 +847,94 @@ var WalkerActor = protocol.ActorClass({
|
|||
return actor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pick a node on click.
|
||||
*/
|
||||
_pickDeferred: null,
|
||||
pick: method(function() {
|
||||
if (this._pickDeferred) {
|
||||
return this._pickDeferred.promise;
|
||||
}
|
||||
|
||||
this._pickDeferred = promise.defer();
|
||||
|
||||
let window = this.rootDoc.defaultView;
|
||||
let isTouch = 'ontouchstart' in window;
|
||||
let event = isTouch ? 'touchstart' : 'click';
|
||||
|
||||
this._onPick = function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
window.removeEventListener(event, this._onPick, true);
|
||||
let u = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let x, y;
|
||||
if (isTouch) {
|
||||
x = e.touches[0].clientX;
|
||||
y = e.touches[0].clientY;
|
||||
} else {
|
||||
x = e.clientX;
|
||||
y = e.clientY;
|
||||
}
|
||||
|
||||
let node = u.elementFromPoint(x, y, false, false);
|
||||
node = this._ref(node);
|
||||
let newParents = this.ensurePathToRoot(node);
|
||||
|
||||
this._pickDeferred.resolve({
|
||||
node: node,
|
||||
newParents: [parent for (parent of newParents)]
|
||||
});
|
||||
this._pickDeferred = null;
|
||||
|
||||
}.bind(this);
|
||||
|
||||
window.addEventListener(event, this._onPick, true);
|
||||
|
||||
return this._pickDeferred.promise;
|
||||
}, { request: { }, response: RetVal("disconnectedNode") }),
|
||||
|
||||
cancelPick: method(function() {
|
||||
if (this._pickDeferred) {
|
||||
let window = this.rootDoc.defaultView;
|
||||
let isTouch = 'ontouchstart' in window;
|
||||
let event = isTouch ? 'touchstart' : 'click';
|
||||
window.removeEventListener(event, this._onPick, true);
|
||||
this._pickDeferred.resolve(null);
|
||||
this._pickDeferred = null;
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Simple highlight mechanism.
|
||||
*/
|
||||
_unhighlight: function() {
|
||||
clearTimeout(this._highlightTimeout);
|
||||
if (!this.rootDoc) {
|
||||
return;
|
||||
}
|
||||
let nodes = this.rootDoc.querySelectorAll(HIGHLIGHTED_PSEUDO_CLASS);
|
||||
for (let node of nodes) {
|
||||
DOMUtils.removePseudoClassLock(node, HIGHLIGHTED_PSEUDO_CLASS);
|
||||
}
|
||||
},
|
||||
|
||||
highlight: method(function(node) {
|
||||
this._installHelperSheet(node);
|
||||
this._unhighlight();
|
||||
|
||||
if (!node ||
|
||||
!node.rawNode ||
|
||||
node.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
LayoutHelpers.scrollIntoViewIfNeeded(node.rawNode);
|
||||
DOMUtils.addPseudoClassLock(node.rawNode, HIGHLIGHTED_PSEUDO_CLASS);
|
||||
this._highlightTimeout = setTimeout(this._unhighlight.bind(this), HIGHLIGHTED_TIMEOUT);
|
||||
|
||||
}, { request: { node: Arg(0, "nullable:domnode") }}),
|
||||
|
||||
/**
|
||||
* Watch the given document node for mutations using the DOM observer
|
||||
* API.
|
||||
|
@ -1742,6 +1836,14 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, {
|
|||
// Set to true if cleanup should be requested after every mutation list.
|
||||
autoCleanup: true,
|
||||
|
||||
pick: protocol.custom(function() {
|
||||
return this._pick().then(response => {
|
||||
return response.node;
|
||||
});
|
||||
}, {
|
||||
impl: "_pick"
|
||||
}),
|
||||
|
||||
initialize: function(client, form) {
|
||||
this._rootNodeDeferred = promise.defer();
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
|
|
Загрузка…
Ссылка в новой задаче