我正在使用JavaScript移动元素,我需要为拖放期间发生的组合创建逻辑
我正在尝试从元素中获取详细信息,像选择器这样的CSS也可以,但是如果可能的话,则不建议使用..(例如chrome开发工具中的复制选择器)
document.onmouseup = function(e){
targetDest = e.target;
//console.log('targetDest: ', targetDest);
let
indexA = Array.from(targetCurr.parentNode.children).indexOf(targetCurr),
indexB = Array.from(targetDest.parentNode.children).indexOf(targetDest);
console.log(indexA, indexB);
if(targetDest != targetCurr){
if(targetDest == document.documentElement){
console.log('document');
}
else if(targetDest == undefined){
console.log('undefined');
}
else if(!targetDest){
console.log('!dest');
}
else if(targetDest == null){
console.log('null');
}
else if(targetDest == false){
console.log('false');
}
else{
console.log('else');
//targetCurr.parentNode.insertBefore(targetDest, targetCurr);
//console.log('...');
}
}else{
console.log('itself');
}
}
Run Code Online (Sandbox Code Playgroud)
mik*_*qex 12
我的解决方案使用:nth-child:
function getSelector(elm)
{
if (elm.tagName === "BODY") return "BODY";
const names = [];
while (elm.parentElement && elm.tagName !== "BODY") {
if (elm.id) {
names.unshift("#" + elm.getAttribute("id")); // getAttribute, because `elm.id` could also return a child element with name "id"
break; // Because ID should be unique, no more is needed. Remove the break, if you always want a full path.
} else {
let c = 1, e = elm;
for (; e.previousElementSibling; e = e.previousElementSibling, c++) ;
names.unshift(elm.tagName + ":nth-child(" + c + ")");
}
elm = elm.parentElement;
}
return names.join(">");
}
var qStr = getSelector(document.querySelector("div.moo"));
alert(qStr);Run Code Online (Sandbox Code Playgroud)
body
<div class="outer">
div.outer
<div class="inner" id="foo">
div#foo.inner
<div class="moo man">
div.moo.man
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
请注意,如果其中包含带有 ID 的元素,它不会返回整个路径 - 每个 ID 在页面上都应该是唯一的,因为有效的 HTML 要求如此。
document.querySelector我稍后在代码中使用此函数的输出,因为我需要将焦点返回到replaceChild其父元素之后的同一元素。
我希望 CollinD 不会介意我借用了他的代码片段标记:-)
我混合了建议的两种解决方案,以获得人类可读的结果,并且如果有几个相似的兄弟姐妹,则给出正确的元素:
function elemToSelector(elem) {
const {
tagName,
id,
className,
parentNode
} = elem;
if (tagName === 'HTML') return 'HTML';
let str = tagName;
str += (id !== '') ? `#${id}` : '';
if (className) {
const classes = className.split(/\s/);
for (let i = 0; i < classes.length; i++) {
str += `.${classes[i]}`;
}
}
let childIndex = 1;
for (let e = elem; e.previousElementSibling; e = e.previousElementSibling) {
childIndex += 1;
}
str += `:nth-child(${childIndex})`;
return `${elemToSelector(parentNode)} > ${str}`;
}
Run Code Online (Sandbox Code Playgroud)
测试:
// Select an element in Elements tab of your navigator Devtools, or replace $0
document.querySelector(elemToSelector($0)) === $0 &&
document.querySelectorAll(elemToSelector($0)).length === 1
Run Code Online (Sandbox Code Playgroud)
这可能会给你一些类似的东西,它有点长,但它是可读的并且总是有效的:
HTML > BODY:nth-child(2) > DIV.container:nth-child(2) > DIV.row:nth-child(2) > DIV.col-md-4:nth-child(2) > DIV.sidebar:nth-child(1) > DIV.sidebar-wrapper:nth-child(2) > DIV.my-4:nth-child(1) > H4:nth-child(3)
Run Code Online (Sandbox Code Playgroud)
编辑:我刚刚找到了这个包unique-selector
请记住,这不一定会唯一标识元素。但是,您可以通过从节点向上遍历并在您所在的元素之前构造这种选择器。您可能会做这样的事情
var generateQuerySelector = function(el) {
if (el.tagName.toLowerCase() == "html")
return "HTML";
var str = el.tagName;
str += (el.id != "") ? "#" + el.id : "";
if (el.className) {
var classes = el.className.split(/\s/);
for (var i = 0; i < classes.length; i++) {
str += "." + classes[i]
}
}
return generateQuerySelector(el.parentNode) + " > " + str;
}
var qStr = generateQuerySelector(document.querySelector("div.moo"));
alert(qStr);Run Code Online (Sandbox Code Playgroud)
body
<div class="outer">
div.outer
<div class="inner" id="foo">
div#foo.inner
<div class="moo man">
div.moo.man
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
除了向用户展示信息之外,我不建议使用太多其他内容。拆分并重新使用部件必定会引起问题。