Toggle between divs: How to show only one div at a time? - javascript

I have two div's with different content. I managed to add show-hide div function when clicking on a button. The problem is, when one div is visible and I click on the second button, they are both visible. I would like to show only one div at a time - while one div is shown and I click on another button, the previous div should hide automatically.
I would not want to use jQuery, hope it's possible with pure JavaScript only.
function horTxtFunction() {
var x = document.getElementById("horTxt");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function verTxtFunction() {
var x = document.getElementById("verTxt");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<button onclick="horTxtFunction()">Horisontaalne tekstiga</button>
<button onclick="verTxtFunction()">Vertikaalne tekstiga</button>
<div id="horTxt" style="display:none;">
<p>Some content here</p>
</div>
<div id="verTxt" style="display:none;">
<p>Some different content here</p>
</div>

Consider wrapping the two <div> tags in a controller <div> tag and then using "state" to control which child <div> will show.
In the example below I am using the attribute dir to hold the state and the CSS to play off the state and the children <div> classes.
var holder = document.querySelector("[dir]");
function horTxtFunction() {
holder.setAttribute('dir', 'hor');
}
function verTxtFunction() {
holder.setAttribute('dir', 'ver');
}
[dir="ver"] > :not(.verTxt),
[dir="hor"] > :not(.horTxt) {
display: none;
}
<button onclick="horTxtFunction()">Horisontaalne tekstiga</button>
<button onclick="verTxtFunction()">Vertikaalne tekstiga</button>
<div dir="hor">
<div class="horTxt">
<p>Some content here</p>
</div>
<div class="verTxt">
<p>Some different content here</p>
</div>
</div>
The major benefit of doing it this way is if you need to add additional children:
var holder = document.querySelector("[dir]");
function toggle(val) {
holder.setAttribute('dir', val);
}
[dir="ver"] > :not(.verTxt),
[dir="hor"] > :not(.horTxt),
[dir="left"] > :not(.leftTxt),
[dir="right"] > :not(.rightTxt) {
display: none;
}
<button onclick="toggle('hor')">Horizontal</button>
<button onclick="toggle('ver')">Vertical</button>
<button onclick="toggle('left')">Left</button>
<button onclick="toggle('right')">Right</button>
<div dir="hor">
<div class="horTxt">
<p>Some content here</p>
</div>
<div class="verTxt">
<p>Some different content here</p>
</div>
<div class="leftTxt">
<p>This is the left text area</p>
</div>
<div class="rightTxt">
<p>This is the right text area</p>
</div>
</div>
Here I change to a single event handler and pass in the section I want to show. Then I had to extend the CSS to handle the new <div> tags. But now growing to more children is just adding the buttons, divs and CSS.
UPDATE
To hide all <div> tags first I made a minor change:
var holder = document.querySelector(".holder");
function toggle(val) {
holder.setAttribute('dir', val);
}
.holder > div {
display: none;
}
[dir=ver] > .verTxt,
[dir=hor] > .horTxt,
[dir=left] > .leftTxt,
[dir=right] > .rightTxt {
display: block;
}
<button onclick="toggle('hor')">Horizontal</button>
<button onclick="toggle('ver')">Vertical</button>
<button onclick="toggle('left')">Left</button>
<button onclick="toggle('right')">Right</button>
<div class="holder">
<div class="horTxt">
<p>Some content here</p>
</div>
<div class="verTxt">
<p>Some different content here</p>
</div>
<div class="leftTxt">
<p>This is the left text area</p>
</div>
<div class="rightTxt">
<p>This is the right text area</p>
</div>
</div>
This hides all of the internal <div> tags and then only shows the correct one based on the value of the dir attribute. Since there is no dir attribute to start then no internal <div>s will show.

You need to make sure to hide the other div and not just show the other.
function horTxtFunction() {
var x = document.getElementById("horTxt");
var otherDiv = document.getElementById("verTxt");
if (x.style.display === "none") {
x.style.display = "block";
overDiv.style.display = "none";
} else {
x.style.display = "none";
overDiv.style.display = "block";
}
}

Related

What's a simple, non-jquery way to toggle between two divs using two buttons?

I'm looking for a simple, non-jquery method of toggling between two divs. Specifically, clicking button A will show div A content (and hide div B content), and clicking button B will show div B content (and hide div A content. I want div A content to appear by default when the page loads.
The code I have isn't hiding the appropriate divs from the onclick
I've looked around, but every solution seems overly complex or seems to involve jquery - which I would really prefer not to use, because I have to work with an old jquery library on a site where I shouldn't be updating that stuff.
<button class="button" onclick="content_A(); Hide_Content_B;">Content A</button>
<button class="button" onclick="content_B(); Hide_Content_A;">Content B</button>
<script>
function Content_A() {
var x = document.getElementById("A");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
<script>
function Hide_Content_B() {
var x = document.getElementById("B");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
</script>
<script>
function Content_B() {
var x = document.getElementById("B");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
<script>
function Hide_Content_A() {
var x = document.getElementById("A");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
</script>
<div id="A"> stuff</div>
<div id="B"> other stuff </div>
Create one function showContent that takes the id of the element you want
to toggle as parameter and just toggles a CSS class, i.e visible on the element with that id.
Use CSS classes to initially hide the "toggleable" elements. You can set the visible class directly on the element you want shown on page load.
Here's an example:
function showContent(id) {
document.getElementById(id).classList.toggle('visible')
}
/*
All elements with class "toggleable"
should be hidden.
*/
.toggleable {
display: none;
}
/*
All elements that have both
class "toggleable" and "visible"
should be visible.
*/
.toggleable.visible {
display: block;
}
<button onclick="showContent('a');" >Show Content A</button>
<button onclick="showContent('b');" >Show Content B</button>
<div class="toggleable visible" id="a">
Hello Content A!
</div>
<div class="toggleable" id="b">
Hello Content B!
</div>
About your code:
You have to call the function using parenthesis like Hide_Content_A() and Hide_Content_B(); which are misssing in onclick of the <button>
The functions Content_B and Content_B start with uppercase C.
The fix your own code, just run Hide_Content_B(); at the end to hide the second one.
Note that you can also use a single <script> block.
function Content_A() {
var x = document.getElementById("A");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function Hide_Content_B() {
var x = document.getElementById("B");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
function Content_B() {
var x = document.getElementById("B");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function Hide_Content_A() {
var x = document.getElementById("A");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "none";
}
}
Hide_Content_B();
<button class="button" onclick="Content_A(); Hide_Content_B();">Content
A
</button>
<button class="button" onclick="Content_B(); Hide_Content_A();">Content
B
</button>
<div id="A"> stuff</div>
<div id="B"> other stuff</div>
If you dont want to use jQuery, you should consider not using javascript at all.
You can do the same with pure css. Also the styling of button tags some times brakes in other devices, so I suggest to use tag or just a span
Here is a pure CSS solution:
input {
display:none;
}
input[name="toggle"] + .toggleContent{
max-height: 0;
overflow: hidden;
transition: max-height .4s;
}
input[name="toggle"]:checked + .toggleContent{
max-height: 100px;
}
<label for="A">A Button</label>
<input type="radio" name="toggle" value="1" id="A" checked="checked">
<div class="toggleContent">This is content for A</div>
<label for="B">B Button</label>
<input type="radio" name="toggle" value="2" id="B">
<div class="toggleContent">This is content for B</div>
Here's a simple solution that requires jQuery 1.7 or above, since you mentioned that you're working with an old jQuery library!
$(document).on('click', '.map-point-sm', function() {
var show = $(this).data('show');
$(show).removeClass("hide").siblings().addClass("hide");
});
.hide {
display: none;
}
.map-container {
text-align: center;
}
button{
width: 5%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<div class="map-container">
<div class="inner-basic division-map div-toggle" data-target=".division-details" id="divisiondetail">
<button class="map-point-sm" data-show=".a">
<div class="content">
<div class="centered-y">
<p>A</p>
</div>
</div>
</button>
<button class="map-point-sm" data-show=".b">
<div class="content">
<div class="centered-y">
<p>B</p>
</div>
</div>
</button>
</div>
</div>
<div class="map-container">
<div class="inner-basic division-details">
<div class="initialmsg">
<p>A Content here</p>
</div>
<div class="a hide">
<p>A Content here</p>
</div>
<div class="b hide">
<p>B Content here</p>
</div>
</div>
</div>
There are some great answers here, but I think I'll probably go with The fourth bird's because it's the simplest. Thanks everybody!
If you are interested in a non-JS solution, you can use sibling input elements to perform a button toggle effect. Simply match the for attributes with the id attributes.
form {
display: flex;
flex-wrap: wrap;
}
input {
display: none;
}
input:checked + label {
background-color: #eee;
}
label {
cursor: pointer;
padding: 12px;
display: inline-block;
}
.container {
display: none;
background-color: #eee;
order: 1;
padding: 12px;
width: 100%;
}
input:checked + label + .container {
display: block;
}
<form>
<input id="a" type="radio" name="container" checked="checked">
<label for="a">button a</label>
<div class="container">content a</div>
<input id="b" type="radio" name="container">
<label for="b">button b</label>
<div class="container">content b</div>
</form>

How could I make sure that at least one DIV is always shown?

I have this piece of code I found that will show or hide a DIV using javascript. It only allows one div to be shown which is what I want. However, I want it where at least one DIV is always shown at a time. It basically toggles between hiding and showing them currently. I want it to be where if i hit DIV two again, it wont hide it and it will do nothing.
Please help, thank you.
page.html
<script src="scripts/pages.js"></script>
<div class="main_div">
<div class="inner_div">
<div id="Div1">I'm Div One</div>
<div id="Div2" style="display: none;">I'm Div Two</div>
<div id="Div3" style="display: none;">I'm Div Three</div>
<div id="Div4" style="display: none;">I'm Div Four</div>
</div>
<div class="buttons">
Div1 |
Div2 |
Div3 |
Div4
</div>
</div>
pages.js
var divs = ["Div1", "Div2", "Div3", "Div4"];
var visibleDivId = null;
function divVisibility(divId) {
if(visibleDivId === divId) {
visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
function hideNonVisibleDivs() {
var i, divId, div;
for(i = 0; i < divs.length; i++) {
divId = divs[i];
div = document.getElementById(divId);
if(visibleDivId === divId) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
You can simplify your code to following. Where you hide all the divs and show the div corresponding to the clicked element.
function divVisibility(divId) {
document.querySelectorAll(".inner_div > div").forEach(e => e.style.display = 'none');
document.getElementById(divId).style.display = 'block';
}
<div class="main_div">
<div class="inner_div">
<div id="Div1">I'm Div One</div>
<div id="Div2" style="display: none;">I'm Div Two</div>
<div id="Div3" style="display: none;">I'm Div Three</div>
<div id="Div4" style="display: none;">I'm Div Four</div>
</div>
<div class="buttons">
Div1 |
Div2 |
Div3 |
Div4
</div>
</div>
The part that causes this function to hide a div is the setting of visibleDivId to null.
function divVisibility(divId) {
if(visibleDivId === divId) {
// visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
Commenting that line out (see line 3) keeps the clicked div as the visibleDivId and the second function (hideNonVisibleDivs) won't hide it.

how to avoid rewriting java script code?

I am looking for a way to avoid rewriting the same code again and again.
I am making a web page that has divs with hide and show option, with the help of a button you toggle between hide and show. I found an easy way to achieve the effect with this code:
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction()">Try it</button>
<div id="myDIV">
This is my DIV element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
This works perfectly but gets a bit tedious when you have a dozen or more divs with said effect. Is there a way to avoid having to rewrite the function for each and every div?
Thank you! :)
Easy, parameterize the id:
function myFunction(divId) {
var x = document.getElementById(divId);
and in the HTML pass the id to the function:
<button onclick="myFunction('myDIV')">Try it</button>
<div id="myDIV"> ...</div>
<button onclick="myFunction('myOtherDIV')">Try it</button>
<div id="myOtherDIV"> ...</div>
... and so on ...
You can keep one single function and handle as many divs as you want.
You could run the javascript function with a parameter. So you only have one function and then you only need to change the parameter name. See the example below.
function myFunction(div) {
var x = document.getElementById(div);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction('myDIV')">Try it</button>
<button onclick="myFunction('myDIV2')">Try it2</button>
<div id="myDIV">
This is my DIV element.
</div>
<div id="myDIV2">
This is my DIV2 element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
</body>
Just pass the div id to a function
function toggleDiv(divId) {
var x = document.getElementById(divId);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
This works perfectly but gets a bit tedious when you have a dozen or
more divs with said effect
Create an array of such div ids to be toggled and iterate the same, for example
var divIds = ["myDIV1", "myDIV2", "myDIV3"];
divIds.forEach( s => toggleDiv(s) );
Pass a parameter into the function.
function myFunction(divName) {
var x = document.getElementById(divName);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction('myDIV')">Try it</button>
<div id="myDIV">
This is my DIV element.
</div>
<button onclick="myFunction('myDIV2')">Try it</button>
<div id="myDIV2">
This is my DIV2 element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
</body>
using event target and operating relatively on elements, can do the task.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<hr>
<div class="wrapper">
<button onclick="myFunction(event)">Try first</button>
<div class="content">
This is my DIV element.
</div>
</div>
<hr>
<div class="wrapper">
<button onclick="myFunction(event)">Try second</button>
<div class="content">
This is my DIV element.
</div>
</div>
<hr>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
<script>
function myFunction(event) {
var wrapper = event.target.parentElement;
var content = wrapper.querySelector('.content');
if (content.style.display === "none") {
content.style.display = "block";
} else {
content.style.display = "none";
}
}
</script>
</body>
</html>
function myFunction() {
var x = document.getElementsByClassName("myDIV");
for (let i = 0; i < x.length; i++){
x[i].style.display = x[i].style.display == "none" ? "block" : "none";
}
}
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<button onclick="myFunction()">Try it</button>
<div class="myDIV">
This is my DIV element.
</div>
<div class="myDIV">
This is my DIV element.
</div>
<div class="myDIV">
This is my DIV element.
</div>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
</body>
function toggleVisibility(selector) {
const elements = document.querySelectorAll(selector);
elements.forEach( element => {
const isVisible = element.offsetHeight;
if (isVisible) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
});
}
<button onclick="toggleVisibility('#myDIV')">Try it</button>
<button onclick="toggleVisibility('.toggle')">Try it with className</button>
<div id="myDIV">
This is my DIV element.
</div>
<div class="toggle">
This is my DIV element.
</div>
<div class="toggle">
This is my DIV element.
</div>

Show/hide multiple Divs with links

I didn't clearly explain what I was trying to do. Hopefully this will be better.
Currently I'm using this Fiddle to toggle some divs. It acts as an accordion and shows only one div at a time. Clicking one of the titles will show the content of that div and clicking another title will hide the first div and show that one.
What I am having trouble with (and would like to do) is when opening one div I would like to hide access to the other divs until that first div is closed.
Meaning if I Click on "Content2" to show that content, I would like to hide access to Content1, Content3, and Content4 until Content 2 is closed again.
function ReverseDisplay(d) {
var els = document.querySelectorAll('.toggle.active:not(#' + d + ')');
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('active');
}
document.getElementById(d).classList.toggle('active')
}
.toggle {
display: none;
}
.toggle.active {
display: block;
}
<a href="javascript:ReverseDisplay('content1')">
Content1
</a>
<a href="javascript:ReverseDisplay('content2')">
Content2
</a>
<a href="javascript:ReverseDisplay('content3')">
Content3
</a>
<a href="javascript:ReverseDisplay('content4')">
Content4
</a>
<div id="content1" class="toggle">
<p>Content 1 goes here.</p>
</div>
<div id="content2" class="toggle">
<p>Content 2 goes here.</p>
</div>
<div id="content3" class="toggle">
<p>Content 3 goes here.</p>
</div>
<div id="content4" class="toggle">
<p>Content 4 goes here.</p>
</div>
This should work... Use the id passed to identify the element and add class by checking if active exists.
function ReverseDisplay(d) {
var id = d
var el = document.getElementById(id)
var elClassList = el.classList
var [...active] = document.querySelectorAll('.toggle.active')
debugger
if (active.length === 0) {
el.classList.add('active')
} else if (id === active[0].id) {
el.classList.remove('active')
}
}
.toggle {
display: none;
margin-top: 40px;
}
.toggle.active {
display: block;
}
a {
position: fixed;
top: 10px;
}
<a href="javascript:ReverseDisplay('uniquename')">
Click to show/hide.
</a>
<div id="uniquename" class="toggle">
<p>Content 1 goes here.</p>
</div>
<a href="javascript:ReverseDisplay('uniquename1')" style="left:150px">
Click to show/hide.
</a>
<div id="uniquename1" class="toggle">
<p>Content 2 goes here.</p>
</div>
Use this javascript function in order to achieve accordion style behaviour, for as many links as you might want to have.
function ReverseDisplay(d) {
var els = document.getElementById(d);
if (els.classList.contains('active')){
els.classList.remove('active');
}else{
var activeDivs = document.getElementsByClassName('active');
for (var i = 0; i < activeDivs.length; i++) {
activeDivs[i].classList.remove('active');
}
els.classList.add('active');
}
}

Javascript error [object HTMLParagraphElement]

I`m begginer in Javascript and I need some help.
So, I need that, when I push the button, paragraph "leftside" appear
<div id="content">
<script>
function myFunction() {
document.getElementById("contentp").innerHTML = leftside;
var x = document.getElementById("leftside")
x.style.display = "normal";
}
</script>
<button id="buttonI" type="button" onclick="myFunction()">Show left side!</button>
<p id="leftside" style="display: none">Left side</p>
<p id="contentp"></p>
x.style.display = "block";
set it block or another value of display except none
You have to append the leftside to the contentp and set its display property to block. normal is not a valid option
<script>
function myFunction() {
document.getElementById("contentp").appendChild(document.getElementById("leftside"));
document.getElementById("leftside").style.display = "block";
}
</script>
<button id="buttonI" type="button" onclick="myFunction()">Show left side!</button>
<p id="leftside" style="display: none">Left side</p>
<p id="contentp"></p>

Categories