Bug 1268441 - Convert markup view key shortcuts to use the shortcut helper module. r=bgrins

This commit is contained in:
Alexandre Poirot
2016-05-12 03:07:56 -07:00
parent 4a0b60932c
commit b51a17c59e
2 changed files with 86 additions and 47 deletions

View File

@@ -44,6 +44,7 @@ const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis",
const {Task} = require("resource://gre/modules/Task.jsm"); const {Task} = require("resource://gre/modules/Task.jsm");
const {scrollIntoViewIfNeeded} = require("devtools/shared/layout/utils"); const {scrollIntoViewIfNeeded} = require("devtools/shared/layout/utils");
const {PrefObserver} = require("devtools/client/styleeditor/utils"); const {PrefObserver} = require("devtools/client/styleeditor/utils");
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
Cu.import("resource://devtools/shared/gcli/Templater.jsm"); Cu.import("resource://devtools/shared/gcli/Templater.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -123,7 +124,6 @@ function MarkupView(inspector, frame, controllerWindow) {
this._onMouseClick = this._onMouseClick.bind(this); this._onMouseClick = this._onMouseClick.bind(this);
this._onMouseUp = this._onMouseUp.bind(this); this._onMouseUp = this._onMouseUp.bind(this);
this._onNewSelection = this._onNewSelection.bind(this); this._onNewSelection = this._onNewSelection.bind(this);
this._onKeyDown = this._onKeyDown.bind(this);
this._onCopy = this._onCopy.bind(this); this._onCopy = this._onCopy.bind(this);
this._onFocus = this._onFocus.bind(this); this._onFocus = this._onFocus.bind(this);
this._onMouseMove = this._onMouseMove.bind(this); this._onMouseMove = this._onMouseMove.bind(this);
@@ -137,7 +137,6 @@ function MarkupView(inspector, frame, controllerWindow) {
this._elt.addEventListener("mousemove", this._onMouseMove, false); this._elt.addEventListener("mousemove", this._onMouseMove, false);
this._elt.addEventListener("mouseleave", this._onMouseLeave, false); this._elt.addEventListener("mouseleave", this._onMouseLeave, false);
this.win.addEventListener("mouseup", this._onMouseUp); this.win.addEventListener("mouseup", this._onMouseUp);
this.win.addEventListener("keydown", this._onKeyDown, false);
this.win.addEventListener("copy", this._onCopy); this.win.addEventListener("copy", this._onCopy);
this._frame.addEventListener("focus", this._onFocus, false); this._frame.addEventListener("focus", this._onFocus, false);
this.walker.on("mutations", this._mutationObserver); this.walker.on("mutations", this._mutationObserver);
@@ -154,6 +153,8 @@ function MarkupView(inspector, frame, controllerWindow) {
this._prefObserver.on(ATTR_COLLAPSE_LENGTH_PREF, this._prefObserver.on(ATTR_COLLAPSE_LENGTH_PREF,
this._onCollapseAttributesPrefChange); this._onCollapseAttributesPrefChange);
this._initShortcuts();
EventEmitter.decorate(this); EventEmitter.decorate(this);
} }
@@ -613,25 +614,40 @@ MarkupView.prototype = {
}, },
/** /**
* Key handling. * Register all key shortcuts.
*/ */
_onKeyDown: function (event) { _initShortcuts: function () {
let handled = true; let shortcuts = new KeyShortcuts({
let previousNode, nextNode; window: this.win,
});
// Ignore keystrokes that originated in editors. this._onShortcut = this._onShortcut.bind(this);
// Process localizable keys
["markupView.hide.key",
"markupView.edit.key",
"markupView.scrollInto.key"].forEach(name => {
let key = this.strings.GetStringFromName(name);
shortcuts.on(key, (_, event) => this._onShortcut(name, event));
});
// Process generic keys:
["Delete", "Backspace", "Home", "Left", "Right", "Up", "Down", "PageUp",
"PageDown", "Esc"].forEach(key => {
shortcuts.on(key, this._onShortcut);
});
},
/**
* Key shortcut listener.
*/
_onShortcut(name, event) {
if (this._isInputOrTextarea(event.target)) { if (this._isInputOrTextarea(event.target)) {
return; return;
} }
switch (name) {
// Ignore keystrokes with modifiers to allow native shortcuts (such as save: // Localizable keys
// accel + S) to bubble up. case "markupView.hide.key": {
if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
return;
}
switch (event.keyCode) {
case Ci.nsIDOMKeyEvent.DOM_VK_H:
let node = this._selectedContainer.node; let node = this._selectedContainer.node;
if (node.hidden) { if (node.hidden) {
this.walker.unhideNode(node); this.walker.unhideNode(node);
@@ -639,17 +655,31 @@ MarkupView.prototype = {
this.walker.hideNode(node); this.walker.hideNode(node);
} }
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_DELETE: }
case "markupView.edit.key": {
this.beginEditingOuterHTML(this._selectedContainer.node);
break;
}
case "markupView.scrollInto.key": {
let selection = this._selectedContainer.node;
this._inspector.scrollNodeIntoView(selection);
break;
}
// Generic keys
case "Delete": {
this.deleteNodeOrAttribute(); this.deleteNodeOrAttribute();
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE: }
case "Backspace": {
this.deleteNodeOrAttribute(true); this.deleteNodeOrAttribute(true);
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_HOME: }
case "Home": {
let rootContainer = this.getContainer(this._rootNode); let rootContainer = this.getContainer(this._rootNode);
this.navigate(rootContainer.children.firstChild.container); this.navigate(rootContainer.children.firstChild.container);
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_LEFT: }
case "Left": {
if (this._selectedContainer.expanded) { if (this._selectedContainer.expanded) {
this.collapseNode(this._selectedContainer.node); this.collapseNode(this._selectedContainer.node);
} else { } else {
@@ -659,7 +689,8 @@ MarkupView.prototype = {
} }
} }
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_RIGHT: }
case "Right": {
if (!this._selectedContainer.expanded && if (!this._selectedContainer.expanded &&
this._selectedContainer.hasChildren) { this._selectedContainer.hasChildren) {
this._expandContainer(this._selectedContainer); this._expandContainer(this._selectedContainer);
@@ -670,23 +701,26 @@ MarkupView.prototype = {
} }
} }
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_UP: }
previousNode = this._selectionWalker().previousNode(); case "Up": {
let previousNode = this._selectionWalker().previousNode();
if (previousNode) { if (previousNode) {
this.navigate(previousNode.container); this.navigate(previousNode.container);
} }
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_DOWN: }
nextNode = this._selectionWalker().nextNode(); case "Down": {
let nextNode = this._selectionWalker().nextNode();
if (nextNode) { if (nextNode) {
this.navigate(nextNode.container); this.navigate(nextNode.container);
} }
break; break;
case Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP: { }
case "PageUp": {
let walker = this._selectionWalker(); let walker = this._selectionWalker();
let selection = this._selectedContainer; let selection = this._selectedContainer;
for (let i = 0; i < PAGE_SIZE; i++) { for (let i = 0; i < PAGE_SIZE; i++) {
previousNode = walker.previousNode(); let previousNode = walker.previousNode();
if (!previousNode) { if (!previousNode) {
break; break;
} }
@@ -695,11 +729,11 @@ MarkupView.prototype = {
this.navigate(selection); this.navigate(selection);
break; break;
} }
case Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN: { case "PageDown": {
let walker = this._selectionWalker(); let walker = this._selectionWalker();
let selection = this._selectedContainer; let selection = this._selectedContainer;
for (let i = 0; i < PAGE_SIZE; i++) { for (let i = 0; i < PAGE_SIZE; i++) {
nextNode = walker.nextNode(); let nextNode = walker.nextNode();
if (!nextNode) { if (!nextNode) {
break; break;
} }
@@ -708,30 +742,23 @@ MarkupView.prototype = {
this.navigate(selection); this.navigate(selection);
break; break;
} }
case Ci.nsIDOMKeyEvent.DOM_VK_F2: { case "Esc": {
this.beginEditingOuterHTML(this._selectedContainer.node);
break;
}
case Ci.nsIDOMKeyEvent.DOM_VK_S: {
let selection = this._selectedContainer.node;
this._inspector.scrollNodeIntoView(selection);
break;
}
case Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE: {
if (this.isDragging) { if (this.isDragging) {
this.cancelDragging(); this.cancelDragging();
break; } else {
// Return early to prevent cancelling the event when not
// dragging, to allow the split console to be toggled.
return;
} }
handled = false;
break; break;
} }
default: default:
handled = false; console.error("Unexpected markup-view key shortcut", name);
return;
} }
if (handled) { // Prevent default for this action
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
}
}, },
/** /**
@@ -1630,7 +1657,6 @@ MarkupView.prototype = {
this._elt.removeEventListener("mousemove", this._onMouseMove, false); this._elt.removeEventListener("mousemove", this._onMouseMove, false);
this._elt.removeEventListener("mouseleave", this._onMouseLeave, false); this._elt.removeEventListener("mouseleave", this._onMouseLeave, false);
this.win.removeEventListener("mouseup", this._onMouseUp); this.win.removeEventListener("mouseup", this._onMouseUp);
this.win.removeEventListener("keydown", this._onKeyDown, false);
this.win.removeEventListener("copy", this._onCopy); this.win.removeEventListener("copy", this._onCopy);
this._frame.removeEventListener("focus", this._onFocus, false); this._frame.removeEventListener("focus", this._onFocus, false);
this.walker.off("mutations", this._mutationObserver); this.walker.off("mutations", this._mutationObserver);

View File

@@ -145,3 +145,16 @@ inspector.nodePreview.highlightNodeLabel=Click to highlight this node in the pag
# Key shortcut used to focus the DOM element search box on top-right corner of # Key shortcut used to focus the DOM element search box on top-right corner of
# the markup view # the markup view
inspector.searchHTML.key=CmdOrCtrl+F inspector.searchHTML.key=CmdOrCtrl+F
# LOCALIZATION NOTE (markupView.hide.key):
# Key shortcut used to hide the selected node in the markup view.
markupView.hide.key=h
# LOCALIZATION NOTE (markupView.edit.key):
# Key shortcut used to hide the selected node in the markup view.
markupView.edit.key=F2
# LOCALIZATION NOTE (markupView.scrollInto.key):
# Key shortcut used to scroll the webpage in order to ensure the selected node
# is visible
markupView.scrollInto.key=s