Open hidden elements one at a time? - javascript

please I am trying to create a FAQ like functionality, I have some elements hidden so when I click on a button it opens and hides it. I have been able to do this but I am not getting what I actually want. I might have done something wrong I suppose. So, there are 5 elements with the same className, this will help me target them all and run a for loop to kind of break them apart. However if I click on this button to open one of the element the other ones open.
const openBtn = document.querySelectorAll(".openBtn")
const openContent = document.querySelectorAll(".openContent")
for(btn of openBtn) {
btn.addEventListener('click', () => {
for(content of openContent) {
if (content.classList.contains('hidden')) {
content.classList.remove('hidden');
content.classList.add('flex')
} else {
content.classList.remove('flex');
content.classList.add('hidden')
}
}
})
}
So as you can see, If I click on the chevron icon for just one of the wither About Us, Careers or just any of the 5 every other one opens. How do I fix this ?

Since you aren't going to post even the most general version of your HTML, here is a general outline.
First, each button gets a data attribute for target,then each FAQ div gets an ID attribute that matches the data target attribute.
I attach the click handler to the document and look for openBTN on the clicked element. Then I loop through every OPENED div to close it. Then I get the target data attribute and add the appropriate classes.
document.addEventListener("click", function(e) {
if (e.target.classList.toString().includes("openBtn")) {
let opened = document.querySelectorAll(".openContent.flex");
opened.forEach(function(el) {
el.classList.add("hidden");
el.classList.remove("flex");
});
let target = document.querySelector(e.target.dataset.target)
target.classList.remove("hidden");
target.classList.add("flex");
}
});
.hidden {
display: none
}
<button data-target="#faq1" class="openBtn">OPEN</button>
<div id="faq1" class="openContent hidden">1</div>
<button data-target="#faq2" class="openBtn">OPEN</button>
<div id="faq2" class="openContent hidden">2</div>
<button data-target="#faq3" class="openBtn">OPEN</button>
<div id="faq3" class="openContent hidden">3</div>
<button data-target="#faq4" class="openBtn">OPEN</button>
<div id="faq4" class="openContent hidden">4</div>

Related

How to have a different popup menu appear depending on which button is pressed

I have 2 containers titled learned__container and I want one to pop up depending on which button is pressed. So for example, if I press the Hello button I want the container that has the header hello to pop up as well. If I press the goodbye button I want the container that has the header of goodbye. Is there an easy way to do this without making the id names unique for each button and container? Or do I need to give unique class/id names and select them both and apply an event listener to both buttons?
HTML:
<button id="subheader--link">Hello</button>
<button id="subheader--link">Goodbye</button>
<div class="hide--learn learned__container">
<h1>Hello</h1>
</div>
<div class="hide--learn learned__container">
<h1>Goodbye</h1>
</div>
JS:
const overlay = document.querySelector('.overlay');
const learnContainer = document.querySelector('.learned__container');
const link = document.querySelectorAll('#subheader--link');
link.forEach(link => {
link.addEventListener('click', function (e) {
overlay.classList.remove('hide--overlay');
console.log(link)
console.log(e)
})
})

How to create curriculum presentation for a course with JavaScript?

I would like to create a curriculum presentation by Java Script similar to the one on Udemy.
https://prnt.sc/22zxxrp
I have tried to put both button and content in the same div and to add an event listener which would on click trigger conditional check if both of the elements are of the same parent and if true to display the content.
But it does not work.
The code would be something like this but with more buttons.
let batonceros = document.getElementsByClassName("batno");
let paragraph = document.getElementsByClassName("para");
batonceros.addEventListener("click", function() {
if( batonceros != paragraph && batonceros.parentNode == paragraph.parentNode) {
batonceros.style.display = "block";
}
else {
batonceros.style.display = "none";
}
});
Not exactly sure what you're trying to accomplish, but maybe this might help. It shows how to reference the parent container to find the relative .para from its .batno
let batonceros = document.querySelectorAll(".batno");
let paragraph = document.querySelectorAll(".para");
batonceros.forEach(button => button.addEventListener("click", e => {
e.target.closest('div').querySelector('.para').classList.toggle('show');
}));
.para {
display: none;
}
.show {
display: block;
}
<div>
<p class='para'>This is a paragraph</p>
<button class='batno'>Button</button>
</div>
<div>
<p class='para'>This is a paragraph</p>
<button class='batno'>Button</button>
</div>
To debug, try to see if it works without checking the parent. Also, no need to check to see if the button equals the paragraph. Also, you are changing the button style, not the paragraph style.
batonceros.addEventListener("click", function() {
paragraph.style.display = "block";
}
If this does cause the paragraph to display, your problem may in your element structure.

How to check if pop up is displayed on page with Jquery

I'm trying to execute a function but only if a pop up is displayed or not. I've used Chrome Dev Tools to find the pop up element:
<div class="modal large popup is-visible" id="verifyIdentity" data-overlay-name="verify-identity">
When I close the pop-up, this changes to the below, with the words is-visible disappearing.
<div class="modal large popup" id="verifyIdentity" data-overlay-name="verify-identity">
I have tried the following:
if ($("#modal large popup").is(':visible')) { // do something }
if ($("verifyIdentity").hasClass('.modal large popup is-visible')) { // do something }
if ($(".parentClass").hasClass('.modal large popup is-visible')) { // do something }
None of these work and I am struggling to work out how to get my code to recognise that the pop-up is visible/not visible.
I'm new to JQuery and Javascript - can anyone help please?
Thanks
You are missing the # inside your selector.
This one should work properly
<button id="verifyBtn" onclick="verify()"> Verify </button>
function verify(){
if ($("#verifyIdentity").hasClass('is-visible')) { }
console.log("works");
}
Check with console.log("works"); if the function is executed properly.
Your has class approach is probably best here, however in the 'selector' for that example you're missing the actual 'ID' selector. Try:
if ($("#verifyIdentity").hasClass('is-visible')) { // do something }
You can also just target the is-visible, the rest we don't care about.
hasClassDetermine whether any of the matched elements are assigned the given
class.
I don't know much about jQuery so can offer no real help there but you ought to be able to do this using the IntersectionObserver API. If you click the button it will assign a class to the modal which I hope will emulate the modal becoming visible. The output element will be updated as a result because the IntersectionObserver callback has determined that it is visible.
const out=document.querySelector('output');
const iocallback=function( entries, observer ){
entries.forEach( e=>{
if( e.isIntersecting && e.intersectionRatio > 0 ) {
out.textContent='isVisible='+e.isVisible;
} else {
out.textContent='isVisible='+e.isVisible;
}
});
}
let modal=document.getElementById( 'verifyIdentity' );
let options={
root:null,
rootMargin:'0px',
threshold:1,
delay:100,
trackVisibility:true
};
let io=new IntersectionObserver( iocallback, options );
io.observe( modal );
document.querySelector('[type="button"]').onclick=(e)=>{
modal.classList.toggle('visible');
};
body,body *{box-sizing:border-box;margin:1rem;padding:1rem}
#verifyIdentity{ display:none; border:1px solid red; }
.visible{display:block!important;}
output{border:1px solid black;}
<div id='verifyIdentity'> #modal# </div>
<output></output>
<input type='button' value='Toggle visibility' />

How to close sidebar on click for anchor using only JavaScript?

I have a sidebar and I want to close it when someone clicks on a link. In my code, the sidebar just closes for a millisecond when I click on an anchor element. How can I fix this without using jQuery?
The a tags are linking to a html page
JS:
var elem = document.getElementById('slidebar').getElementsByClassName('button')[0]
element.addEventListener("click", slide);
function slide() {
document.getElementById('slidebar').classList.toggle('active');
}
var slidebar = document.getElementById('slidebar');
slidebar.addEventListener('click', handleMenuClick);
function handleMenuClick(event) {
if (event.target instanceof HTMLAnchorElement) {
document.getElementById('slidebar').classList.add('close');
}
}
CSS:
#slidebar.active {
left: 0px;
}
#slidebar.close {
display: none;
}
First, make sure you prevent the default event when clicking the anchor tag. Otherwise, it might be re-rendering the page.
But based on your code, it looks like you're adding two functions onto the slidebar. One that closes and one that opens. Since the anchor tag that closes the slidebar is inside the slidebar - when you click it you first fire off the handleMenuClick function and then it bubbles up and fires off the slide function. So it closes and opens quickly.
Instead, add a third element that is used to open the slidebar and attach the slide function there.
Also, you don't need two classes for managing the state of hidden/not hidden. You can just provide a class that sets the display to none and toggle that class list. If you want transition effects you can do that in CSS
Maybe something like this:
window.addEventListener('DOMContentLoaded', e => {
let slidebar = document.getElementById('slidebar')
let collapseButton = slidebar.getElementById('close-button')
let openButton = slidebar.getElementById('open-button')
collapseButton.on('click', toggleClassList)
openButton.on('click', toggleClassList)
const toggleClassList = e => {
e.preventDefault()
slidebar.classList.toggle('hidden')
}
})
#slide-bar.hidden {
display: none;
}
#slide-bar.hidden #close-button {
display: none;
}
#slide-bar #open-button {
display: none;
}
Obviously, it depends a bit on the code you have already written. But this is a basic example that would work. Just need to add the transitions for the sliding effect in CSS

Javascript Collapsible Menu (hide the other elements)

I have the following working Javascript function:
function collapsible(zap) {
if (document.getElementById) {
var abra = document.getElementById(zap).style;
if (abra.display == "block") {
abra.display = "none";
} else {
abra.display = "block";
}
return false;
} else {
return true;
}
}
When I use the following in html code it displays or hides the "element" div:
<li>Element</li>
Thats working fine. But the problem is, that I want to use the function for multiple links, and then the other elements, that were clicked before, stay, open.
How can I reprogram the code, so that only one div stays open and the other gets closed if i click on another link?
Thanks beforehand!
If you could use jQuery and more importantly jQueryUI accordion I think it would accomplish exactly what you're looking for.
However, without using those two, here is how I would structure it. Like mentioned above, I would use classes to modify the styles of the divs you want shown or hidden. Then the js code can just toggle those classes on each of your elements. The slightly more difficult part (without jquery) is modifying class values since in your final application you may have lots of classes on each div. This is just a very crude example to get you going.
Working JSFiddle Example
Sample DOM
<div >
<li>Element1</li>
<div id='elem1' class='myelem visible'>
Element 1 contents
</div>
</div>
<div >
<li>Element2</li>
<div id='elem2' class='myelem'>
Element 2 contents
</div>
</div>
<div >
<li>Element3</li>
<div id='elem3' class='myelem'>
Element 3 contents
</div>
</div>
Sample JS
window['collapsible'] = function(zap) {
if (document.getElementById)
{
var visDivs = document.getElementsByClassName('visible');
for(var i = 0; i < visDivs.length; i++)
{
visDivs[i].className = visDivs[i].className.replace('visible','');
}
document.getElementById(zap).className += " visible";
return false;
}
else
return true;
}
Sample CSS:
.myelem {
display: none;
}
.visible {
display: block;
}
The way to go is to create a class(or maybe two), like collapsible and active or open that has this style(display: block or none) and then you working adding or removing the class.
The logic would be:
Links that has the class collapsible when clicked would add the active or open class which would give the behavior that remains opens(or active) by css.
If you want to hide others elements you would look for the elements with the class collapsible and then remove the active(or open) class if has any.
Here is my solution: http://jsfiddle.net/g5oc0uoq/
$('.content').hide();
$('.listelement').on('click', function(){
if(!($(this).children('.content').is(':visible'))){
$('.content').slideUp();
$(this).children('.content').slideDown();
} else {
$('.content').slideUp();
}
});
show() and hide() can be used instead of slideUp() and slideDown() if you have performance issues.

Categories