I currently have four divs, which are each linked to a hidden div:
div1 - div1hidden
div2 - div2hidden
div3 - div3hidden
div4 - div4hidden
When a user clicks on one of the divs the hidden div appears. When clicked on again the div disappears.
The problem I have is if all four divs are clicked on all four hidden will appear. What I would like to do is only show one at a time.
For Example if 'div1hidden' is showing and the user clicks on div2 before hiding div1hidden, div1hidden will hide and div2hidden will appear.
This is the code I have so far:
function hide_menu(id){document.getElementById(id).style.display = "none";}
function show_menu(id){document.getElementById(id).style.display = "block";}
<div class="div1" onclick="if (document.getElementById('div1hidden').style.display=='none') show_menu('div1hidden'); else hide_menu('div1hidden');"></div>
<div class="div2" onclick="if (document.getElementById('div2hidden').style.display=='none') show_menu('div2hidden'); else hide_menu('div2hidden');"></div>
<div class="div3" onclick="if (document.getElementById('div3hidden').style.display=='none') show_menu('div3hidden'); else hide_menu('div3hidden');"></div>
<div class="div4" onclick="if (document.getElementById('div4hidden').style.display=='none') show_menu('div4hidden'); else hide_menu('div4hidden');"></div>
Thanks in advance
Rick
Try something like this:
Add a function:
function hide_all() {
hide_menu('div1hidden');
hide_menu('div2hidden');
hide_menu('div3hidden');
hide_menu('div4hidden');
}
Now call that function before you show any hidden div:
<div class="div1" onclick="if (document.getElementById('div1hidden').style.display=='none') {hide_all(); show_menu('div1hidden'); } else { hide_menu('div1hidden'); }"></div>
I'm not sure what's wrong with just hiding all other divs before opening the one your need:
<div class="div1" onclick="if (document.getElementById('div1hidden').style.display=='none') { hide_menu('div2hidden'); hide_menu('div3hidden'); hide_menu('div4hidden'); show_menu('div1hidden');} else hide_menu('div1hidden');"></div>
<!-- and so on -->
I must say that this isn't exactly the best approach to do the comparison in the onclick - instead I suggest putting it inside the function, something like this:
<script type="text/javascript">
function flipDiv(id)
{
var vis = document.getElementById('div' + id + 'hidden').style.display;
if(vis == 'none')
{
document.getElementById('div1hidden').style.display = 'none';
document.getElementById('div2hidden').style.display = 'none';
document.getElementById('div3hidden').style.display = 'none';
document.getElementById('div4hidden').style.display = 'none';
document.getElementById('div' + id + 'hidden').style.display = 'block';
}
else
{
document.getElementById('div' + id + 'hidden').style.display = 'block';
}
}
</script>
...
<div class="div1" onclick="flipDiv(1)">...</div>
...
The easiest way will be to cache the current open menu.
<head>
<script type="text/javascript">
var current = null; //current is stored here
function hide_current(){
if(current !=null){
document.getElementById(current).style.display = "none";
}
}
function show_menu(id){
if(current == id){
hide_current(); //current is already open, close it
current = null; //reset current
} else {
document.getElementById(id).style.display = "block";
current = id;
}
}
</script>
</head>
<body>
<div class="div1" onclick="hide_current();show_menu('div1hidden');"></div>
<div class="div2" onclick="hide_current();show_menu('div2hidden');"></div>
<div class="div3" onclick="hide_current();show_menu('div3hidden');"></div>
<div class="div4" onclick="hide_current();show_menu('div4hidden');"></div>
</body>
Although the other suggested answers will accomplish what you want, none of them are very robust. This is based on the fact that your sample code is not very robust. It relies on inline javascript calls and hard coding to your elements.
Something like this will be easily extendable and less prone to breakage. Please note that some modifications will be necessary to accommodate old versions of IE (attachEvent support and getElementsByClassName support). But the concepts are the important thing.
Basically we get all the parent divs. Attach an event to their click. When they are clicked we hide all the divs that are supposed to be hidden and show the one we want.
http://jsfiddle.net/mrtsherman/8sgC2/2/
var divs = document.getElementsByClassName('menu');
for (var index = 0; index < divs.length; index++) {
divs[index].addEventListener('click', function() {
var contentDiv = null;
//hide all other divs
for (var i = 0; i < divs.length; i++) {
contentDiv = document.getElementById(divs[i].id + 'content');
contentDiv.style.display = 'none';
}
//show current item
contentDiv = document.getElementById(this.id + 'content');
contentDiv.style.display = 'block';
}, false)
}
<div class="menu" id="div1">one</div>
<div class="menu" id="div2">two</div>
<div class="menu" id="div3">three</div>
<div class="menu" id="div4">four</div>
<div class="content" id="div1content">one content</div>
<div class="content" id="div2content">two content</div>
<div class="content" id="div3content">three content</div>
<div class="content" id="div4content">four content</div>
Note that libaries like jQuery can do this in far less code, without having to account for browser differences and with cool effects like sliding or fading in.
http://jsfiddle.net/mrtsherman/8sgC2/3/
//bind to click event on the div
$('.menu').click( function() {
//get content div associated with the clicked div
var contentDiv = $(this).attr('id') + 'content';
//if no items are visible yet then show current
if ($('.content').filter(':visible').length == 0) {
$('#' + contentDiv).slideDown();
return;
}
//hide visible divs and show new div
$('.content').filter(':visible').slideUp('fast', function() {
$('#' + contentDiv).slideDown();
});
});
You can create the Display Div & Hidden div
at the same time and creating the click event in loop
This is source code which you can use to apply for unlimited divs
var n = 10;
var did = 'divDisplay';
var hid = 'divHidden';
function divDisplayOnclick()
{
for(var i=0; i<n; i++)
{
document.getElementById(did+i+hid).style.display = 'none';
}
document.getElementById(this.id+hid).style.display = 'block';
}
function createDivDisplay()
{
for(var i=0; i<n;i++)
{
var divDisplay = document.createElement('div');
divDisplay.id = did+i;
divDisplay.innerHTML = 'Click to display hidden div '+i;
divDisplay.className = did;
divDisplay.onclick = divDisplayOnclick;
document.body.appendChild(divDisplay);
var divHidden = document.createElement('div');
divHidden.id = did+i+hid;
divHidden.innerHTML = 'This is hidden div '+i;
divHidden.className = hid;
document.body.appendChild(divHidden);
}
}
createDivDisplay();
.divDisplay
{
border: 1px solid powderblue;
margin-bottom: 5px;
cursor: pointer;
}
.divHidden
{
border: 1px solid red;
margin-left: 20px;
margin-bottom: 10px;
display: none;
}
Related
I have a div container with a certain number of div's created with a for loop inside of it. When i click one of these a divs, i need to make it change the colour. My problem is can't figure out how to select an specific element with the addEventListener to change the color.
<body>
<div id="main-container"></div>
<script src="script.js"></script>
</body>
const mainContainer = document.getElementById("main-container");
for (let i = 0; i <= 11; ++i) {
const gridChildrens = document.createElement("div");
gridChildrens.setAttribute("class", `gridChildrens`);
const grids = document.querySelector('.gridChildrens')
mainContainer.appendChild(gridChildrens);
}
For the moment, i figure out how to change the color of the firt or the last of the elements with a click listener, but not for the rest of the of the divs.
For the moment, i figure out how to change the color of the firt or the last of the elements with a click listener, but not for the rest of the of the divs.
I expect to click any of the divs and change the color.
Try to add an event listener to each div created in the loop and then use 'this' to set your colour. Here's an example :
const mainContainer = document.getElementById("main-container");
for (let i = 0; i <= 11; ++i) {
const gridChildrens = document.createElement("div");
gridChildrens.setAttribute("class", `gridChildrens`);
gridChildrens.addEventListener('click', function() {
this.style.backgroundColor = 'red';
});
mainContainer.appendChild(gridChildrens);
}
Code snippet sample:
<html>
<head>
<style>
.gridChildrens {
width: 50px;
height: 50px;
background-color: blue;
margin: 10px;
}
</style>
</head>
<body>
<div id="main-container"></div>
<script>
const mainContainer = document.getElementById("main-container");
for (let i = 0; i <= 11; ++i) {
const gridChildrens = document.createElement("div");
gridChildrens.setAttribute("class", `gridChildrens`);
gridChildrens.addEventListener('click', function() {
this.style.backgroundColor = 'red';
});
mainContainer.appendChild(gridChildrens);
}
</script>
</body>
</html>
To explicitly target an element the querySelector without click event (which will inspect the event.target ) you can use the nth-child or nth-of-type style css selector as below.
To identify an element based upon user click the event itself will expose the target property which will be the element that caused the event handler to fire. The following uses a delegated event listener bound to the document itself which processes all click events if required but here responds only to those bound to the gridChildrens elements
const mainContainer = document.getElementById("main-container");
for (let i = 0; i <= 11; ++i) {
const div = document.createElement("div");
div.setAttribute("class", `gridChildrens`);
div.textContent=i;
mainContainer.appendChild( div );
}
document.querySelector('.gridChildrens:nth-of-type(4)').classList.add('banana')
document.querySelector('.gridChildrens:nth-of-type(7)').classList.add('banana')
document.querySelector('.gridChildrens:nth-of-type(10)').classList.add('banana')
document.addEventListener('click',e=>{
if( e.target instanceof HTMLDivElement && e.target.classList.contains('gridChildrens') ){
e.target.classList.toggle('tomato')
}
})
.gridChildrens{
width:50%;
height:1rem;
margin:0.25rem;
}
.banana{
background:yellow
}
.tomato{
background:tomato
}
<div id="main-container"></div>
This should give you a good idea of how to use addEventlistner. Basically, you can pass the event object whenever you make some event. That has all the information of the specific div that you are looking for, you can change anything with that. But remember to bind the elements with addEventlistner first.
var containers= document.getElementsByClassName("container");
const changeColor = (e)=>{
if(e.target.style.background =="orange"){
e.target.style.background ="red"
}
else
e.target.style.background ="orange";
}
for(var i=0; i< containers.length; i++){
containers[i].addEventListener('click',function(e){
changeColor(e)
} );
}
.container{
height:50px;
width:100px;
background: #000;
margin :10px 10px;
border-radius:10px;
cursor:pointer;
}
.holder{
display:flex;
flex-wrap:wrap;
}
<div class="holder">
<div class="container"></div>
<div class="container"></div>
<div class="container"></div>
<div class="container"></div>
<div class="container"></div>
</div>
There are several ways to do this. For example, you can add the same class to your divs inside the loop. Then you can access them via document.querySelectorAll('.class-name'). So smth like this:
[...document.querySelectorAll('.class-name')].forEach( el => {
el.addEventListener('click', (e) => { changeColor(e); });
});
There are 7 links in one div and 7 divs in another. Example https://jsfiddle.net/tania_poltava/2oqtr9v1/
I want, when the first link is hovered to influent on first img, adding class; and with other links.
im triing to do this - getting the number of hovered link, then looking for the div with classname with such number, and try to add new class.
<div class="links">
button1
button2
button3
button4
button5
button6
button7
</div>
<div class="rounds">
<div class="services__round--1"></div>
<div class="services__round--2"></div>
<div class="services__round--3"></div>
<div class="services__round--4"></div>
<div class="services__round--5"></div>
<div class="services__round--6"></div>
<div class="services__round--7"></div>
</div>
.rounds div {
background: grey;
width:40px;
height: 40px;
border-radius: 50%;
}
.services__round--active {
background: green;
}
jQuery(function ($) {
$(document).ready(function() {
var link = $(".links a");
var linkClass = $(link).attr('class');
var linkNumb = linkClass.replace(/[^0-9]/g,'');
var roundClass = "services__round--" + linkNumb;
$(link).hover(function(){
var round = $(roundClass).addClass('services__round--active');
// check
console.log(linkNumb);
console.log(linkClass);
console.log(roundClass);
})
})
})
EDITED: Answer for your code is;
https://jsfiddle.net/g3wjc6tz/
jQuery(function($) {
$(document).ready(function() {
var link = $(".links a");
$(link).hover(function() {
// check
$('.services__round--active').removeClass('services__round--active')
var linkClass = $(this).attr('class');
var linkNumb = linkClass.replace(/[^0-9]/g, '');
var roundClass = "services__round--" + linkNumb;
var round = $('.' + roundClass).addClass('services__round--active');
console.log(linkNumb);
console.log(linkClass);
console.log(roundClass);
})
})
})
Not the best but more simple and proper way to do it: https://jsfiddle.net/g3wjc6tz/1/
Just to make it easier Im explaining what I wish to do in a simplified example.
I have 100 boxes on my site using simple html/css. (styling not shown)
I have written a bit of JS to open a modal that opens when clicking on one of the 100 boxes carrying the same class: class="boxes":
The modal has an Id of "modal":
var modal = document.getElementById("modal");
var boxes = document.getElementsByClassName("box");
var boxesLength = boxes.length;
When any box is clicked the modal appears:
for (var i = 0; i < boxesLength; i++) {
boxes[i].onclick = function () {
modal.style.display = "block";
};
}
Now I wish to color the box that was clicked using a button in the modal that was opened. The code that doesn't work but is my closest guess looks like this:
//get the coloring button in the modal which has Id of "green".
var coloring = document.getElementById("green");
coloring.onclick = function () {
boxes[i].style.backgroundColor = "#90EE90";
//closing the modal after clicking which works
modal.style.display = "none";
};
Writing "boxes[0]" will color the first box, but that is of course not what I wish. I wish to color the box that was clicked.
Thank you for any input. Good day!
on request ive added som simple html
//The modal
<div id="modal">
<button id="green">Completed</button>
</div>
//just some boxes
<div class="boxes"></div>
<div class="boxes"></div>
<div class="boxes"></div>
<div class="boxes"></div>
.... 96 more boxes
In accordance to how I understood your issue.You want the background color to show on the box that was clicked for it to show the modal.
Here is my solution.
//to pass it as a global variable between functions
var randomv = {}
var modal = document.getElementById("modal");
var close = document.querySelector('.close')
//get all box
var x = document.getElementById("innerBox").querySelectorAll(".box");
//for each box execute the following
x.forEach(box => {
//on clicking each box, execute a function
box.addEventListener("click", function () {
//this references the parent element which in this case is the box
randomv.parent = this
//display the modal on clicking the box
modal.style.display = "block";
})
});
//hide the modal on clicking the x
close.addEventListener("click", function(){
modal.style.display = "none"
});
function changeColor() {
//first ensure the background color is normal for each box
x.forEach(box => {
box.style.backgroundColor = "white";
});
//reserve the parent element to a variable
var parent_div = randomv.parent
//change the parent's bg color
parent_div.style.backgroundColor = "green";
}
</script>
#modal {
display: none;
}
#innerBox {
width: 100vw;
display: flex;
}
.box{
flex-grow: 1;
}
.close,.box{
cursor: pointer;
}
<div class="container">
<div id="modal">model content
<div class="close"> x </div>
<button onclick="changeColor()">green</button>
</div>
<div id="innerBox">
<div class="box 1">box1</div>
<div class="box 2">box2</div>
<div class="box 3">box3</div>
<div class="box 4">box4</div>
</div>
</div>
I believe your issue is here. You have: for (var i = 0; i < btnsLength; i++) {, but should be referring to boxesLength so for (var i = 0; i < boxesLength; i++.
This would be an ideal application for 'event delegation'. Read more here: https://javascript.info/event-delegation.
Essentially you put the click handler on the parent container for all of your boxes and then use target to point to the clicked box. That gives you 1 event handler instead of 100.
I figured it out using "this":
for (var i = 0; i < boxesLength; i++) {
boxes[i].onclick = function () {
modal.style.display = "block";
var koko = this;
green.onclick = function () {
koko.style.backgroundColor = "#90EE90";
modal.style.display = "none";
};
};
I have 3 div which are hidden by default. I want to create a toggle for these 3 but I don't want to create onclick for each div and add this to the js file:
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
I tried creating this scenario with clicked_id but it failed. When I click on the third div, the second one views aswell.
var projectEen = document.getElementById("projectInhoud");
projectEen.style.display = "none";
var projectTwee = document.getElementById("projectInhoudTwee");
projectTwee.style.display = "none";
var projectDrie = document.getElementById("projectInhoudDrie");
projectDrie.style.display = "none";
function displayFunction(clicked_id) {
if (clicked_id == 1) {
projectEen.style.display = "block";
} else {
projectTwee.style.display = "block";
} if(clicked_id == 3) {
projectDrie.style.display = "block";
} else {
projectTwee.style.display = "none";
}
}
How can I use the first code but to display all 3 div without creating the function 3 times?
EDIT:
My html
<div id="1" onclick="displayFunction(this.id)" class="projectTitel">
<h1>Project: a</h1>
</div>
<div id="projectInhoudEen" class="projectInhoud"> content </div>
<div id="2" onclick="displayFunction(this.id)" class="projectTitel">
<h1>Project: b</h1>
</div>
<div id="projectInhoudTwee" class="projectInhoud"> content </div>
<div id="3" onclick="displayFunction(this.id)" class="projectTitel">
<h1>Project: c</h1>
</div>
<div id="projectInhoudDrie" class="projectInhoud"> content </div>
By combining document.getElementsByClassName and EventTarget.addEventListener, you can attach the same event handler to your divs. Inside this handler, you can retrieve the element you clicked on with the event object, provided by the event listener.
EDIT : The HTML you provided makes things a little more complicated because the projectTitel and projectInhoud divs aren't related to each other, except by position.
So, in order to display the right projectInhoud div, we need to find the next projectInhoud after the projectTitel that was clicked on.
To make things better, I would suggest editing the HTML to make projectTitel and projectInhoud divs children of a same parent div.
Meanwhile, I added a getClickedProjectIndex function returns the index of the clicked projectTitel div. And the click event uses this index to show the right projectInhoud.
Then, you can use a simple toggle function that displays the div if it's not visible or hide it if it's visible.
var divs = document.getElementsByClassName("projectTitel");
[...divs].forEach(someDiv => someDiv.addEventListener("click", handler));
// by default, all projectInHound are hidden
hideElements("projectInhoud");
function handler(event) {
// get the clicked project's index :
var projectIndex = getClickedProjectIndex(event);
// toggle the right projectInhoud div :
toggleDiv(document.getElementsByClassName("projectInhoud")[projectIndex]);
}
// hide all elements that have the provided class name
function hideElements(className) {
var elements = document.getElementsByClassName(className);
[...elements].forEach(element => element.style.display = "none");
}
function getClickedProjectIndex(event) {
var elements = document.getElementsByClassName("projectTitel");
var projectIndex = 0;
[...elements].forEach((element, index) => {
if (element.id == event.currentTarget.id) {
projectIndex = index;
}
});
return projectIndex;
}
function toggleDiv(element) {
if (element.style.display === 'none') {
element.style.display = 'block';
} else {
element.style.display = 'none';
}
}
<div id="1" class="projectTitel">
<h1>Project: a</h1>
</div>
<div id="projectInhoudEen" class="projectInhoud" > content a</div>
<div id="2" class="projectTitel">
<h1>Project: b</h1>
</div>
<div id="projectInhoudTwee" class="projectInhoud"> content b</div>
<div id="3" class="projectTitel">
<h1>Project: c</h1>
</div>
<div id="projectInhoudDrie" class="projectInhoud"> content c</div>
I would try something like this in the HTML:
<div class=myDiv onclick=myFunction(this)></div>
<div class=myDiv onclick=myFunction(this)></div>
<div class=myDiv onclick=myFunction(this)></div>
And for your JavaScript:
function myFunction(element){
if(element.style.display = "none"){
element.style.display = "block";
else{
element.style.display = "none";
}
}
I have two checkboxes. The checkBoxValidate function triggered by "onclick" assures that the two checkboxes cannot be both selected at the same time. The showMe function, also triggered by "onclick", displays a hidden div when check box is clicked. Everything just fine.
The problem:
When clicking on checkbox1 and then on checkbox2, the div triggered by checkbox1 is not automatically hidden. The idea is than when a checkbox is not selected the div triggered by it should not be visible... Please look at the demo.
Thank you!
DEMO:
http://jsbin.com/iNuPAREq/1/edit?html,js,output
HTML:
<form action="whatever" name="comanda11" method="post" onsubmit="return validate(this)">
<input type="checkbox" name="c1" onclick="showMe('content1'); checkBoxValidate(0);">
<input type="checkbox" name="c1" onclick=" showMe('content2'); checkBoxValidate(1);">
<div id="content1" style="display:none">
Content 1
</div>
<div id="content2" style="display:none">
Content 2
</div>
</form>
JS:
function showMe(box) {
var chboxs = document.getElementsByName("c1");
var vis = "none";
for (var i = 0; i < chboxs.length; i++) {
if (chboxs[i].checked) {
vis = "block";
break;
}
}
document.getElementById(box).style.display = vis;
}
function checkBoxValidate(cb) {
for (j = 0; j < 8; j++) {
if (eval("document.comanda11.c1[" + j + "].checked") == true) {
document.comanda11.c1[j].checked = false;
if (j == cb) {
document.comanda11.c1[j].checked = true;
}
}
}
}
change the markup to use radio buttons, and remove the inline javascript:
<form action="whatever" name="comanda11" method="post">
<input type="radio" name="c1" data-rel="content1" />
<input type="radio" name="c1" data-rel="content2" />
<div id="content1" style="display:none">Content 1</div>
<div id="content2" style="display:none">Content 2</div>
</form>
then do
var elems = document.getElementsByName('c1');
for (var i=elems.length; i--;) {
if (elems[i].addEventListener) {
elems[i].addEventListener ('change',fn,false);
}else if (elems[i].attachEvent) {
elems[i].attachEvent ('onchange',fn);
}
}
function fn() {
var rel = this.getAttribute('data-rel');
document.getElementById(rel=='content1'?'content2':'content1').style.display = 'none';
document.getElementById(rel).style.display = 'block';
}
FIDDLE
If you just have to use checkboxes, here's a working solution:
var elems = document.getElementsByName('c1');
for (var i=elems.length; i--;) {
if (elems[i].addEventListener) {
elems[i].addEventListener ('change',fn,false);
}else if (elems[i].attachEvent) {
elems[i].attachEvent ('onchange',fn);
}
}
function fn() {
var rel = this.getAttribute('data-rel');
for (var i=elems.length; i--;) {
if (elems[i] != this) elems[i].checked = false;
var id = elems[i].getAttribute('data-rel');
document.getElementById(id).style.display = elems[i].checked ? 'block' : 'none';
}
}
FIDDLE
Not an elegant solution but it works for your situation
function showMe (box) {
var chboxs = document.getElementsByName("c1");
var vis = "none";
document.getElementById("content1").style.display = "none";
document.getElementById("content2").style.display = "none";
for(var i=0;i<chboxs.length;i++)
{
if(chboxs[i].checked)
{
vis = "block";
break;
}
}
document.getElementById(box).style.display = vis;
}
The simplest way to get this to behave correctly is to set all divs to hidden before setting the div selected to block.
var divs = [document.getElementsByName("content1"),document.getElementsByName("content2")];
for(var i=0; i < divs.length; i++_ {
divs[i].style.display = 'none'
}
The above code should go above
document.getElementById(box).style.display = vis;
Note that There are much better ways to work with DOM elements. I would recommend looking into jQuery as a much simpler way of doing this. Also, manually building an array of two div elements is not the best way to do this, but I don't want to risk grabbing other divs that might be in your document.
In this situation, I set a global variable to the div being displayed at the time it is "unhidden". lets call it "lastdiv" as an example.
var lastdiv=false;
function showme(){
if(lastdiv){lastdiv.style.display='none';}
lastdiv=?????? // your code to find the div to unhide
lastdiv.style.display='block';
}
You have lots of other issues in your code to work out including the use of eval in a situation where it is clearly not warranted. There are better ways to do it without using eval.