[英]How to get the HTML element but exclude all child elements with querySelector
[英]How can I select all child elements with a certain class using querySelector in JavaScript regardless of the order they appear in HTML?
我正在过滤一个目录,该目录通过我们的 CMS 创建的组件提供,我无法控制。 我要过滤的每个目录成员的标签都在类为 d-none 的 div 中。 我正在使用的脚本有效,除了它只显示我想要过滤的项目,当它们是卡内的第一个 div 时。 如果标签不是卡片中的第一项,我想弄清楚如何过滤标签。
例如,在下面的代码中,过滤器按钮一直有效,直到您按下所有员工按钮。 然后只显示 Christina 的名字,因为“Employee”是她名片中的第一个标签。
<h1>Employees</h1>
<p>
<button onclick="queryButton('FULL TIME')">Full Time</button>
<button onclick="queryButton('PART TIME')">Part Time</button>
<button onclick="queryButton('SEASONAL')">Seasonal</button>
<button onclick="queryButton('EMPLOYEE')">All Employees</button>
</p>
<div class="cpFeed">
<div class="card-news">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Adele</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Full Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Agnes</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Seasonal</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Billy</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Bob</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Seasonal</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Calvin</div>
</div>
<div class="card-news" class="d-none">
<div style="display: none;" class="d-none">Employee</div>
<div style="display: none;" class="d-none">Seasonal</div>
<div>Christina</div>
</div>
<div class="card-news" class="d-none">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Cindy</div>
</div>
</div>
<script>
function queryButton(queryFilter) {
var filter, feedDiv, cardDiv, unnamedDiv, i, txtValue;
filter = queryFilter;
feedDiv = document.querySelector("div.cpFeed");
cardDiv = feedDiv.querySelectorAll("div.card-news");
for (i = 0; i < cardDiv.length; i++) {
unnamedDiv = cardDiv[i].querySelector(".d-none");
[0];
txtValue = unnamedDiv.textContent || div.div.innerHTML;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
cardDiv[i].style.display = "";
} else {
cardDiv[i].style.display = "none";
}
}
}
</script>
我尝试在下一行中将 querySelector 更改为 querySelectorAll。 这
unnamedDiv = cardDiv[i].querySelectorAll(".d-none");
这会导致按钮的功能停止工作。 我在控制台中收到以下错误:
Uncaught ReferenceError: div is not defined
at queryButton (example.html:56:44)
at HTMLButtonElement.onclick (example.html:5:45)
有什么我想念的吗?
<h1>Employees</h1>
<p>
<button onclick="queryButton('FULL TIME')">Full Time</button>
<button onclick="queryButton('PART TIME')">Part Time</button>
<button onclick="queryButton('SEASONAL')">Seasonal</button>
<button onclick="queryButton('EMPLOYEE')">All Employees</button>
</p>
<div class="cpFeed">
<div class="card-news">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Adele</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Full Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Agnes</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Seasonal</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Billy</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Bob</div>
</div>
<div class="card-news">
<div style="display: none;" class="d-none">Seasonal</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Calvin</div>
</div>
<div class="card-news" class="d-none">
<div style="display: none;" class="d-none">Employee</div>
<div style="display: none;" class="d-none">Seasonal</div>
<div>Christina</div>
</div>
<div class="card-news" class="d-none">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Cindy</div>
</div>
</div>
<script>
function queryButton(queryFilter) {
var filter, feedDiv, cardDiv, i;
filter = queryFilter;
feedDiv = document.querySelector("div.cpFeed");
cardDiv = feedDiv.querySelectorAll("div.card-news");
for (i = 0; i < cardDiv.length; i++) {
let unnamedDiv = cardDiv[i].querySelectorAll(".d-none");
console.log(unnamedDiv);
let display = "none";
unnamedDiv.forEach((ldiv) => {
txtValue = ldiv.textContent || div.div.innerHTML;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
display = ""
}
// else{
// display = "none"
// }
})
cardDiv[i].style.display = display;
}
}
</script>
我可以看到您的代码存在一些问题,所以这里有一个解释。
首先,这是我自己编写<script>
的方式,希望能让它更容易理解。 如果您不想,则不必以这种方式构建它。 此块不会更改您的代码所做的任何事情。
function queryButton(filter) {
let feedDiv = document.querySelector("div.cpFeed"), // Get's the first <div> with a class of cpFeed
cardDiv = feedDiv.querySelectorAll("div.card-news"), // Get's all <div> children of feedDiv with a class of card-news
unnamedDiv, // pre-sets to a variable to undefined
i, // pre-sets to a variable to undefined
txtValue // pre-sets to a variable to undefined
for (i = 0; i < cardDiv.length; i++) { // Sets a previously undefined variable to 0, to be looped through
unnamedDiv = cardDiv[i].querySelector(".d-none") // Gets first of any element, child of the indexed (i) cardDiv, with a class d-none
[0] // Does nothing
txtValue = unnamedDiv.textContent || div.div.innerHTML // returns unnamedDiv.textContent if unnamedDiv.textContent is not undefined. Otherwise, returns div.div.innerHTML, which is not assigned, so it will error out.
// Returned error from div.div.innerHTML:
// Uncaught ReferenceError: div is not defined
// at queryButton (example.html:56:44)
// at HTMLButtonElement.onclick (example.html:5:45)
if (txtValue.toUpperCase().indexOf(filter) > -1) { // Checks whether an uppercase string's index of the filter param is greater than -1
cardDiv[i].style.display = "" // Sets the indexed (i) cardDiv's display to empty / it's default value.
} else {
cardDiv[i].style.display = "none" // Sets the indexed (i) cardDiv's display to "none"
}
}
}
希望仅仅根据上面的评论,您就能够以自己的方式解决错误。
当然,如果你只想有一个工作示例,这里是我实际使脚本工作。
function queryButton(filter) {
// Switched to const since these variable will not be changed
const feedDiv = document.querySelector(".cpFeed"), // Get's the first of any element with a class of cpFeed
cardDivs = feedDiv.querySelectorAll(".card-news") // Get's all of any element, children of feedDiv, with a class of card-news
// unnamedDiv, – Removed to be assigned per cardDiv later
// i, – Removed because for loop is swtiched to forEach()
// txtValue – Removed to be assigned per cardDiv later
// New forEach() instead of for loop
cardDivs?.forEach((cardDiv) => {
// Adding variables as const since they do not change
const unnamedDivs = cardDiv.querySelectorAll(".d-none") // Gets all of any element, child of the the current cardDiv, with a class d-none
let display = "none" // preset to none
unnamedDivs?.forEach((unnamedDiv) => {
// Checks whether display has already succeeded in one of the unnamedDivs
if (display !== "none") display = unnamedDiv.textContent.toUpperCase() === filter ? "" : "none"
// Always returns something
cardDiv.style.display = display
})
})
}
如您所见,我在这里做了一些事情来简化代码,使其更具可读性,并添加了一些安全检查,因此我们尽可能避免了错误。
我还注意到您的 HTML 中存在一些错误:
<!-- Two class attributes will break things -->
<!-- BEFORE: <div class="card-news" class="d-none"> -->
<div class="card-news">
<div style="display: none;" class="d-none">Employee</div>
<div style="display: none;" class="d-none">Seasonal</div>
<div>Christina</div>
</div>
<!-- Two class attributes will break things -->
<!-- BEFORE: <div class="card-news" class="d-none"> -->
<div class="card-news">
<div style="display: none;" class="d-none">Part Time</div>
<div style="display: none;" class="d-none">Employee</div>
<div>Cindy</div>
</div>
我还制作了一个 CodePen,因此您可以看到它的实际效果:转到 CodePen
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.