Hide/display div onclick - javascript

I have a script which hides an image and displays a text on the click of a button. However, I have similar buttons doing the same action in different divs. When I click the button the first button gets affected, no matter what button is pressed.
How do I manage to fix this?
Underneath is my JS. How do I make it so that the button only affects itself, and not just the first button?
function hideText() {
const btn = document.querySelector('#info');
const infoHide = document.querySelector('.info-hide');
infoHide.style.display = "block"
btn.style.display = 'none'
setTimeout(()=>{btn.style.display = 'block'; infoHide.style.display= "none"}, 2000)
}
<div>
<button id="info" onClick="hideText()"> A button </button>
<div class="info-hide" style="display:none;">Copied!</div>
</div>
<div>
<button id="info" onClick="hideText()"> A button </button>
<div class="info-hide" style="display:none;">Copied!</div>
</div>

I changed your event listener to be aware of the element that triggered the event. Actually that's not strictly an event listener but just a function that gets called when the event occurs.
There are better ways to deal with it using .addEventListener
function hideText(target) {
const infoHide = target.parentElement.querySelector('.info-hide');
infoHide.style.display = "block"
target.style.display = 'none'
setTimeout(() => {
target.style.display = 'block';
infoHide.style.display = "none";
}, 2000)
}
button{
cursor: pointer;
margin-bottom: 1rem;
}
<div>
<button id="info1" onClick="hideText(this);">A button</button>
<div class="info-hide" style="display:none;">Copied!</div>
</div>
<div>
<button id="info2" onClick="hideText(this);">A button</button>
<div class="info-hide" style="display:none;">Copied!</div>
</div>
Anyway as another user pointed out in comments, the id attribute should be unique so I edited the answer to fulfill that condition.
And here I added the approach using a strategy not involving the event listener defined declaratively in the html:
document.addEventListener('DOMContentLoaded',()=>{
document.querySelectorAll('.smartbutton').forEach((btn)=>{
btn.addEventListener('click', (event)=>{ hideText(event.target); });
});
});
function hideText(target) {
const infoHide = target.parentElement.querySelector('.info-hide');
infoHide.style.display = "block"
target.style.display = 'none'
setTimeout(() => {
target.style.display = 'block';
infoHide.style.display = "none";
}, 2000)
}
.smartbutton{
cursor: pointer;
margin-bottom: 1rem;
}
.info-hide{
display: none;
}
<div>
<button id="info1" class="smartbutton">A button</button>
<div class="info-hide">Copied!</div>
</div>
<div>
<button id="info2" class="smartbutton">A button</button>
<div class="info-hide">Copied!</div>
</div>

querySelector pulls the first element that matches your string. Thats why always first button and first info gets affected. You can provide button itself with this keyword and provide an id which determines the div to appear.
function hideText(button, infoClassname) {
const info = document.querySelector(`.${infoClassname}`);
console.log(button)
info.style.display = "block"
button.style.display = 'none'
setTimeout(() => {
button.style.display = 'block';
info.style.display = "none"
}, 2000)
}
<div>
<button id="info" onClick="hideText(this, 'info-hide-1')"> A button </button>
<div class="info-hide-1" style="display:none;">Copied!</div>
</div>
<div>
<button id="info" onClick="hideText(this, 'info-hide-2')"> A button </button>
<div class="info-hide-2" style="display:none;">Copied!</div>
</div>

change your id in div from all 'info' to 'info1'/'info2'/'info3'/, and do same change in your js const btn = document.querySelector('#info1');

Related

How to simplify this code shared in image below?

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>

Initially I want ON button to be display block and off to display none, if I click ON button, OFF appears & On disappears, and vice versa

I am trying to achieve a toggle effect using display properties, only one button should be on display at a time, while the other is hidden and vice versa. Currently, I am able to hide the off button if I click any of the buttons, so what do I do to get only one displayed at a time
function myFunction() {
var x = document.getElementById("on");
var y = document.getElementById("off");
y.style.display ="none";
if (x.style.display === "none") {
x.style.display = "block";
}
else {
y.style.display = "none";
x.style.display = "block";
}
}
<button onclick="myFunction()" id="on">ON</button>
<button onclick="myFunction()" id="off">OFF</button>
The issue with your logic is that you need to switch the display state of both elements within the function you call:
var on = document.getElementById("on");
var off = document.getElementById("off");
function myFunction() {
if (on.style.display === "none") {
off.style.display = "none";
on.style.display = "block";
} else {
off.style.display = "block";
on.style.display = "none";
}
}
<button onclick="myFunction()" id="on">ON</button>
<button onclick="myFunction()" id="off" style="display: none;">OFF</button>
Another way to do what you require would be to use a CSS class to hide the required element. This avoids the need for the if condition. You can then use classList.toggle() to switch the class on/off on each element on successive clicks. Something like this:
let toggles = document.querySelectorAll('.toggle');
toggles.forEach(toggle => {
toggle.addEventListener('click', e => {
toggles.forEach(el => el.classList.toggle('hide'));
});
});
.hide { display: none; }
<button class="toggle" id="on">ON</button>
<button class="toggle hide" id="off">OFF</button>
Or even more simply using jQuery:
let $toggles = $('.toggle').on('click', () => $toggles.toggleClass('hide'));
.hide { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button class="toggle" id="on">ON</button>
<button class="toggle hide" id="off">OFF</button>
In this solution, when the on and off buttons are clicked, the toggle() method is called and the display properties are changed. In order to hide a button initially, I set the display property of the <button> with an off id value to none; this feature can also be provided by using the onload event that is triggered when the page is loaded.
const on = document.getElementById('on');
const off = document.getElementById('off');
function toggle(){
if(on.style.display === 'none'){
on.style.display = 'block';
off.style.display = 'none';
}
else{
on.style.display = 'none';
off.style.display = 'block';
}
}
on.addEventListener('click', function(){
toggle();
});
off.addEventListener('click', function(){
toggle();
});
#on {
display: block;
}
#off {
display: none;
}
<button id="on">ON</button>
<button id="off">OFF</button>

Collapse one at the time on different divs

const buttons = document.querySelectorAll('.collaps');
const colls = document.querySelectorAll('.collaps_content');
buttons.forEach((thisButton, index) => {
thisButton.addEventListener('click', () => {
colls[index].style.display !== 'none'
? colls[index].style.display = 'none'
: colls[index].style.display = 'block';
});
});
Html
<div class="container-content">
<div class="buttons">
<button class="collaps">Btn1</button>
<button class="collaps">Btn2</button>
<button class="collaps">Btn3</button>
<button class="collaps">Btn4</button>
</div>
<div class="collaps_content" style="display: none;">
Btn1
</div>
<div class="collaps_content" style="display: none;">
Btn2
</div>
<div class="collaps_content" style="display: none;">
Btn3
</div>
<div class="collaps_content" style="display: none;">
Btn4
</div>
</div>
Is working fine, but I only want one collaps_content open at a time, that part is not working.
When I click on every button they are all open and I don't want that to happen.
I tried to look for solutions but so far none worked.
If I understood correctly, you want to close any other open collapsible divs when clicking a button. You can do this by first closing all collapsible divs, and then open the correct one like this:
const buttons = document.querySelectorAll('.collaps');
const colls = document.querySelectorAll('.collaps_content');
buttons.forEach((thisButton, index) => {
thisButton.addEventListener('click', () => {
colls.forEach(b => b.style.display = 'none');
colls[index].style.display !== 'none'
? colls[index].style.display = 'none'
: colls[index].style.display = 'block';
});
});
I just added the colls.forEach(b => b.style.display = 'none'); in your existing JS.

window.addEventListener function is not working at all times

Through this code i have to hide the dropdown-container when a user clicked outside of the button. And the code works fine initially. But later, it is not responding to the onclick event on button also. sometimes it closes the dropdown if i cliked a button. I have tried with many stackoverflow questions but i didnot get answer. Here is my code. Hope someone could solve this issue.
<div class="button-grp">
<button class="icon-button" type="button" onclick="menu(event, '1')"><img
src="../../Images/icons/local_library-white-24dp.svg" class="icon"><br>Learning
</button>
<button class="icon-button" type="button" onclick="menu(event, '2')"><img
src="../../Images/icons/gamepad-white-24dp.svg" class="icon"><br>Tools
</button>
</div>
<div class="sidebar-open">
<div class="main-options" id="0">
<button class="options-button" type="button">Academics</button>
<div class="dropdown-container">
Course Details
Assignments
</div>
<button class="options-button" type="button">Schedule</button>
<div class="dropdown-container">
Exams
Classes
</div>
</div>
</div>
<div id="mainmenu">
Lorem ipsum dolor sit,
</div>
And my Javascript code is as follows..
//function to toggle between clicked buttons and close when double clicked on it.
function menu(evt, id) {
document.querySelectorAll(".main-options").forEach(function(div) {
if (div.id === id) {
// Toggle specified DIV
if(div.style.display === "block"){
div.style.display = "none";
document.getElementById("mainmenu").style.marginLeft = "80px";
document.body.style.backgroundColor = "#fff";
}else{
div.style.display = "block";
document.getElementById("mainmenu").style.marginLeft = "230px";
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
} else {
// Hide other DIVs
div.style.display = "none";
}
});
}
//function to hide the dropdown when clicked outside the button.
window.addEventListener('click', function(event){
if (!event.target.matches('.icon-button') ){
var dropdowns = document.getElementsByClassName("main-options");
var i;
for (i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].style.display === "block") {
dropdowns[i].style.display ="none";
document.getElementById("mainmenu").style.marginLeft = "80px";
document.body.style.backgroundColor = "#fff";
}
}
}
});
Why don't you try this:
document.addEventListener("DOMContentLoaded", () => {
document.querySelector(".icon-button").forEach((button) => {
button.addEventListener('click', ()=>{
...
});
});
});

How do I remove a specific div out of many using one function in JavaScript?

I'm learning JavaScript and this is a practice scenario for me.
What I have already is a button that clones content, and within that content that has been cloned, there is a button to remove it.
When I click the button that prompts you to remove the content, it removes the first set of content.
What I want to happen is when you click the button that prompts you to remove the content, it removes the content related to that button and nothing else.
This is the CodePen link.
https://codepen.io/JosephChunta/pen/YzwwgvQ
Here is the code.
function addContent() {
var itm = document.getElementById("newContent");
var cln = itm.cloneNode(true);
document.getElementById("placeToStoreContent").appendChild(cln);
}
function removeContent() {
var x = document.getElementById("content").parentNode.remove();
}
// This is for debug purposes to see which content is which
document.getElementById('orderContent')
.addEventListener('click', function(e) {
const orderedNumber = document.querySelectorAll('.thisIsContent');
let i = 1;
for (p of orderedNumber) {
p.innerText = '' + (i++);
}
});
.contentThatShouldBeHidden {
display: none;
}
<div id="placeToStoreContent">
</div>
<button id="orderContent" onclick="addContent()">Add Content</button>
<div class="contentThatShouldBeHidden">
<div id="newContent">
<div id="content">
<p class="thisIsContent">This is a prompt</p>
<button onclick="removeContent()">Remove this</button>
<hr />
</div>
</div>
</div>
When you'r trying to remove by ID, it takes the first ID it finds.
To remove the correct content, send this onclick.
<button onclick="removeContent(this)">Remove this</button>
And handle it in your function:
function removeContent(el) {
el.parentNode.remove();
}
Example:
function addContent() {
var itm = document.getElementById("newContent");
var cln = itm.cloneNode(true);
document.getElementById("placeToStoreContent").appendChild(cln);
}
function removeContent(el) {
el.parentNode.remove();
}
// This is for debug purposes to see which content is which
document.getElementById('orderContent')
.addEventListener('click', function(e) {
const orderedNumber = document.querySelectorAll('.thisIsContent');
let i = 1;
for (p of orderedNumber) {
p.innerText = '' + (i++);
}
});
.contentThatShouldBeHidden { display: none; }
<div id="placeToStoreContent">
</div>
<button id="orderContent" onclick="addContent()">Add Content</button>
<div class="contentThatShouldBeHidden">
<div id="newContent">
<div id="content">
<p class="thisIsContent">This is a prompt</p>
<button onclick="removeContent(this)">Remove this</button>
<hr />
</div>
</div>
</div>
In your remove button, do this:
<!-- The "this" keyword is a reference to the button element itself -->
<button onclick="removeContent(this)">Remove this</button>
And in your javascript:
function removeContent(element) {
element.parentNode.remove();
}

Categories

Resources