I want to individually toggle to different divs using the same function. Each of these divs has a common class and a different id. The function toggle is called using an onclick parameter on two separate <a> elements:
<a class="btn" id="btnOne" onclick="toggler();">Show/hide divOne</a>
<div class="box" id="divOne">
<a class="btn" id="btnTwo" onclick="toggler();">Show/hide divTwo</a>
<div class="box" id="divTwo">
I first tried to get these divs with getElementsByClassName but, as it returns an HTMLCollection, the script can't target each div individually.
So I tried to select the <a> tags ids (btnOne and btnTwo), but couldn't figure out how to retrieve the divs class using these ids (as we're talking about two different elements here).
In the end, I came back to the getElementById method, as I couldn't figure out how to select them based on their class:
function toggler() {
var id = document.getElementById("divId");
if (id.style.display === "none") {
id.style.display = "block";
} else {
id.style.display = "none";
}
};
This leaves me with two functions instead of just one. Any suggestion on how to target the two divs individually?
You can access the next sibling using nextElementSibling presuming the box will always be right after the hyperlink.
// Put the buttons into an array
const buttons = [...document.getElementsByClassName("btn")];
// Assing an event listener for every button
buttons.map(button => button.addEventListener("click", function(e) {
// Find the next sibling
const box = e.target.nextElementSibling;
// Toggle the display value
if (box.style.display === "none") {
box.style.display = "block";
} else {
box.style.display = "none";
}
}));
a {
display: block;
}
.box {
width: 5rem;
height: 2rem;
background-color: blue;
}
<a class="btn">Show/hide divOne</a>
<div class="box"></div>
<a class="btn">Show/hide divTwo</a>
<div class="box"></div>
There is a simple way to select the divs with their class name and you already used it.
The answer is getElementsByClassName. But in vanilla JS things are a little bit (over)complicated.
It will not target both divs individually. Instead, if you want to select the first div with this class you would do it like this:
getElementsByClassName('classname')[0]
If you want to select the second div you would use:
getElementsByClassName('classname')[1]
and so on. But there is a way of course.
You want to use loops:
var x = document.getElementsByClassName("classname");
for (var i = 0; i < x.length; i++) {
if (x[i].style.display === "none") {
x[i].style.display = "block";
} else {
x[i].style.display = "none";
}
}
In this way, you will target ALL divs with this class.
I'd dynamically add the events on the switches, using their classes. I added the class showHideDivBtn to them. To make sure you know which div you have to toggle, I used a data-id.
With addEventListener, I can use the event variable I named e. With this one, I have access to properties, such as the data-id I wrote.
let buttons = document.getElementsByClassName("showHideDivBtn");
for (let i = 0; i < buttons.length; ++i)
{
buttons[i].addEventListener('click', function(e)
{
let divToToggle = document.getElementById(e.srcElement.dataset.id);
if (divToToggle.style.display === "none")
divToToggle.style.display = "block";
else
divToToggle.style.display = "none";
});
}
<a class="btn showHideDivBtn" data-id="divOne" id="btnOne">Show/hide divOne</a>
<div class="box" id="divOne">One</div>
<br />
<a class="btn showHideDivBtn" data-id="divTwo" id="btnTwo">Show/hide divTwo</a>
<div class="box" id="divTwo">Two</div>
Use substr to get the word after extracting 'btn' from anchor id which will result in One or Two then while defining the if use "div"+word this will get the div by it is related a tag
function toggler() {
var word=this.id.substr(3);
var id = document.getElementById("div"+word);
if (id.style.display === "none") {
id.style.display = "block";
} else {
id.style.display = "none";
}
};
Related
I want to simplify this code
let a = document.querySelector(".arrow");
b = document.querySelector(".demo-desc1");
c = document.querySelector(".demo-title h3");
a.style.display = "none";
b.style.display = "none";
c.style.display = "none";
so I don't have to write style.display = "none" for every variable but rather to apply the propery for all variables at once.
Thank you.
If there's only one element of each in the DOM, put them all into a selector string, then iterate over the matching elements.
for (const elm of document.querySelectorAll('.arrow, .demo-desc1, .demo-title h3')) {
elm.style.display = 'none';
}
If there are multiple such elements, then you'll need
const selectors = ['.arrow', '.demo-desc1', '.demo-title h3'];
for (const s of selectors) {
document.querySelector(s).style.display = 'none';
}
But, in this sort of situation, an even better approach would be to toggle a class of a parent container, and have CSS rules that hide those elements when the class is on the parent container. I don't know what the rest of your HTML is like, but perhaps something like
<div class="demo-container">
<more HTML here>
</div>
.hide-children .arrow, .hide-children .demo-desc1, .hide-children .demo-title h3 {
display: none;
}
Then all you need is
document.querySelector('.demo-container').classList.add('hide-children');
I'm new to JS, but I was hoping there might be a selector like document.getElementsByClassName("div:not(div-1)") that selects elements by class name, unless they also have another class name, that I can define.
Basically my project is a list of movies and their genres.
Using an onclick function, if you click on a genre, I'm trying to hide all other movies that don't belong to that genre. Now I'm looking for a way to select the DIVs without having to add a "not-comedy", "not-action", etc… class to every single movie.
So far I got this:
function test() {
var x = document.getElementsByClassName("movie-div");
var i;
for (i=0; i < x.length; i++) {
if (x[i].style.display === "none") {
x[i].style.display = "block";
} else {
x[i].style.display = "none";
}
}
}
Use querySelectorAll with i.e: the :not() selector
const ELS_x = document.querySelectorAll(".x:not(.zzz)");
ELS_x.forEach(EL => {
// do something with EL
EL.classList.toggle("active");
});
.active {background: gold;}
<div class="x">a</div>
<div class="x zzz">b</div>
<div class="x">a</div>
or if you want to do the class check inside the loop use classList.contains()
const ELS_x = document.querySelectorAll(".x");
ELS_x.forEach(EL => {
if (!EL.classList.contains("zzz")) {
// do something with NON .zzz Elements
EL.classList.toggle("active");
}
});
.active {background: gold;}
<div class="x">a</div>
<div class="x zzz">b</div>
<div class="x">a</div>
if you want to filter out some Elements, use .filter()
const ELS_x = document.querySelectorAll(".x");
const ELS_without_zzz = [...ELS_x].filter(EL => !EL.classList.contains("zzz"));
ELS_without_zzz.forEach(EL => {
// do something with NON .zzz Elements
EL.classList.toggle("active")
});
.active {background: gold;}
<div class="x">a</div>
<div class="x zzz">b</div>
<div class="x">a</div>
Javascript newbie here. This is basically what I'm working with.
The function below is intended to hide everything enclosed in the newsDisplay class, but nothing happens when clicking the button that calls it.
function showHide() {
var x = document.getElementsByClassName('newsDisplay');
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
.newsDisplay {
display: block;
}
<h1>News<button onclick="showHide();"><img src="..\Images\showHide.png"></button></h1>
<div class="newsDisplay">
<div class="bodyBox">
<h2>Diablo 3</h2>
TEXT/PARAGRAPHS
</div>
</div>
Manually changing display: block; to display: none; behaves exactly as expected, so either the syntax or logic of the function is incorrect, or something is preventing the function from executing when clicking the button.
Could really use some help, thank you!
Try the first element of this class as follows
var x = document.getElementsByClassName('newsDisplay')[0];
Document document.single getElementsByClassName() will return an array of elements with the same class. It is different from document.getElementById() in so far as the latter returns a DOM object rather than an array of DOM objects.
As stated from it's name getElementsByClassName get elements (and not single element), so result of this function call is a collection of elements.
To access to first element of collection you can:
x = document.getElementsByClassName('newsDisplay')[0];
// or
X = document.getElementsByClassName('newsDisplay').item(0);
You can try a loop if you want multiple of the page. The key is you're grabbing a list of elements with the class, since classes aren't unique identifiers. You can either use my code below or switch it to an id and grab it by document.getElementById. Notice the s in document.getElementsByClassName
var x = document.getElementsByClassName('newsDisplay');
function showHide() {
for (var i = 0; i < x.length; i++){
x[i].style.display === 'none'
? x[i].style.display = 'block'
: x[i].style.display = 'none';
}
}
<h1>News<button onclick="showHide();"><img src="..\Images\showHide.png"></button></h1>
<div class="newsDisplay">
<div class="bodyBox">
<h2>Diablo 3</h2>
TEXT/PARAGRAPHS
</div>
</div>
<h1>News<button onclick="showHide();"><img src="..\Images\showHide.png"></button></h1>
<div class="newsDisplay">
<div class="bodyBox">
<h2>Diablo 3</h2>
TEXT/PARAGRAPHS
</div>
</div>
Try the code below.
Use this
var x = document.getElementsByClassName('newsDisplay')[0];
function showHide() {
var x = document.getElementsByClassName('newsDisplay')[0];
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
.newsDisplay {
display: block;
}
<h1>News<button onclick="showHide();"><img src="..\Images\showHide.png"></button></h1>
<div class="newsDisplay">
<div class="bodyBox">
<h2>Diablo 3</h2>
TEXT/PARAGRAPHS
</div>
</div>
If you hit F12, navigate to the sources tab (on google chrome) you can set a breakpoint on your javascript function, your code is running, but you are getting a
Uncaught TypeError: Cannot read property 'display' of undefined
The reason for this is getElementsByClassName is returning a list of elements with that class selector, not just the one. If you want to just do this to the first element you can simply do:
function showHide() {
var x = document.getElementsByClassName('newsDisplay')[0];
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
}
my html code:
<div class="mydiv" onclick="clickonelement()">div1</div>
<div class="mydiv" onclick="clickonelement()">div2</div>
<div class="mydiv" onclick="clickonelement()">div3</div>
<div class="mydiv" onclick="clickonelement()">div4</div>
<div class="mydiv" onclick="clickonelement()">div5</div>
<div class="mydiv" onclick="clickonelement()">div6</div>
<!-- javascript code -->
function clickonelement(){
mydiv = document.getElementsByClassName("mydiv");
for(i=0; i<mydiv.length; i++){
mydiv.item(i).style.backgroundColor = "red";
mydiv[this].style.backgroundColor = "#fff";
}
}
css code
.mydiv{width:300px; height:30px;}
I want on onClick event to change clicked element's background to white and other elements background remain red in color but my code
mydiv[this].style.backgroundColor = "#fff";
is not working. please solve this problem in JavaScript only. I am in basic stage of JavaScript.
You need to pass a reference to the element that you want to refer to with this, e.g. onclick="clickonelement(this)":
function clickonelement(elem) {
mydiv = document.getElementsByClassName("mydiv");
for (i = 0; i < mydiv.length; i++) {
mydiv.item(i).style.backgroundColor = "red";
elem.style.backgroundColor = "#fff";
}
}
<div class="mydiv" onclick="clickonelement(this)">div1</div>
<div class="mydiv" onclick="clickonelement(this)">div2</div>
<div class="mydiv" onclick="clickonelement(this)">div3</div>
<div class="mydiv" onclick="clickonelement(this)">div4</div>
<div class="mydiv" onclick="clickonelement(this)">div5</div>
<div class="mydiv" onclick="clickonelement(this)">div6</div>
This is JS code for your HTML code, you need add addEventListener.
function clickonelement() {
mydiv = document.getElementsByClassName("mydiv");
for (var i = 0; i < mydiv.length; i++) {
mydiv[i].addEventListener('click', function() {
this.style.backgroundColor = "red";
this.style.backgroundColor = "#fff";
});
}
}
Here is just another way of achieving the same functionality.
Objective
To remove inline event handler
Use loop only once instead of looping over all the matched class name (mydiv) on every click.
Used javascript functions & concepts
querySelectorAll : - Used to select all matched elements with same class that is mydiv. It will return an nodelist containing all matched elements
forEach:- is an array method which used to loop over list.It accepts three arguments. For this case two will be enough.
addEventListener:- Is use to attach event to an element
Closures:These functions 'remember' the environment in which they were created.
Hope this snippet will be useful
//Get all the matched Elements
var matches = document.querySelectorAll("div.mydiv");
//Use an variable to rememeber previous clicked element
var prevIndex = -1; //
// Loop over the list
matches.forEach(function(item,index){
(function(i){ // A closure is created
item.addEventListener('click',function(){
// if any previous element was clicked then rest it's background
if(prevIndex !== -1){
matches[prevIndex].style.background="red";
}
// change background of current element
item.style.background="#fff";
// update prevIndex
prevIndex = i;
})
}(index))
})
Check this DEMO
I have multiple divs that are switched using this javascript
<script language="JavaScript">
//here you place the ids of every element you want.
var ids = new Array('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'a10');
function switchid(id) {
hideallids();
showdiv(id);
}
function hideallids() {
//loop through the array and hide each element by id
for (var i = 0; i < ids.length; i++) {
hidediv(ids[i]);
}
}
function hidediv(id) {
//safe function to hide an element with a specified id
if (document.getElementById) { // DOM3 = IE5, NS6
document.getElementById(id).style.display = 'none';
}
else {
if (document.layers) { // Netscape 4
document.id.display = 'none';
}
else { // IE 4
document.all.id.style.display = 'none';
}
}
}
function showdiv(id) {
//safe function to show an element with a specified id
if (document.getElementById) { // DOM3 = IE5, NS6
document.getElementById(id).style.display = 'block';
}
else {
if (document.layers) { // Netscape 4
document.id.display = 'block';
}
else { // IE 4
document.all.id.style.display = 'block';
}
}
}
</script>
Then each div has some option (yes,no,continue,etc..) that switches from one div to another
<div id='a1' style="display:block;">
<div style="border-bottom: 1px solid black;margin-left: auto; margin-right: auto;text-align: center;">
<i>"I'm sorry to hear you have lost your card. I can cancel the lost card for your proection."</i><br />
<b>Find the most recent card by checking it's ISSUE date.</b><br /><br />
</div>
<div style="margin-left: auto; margin-right: auto;text-align: center;">
<span style="color:red;">Has the card been deactivated already?</span><br /><br />
<a class="spl_btn btn_green" href="javascript:switchid('a2');" onclick="document.getElementById('back').href='javascript:switchid(\'a1\');';"><span><span>Yes</span></span></a>
<a class="spl_btn btn_pink" href="javascript:switchid('a3');" onclick="document.getElementById('back').href='javascript:switchid(\'a1\');';"><span><span>No</span></span></a>
</div>
</div>
Then outside of the switching divs i have a back button. If you can see from above when you choose an option it changes to the corresponding div and then switches the back buttons href value. Now my only problem is I have 2 divs (numbers 3 and 4) that both have an option (no in this case) that lead to either 5 or 6. This specific button I have in a php variable like so
<?php echo $addr_update; ?>
Then the variables them self work like this
$project_id = $_GET["project_id"];
switch ($project_id) {
case "al":
$addr_update = "<a class=\"spl_btn btn_pink\" href=\"javascript:switchid('a5');\"><span><span>No</span></span></a>";
break;
So there are 32 different variables for this one button. I would like to be able to add an onclick event to the variable that would possibly have it grab its div id and then change the back button accordingly.
For example you are on div 2 and press no which in this case will lead you to div 5 and not div 6. The back button needs to point back to div 2. Because both div 2 and div 3 can lead to either 5 or 6 depending on the variable I cannot just add the onclick event to change the back button without knowing where the user was before.
EDIT: Just to add a little more. If you clicked the option on DIV 2 then it would set the back button to DIV 2. So in my mind if i can grab the DIV ID and then apply it to the href="javascript:switchid('a4');" part of it, it should be simple. kind of like this:
<a class="spl_btn btn_green" href="javascript:switchid('a2');" **onclick="document.getElementById('back').href='javascript:switchid(\'a1\');'; Some sort of function that would grab the containing divs id and then put it in the .href value of the document.getElement part**"><span><span>Yes</span></span></a>
Hope this makes sense and any help would be greatly appreciated.
you could use data-attributes on your divs for knowing where to go on which click:
<div id="div1" data-on-yes="div2" data-on-no="div3"></div>
and so on.
in your script you could then read that attribute
document.getElementById('div1').getAttribute('data-on-yes')
hope that helps, your question is kind of confusing ;-)
Aside from data-attributes you can track current and prev ids
<script type="text/javascript">
//here you place the ids of every element you want.
var ids = ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'a10'];
function switchid(id) {
if(id === current) {return;}
hideallids();
showdiv(id);
current = id;
}
//previous and current id;
var prev, current;
function switchNext() {
var next = this.getAttribute("data-next-id"); //get next id from data-attr
prev = this.parentNode.parentNode.id; //get parent div's id
switchid(next);
}
function switchPrev() { //For back link
if(!prev) {return;}
var curr = current; //store current id
switchid(prev); //switch to what was previous
prev = curr; //set prev to what was current. Not sure if you need this
}
function hideallids() {
//loop through the array and hide each element by id
for (var i = 0; i < ids.length; i++) {
hidediv(ids[i]);
}
}
function hidediv(id) {
document.getElementById(id).style.display = 'none';
}
function showdiv(id) {
document.getElementById(id).style.display = 'block';
}
</script>
Markup
<div id='a1' style="display:block;">
<div style="border-bottom: 1px solid black;margin-left: auto; margin-right: auto;text-align: center;">
<i>"I'm sorry to hear you have lost your card. I can cancel the lost card for your proection."</i><br />
<b>Find the most recent card by checking it's ISSUE date.</b><br /><br />
</div>
<div style="margin-left: auto; margin-right: auto;text-align: center;">
<span style="color:red;">Has the card been deactivated already?</span><br /><br />
<a class="spl_btn btn_green" data-next-id="a2" href="#" onclick="switchNext.call(this);"><span><span>Yes</span></span></a>
<a class="spl_btn btn_pink" data-next-id="a3" href="#" onclick="switchNext.call(this);"><span><span>No</span></span></a>
</div>
</div>
And for back button
<a id="back" onclick="switchPrev.call(this);" href="#">Back</a>