I am trying to get the the first element with a specific class which follow the element clicked with pure JS (no JQuery) in the following way but get el.nextSibling is not a function error. Initially I was using JQuery parents().next() but would like to do this with pure JS:
const togglers = document.querySelectorAll('.toggler'); //console.log(togglers); togglers.forEach(function(el) { el.addEventListener('click', function(e) { //const content = el.innerHTML; //console.log(content); el.nextSibling('.folder-content').style.display = 'block'; }) });
<div class="folder"> <div class="toggler">Click me 1</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div> <div class="folder"> <div class="toggler">Click me 2</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div>
Any help would be appreciated :)
nextElement
is a property, not a function, so you don't use ()
with it. That said, using nextSibling
can give you white space content which you don't want. Instead you can use nextElementSibling
:
el.nextElementSibling.style.display = 'block';
const togglers = document.querySelectorAll('.toggler'); //console.log(togglers); togglers.forEach(function(el) { el.addEventListener('click', function(e) { //const content = el.innerHTML; //console.log(content); el.nextElementSibling.style.display = 'block'; }) });
<div class="folder"> <div class="toggler">Click me 1</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div> <div class="folder"> <div class="toggler">Click me 2</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div>
You can add a while
loop to go searching for the first nextSibling
that matches your criteria.
edit: As @j08691 points out, if your real code only cares about elements and not other node types, you can use nextElementSibling.
const togglers = document.querySelectorAll('.toggler'); //console.log(togglers); togglers.forEach(function(el) { el.addEventListener('click', function(e) { var nextSibling = el.nextSibling; while (nextSibling) { if ( nextSibling.nodeType == Node.ELEMENT_NODE && nextSibling.classList.contains('folder-content') ) { nextSibling.style.display = 'block'; break; } nextSibling = nextSibling.nextSibling; } }) });
<div class="folder"> <div class="toggler">Click me 1</div> <div>not this</div> <div>not this</div> <div class="folder-content" style="display: none"> Lorem ipsum 1! </div> <div>not this</div> <div class="toggler">Click me 1.5</div> <div>not this</div> <div class="folder-content" style="display: none"> Lorem ipsum 1.5! </div> <div>not this</div> <div>not this</div> </div> <div class="folder"> <div class="toggler">Click me 2</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div> <div class="folder"> <div class="toggler">Click me 3</div> <div>no folder content here!</div> </div>
I was building this answer while the others were coming in and, in the interest of variety and neat DOM programming, here's another way to skin this cat:
Here is the initial code that you have provided with a call to a separate function to do what was requested(find the next sibling matching a specified query string)
const togglers = document.querySelectorAll('.toggler');
togglers.forEach(function(el, i) {
el.addEventListener('click', function(e) {
searchNextSiblings(el, ".folder-content", function(ele) {
ele.style.display = "block";
});
})
});
You'll notice that the function I am providing is called searchNextSiblings
and it takes three parameters:
Here is the function itself:
function searchNextSiblings(ele, q, fn) {
let flag = false;
const nodeIterator = document.createNodeIterator(
ele.parentNode,
NodeFilter.SHOW_ELEMENT,
function(node) {
if (ele.isSameNode(node)) flag = true;
if (!flag) return NodeFilter.FILTER_REJECT;
else {
if (node.matches(q)) {
flag = false;
return NodeFilter.FILTER_ACCEPT
};
}
});
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
fn(currentNode);
}
}
And here is the annotated version:
function searchNextSiblings(ele, q, fn) {
// we want to search from the first Element provided
// to properly search we will set our crawler to begin
// from its parent node, and when we reach the first Element
// we will begin searching for the Query String
// in order to do this we declare a flag to False
// when we reach the first Element we will set it as True
// This will let us know when we can search for the Matching Query
let flag = false;
const nodeIterator = document.createNodeIterator(
ele.parentNode, //root to search from
NodeFilter.SHOW_ELEMENT, //set the iterator to search for elements
function(node) {
if (ele.isSameNode(node)) flag = true;
//if we've found the first Element, set the flag to True
if (!flag) return NodeFilter.FILTER_REJECT;
//if the flag is False, continue searching for first Element
else {
//if we have found the first Element,
//we are now searching for the Element that Matches the Query
if (node.matches(q)) {
//if we find a matching element
flag = false;
//set the flag to false to stop the search
return NodeFilter.FILTER_ACCEPT
//return the found node
};
}
});
// the above declares the node iterator
// but does not start it up
let currentNode;
while (currentNode = nodeIterator.nextNode()) {
fn(currentNode);
}
//the above "starts up" the nodeIterator
}
const togglers = document.querySelectorAll('.toggler'); togglers.forEach(function(el, i) { el.addEventListener('click', function(e) { searchNextSiblings(el, ".folder-content", function(ele) { ele.style.display = "block"; }); }) }); function searchNextSiblings(ele, q, fn) { let flag = false; const nodeIterator = document.createNodeIterator( ele.parentNode, NodeFilter.SHOW_ELEMENT, function(node) { if (ele.isSameNode(node)) flag = true; if (!flag) return NodeFilter.FILTER_REJECT; else { if (node.matches(q)) { flag = false; return NodeFilter.FILTER_ACCEPT }; } }); let currentNode; while (currentNode = nodeIterator.nextNode()) { fn(currentNode); } }
<div class="folder"> <div class="toggler">Click me 1</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div> <div class="folder"> <div class="toggler">Click me 2</div> <div class="folder-content" style="display: none"> Lorem ipsum </div> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.