Reputation: 143
I've searched for same questions and found only jQuery solutions but I'd like to make it using JS only.
I have multiple div
s with same class name and multiple a
tags. I want the info show up when user press on a
element associated with div
.
Here's my function. I've created 2 loops: one for a
elements and second is for div
s.
function toggle() {
var ele = document.getElementsByClassName("toggleText");
var btn = document.getElementsByClassName("displayText");
for(var i=0; i<btn.length; i++){
for(var j=0; j<ele.length; j++){
btn[i].onclick = function(){
if(ele[j].style.display == "none") {
ele[j].style.display = "block";
}
else {
ele[j].style.display = "block";
}
}}}}
.displayText {
display: none;
}
<a class='toggleText' href="javascript:toggle();">Show1</a>
<div class='displayText'>
Text1
</div>
<a class='toggleText' href="javascript:toggle();">Show2</a>
<div class='displayText'>
Text2
</div>
<a class='toggleText' href="javascript:toggle();">Show3</a>
<div class='displayText'>
Text3
</div>
<a class='toggleText' href="javascript:toggle();">Show4</a>
<div class='displayText'>
Text4
</div>
What's wrong with my code?
Upvotes: 1
Views: 4878
Reputation: 43863
EDIT
@cirix has brought to my attention that my original code breaks because of the use of nextElementSibling
without the necessary precautions to terminate the sibling chain. As it was before the edit if the last div was clicked it nextElementSibling
would report a null since the last element would never have a next sibling (that's what makes last ...last).
There are 2 changes:
event.target
s dealt with are <a>
nchors, thereby fixing the issue.classList.add/remove
and replaced them with classList.toggle()
, that's an improvement, not a fix.Use event delegation by wrapping all of your elements in one element. Then register the click event on it. With a little more setup you'll be able to control as many links as you want with just one eventListener. Details commented in Snippet.
SNIPPET
// Reference the parent element
var main = document.getElementById('main');
/* Register main to the click event
|| when clicked ANYWHERE within main
|| toggle() is called
*/
main.addEventListener('click', toggle, false);
function toggle(e) {
/* Determine if the current element in the
|| event chain is the anchor that was
|| clicked.
*/
if (e.target !== e.currentTarget && e.target.nodeName === "A") {
/* tgt is the clicked link
|| txt is the div that follows tgt
*/
var tgt = e.target;
var txt = tgt.nextElementSibling;
// Toggle classes .on and .off
txt.classList.toggle('on');
txt.classList.toggle('off');
}
}
.off {
display: none;
}
.on {
display: inline-block;
}
<section id='main'>
<a class='toggleText' href="#/">Show1</a>
<div class='displayText off'>
Text1
</div>
<a class='toggleText' href="#/">Show2</a>
<div class='displayText off'>
Text2
</div>
<a class='toggleText' href="#/">Show3</a>
<div class='displayText off'>
Text3
</div>
<a class='toggleText' href="#/">Show4</a>
<div class='displayText off'>
Text4
</div>
</section>
Upvotes: 1
Reputation: 14257
Add an EventListener to the parent container and detect which link was clicked and show/hide its next sibling div:
var linkClass = 'toggleText';
var textClass = 'displayText';
var visibilityClass = '-isVisible';
var container = document.querySelector('.container');
container && container.addEventListener('click', function(event) {
var target = event.target;
if(target.classList.contains(linkClass)) {
var sibling = target.nextElementSibling;
if(sibling && sibling.classList.contains(textClass)) {
sibling.classList.toggle(visibilityClass, !sibling.classList.contains(visibilityClass));
}
}
});
.displayText {
display: none;
}
.displayText.-isVisible {
display: inline-block;
}
<div class="container">
<a class='toggleText' href="javascript:void(0);">Show1</a>
<div class='displayText'>
Text1
</div>
<a class='toggleText' href="javascript:void(0);">Show2</a>
<div class='displayText'>
Text2
</div>
<a class='toggleText' href="javascript:void(0);">Show3</a>
<div class='displayText'>
Text3
</div>
<a class='toggleText' href="javascript:void(0);">Show4</a>
<div class='displayText'>
Text4
</div>
</div>
Upvotes: 1