I got problem with my accordion script. I'm trying to create accordion looking like this in screen
var accordionItem = document.querySelectorAll('.accordion-item');
var accordionContent = document.querySelectorAll('.accordion-item_content');
var accordionButton = document.querySelectorAll('.accordion-btn');
for (i = 0; i < accordionButton.length; i++) {
accordionButton[i].addEventListener('click', () => {
accordionContent[i].classList.add('opnen')
})
}
<div class="accordion-item">
<div class="accordion-item_header">
<h3>Experience</h3>
<button class="accordion-btn">+</button>
</div>
<div class="accordion-item_content container">
</div>
</div>
After click on my button i got console error
I want to open my content box after clicking only button in accordion header div. How to do it?
Issue:
Your i variable is globallly scoped, therefore at the time you click it — its value already incremented to 1 - and there's no such accordionContent[1] element.
Solution:
Scope your variable using the let keyword: let i = 0;
var accordionItem = document.querySelectorAll('.accordion-item');
var accordionContent = document.querySelectorAll('.accordion-item_content');
var accordionButton = document.querySelectorAll('.accordion-btn');
for (let i = 0; i < accordionButton.length; i++) {
accordionButton[i].addEventListener('click', () => {
accordionContent[i].classList.add('open');
});
}
.accordion-item_content { display: none; }
.accordion-item_content.open { display: block; }
<div class="accordion-item">
<div class="accordion-item_header">
<h3>Experience</h3>
<button class="accordion-btn" type="button" aria-label="Toggle content">+</button>
</div>
<div class="accordion-item_content container">content here</div>
</div>
Anyways, I might suggest you another way to implement the desired, and that's by using data-* attribute selectors like in this related answer: Toggle elements on buttons click or Dropdown Menu Toggle
Or by using the Details element
<details>
<summary>Experience</summary>
content here
</details>
Related
I want to show div content on button click .and thee is 3 different button following 3 different content. I tried this logic and it made my code lengthy. how to simplify is code using loop or condition?
function replace1(){
document.getElementById("con1").style.visibility="visible";
document.getElementById("con2").style.visibility="hidden";
document.getElementById("con3").style.visibility="hidden";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
function replace2(){
document.getElementById("con1").style.visibility="hidden";
document.getElementById("con2").style.visibility="visible";
document.getElementById("con3").style.visibility="hidden";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
function replace3(){
document.getElementById("con1").style.visibility="hidden";
document.getElementById("con2").style.visibility="hidden";
document.getElementById("con3").style.visibility="visible";
document.getElementById("con4").style.visibility="hidden";
document.getElementById("con5").style.visibility="hidden";
document.getElementById("con6").style.visibility="hidden";
}
enter image description here
.active-button {
background: red;
}
<button class="replace-button" onclick="replace(1, this)"></button>
<button class="replace-button" onclick="replace(2, this)"></button>
<button class="replace-button" onclick="replace(3, this)"></button>
function replace(visibleIndex, _this) {
const buttons = document.querySelectorAll('.replace-button');
buttons.forEach(button => button.classList.remove("active-button"));
_this.classList.add("active-button");
for(let i = 1; i < 7; i++) {
let element = document.getElementById("con" + i)
i === visibleIndex ? element.style.visibility = "visible" : element.style.visibility = "hidden";
}
}
Use a class - add class="con" to each element - also use hidden instead of visibility since the hidden divs still will take up space
const toggle = id => cons
.forEach(con => con.hidden = con.id !== id);
Here is a version that will change the colour of the button too.
You will need to use hidden or display:none to have the divs stay in one place
window.addEventListener('DOMContentLoaded', function() {
const cons = document.querySelectorAll('.con');
const buts = document.querySelectorAll('.toggle');
const toggle = id => cons
.forEach(con => con.hidden = con.id !== id);
document.getElementById('nav').addEventListener('click', function(e) {
const tgt = e.target.closest('button');
if (tgt.classList.contains('toggle')) {
toggle(tgt.dataset.id)
buts.forEach(but => but.classList.remove('active'));
tgt.classList.add('active');
}
})
})
.active {
background-color: green;
}
<nav id="nav">
<button type="button" class="toggle" data-id="con1">Con 1</button>
<button type="button" class="toggle" data-id="con2">Con 2</button>
<button type="button" class="toggle" data-id="con3">Con 3</button>
</nav>
<div id="con1" class="con" hidden>
<h1>Con 1</h1>
</div>
<div id="con2" class="con"hidden>
<h1>Con 2</h1>
</div>
<div id="con3" class="con" hidden>
<h1>Con 3</h1>
</div>
as a JS noob I'm stuck right now and would highly appreciate some help. My goal is to have a JS pagebrowser that works with content generated by my CMS (TYPO3). Content of different pages is rendered in divs with speaking ids; below you have links to these anchors plus a "show all" link. When you klick on a link to a "page" the respective page content div is shown and the others are hidden; if you click on "show all" all the page content divs are shown. However, if I click a page link after having clicked "show all" not all of the other page content divs are hidden as they should. I guess it has something to do with JS processing order but couldn't find out so far.
window.onload = function () {
var pagelinks = document.querySelectorAll("a.subpage-toggle");
for (var i = 0; i < pagelinks.length; i++) {
pagelinks[i].onclick = function () {
// Finding all elements of class 'active' (creates an array of results)
let x = document.getElementsByClassName("active");
// If class 'active' exists, remove it.
if (x.length > 0) {
x[0].classList.remove("active");
}
if ((this.href.split("#")[1]) !== "show-all") {
// add class 'active' if ID matches href of link
document.querySelector("#" + this.href.split("#")[1]).classList.add("active");
} else {
var subpagecontents = document.getElementsByClassName("subpage-content"),
len = subpagecontents !== null ? subpagecontents.length : 0,
j = 0;
for (j; j < len; j++) {
subpagecontents[j].classList.add("active");
}
}
};
}
};
.subpage-toggle {
display: block;
}
.subpage-content {
display: none;
}
.subpage-content.active {
display: block;
}
<div class="main">
<div id="name-of-page-one" class="subpage-content active">
<p>
Content Page 1
</p>
</div>
<div id="page-two-is-cool" class="subpage-content">
<p>
Content Page 2
</p>
</div>
<div id="nickname-of-page-three" class="subpage-content">
<p>
Content Page 3
</p>
</div>
<div class="pageoverview">
<ul>
<li><a class="subpage-toggle" href="#name-of-page-one">Name of page one</a></li>
<li><a class="subpage-toggle" href="#page-two-is-cool">Page two is cool</a></li>
<li><a class="subpage-toggle" href="#nickname-of-page-three">Nickname of page three</a></li>
</ul>
<a class="subpage-toggle" href="#show-all">Show all</a>
</div>
</div>
JSFiddle: https://jsfiddle.net/Jaydot/62cx5sh0/14/
You need to hide all the previous showing instead of just the first one:
Instead of
x[0].classList.remove("active");
do:
Array.from(x).forEach((element) => element.classList.remove("active"));
https://jsfiddle.net/nvg2aojb/
I know this has been asked, but I cannot figure out how to fix my issue. I have 2 buttons a drink menu and a food menu. I'm able to correctly show the different menus show when their button is clicked. However when the page loads the drink menu appears below the food menu. Once I click food menu buttons the drink menu disappears,and the buttons function as you would expect ie. one menu is shown while the other one is not. I'm not sure what the best method is to hide the drink menu. Any help would be much appreciated.
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu">
<h1>Drink Menu</h1>
</div>
var divs = [ "foodMenu", "drinkMenu" ];
function toggle(layer) {
var d
for(var i = 0; i < divs.length; i += 1) {
d = document.getElementById(divs[i]);
d.style.display = 'none';
}
}
I rewrote your script some. I used a class of menu to reference the divs and to set them default to be hidden.
Its also setup to hide any div not selected but only show the selected div.
var divs = [ "foodMenu", "drinkMenu" ];
function toggle(layer) {
var _menus = document.getElementsByClassName("menu");
for(var i = 0; i < _menus.length; i++) {
_menu = _menus[i];
_menu.style.display = 'none';
}
var _menu = document.getElementById(layer);
_menu.style.display = 'block';
}
.menu{
display:none;
}
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div class="menu" id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div class="menu" id="drinkMenu">
<h1>Drink Menu</h1>
</div>
You can toggle by default the food menu, so every time you click a button, you color its text with red, so you know it is selected: its corresponding menu block will show.
Your HTML code:
<button onclick="javascript:toggle('foodMenu')" class="btnMenu" id="foodMenu-btn">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu" id="drinkMenu-btn">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu">
<h1>Drink Menu</h1>
</div>
Your JavaScript code:
// available menu divs
let divs = ["foodMenu", "drinkMenu"];
function toggle(layer) {
// reset all buttons and divs
for (let i = 0; i < divs.length; i += 1) {
let d = document.getElementById(divs[i]);
d.style.display = 'none';
// reset all buttons text colors
let b = document.getElementById(divs[i] + '-btn');
b.style.color = 'black';
}
// set current menu visible
let menu = document.getElementById(layer);
menu.style.display = 'block';
// set current menu button colored "red"
let btn = document.getElementById(layer + '-btn');
btn.style.color = 'red';
}
// select food menu by default
toggle('foodMenu')
I added style="display:none" to the second div in your first block of code. So when the page loads it will display the food Menu.
<button onclick="javascript:toggle('foodMenu')" class="btnMenu">Food</button>
<button onclick="javascript:toggle('drinkMenu')" class="btnMenu">Drink</button>
<div id="foodMenu">
<h1 class="menuHD">Food Menu</h1>
</div>
<div id="drinkMenu" style="display:none">
<h1>Drink Menu</h1>
</div>
For the javascript part use the following code. It will toggle between displaying the food and drink menu.
function toggle(layer) {
const hidingDiv = (layer == 'foodMenu') ? 'drinkMenu' : 'foodMenu';
document.getElementById(layer).style.display = 'block';
document.getElementById(hidingDiv).style.display = 'none';
}
Here is the concept of my content being shown/hidden. It also works.
https://jsfiddle.net/mplungjan/a7Lfjsgh/
It works in the small html code above. However, it does not work when I apply it to my larger HTML code. Does someone know why?
My goal is to have many list items with spans attached to the reveal answers button.
HTML:
<nav class="Rightbox" id="RightFrench">
<div id="Stage1">
<h1>Stage 1</h1>
<h5> <span class="HighlightBlue">Exercise 1 - </span></h5>
<h5><button class="AnswerTitle" id="AnswersFrenchStage1Ex1">Reveal Answers</button></h5>
<p class="Task">
<span class="HighlightBlue">Translate the following</span>
</p>
<ul>
<li>
<p> the passeport <textarea></textarea>
<span class="FrenchStage1Ex1">la passeport</span>
</p>
</li>
<li>
<p>the passeport <textarea></textarea>
<span class="FrenchStage1Ex1">la passeport</span>
</p>
</li>
</div>
</nav>
Javascript:
window.onload = function() {
var buttons = document.querySelectorAll(".AnswerTitle");
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
var id = this.id.replace(/reveal/, "FrenchStage");
var answers = document.querySelectorAll("." + id);
for (var i = 0; i < answers.length; i++) {
answers[i].style.display = answers[i].style.display == "inline" ? "none" : "inline";
}
}
}
}
CSS:
.Rightbox ul li p span {display:none;}
the problem turns out to be I changed the id of the button, thinking that the javascript was not using the button id. turns out the
var id = this.id.replace(/reveal/, "FrenchStage")
really wanted the button to have an ID containing "reveal"
My HTML
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">button</button>
My js
var button = document.querySelector('#button');
var chapter = document.querySelectorAll('.chapter');
for(var i = 0; i < chapter.length; i++){
button.addEventListener('click', function(){
for(var i = 0; i < chapter.length; i++) {
chapter[i].classList.add('active');
}
});
}
This adds the class of "active" on clicking the button.
But toggle doesn't work. Instead of
chapter[i].classList.add('active');
When I do,
chapter[i].classList.toggle('active');
the class of "active" does not toggle. console shows no error.
So I tried to check the class of "active" first & remove the class if the class exists. I know I was trying to reinvent the toggle function; as stated above, toggle wasn't working so I tried it anyway.
if (chapter[i].contains('active')){
chapter[i].classList.remove('active');
And I got a slew of error messages. This is as far as I got. I somehow felt that this wasn't going to work but just tried it anyway.
I am stumped.
Can anyone point out why classList.toggle isn't working in my code & how this can be fixed?
Thanks.
You have one too many loop. Remove the outer one:
var button = document.querySelector('#button');
var chapter = document.querySelectorAll('.chapter');
button.addEventListener('click', function(){
for(var i = 0; i < chapter.length; i++) {
chapter[i].classList.toggle('active');
}
});
.active{
color: red;
}
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">button</button>
var button = document.querySelector('#button');
var chapters = document.querySelectorAll('.chapter');
button.addEventListener('click', function(){
for(var index = 0; index < chapters.length; index++) {
if(chapters[index].classList.contains('active')){
chapters[index].classList.remove('active');
}else{
chapters[index].classList.add('active');
}
}
});
.active {
color: red;
}
<div class="chapter">text text text </div>
<div class="chapter">text text text </div>
<button id="button">Toggle Color</button>