Bug 1449972 - part2: Move getCssPath and getXPath to toolkit css-selector;r=bgrins
getCssPath and getXPath will need to reuse the same logic as findCssSelector to handle shadowDOM support. This patch moves the methods next to findCssSelector, in toolkit's css-selector.js to avoid duplicating logic between devtools/ and toolkit/ The content of the methods is stricltly the same, except for the Node global not available in css-selector.js. Instead we use `ele.ownerGlobal.Node` here. MozReview-Commit-ID: J0KuORWLUoO
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { getRootBindingParent } = require("devtools/shared/layout/utils");
|
||||
const { getTabPrefs } = require("devtools/shared/indentation");
|
||||
const InspectorUtils = require("InspectorUtils");
|
||||
|
||||
@@ -49,6 +48,8 @@ const MAX_DATA_URL_LENGTH = 40;
|
||||
const Services = require("Services");
|
||||
|
||||
loader.lazyImporter(this, "findCssSelector", "resource://gre/modules/css-selector.js");
|
||||
loader.lazyImporter(this, "getCssPath", "resource://gre/modules/css-selector.js");
|
||||
loader.lazyImporter(this, "getXPath", "resource://gre/modules/css-selector.js");
|
||||
|
||||
const CSSLexer = require("devtools/shared/css/lexer");
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
@@ -374,49 +375,6 @@ exports.findCssSelector = findCssSelector;
|
||||
* match the element uniquely. It does however, represent the full path from the root
|
||||
* node to the element.
|
||||
*/
|
||||
function getCssPath(ele) {
|
||||
ele = getRootBindingParent(ele);
|
||||
const document = ele.ownerDocument;
|
||||
if (!document || !document.contains(ele)) {
|
||||
// getCssPath received element not inside document.
|
||||
return "";
|
||||
}
|
||||
|
||||
const getElementSelector = element => {
|
||||
if (!element.localName) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let label = element.nodeName == element.nodeName.toUpperCase()
|
||||
? element.localName.toLowerCase()
|
||||
: element.localName;
|
||||
|
||||
if (element.id) {
|
||||
label += "#" + element.id;
|
||||
}
|
||||
|
||||
if (element.classList) {
|
||||
for (const cl of element.classList) {
|
||||
label += "." + cl;
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
const paths = [];
|
||||
|
||||
while (ele) {
|
||||
if (!ele || ele.nodeType !== Node.ELEMENT_NODE) {
|
||||
break;
|
||||
}
|
||||
|
||||
paths.splice(0, 0, getElementSelector(ele));
|
||||
ele = ele.parentNode;
|
||||
}
|
||||
|
||||
return paths.length ? paths.join(" ") : "";
|
||||
}
|
||||
exports.getCssPath = getCssPath;
|
||||
|
||||
/**
|
||||
@@ -424,60 +382,6 @@ exports.getCssPath = getCssPath;
|
||||
* @param {DomNode} ele
|
||||
* @returns a string that can be used as an XPath to find the element uniquely.
|
||||
*/
|
||||
function getXPath(ele) {
|
||||
ele = getRootBindingParent(ele);
|
||||
const document = ele.ownerDocument;
|
||||
if (!document || !document.contains(ele)) {
|
||||
// getXPath received element not inside document.
|
||||
return "";
|
||||
}
|
||||
|
||||
// Create a short XPath for elements with IDs.
|
||||
if (ele.id) {
|
||||
return `//*[@id="${ele.id}"]`;
|
||||
}
|
||||
|
||||
// Otherwise walk the DOM up and create a part for each ancestor.
|
||||
const parts = [];
|
||||
|
||||
// Use nodeName (instead of localName) so namespace prefix is included (if any).
|
||||
while (ele && ele.nodeType === Node.ELEMENT_NODE) {
|
||||
let nbOfPreviousSiblings = 0;
|
||||
let hasNextSiblings = false;
|
||||
|
||||
// Count how many previous same-name siblings the element has.
|
||||
let sibling = ele.previousSibling;
|
||||
while (sibling) {
|
||||
// Ignore document type declaration.
|
||||
if (sibling.nodeType !== Node.DOCUMENT_TYPE_NODE &&
|
||||
sibling.nodeName == ele.nodeName) {
|
||||
nbOfPreviousSiblings++;
|
||||
}
|
||||
|
||||
sibling = sibling.previousSibling;
|
||||
}
|
||||
|
||||
// Check if the element has at least 1 next same-name sibling.
|
||||
sibling = ele.nextSibling;
|
||||
while (sibling) {
|
||||
if (sibling.nodeName == ele.nodeName) {
|
||||
hasNextSiblings = true;
|
||||
break;
|
||||
}
|
||||
sibling = sibling.nextSibling;
|
||||
}
|
||||
|
||||
const prefix = ele.prefix ? ele.prefix + ":" : "";
|
||||
const nth = nbOfPreviousSiblings || hasNextSiblings
|
||||
? `[${nbOfPreviousSiblings + 1}]` : "";
|
||||
|
||||
parts.push(prefix + ele.localName + nth);
|
||||
|
||||
ele = ele.parentNode;
|
||||
}
|
||||
|
||||
return parts.length ? "/" + parts.reverse().join("/") : "";
|
||||
}
|
||||
exports.getXPath = getXPath;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user