Bug 701419 - Add a "Copy Unique Selector" option in the inspected element's menu and the corresponding test. f=paul r=jwalker

This commit is contained in:
Christos Stathis 2013-02-07 12:41:00 +02:00
Родитель 789442d7d4
Коммит a9ab361602
5 изменённых файлов: 106 добавлений и 0 удалений

Просмотреть файл

@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
Cu.import("resource:///modules/devtools/CssLogic.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MarkupView",
"resource:///modules/devtools/MarkupView.jsm");
@ -645,6 +646,21 @@ InspectorPanel.prototype = {
}
},
/**
* Copy a unique selector of the selected Node to the clipboard.
*/
copyUniqueSelector: function InspectorPanel_copyUniqueSelector()
{
if (!this.selection.isNode()) {
return;
}
let toCopy = CssLogic.findCssSelector(this.selection.node);
if (toCopy) {
clipboardHelper.copyString(toCopy);
}
},
/**
* Delete the selected node.
*/

Просмотреть файл

@ -39,6 +39,10 @@
label="&inspectorHTMLCopyOuter.label;"
accesskey="&inspectorHTMLCopyOuter.accesskey;"
oncommand="inspector.copyOuterHTML()"/>
<menuitem id="node-menu-copyuniqueselector"
label="&inspectorCopyUniqueSelector.label;"
accesskey="&inspectorCopyUniqueSelector.accesskey;"
oncommand="inspector.copyUniqueSelector()"/>
<menuseparator/>
<menuitem id="node-menu-delete"
label="&inspectorHTMLDelete.label;"

Просмотреть файл

@ -56,6 +56,15 @@ function test() {
waitForClipboard("<p>This is some example text</p>",
function() { copyOuter.doCommand(); },
testCopyUniqueSelectorMenu, testCopyUniqueSelectorMenu);
}
function testCopyUniqueSelectorMenu() {
let copyUniqueSelector = inspector.panelDoc.getElementById("node-menu-copyuniqueselector");
ok(copyUniqueSelector, "the popup menu has a copy unique selector menu item");
waitForClipboard("body > div:nth-child(1) > p:nth-child(2)",
function() { copyUniqueSelector.doCommand(); },
testDeleteNode, testDeleteNode);
}

Просмотреть файл

@ -821,6 +821,80 @@ CssLogic.shortSource = function CssLogic_shortSource(aSheet)
return dataUrl ? dataUrl[1] : aSheet.href;
}
/**
* Find the position of [element] in [nodeList].
* @returns an index of the match, or -1 if there is no match
*/
function positionInNodeList(element, nodeList) {
for (var i = 0; i < nodeList.length; i++) {
if (element === nodeList[i]) {
return i;
}
}
return -1;
}
/**
* Find a unique CSS selector for a given element
* @returns a string such that ele.ownerDocument.querySelector(reply) === ele
* and ele.ownerDocument.querySelectorAll(reply).length === 1
*/
CssLogic.findCssSelector = function CssLogic_findCssSelector(ele) {
var document = ele.ownerDocument;
if (ele.id && document.getElementById(ele.id) === ele) {
return '#' + ele.id;
}
// Inherently unique by tag name
var tagName = ele.tagName.toLowerCase();
if (tagName === 'html') {
return 'html';
}
if (tagName === 'head') {
return 'head';
}
if (tagName === 'body') {
return 'body';
}
if (ele.parentNode == null) {
console.log('danger: ' + tagName);
}
// We might be able to find a unique class name
var selector, index, matches;
if (ele.classList.length > 0) {
for (var i = 0; i < ele.classList.length; i++) {
// Is this className unique by itself?
selector = '.' + ele.classList.item(i);
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
// Maybe it's unique with a tag name?
selector = tagName + selector;
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
// Maybe it's unique using a tag name and nth-child
index = positionInNodeList(ele, ele.parentNode.children) + 1;
selector = selector + ':nth-child(' + index + ')';
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
}
}
// So we can be unique w.r.t. our parent, and use recursion
index = positionInNodeList(ele, ele.parentNode.children) + 1;
selector = CssLogic_findCssSelector(ele.parentNode) + ' > ' +
tagName + ':nth-child(' + index + ')';
return selector;
};
/**
* A safe way to access cached bits of information about a stylesheet.
*

Просмотреть файл

@ -4,6 +4,9 @@
<!ENTITY inspectorHTMLCopyOuter.label "Copy Outer HTML">
<!ENTITY inspectorHTMLCopyOuter.accesskey "O">
<!ENTITY inspectorCopyUniqueSelector.label "Copy Unique Selector">
<!ENTITY inspectorCopyUniqueSelector.accesskey "U">
<!ENTITY inspectorHTMLDelete.label "Delete Node">
<!ENTITY inspectorHTMLDelete.accesskey "D">