Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1447)

Unified Diff: Source/devtools/front_end/elements/ElementsTreeOutline.js

Issue 397303002: DevTools: [Elements] Implement shortcut-based node cut-copy-pasting (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/devtools/front_end/elements/ElementsPanel.js ('k') | Source/devtools/front_end/inspectorStyle.css » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/devtools/front_end/elements/ElementsTreeOutline.js
diff --git a/Source/devtools/front_end/elements/ElementsTreeOutline.js b/Source/devtools/front_end/elements/ElementsTreeOutline.js
index 9cc824b7538c809813e0b79de20e8689cc68ab22..7d1c1876f991bee0436a090ce98a0b0b0bb09839 100644
--- a/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -71,6 +71,9 @@ WebInspector.ElementsTreeOutline = function(target, omitRootDOMNode, selectEnabl
this._createNodeDecorators();
}
+/** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */
+WebInspector.ElementsTreeOutline.ClipboardData;
+
/**
* @enum {string}
*/
@@ -144,6 +147,153 @@ WebInspector.ElementsTreeOutline.prototype = {
if (this._elementsTreeUpdater)
this._elementsTreeUpdater.dispose();
},
+
+ /**
+ * @param {?WebInspector.ElementsTreeOutline.ClipboardData} data
+ */
+ _setClipboardData: function(data)
+ {
+ if (this._clipboardNodeData) {
+ var treeElement = this.findTreeElement(this._clipboardNodeData.node);
+ if (treeElement)
+ treeElement.setInClipboard(false);
+ delete this._clipboardNodeData;
+ }
+
+ if (data) {
+ var treeElement = this.findTreeElement(data.node);
+ if (treeElement)
+ treeElement.setInClipboard(true);
+ this._clipboardNodeData = data;
+ }
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ _cutNode: function(node)
aandrey 2014/07/25 15:44:27 remove this in favor of .bind(..., true)?
apavlov 2014/07/25 16:09:56 Done.
+ {
+ this._performCopyOrCut(true, node);
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ _copyNode: function(node)
aandrey 2014/07/25 15:44:27 ditto
apavlov 2014/07/25 16:09:56 Done.
+ {
+ this._performCopyOrCut(false, node);
+ },
+
+ /**
+ * @param {boolean} isCut
+ * @param {!Event} event
+ */
+ handleCopyOrCutKeyboardEvent: function(isCut, event)
+ {
+ this._setClipboardData(null);
aandrey 2014/07/25 15:44:26 should it be after all the returns?
apavlov 2014/07/25 16:09:57 Nope. We don't want users to go dizzy about having
+
+ // Do not interfere with text editing.
+ var currentFocusElement = WebInspector.currentFocusElement();
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement))
+ return;
+
+ var targetNode = this.selectedDOMNode();
+ if (!targetNode)
+ return;
+
+ if (isCut && (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot()))
+ return;
+
+ event.clipboardData.clearData();
+ event.preventDefault();
+ this._performCopyOrCut(isCut, targetNode);
+ },
+
+ /**
+ * @param {boolean} isCut
+ * @param {?WebInspector.DOMNode} node
+ */
+ _performCopyOrCut: function(isCut, node)
+ {
+ node.copyNode();
+ this._setClipboardData({node: node, isCut: isCut});
aandrey 2014/07/25 15:44:27 nit: spaces after { and before }
apavlov 2014/07/25 16:09:57 Done.
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} targetNode
+ * @return {boolean}
+ */
+ _canPaste: function(targetNode)
+ {
+ if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot())
+ return false;
+
+ if (!this._clipboardNodeData)
+ return false;
+
+ var node = this._clipboardNodeData.node;
+ if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode)))
+ return false;
+
+ if (targetNode.target() !== node.target())
+ return false;
+ return true;
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} targetNode
+ */
+ _pasteNode: function(targetNode)
aandrey 2014/07/25 15:44:26 remove this (looks like the code would be a lot si
apavlov 2014/07/25 16:09:57 Done.
+ {
+ this._performPaste(targetNode);
+ },
+
+ /**
+ * @param {!Event} event
+ */
+ handlePasteKeyboardEvent: function(event)
+ {
+ // Do not interfere with text editing.
+ var currentFocusElement = WebInspector.currentFocusElement();
+ if (currentFocusElement && WebInspector.isBeingEdited(currentFocusElement))
+ return;
+
+ var targetNode = this.selectedDOMNode();
+ if (!targetNode || !this._canPaste(targetNode))
+ return;
+
+ event.preventDefault();
aandrey 2014/07/25 15:44:27 maybe event.consume(false); ?
apavlov 2014/07/25 16:09:57 true, since we need to preventDefault(). Done.
+ this._performPaste(targetNode);
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} targetNode
+ */
+ _performPaste: function(targetNode)
+ {
+ if (this._clipboardNodeData.isCut) {
+ this._clipboardNodeData.node.moveTo(targetNode, null, expandCallback.bind(this));
+ this._setClipboardData(null);
+ } else {
+ this._clipboardNodeData.node.copyTo(targetNode, null, expandCallback.bind(this));
+ }
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!DOMAgent.NodeId} nodeId
+ * @this {WebInspector.ElementsTreeOutline}
+ */
+ function expandCallback(error, nodeId)
+ {
+ if (error)
+ return;
+ var pastedNode = this._domModel.nodeForId(nodeId);
+ if (!pastedNode)
+ return;
+ this.selectDOMNode(pastedNode);
+ }
+ },
+
/**
* @param {boolean} visible
*/
@@ -350,6 +500,8 @@ WebInspector.ElementsTreeOutline.prototype = {
if (this._suppressRevealAndSelect)
return;
+ this._updateModifiedNodes();
+
if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode)
node = this.rootDOMNode.firstChild;
if (!node)
@@ -613,7 +765,7 @@ WebInspector.ElementsTreeOutline.prototype = {
treeElement._populateTagContextMenu(contextMenu, event);
} else if (commentNode) {
contextMenu.appendSeparator();
- treeElement._populateNodeContextMenu(contextMenu, textNode);
+ treeElement._populateNodeContextMenu(contextMenu);
} else if (isPseudoElement) {
treeElement._populateScrollIntoView(contextMenu);
} else if (treeElement._node.isShadowRoot()) {
@@ -920,6 +1072,17 @@ WebInspector.ElementsTreeElement.prototype = {
}
},
+ /**
+ * @param {boolean} inClipboard
+ */
+ setInClipboard: function(inClipboard)
+ {
+ if (this._inClipboard === inClipboard)
+ return;
+ this._inClipboard = inClipboard;
+ this.listItemElement.classList.toggle("in-clipboard", inClipboard);
+ },
+
get hovered()
{
return this._hovered;
@@ -1453,14 +1616,19 @@ WebInspector.ElementsTreeElement.prototype = {
if (isEditable && !this._editing)
contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), openTagElement._editAsHTML.bind(openTagElement));
var isShadowRoot = this.representedObject.isShadowRoot();
- if (!isShadowRoot)
- contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this));
// Place it here so that all "Copy"-ing items stick together.
if (this.representedObject.nodeType() === Node.ELEMENT_NODE)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy CSS path" : "Copy CSS Path"), this._copyCSSPath.bind(this));
if (!isShadowRoot)
contextMenu.appendItem(WebInspector.UIString("Copy XPath"), this._copyXPath.bind(this));
+ if (!isShadowRoot) {
+ var treeOutline = this.treeOutline;
+ contextMenu.appendItem(WebInspector.UIString("Copy"), treeOutline._copyNode.bind(treeOutline, this.representedObject));
+ contextMenu.appendItem(WebInspector.UIString("Cut"), treeOutline._cutNode.bind(treeOutline, this.representedObject), !this.hasEditableNode());
+ contextMenu.appendItem(WebInspector.UIString("Paste"), treeOutline._pasteNode.bind(treeOutline, this.representedObject), !treeOutline._canPaste(this.representedObject));
+ }
+
if (isEditable)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this));
},
@@ -2347,11 +2515,6 @@ WebInspector.ElementsTreeElement.prototype = {
node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange));
},
- _copyHTML: function()
- {
- this._node.copyNode();
- },
-
_copyCSSPath: function()
{
InspectorFrontendHost.copyText(WebInspector.DOMPresentationUtils.cssPath(this._node, true));
@@ -2635,6 +2798,7 @@ WebInspector.ElementsTreeUpdater.prototype = {
this._treeOutline.selectDOMNode(null, false);
this._domModel.hideDOMNodeHighlight();
this._recentlyModifiedNodes.clear();
+ delete this._treeOutline._clipboardNodeData;
}
}
« no previous file with comments | « Source/devtools/front_end/elements/ElementsPanel.js ('k') | Source/devtools/front_end/inspectorStyle.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698