I created a click event that opens a previously 'hidden' div and closes it again once you click the same button.
However, it only runs once (one open and one close) - I'm at a loss to explain why it doesn't work if I click it again.
let readMore = document.getElementById('clickAbout');
let moreInfo = document.getElementById('about');
let changeSepa = document.getElementById('sepChange');
readMore.addEventListener('click', function(){
changeSepa.style.height = '2rem';
if (moreInfo.className == "") {
moreInfo.className = "open";
moreInfo.style.display = 'block';
} else {
moreInfo.style.display = 'none';
}
});
this happens because you're checking if className == "", but you are modifying the className to be "open". On the second click it checks the className which is now "open" and goes to the else block. On the third click you expect for it to go into the first block but the className is still "open".
For an easy fix just change the className in the else block
else {
moreInfo.className = "";
moreInfo.style.display = 'none';
}
Also i suggest you make use of the classList property on elements
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
using the class list it could look like this:
readMore.addEventListener("click", function () {
changeSepa.style.height = "2rem";
if (moreInfo.className == "") {
moreInfo.classList.add("open");
moreInfo.style.display = "block";
} else {
moreInfo.classList.remove("open");
moreInfo.style.display = "none";
}
});
Or even
readMore.addEventListener("click", function () {
changeSepa.style.height = "2rem";
moreInfo.classList.toggle("open");
if (moreInfo.className == "") {
moreInfo.style.display = "block";
} else {
moreInfo.style.display = "none";
}
});
Related
A basic question by a newbie…
I always encounter the same problem :
I often want an element "A" to show an element "B" on click when "B" is hidden, but to hide it when it is visible. Here are two different try that doesn't work :
let ref = document.getElementsByTagName('sup');
let refContent = document.getElementsByTagName('i');
for(let i = 0; i < ref.length ; i++) {
ref[i].addEventListener('click', function() {
if (refContent[i].style.display == "inline") {
refContent[i].style.display = "none";
} else {
refContent[i].style.display = "none";
};
});
}
let ref = document.getElementsByTagName('sup');
let refContent = document.getElementsByTagName('i');
for(let i = 0; i < ref.length ; i++) {
if (refContent[i].style.display == "") {
ref[i].addEventListener('click', function() {
refContent[i].style.display = "inline";
});
} else {
ref[i].addEventListener('click', function() {
refContent[i].style.display = "none";
});
}
}
Hi
I'm gonna change some variable names to make this easier to talk about. So, you start off strong
// get all elements with tag sup
let buttons = document.getElementsByTagName('sup');
//get all elements with tag i
let showables = document.getElementsByTagName('i');
For each element buttons we want to bind an onclick event listener. showables should respond to those clicks. You write
//for every `button` bind this `event listener`
buttons[i].addEventListener('click', function() {
if (showable[i].style.display == "inline") {
showable[i].style.display = "none";
} else {
showable[i].style.display = "none";
};
});
}
To make this a little more clear lets take out the function and give it a name
let show_hide = function(i) {
if (showable[i].style.display == "inline") {
showable[i].style.display = "none";
} else {
showable[i].style.display = "none";
};
});
//for each button, bind show_hide
for(let i = 0; i < buttons.length ; i++) {
buttons[i].addEventListener('click', show_hide(i))
}
The loop there does exactly what you'd expect; it binds show_hide to each button.
What does show_hide do?
//if the element is shown, hide it
if (showable[i].style.display == "inline") {
showable[i].style.display = "none";
//if the element is not shown, hide it
} else {
showable[i].style.display = "none";
};
as you can see that no matter what, show_hide hides the element!
so a quick change will fix this for you.
if (showable[i].style.display == "inline") {
showable[i].style.display = "none";
//if not shown, show
else {
**** showable[i].style.display = "inline";
};
putting it all together, this should work
let show_hide = function(i) {
if (showable[i].style.display == "inline") {
showable[i].style.display = "none";
} else {
showable[i].style.display = "inline";
};
});
//for each button, bind show_hide
for(let i = 0; i < buttons.length ; i++) {
buttons[i].addEventListener('click', show_hide(i))
}
If you want my solution to this problem I'd be more than willing to solve this problem in my own way. Comment and let me know! I hope this helps
fin
I will interpret what you have written but I do not have the complete code I will fix some issues and update if/when you update your code by adding the markup (html).
You should put your selected elements in an array because some browsers will not let you loop over a NodeLists. You can change a NodeLists into an array in a few ways I like the Array.From() way. After changing the NodeLists into an array you can safely loop over the elements in the array using a forEach() loop.
let ref = Array.from(document.getElementsByTagName('sup'));
let refContent = Array.from(document.getElementsByTagName('i'));
ref.forEach(el => {
el.addEventListener('click', e => {
e.target.getElementsByTagName('i').style.display = '' // do something
});
});
This snippet will most likely not work as-is, I'm missing information to finish this script, but perhaps this is a good starting point for further exploration. (Search for stuff and add 'mdn', to get good results).
In stead of directly changing the style of an element it is better to either add or remove a css class which contains the css properties you desire. You can also toggle a class: element.toggle('className).
I'm implementing inventory mechanics on my webgame and I want to complicate stuff a little.
In order to open the gate you need to find boltcutters. When you find it, you need to click on boltcutters and then on a chain to break it, and that's the part I have working.
But I want to implement some kind of function that if after clicking boltcutters I click anywhere but on the chain I want to run a function cancelling chain function (changing color) and displaying "Cant use it here" msg for example.
So in short, I need to find a solution where (pseudocode):
If(boltcutters_clicked){
if(clicked_on_chain){
openthedoor()}
else {
cancelBoltcutters()}
Here is the part of the code I have for now, if thats helping:
// chain mechanics
var boltcutters_used = false;
document.getElementById('item_boltcutters').onmousedown = function(){
boltcutters_used = true;
document.getElementById('item_boltcutters').style.color = "red";
document.getElementById('item_boltcutters').style.border = "1px solid red";
}
var boltcutters_found = false;
document.getElementById("chain").onmousedown = function(){
if(boltcutters_used){
alert('you open the door');
} else if(!boltcutters_found){
alert("I need to find something to break this chain...")
} else {
alert("Boltcutters could do the trick")
}
}
Thanks to the idea mentioned below I came up with following solution:
var last_clicked = null;
var test=0;
window.onclick = function (e) {
last_clicked = e.target;
if(boltcutters_used == true){
test++;
}
if(boltcutters_used == true && last_clicked !== document.getElementById("chain") && test >1){
alert("Can't use it here");
boltcutters_used = false;
test=0;
}
}
And it works :)
Maintain the last clicked item
Have a variable to store the last clicked element
On window click update the value of that variable
Check for this variable in your chain event handler
var last_clicked = null;
window.onclick = function (e) {
last_clicked = e.target;
}
var boltcutters_used = false;
document.getElementById('item_boltcutters').onmousedown = function(){
boltcutters_used = true;
document.getElementById('item_boltcutters').style.color = "red";
document.getElementById('item_boltcutters').style.border = "1px solid red";
}
var boltcutters_found = false;
document.getElementById("chain").onmousedown = function(){
if(boltcutters_used){
if(last_clicked === document.getElementById("item_boltcutters")) {
alert('you open the door');
} else {
alert("You should use the bolt cutters on this");
}
} else if(!boltcutters_found){
alert("I need to find something to break this chain...")
} else {
alert("Boltcutters could do the trick")
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am really new to JS and I'm having some issues.
So I have this JS file: that is basically the same function repeating with different <div id="">.
var button = document.getElementById("obj-trigger");
button.onclick = function () {
var div = document.getElementById("obj-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("lineas-trigger");
button.onclick = function() {
var div = document.getElementById("lineas-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("cultura-trigger");
button.onclick = function() {
var div = document.getElementById("cultura-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("igualdad-trigger");
button.onclick = function() {
var div = document.getElementById("igualdad-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("proyectos-trigger");
button.onclick = function() {
var div = document.getElementById("proyectos-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("estigmas-trigger");
button.onclick = function() {
var div = document.getElementById("estigmas-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("soy-trigger");
button.onclick = function() {
var div = document.getElementById("soy-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
var button = document.getElementById("tudef-trigger");
button.onclick = function() {
var div = document.getElementById("tudef-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
And it works perfectly when I am using ALL the functions, however if I remove a <div> from my HTML, let's say: <div id="estigmas-trigger">, my JS will work until it reaches:
var button = document.getElementById("estigmas-trigger");
button.onclick = function() {
var div = document.getElementById("estigmas-cont");
if (div.style.display !== "none") {
div.style.display = "none"
}
else {
div.style.display = "block";
}
};
All code below that will stop working, so no more collapsing. :(
Why is that? And... how can I fix it?
It's because button will be null if there are no element with id estigmas-trigger, and you should get error that you can't set value onclick on null, try adding a check to test if button is not null:
var button = document.getElementById("estigmas-trigger");
if (button) {
button.onclick = function() {
var div = document.getElementById("estigmas-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
}
Your error is caused because when you remove an element from the HTML and then your Javascript tries to refer to that element without proper protections, it causes a script error and the script aborts execution because of the error.
The second thing you need to do when learning Javascript (after learning how to write your first script) is to learn how to check for errors in the debug console in the browser. That will show you when you have execution errors that are aborting your script and they will usually show you what line the error occurs on.
In this case, you would attempt to get a DOM element with a line such as:
var button = document.getElementById("estigmas-trigger");
And, then you would attempt to use the button variable. But, if the estigmas-trigger element was not in the page, then button would be null and it would be an error to reference a property of null such as .onclick.
In addition, your code is horribly repetitive. You really should never copy nearly identical code multiple times into your code. Instead, create a reusable function and use that function multiple places or if your code is almost entirely identical except for one input parameter (which is the case for you), then you can just put the one input parameter into an array and loop through the array.
Here's a much more DRY implementation (this replaces all of your code):
var buttons = ["obj-trigger", "lineas-trigger", "cultura-trigger",
"igualdad-trigger", "proyectos-trigger", "estigmas-trigger",
"soy-trigger", "tudef-trigger"];
buttons.forEach(function(id) {
var button = document.getElementById(id);
if (button) {
button.addEventListener("click", function(e) {
var cont_id = this.id.replace("trigger", "cont");
var elem = document.getElementById(cont_id);
if (elem) {
var style = elem.style;
if (style.display !== "none") {
style.display = "none";
} else {
style.display = "block";
}
}
});
}
});
Summary of changes:
Put all the trigger ID values into an array of strings so you can just loop through each one that you want to apply identical code to.
Use .forEach() to loop through the array of strings.
Get the DOM element for each id and check to see if it is present before trying to use it (this will solve your original problem).
Use .addEventListener() to add the click event handler as this is much more scalable than .onclick because you can have multiple click handlers for the same element this way. It is a generally good habit to switch to use .addEventListener().
Rather than refer to the xxx-cont ids by name, just derive them from the xxx-trigger ids using a simple text replacement. This saves more duplication and typing in your code.
Get the xxx-cont object in the DOM and also check to see if it exists before attempting to use it (safe coding).
One way is:
var button = document.getElementById("estigmas-trigger");
//that way you prevent define a function in a null object
if(button){
button.onclick = function() {
var div = document.getElementById("estigmas-cont");
if (div.style.display !== "none") {
div.style.display = "none";
}
else {
div.style.display = "block";
}
};
}
I have the javascript below, it shows and hides a layer when a button is clicked. However I have 2 of these installed on the same page and closing/opening does not work efficiently in that scenario
function setVisibility(id) {
if (document.getElementById('button').value == 'Close') {
document.getElementById('button').value = 'Open';
document.getElementById(id).style.display = 'none';
} else {
document.getElementById('button').value = 'Close';
document.getElementById(id).style.display = 'inline';
}
}
function setVisibility(id) {
if (document.getElementById('button_2').value == 'Close') {
document.getElementById('button_2').value = 'Open';
document.getElementById(id).style.display = 'none';
} else {
document.getElementById('button_2').value = 'Close';
document.getElementById(id).style.display = 'inline';
}
}
http://codepen.io/anon/pen/EadRvW
If you click on each Open button, you will see after one button is clicked, it takes 2 clicks for the other button to successfully open the layer. The same with closing them. Clicking alternately on each Open button, shows they don't respond as they should when clicked.
I am not sure what needs to be done to allow them to work together. They work fine when just 1 exists on the page. Does anyone see the problem?
You had the same function (setVisibility) defined twice, so the first definition was replaced by the second one.
Setting your javascript like this fixes the problem:
edit: I prefer this version more, and I set it to change the button text as well:
function setVisibility(id) {
var targetButton;
switch( id ) {
case "layer":
targetButton = "button";
break;
case "layer_2":
targetButton = "button_2";
break;
}
if (document.getElementById(targetButton).value == 'Close') {
document.getElementById(targetButton).innerHTML = 'Open';
document.getElementById(targetButton).value = 'Open';
document.getElementById(id).style.display = 'none';
} else {
document.getElementById(targetButton).innerHTML = 'Close';
document.getElementById(targetButton).value = 'Close';
document.getElementById(id).style.display = 'inline';
}
}
http://codepen.io/anon/pen/JomBbm
As Mike Willis has mentioned you have defined the same function twice and it is causing the issues and I understand that you want to change the button's label on click based on your code then you should change innerHTML instead of value.
function setVisibility(id) {
if (document.getElementById('button').innerHTML == 'Close' && id=="layer") {
document.getElementById('button').innerHTML = 'Open';
document.getElementById(id).style.display = 'none';
} else if (document.getElementById('button').innerHTML == 'Open' && id=="layer") {
document.getElementById('button').innerHTML = 'Close';
document.getElementById(id).style.display = 'inline';
} else if (document.getElementById('button_2').innerHTML == 'Close' && id=="layer_2") {
document.getElementById('button_2').innerHTML = 'Open';
document.getElementById(id).style.display = 'none';
} else {
document.getElementById('button_2').innerHTML = 'Close';
document.getElementById(id).style.display = 'inline';
}
}
http://codepen.io/anon/pen/vEVayq
I have this script on dynamic radio buttons... On load the divs display, great. One is automatically checked, great. If I click the other radio button the divs hide, great. When I click back to the main radio button to show the divs again the divs don't reappear.
How do I get the divs to reappear (show)?????
function hide() {
var ele = document.getElementById("hideRow");
var coup = document.getElementById("coup");
if ("hideRow") {
ele.style.display = "none";
coup.style.display = "none";
} else {
ele.style.display = "block";
coup.style.display = "block";
}
}
Try :
function hide() {
var ele = document.getElementById("hideRow");
var coup = document.getElementById("coup");
if (ele.style.display == "block") {
ele.style.display = "none";
coup.style.display = "none";
} else {
ele.style.display = "block";
coup.style.display = "block";
}
}
This is always true:
if ("hideRow") {
// Always executes
}
So, you only ever get to the if-block. You need to change the conditional on your if-statement.
if (ele.style.visibility == 'visible';) {
ele.style.visibility = 'hidden';
coup.style.visibility = 'hidden';
} else {
ele.style.visibility = 'visible';
coup.style.visibility = 'visible';
}
I may have entirely missed the mark and not understood what your trying to do, but that's the way I'd do it (I think - you may be trying to do something else).