javascript toggle showing and hiding several div elements - javascript

I have two divs on a page (id's MAY and JUNE) and two buttons on the page. The page startes off by showing the May div, with the June div hidden using css display: none
I am trying to create the correct javascript that will toggle between the two of them, but (after searching on here) I can only manage to get one to work.
Codepen showing issue is https://codepen.io/billteale/pen/zwBBez
<a href="#" id="button" >MAY</a>
<a href="#" id="button" >JUNE</a>
<!-- first div, shows on page load -->
<div id="MAY">
<div style="background-color: lightgrey"><h1 style="padding: 5px"><strong>May 2017</strong></h1>
</div>
<!-- second div, hidden originally -->
<div class="hidden" id="JUNE">
<div style="background-color: lightgrey"><h1 style="padding: 5px"><strong>June 2017</strong></h1>
</div>
...and the current js is
var button = document.getElementById('button'); // Assumes element with id='button'
button.onclick = function() {
var div = document.getElementById('MAY');
if (div.style.display !== 'none') {
div.style.display = 'none';
}
else {
div.style.display = 'block';
}
};
Eventually I will have four or more divs to toggle between, with each button showing its relevant div, and hiding the others.
Can anybody tell me how to add to the code I have here to make this work for multiple elements?

It can be done by setting the div id's in the anchor tag's href attribute, and showing the corresponding div while hiding the rest. It can be done for any number of div's with no extra script, Just add the new div id to the new anchor tags href. You should give a common class to all the div's like month to select them all.
$("a.btn").click(function() {
var id = $(this).attr("href");
$("div.month:visible").hide();
$(id).show();
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
MAY
JUNE
<!-- first div, shows on page load -->
<div id="MAY" class="month">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>May 2017</strong></h1>
</div>
</div>
<!-- second div, hidden originally -->
<div class="month hidden" id="JUNE">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>June 2017</strong></h1>
</div>
</div>

First you add a "div-toggle" class to each one of the divs you want to toggle. After that, you bind click events on your buttons, firing a function which takes an identifier as argument.
The function will run through your divs and set the one that has the argument id as visible, and hide the others.
This way you can add more divs to be toggled. You just have to mark them with the "div-toggle" class, set their id's and create their respective buttons.
var divs = document.getElementsByClassName('div-toggle');
function toggle(id) {
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
if (div.id == id)
div.style.display = 'block';
else
div.style.display = 'none';
}
}
<a href="#" onclick="toggle('MAY')" >MAY</a>
<a href="#" onclick="toggle('JUNE')" >JUNE</a>
<!-- first div, shows on page load -->
<div class="div-toggle" style="display:block;" id="MAY">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>May 2017</strong></h1>
</div>
</div>
<!-- second div, hidden originally -->
<div class="div-toggle" style="display:none;" id="JUNE">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>June 2017</strong></h1>
</div>
</div>

div.style.visibility = "hidden"
this will completely hide your div. I'm pretty sure this is what you are asking for
also instead of that you can make a separate function and add o'clock to div
<div onclick="nameoffunction()"></div>
the function can take in a parameter and each div on click function can have the parameter of its id

Your div were messed up! The snippet is working now with the help of jQuery.
$("#JUNE").hide();
$("#MAY").show();
$('#button-may').on("click", function() {
$("#JUNE").hide();
$("#MAY").show();
});
$('#button-june').on("click", function() {
$("#JUNE").show();
$("#MAY").hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
MAY
JUNE
<!-- first div, shows on page load -->
<div id="MAY">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>May 2017</strong></h1>
</div>
</div>
<!-- second div, hidden originally -->
<div class="hidden" id="JUNE">
<div style="background-color: lightgrey">
<h1 style="padding: 5px"><strong>June 2017</strong></h1>
</div>
</div>

Related

Display none some content and block one element

I would like to make 3 buttons with each one make all the content div to display: none and depending on the button you have click one of the content div change to display: block. For example, If I click on the second button It will show only the second div content.
function showPanel(id) {
var elements = document.getElementsByClassName("content");
for (let i = 0; i < elements.length; i++) {
document.getElementById(i).style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<div class="content">
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
There's a couple of issues in your code. Firstly length is a property, not a method, so you don't need the () suffix to invoke it. Secondly, there's no className attribute in HTML. This should just be class. Lastly the parent container shares the same class as the elements you're hiding, so all the child elements get hidden, even if they have display: block applied to them.
With these issues corrected, your code would look like this:
function showPanel(id) {
var elements = document.getElementsByClassName("panel");
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('p1')">test1</button>
<button onclick="showPanel('p2')">test2</button>
<button onclick="showPanel('p3')">test3</button>
<div class="content">
<div id="p1" class="panel">
<p>TEST1</p>
</div>
<div id="p2" class="panel">
<p class="other">TEST2</p>
</div>
<div id="p3" class="panel">
<p class="other">TEST3</p>
</div>
</div>
However it's worth noting that using onX attributes is outdated and not good practice. A better solution would be to use unobtrusive event handlers and provide custom metadata to the event handler through data attributes placed on the elements.
The improved version of the logic would look like this:
let buttons = document.querySelectorAll('button');
let panels = document.querySelectorAll('.panel');
buttons.forEach(button => {
button.addEventListener('click', e => {
panels.forEach(panel => {
panel.style.display = panel.id === e.target.dataset.panel ? 'block' : 'none';
});
});
});
<button data-panel="1">test1</button>
<button data-panel="2">test2</button>
<button data-panel="3">test3</button>
<div class="content">
<div id="1" class="panel">
<p>TEST1</p>
</div>
<div id="2" class="panel">
<p class="other">TEST2</p>
</div>
<div id="3" class="panel">
<p class="other">TEST3</p>
</div>
</div>
No need for JS or Jquery. Instead of a button you can use an anchor tag. Then you calling with the anchor the id of the element. Last but not least you make the boxes hidden through CSS and use the :target selector to display the elements:
.content {
display: none;
}
.content:target {
display: block;
}
test1<br>
test2<br>
test3<br>
<div class="content-container">
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
Multiple issues.
Length can be calculated using elements.length and not elements.length()
You have given same class name to both the parent and the child divs. So hiding all elements with class name content will hide your whole parents itself. So after updating style.display = "block" to the required target, it will not work. Because your parent is already style.display = "none". So you should make a logic update there. So I changed the parent class name.
function showPanel(id) {
var elements = document.getElementsByClassName("content");
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = "none";
}
document.getElementById(id).style.display = "block";
}
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<div>
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p class="other">TEST2</p>
</div>
<div id="3" class="content ">
<p class="other">TEST3</p>
</div>
</div>
A more elegant way I might approach a prob,problem like this would be to tie the panels and their triggers together using data-attributes. This way, you don't risk conflicts with other IDs that m ay be the same on the page (IDs should always be unique).
Before setting up my event listener, I would initialize an openPanel variable and set it to any panel that is already created with the active class name. Whenever we open a new panel, we will overwrite this variable vaklue, so we don't need to do a new querySelctor each time.
Then, in the CSS, rather than hiding all panels and then showing the one with the active class, we can write a single style that hides any panels without the active class using the :not negation selector.
This is how that would look (initializing this with panel #1 open by default, but you can simply remove the active class from it in the HTML if you don't want that):
let openPanel = document.querySelector('[data-panel-id].active');
document.addEventListener('click', e => {
if (e.target?.matches?.('[data-panel-target]')) {
const id = e.target.dataset.panelTarget;
if (id) {
const panel = document.querySelector(`[data-panel-id="${id}"]`);
if (panel) {
openPanel?.classList.remove('active');
panel.classList.add('active');
openPanel = panel;
}
}
}
})
[data-panel-id]:not(.active) {
display: none;
}
<button data-panel-target="1">test1</button>
<button data-panel-target="2">test2</button>
<button data-panel-target="3">test3</button>
<main>
<div data-panel-id="1" class="active">
<p>TEST #1</p>
</div>
<div data-panel-id="2">
<p>TEST #2</p>
</div>
<div data-panel-id="3">
<p>TEST #3</p>
</div>
</main>
I already submitted a separate solution with my preferred recommendation, but I wanted to provide an answer to your question using the same approach you started with so as not to deviate from the code you already have in place.
The code you already had in place was actually fairly close to working already. The main issue I saw was that you were using document.getElementById(i) where you should actually have been using elements[i]. We can improve this further though, by replacing the for loop with a for..of loop, and determining inline whether the current element being evaluated is the one we want to show. If so, we use 'block', otherwise 'none'.
After initializing our function, we can call it on one of our IDs within the JS to have one panel open by default. **It's also important that the parent of all these .content elements NOT contain the class name content as well, as that would conflict with your function. I have replaced that parent element with a simple <main>…</main> element.
Here is how I would achieve solving this using your existing approach:
function showPanel(contentId) {
const elements = Array.from(document.getElementsByClassName('content'));
for (const element of elements) {
element.style.display = element.id === contentId ? 'block' : 'none';
}
}
showPanel('1');
<button onclick="showPanel('1')">test1</button>
<button onclick="showPanel('2')">test2</button>
<button onclick="showPanel('3')">test3</button>
<main>
<div id="1" class="content">
<p>TEST1</p>
</div>
<div id="2" class="content">
<p>TEST2</p>
</div>
<div id="3" class="content ">
<p>TEST3</p>
</div>
</main>

JQuery hide() not persisting after hide event

I'm trying to hide a visible section then show a hidden section using JQuery .hide() and .show(). When the event fires (on clicking an image) it only hides the visible section momentarily, then becomes visible again with the previously hidden section now visible below the first visible section. Based on the docs I've read and some tutorials I've watched this shouldn't be happening.
HTML:
<div class="transition-div">
<section class="project-section">
<div class="project-wrapper" id="project-one">
<div class="desc-text">
<h2>Header</h2>
</div>
<div class="project-image-wrapper">
<img class="project-image" id="project-img-one" src="images/img1.png">
<button class="project-button">Button
</button>
</div>
</div>
</section>
<section class="project-section hidden">
<div class="project-wrapper">
<div class="desc-text">
<h2>Header</h2>
<p>Some description text</p>
</div>
<div class="project-image-wrapper">
<img class="project-image" src="images/img1.png">
</div>
</div>
</section>
</div>
JS:
$('.hidden').hide();
var slideSection = function() {
$('.project-image-wrapper').click(function() {
var $parentDiv = $(this).parents('.transition-div');
var $childToShow = $parentDiv.find('.hidden');
var $childToHide = $childToShow.siblings('.project-section');
$childToHide.hide(300, hideActiveSection());
function hideActiveSection() {
$childToHide.addClass('hidden');
$childToShow.show(300, function() {
$(this).removeClass('hidden');
});
}
});
};
slideSection();
How would I get the section I want to hide to do so persistently until I click the currently visible project image to show it? Could my CSS be interfering with what I want to do here? If so I'll post the code. Thanks!

How to show one div and hide another div in javascript on same html page

I am having one html page in which all navigation (lets say them the TABS) resides.
I wrote a javascript to show one and hide another one on link click.
It works well on the tab i want but when i navigate to another tabs that div is showing on the bottom. I dont want it to display it in all other tabs.
This is my javascript code:
function displayBlock(divName){
if(document.getElementById("vend")) {
var oldDiv = document.getElementById("vend");
oldDiv.style.display = 'none';
//show div
var newDiv = document.getElementById(divName);
newDiv.style.display = 'block';
}
else{
var newDiv = document.getElementById(divName);
newDiv.style.display = 'none';
}
}
How to modify it to meet the need?
HTML Structure:
<div class="tab-content">
<div class="tab-pane" id="dashboard">
<div class="container">
<!-- Container code -->
</div>
</div>
<div class="tab-pane" id="vend">
<div class="container">
<!-- Container code -->
<a id="auto-topup2" href="dashboard#auto-topup" onclick="displayBlock('schedule');">
Schedule Autovend
</a>
</div>
</div>
<div class="tab-pane" id="commision">
<div class="container">
<!-- Container code -->
</div>
</div>
<div id="schedule" style="display:none">
<div class="tab-pane" id="auto-topup">
<div class="container">
<!-- Container code -->
</div>
</div>
</div>
In the vend section i have created a whose onclick will call the function and hide the Div with vend id and show Div with schedule ID....But the DIV with scehdule ID is showing in all the tabs..
I hope now it can be somewhat undestandable
To hide all tabs without the selected one you can use this function:
function displayBlock(idOfBlock) {
document.getElementByClass('block').style.display = 'none';
document.getElementById(idOfBlock).style.display = 'block'
}
<div class="block" id="hello">
hello
</div>
<div class="block" id="foobar">
foobar
</div>

toggle visibility multiple divs javascript

Afternoon guys, I am hoping you can help me put the finishing touches to this page. Basically I have four links - each of which will be linked to a different version of content - that will be displayed in the same 3 divs by way of togglevisibility. That is to say that onload, the first link’s content will be displayed (in the three divs) and then the aim is that when another of the four links is clicked, the visible content from the open link closes and the clicked link’s content opens instead. (One thing I have successfully avoided in the code I have so far - and am eager to avoid in the final model - is toggling the page to empty. That is to say if link1’s content is displayed and you click on link1 again, the content stays visible and does not simply toggle on and off.)
Now using the markup below I am oh so close (!) except for the following…
When the page loads the first link’s content is displayed as I want to be, but whenever you click one of the other 3 links it is only div1’s content that successfully loads while the other two divs become empty. I have attempted to alter the toggleVisibility coding (quite crudely I know!) so that each of the 4 links are dealt with as follows;
<a href=“#” onclick=“togglevisibility(‘link1div1’); togglevisibility(‘link1div2’);togglevisibility(‘link1div3’);”>Link 1</a>
Is there a way to fix this error from within the link line (above) so that clicking the link loads the corresponding content into all three divs and not just the first? I am sure it is something simple that I have overlooked or ill-coded!
Thanks very much for your time and advice in advance.
CSS
.section {display:none;}
#link1div1 {display:block;}
#link1div2 {display:block;}
#link1div3 {display:block;}
HTML
<a href=“#” onclick=“togglevisibility(‘link1div1’); togglevisibility(‘link1div2’);togglevisibility(‘link1div3’);”>Link 1</a>
<a href=“#” onclick=“togglevisibility(‘link2div1’); togglevisibility(‘link2div2’);togglevisibility(‘link2div3’);”>Link 2</a>
<a href=“#” onclick=“togglevisibility(‘link3div1’); togglevisibility(‘link3div2’);togglevisibility(‘link3div3’);”>Link 3</a>
<a href=“#” onclick=“togglevisibility(‘link4div1’); togglevisibility(‘link4div2’);togglevisibility(‘link4div3’);”>Link 4</a>
<div id=“div1”>
<div id=“link1div1” class=“section”></div>
<div id=“link2div1” class=“section”></div>
<div id=“link3div1” class=“section”></div>
<div id=“link4div1” class=“section”></div>
</div>
<div id=“div2”>
<div id=“link1div2” class=“section”></div>
<div id=“link2div2” class=“section”></div>
<div id=“link3div2” class=“section”></div>
<div id=“link4div2” class=“section”></div>
</div>
<div id=“div3”>
<div id=“link1div3” class=“section”></div>
<div id=“link2div3” class=“section”></div>
<div id=“link3div3” class=“section”></div>
<div id=“link4div3” class=“section”></div>
</div>
JS
<script type="text/javascript">
function toggleVisibility(selectedTab) {
var section = document.getElementsByClassName('section')
for(var i=0; i<section.length; i++) {
if(section[i].id == selectedTab) {
section[i].style.display = 'block';
} else {
section[i].style.display = 'none';
}
}
}
</script>
I would minimise the use of javascript and do that using css, like this:
DEMO HERE
javascript:
function clickHandler(lnk) {
document.getElementById('sections').className = lnk;
return false;
}
css:
#sections .section {display:none;}
#sections.link1 .link1,
#sections.link2 .link2,
#sections.link3 .link3,
#sections.link4 .link4 { display: block; }
html:
Link 1
Link 2
Link 3
Link 4
<div id="sections" class="link1">
<div id="div1">
<div id="link1div1" class="section link1">11</div>
<div id="link2div1" class="section link2">21</div>
<div id="link3div1" class="section link3">31</div>
<div id="link4div1" class="section link4">41</div>
</div>
<div id="div2">
<div id="link1div2" class="section link1">12</div>
<div id="link2div2" class="section link2">22</div>
<div id="link3div2" class="section link3">32</div>
<div id="link4div2" class="section link4">42</div>
</div>
<div id="div3">
<div id="link1div3" class="section link1">13</div>
<div id="link2div3" class="section link2">23</div>
<div id="link3div3" class="section link3">33</div>
<div id="link4div3" class="section link4">43</div>
</div>
</div>
The reason only one of those is showing is because when you run toggle visibility youre getting every element with the class section then toggling them all off except for the ONE that is called into the function. So when your onclick is done running youve turned on the first two then turned them off when you call the last one.
A simple fix would be to give each div in the big div a classname determining the link.
<div id=“div3”>
<div id=“link1div3” class=“section link1”></div>
<div id=“link2div3” class=“section link2”></div>
<div id=“link3div3” class=“section link3”></div>
<div id=“link4div3” class=“section link4”></div>
</div>
Do the same for the other divs. Then your links be like this ....
<a href=“#” onclick=“togglevisibility(‘link1’);>Link 1 </a>
Change your javascript to.
<script type="text/javascript">
function toggleVisibility(selectedClass) {
var turnOn = document.getElementsByClassName('selectedClass');
var allDivs = document.getElementsByClassName('section');
for(var i=0; i<section.length; i++) { //this for loop hides all the divs
section[i].style.display = 'none';
}
for(var i=0; i<turnOn.length; i++) { // this for loop shows the divs
turnOn[i].style.display = 'block'; // with the link1 class
}
}
</script>
This solution if it works (I havent been able to test) will also keep something on the page at all times which I saw you mentioned in bold in your post.

Accordion Box malfunction in firefox

i have the following function written in javascript which operate a slide up/down box. but in firefox, it malfunctions. it just opens/closes once. after that no play.
i am getting the height() param from the box and storing it in hidden input. but firefox is unable to read the correct height of the box.
look at the code to understand better :
JS :
function boxCollapse() {
$("#boxHeight").attr("value", parseInt($("#accTipsBox").height()));
$("#accTipsBox").animate({height:'0px'});
$(".btnCollapse").css({display:'none'});
$(".btnExpand").css({display:'block'});
$("#accTipsBox").css({padding:'0px'});
}
function boxExpand() {
$("#accTipsBox").animate({height: $("#boxHeight").attr("value")});
$(".btnExpand").css({display:'none'});
$(".btnCollapse").css({display:'block'});
$("#accTipsBox").css({padding:'0px'});
}
HTML :
<section class="accBox grey">
<header>
<div class="title">DISCLAIMERS</div>
<a style="display: none;" class="btnExpand" href="javascript:void(0);"><img src="/resources/images/boxExpandGrey.jpg" alt="button"></a>
<a style="display: block;" class="btnCollapse" href="javascript:void(0);"><img src="/resources/images/boxCollapseGrey.jpg" alt="button"></a>
</header>
<div id="accTipsBox" style="height: 125px; padding: 0px;">
<input type="hidden" id="boxHeight" value="125">
<div class="accBoxContent">
<div><p></p><p></p><p></p></div>
</div>
</div>
</section>
I think this is what you were going for:
//bind a `click` event handler to all the elements with the `btnExpandCollapse` class
$('.btnExpandCollapse').on('click', function (event) {
//stop the default behavior of clicking the link (stop the browser from scrolling to the top of the page)
event.preventDefault();
//first select the parent of this element (`header` tag) and then get its sibling element that has the `accTipsBox` class, then take that element and slide it up or down depending on its current state
$(this).parent().siblings('.accTipsBox').slideToggle(500);
});
With some slight tweaks to your HTML:
<section class="accBox grey">
<header>
<div class="title">DISCLAIMERS</div>
<!-- Notice there is only one link now that does the job of both -->
<a class="btnExpandCollapse" href="#"><img src="/resources/images/boxExpandGrey.jpg" alt="button"></a>
</header>
<!-- Notice I changed the ID attribute to CLASS so this code will work for repeated structure -->
<div class="accTipsBox" style="height: 125px; padding: 0px;">
<div class="accBoxContent">
<div>
<p>1</p>
<p>2</p>
<p>3</p>
</div>
</div>
</div>
</section>
Here is a demo: http://jsfiddle.net/VGN64/
Here is some documentation:
.slideToggle(): http://api.jquery.com/slidetoggle
.siblings(): http://api.jquery.com/siblings
On a side-note, if you want to store data about a DOM element, use jQuery's $.data() method:
var $box = $("#accTipsBox");
$.data($box[0], 'height', $box.height());
You can then access this data like this
var height = $.data($('#accTipsBox')[0], 'height');
Notice that I appended [0] onto the end of the jQuery object to return just the DOM node associated with the object, this is required by the $.data() method: http://api.jquery.com/jquery.data. This is a very fast method of storing data associated with DOM elements.

Categories