我希望能够点击 <i>
、<a>
或 <li>
并获得所有 <li>
。
关键是要检测最接近的重复元素,无论您点击它的子元素有多深。
这是我目前所拥有的:它显示了兄弟姐妹的数量,但我想隔离的是相同性。
例如:<body>
显示 2 个兄弟姐妹,但它们不是 <body>
。 <header>
显示了 4 个,但不是全部 <header>
。我如何只计算相同的兄弟姐妹。在这种情况下 <li>
但可以是任何东西。
//整页运行↗️
$('body').on('click', (e) => {
$el = $(e.target);
$parentsAndSelf = $el.parents().addBack();
$parentsAndSelf.each( (i,el) => {
if( $(el).siblings().addBack().length > 1){
console.log( el, $(el).siblings().addBack().length );
//return false;
}
});
});
* {
padding: 5px;
margin:5px;
outline: 1px solid pink;
list-style-position: inside;
}
a {
display: block
}
.highlight{
background:yellow;
}
*:hover {
outline: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
HEADER:
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</header>
答案 0 :(得分:2)
这真的让我很忙呵呵。
如果:
<块引用>关键是无论如何都要检测最近的重复元素 在你点击的孩子的深处。
意思是:
我希望能够点击 <i>
、<a>
或 <li>
和
获取所有 <li>
。
示例:
let num
document.addEventListener("click", function(event) {
num = 1;
let el = event.target
let s
check(s, el)
})
function check(s, el) {
console.clear()
// jumping parents part and getting only first level children
let ss = ".parentNode"
s = "el" + ss.repeat(num) + ".children"
// map tagnames
let c = [...eval(s)].map(type => type.tagName)
// isolate duplicates part
const yourArray = c
const yourArrayWithoutDuplicates = [...new Set(yourArray)]
let duplicates = [...yourArray]
yourArrayWithoutDuplicates.forEach((item) => {
const i = duplicates.indexOf(item)
duplicates = duplicates
.slice(0, i)
.concat(duplicates.slice(i + 1, duplicates.length))
})
// if no duplicates call this same function just add num++ to add .parentNode
// it will loop unitl it hits 2 same tagnames on same level, sibilings
duplicates.length === 0 ? (num++, check(eval(s), el)) : (console.log("Repeting element :" + duplicates[0]), console.log("Repets: " + (parseInt(duplicates.length) + 1)), console.log("Position from clicked element: " + s))
}
* {
padding: 5px;
margin: 5px;
outline: 1px solid pink;
list-style-position: inside;
}
a {
display: block
}
.highlight {
background: yellow;
}
*:hover {
outline: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<div>1</div>
<div>2</div>
HEADER:
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</header>
编辑:
这里有一个更简化的版本,仍然遵循相同的逻辑:
let num
document.addEventListener("click", function(event) {
num = 1;
let s
check(s, event.target)
})
function check(s, el) {
console.clear()
const ss = ".parentNode"
s = "el" + ss.repeat(num) + ".children";
let count = {};
[...eval(s)].map(type => type.tagName).forEach( i => {count[i] = (count[i] || 0) + 1})
const max = Math.max.apply(null, Object.values(count));
max <= 1 ? (num++, check(eval(s), el)) : (console.log("Repeting element :" + Object.keys(count)[0]), console.log("Repets: " + max), console.log("Position from clicked element: " + s))
}
* {
padding: 5px;
margin: 5px;
outline: 1px solid pink;
list-style-position: inside;
}
a {
display: block
}
.highlight {
background: yellow;
}
*:hover {
outline: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<div>1</div>
<div>2</div>
HEADER:
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</header>
答案 1 :(得分:2)
在介绍 jQuery 之前,让我从一个非常简单的 JavaScript 想法开始:
这可以通过使用 Element.querySelectorAll() 和 ":scope >"
查询相同 Element.tagName
的直接子元素以及递归函数轻松实现:: >
const closestMultiple = el => {
const par = el.parentElement;
const sib = par && par.querySelectorAll(`:scope > ${el.tagName}`);
return (sib && sib.length > 1 ? sib : par && closestMultiple(par))
}
document.body.addEventListener("click", (ev) => {
const cm = closestMultiple(ev.target)
if(cm) cm.forEach(EL => EL.classList.toggle("highlight"));
});
* {
padding: 5px;
margin: 5px;
outline: 1px solid pink;
list-style-position: inside;
background: #fff;
}
*:hover {
outline: 1px solid red;
}
a {
display: block
}
.highlight {
background: yellow;
}
<header>
<div>
HEADER:
</div>
<div>
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</div>
</header>
.reverse()
反转数组以加快从目标元素(而不是文档)开始的过程。length > 1
条件匹配,就停止循环:function closestMultiple(el, $mu) {
return $(el).parents().addBack().get().reverse().some(el => {
const $gr = $(el).siblings(el.tagName).addBack();
return ($gr.length > 1 ? $mu = $gr : 0);
}) && $mu || $();
}
function closestMultiple(el, $mu) {
return $(el).parents().addBack().get().reverse().some(el => {
const $gr = $(el).siblings(el.tagName).addBack();
return ($gr.length > 1 ? $mu = $gr : 0);
}) && $mu || $();
}
$(document).on('click', (ev) => {
const $clRep = closestMultiple(ev.target).toggleClass("highlight");
console.clear(); console.log($clRep.length +" "+ $clRep.prop("tagName"));
});
* {
padding: 5px;
margin: 5px;
outline: 1px solid pink;
list-style-position: inside;
background: #fff;
}
*:hover {
outline: 1px solid red;
}
a {
display: block
}
.highlight {
background: yellow;
}
<header>
<div>
HEADER:
</div>
<div>
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</div>
</header>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
为了获得更好的体验(因为您已经在使用 jQuery),您可以使用自己的 jQuery
方法扩展 .closestMultiple()
构造函数。
以下是对微插件的建议:
$.fn.closestMultiple = function($mu) {
return this.parents().addBack().get().reverse().some(el => {
const $gr = $(el).siblings(el.tagName).addBack();
return ($gr.length > 1 ? $mu = $gr : 0);
}) && $mu || $();
}
$(document).on('click', (ev) => {
$(ev.target).closestMultiple().toggleClass("highlight");
});
* {
padding: 5px;
margin: 5px;
outline: 1px solid pink;
list-style-position: inside;
background: #fff;
}
a {
display: block
}
.highlight {
background: yellow;
}
*:hover {
outline: 1px solid red;
}
<header>
<div>
HEADER:
</div>
<div>
<nav>
NAV:
<ul>
UL:
<li>li <a href="#">item <i>1</i></a> </li>
<li>li <a href="#">item <i>2</i></a> </li>
<li>li <a href="#">item <i>3</i></a> </li>
<li>li <a href="#">item <i>4</i></a> </li>
</ul>
</nav>
</div>
</header>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
答案 2 :(得分:-2)
我认为这个简单的方法可以帮助您:
$("i, a, li").on('click', function(event) {
var closest_li = $(this).closest('ul').find('li');
console.log(closest_li);
});
因此,您将获得父 <li>
中存在的所有 <ul>
元素的数组。