Hide div when other div is showing - javascript

I am building a page with 3 buttons, each opening a different div-element. What I want, is to show just one div at the time. So when one div is opened, the other div should close.
I managed to create the buttons each opening a different div-element. But I cannot figure out a way to automatically close the div when other div is opened.
var button1 = document.getElementById("button1");
var button2 = document.getElementById("button2");
var button3 = document.getElementById("button3");
var content1 = document.getElementById("content1");
var content2 = document.getElementById("content2");
var content3 = document.getElementById("content3");
content1.style.display = "none";
content2.style.display = "none";
content3.style.display = "none";
button1.addEventListener("click", showContent1);
button2.addEventListener("click", showContent2);
button3.addEventListener("click", showContent3);
function showContent1() {
if (content1.style.display !== "none") {
content1.style.display = "none"
} else {
content1.style.display = "block";
}
}
function showContent2() {
if (content2.style.display !== "none") {
content2.style.display = "none"
} else {
content2.style.display = "block";
}
}
function showContent3() {
if (content3.style.display !== "none") {
content3.style.display = "none"
} else {
content3.style.display = "block";
}
}
#button1,
#button2,
#button3 {
width: 50px;
height: 50px;
background: lightblue;
margin: 5px;
cursor: pointer;
}
#content1,
#content2,
#content3 {
width: 100px;
height: 50px;
background: blue;
color: white;
margin: 5px;
}
<div id="button1">button 1</div>
<div id="button2">button 2</div>
<div id="button3">button 3</div>
<div id="content1">content 1</div>
<div id="content2">content 2</div>
<div id="content3">content 3</div>

You can cut down your code to something like this:
$("[id^=button]").click(function() {
var id = $(this).attr("id").replace("button", "")
$("#content" + id).toggle();
});
The code below will only allow 1 div to show at the time.
$("[id^=button]").click(function() {
var id = $(this).attr("id").replace("button", "");
$("[id^=content]").hide()
$("#content" + id).show();
});
Here we are using the ^ to say that we want all element starting with button to trigger the click event.
Demo
$("[id^=button]").click(function() {
var id = $(this).attr("id").replace("button", "")
$("#content" + id).toggle();
});
#button1,
#button2,
#button3 {
width: 50px;
height: 50px;
background: lightblue;
margin: 5px;
cursor: pointer;
}
#content1,
#content2,
#content3 {
width: 100px;
height: 50px;
background: blue;
color: white;
margin: 5px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="button1">button 1</div>
<div id="button2">button 2</div>
<div id="button3">button 3</div>
<div id="content1">content 1</div>
<div id="content2">content 2</div>
<div id="content3">content 3</div>

Here is a canonical way to do this.
Please study and look at where I delegate and have added classes
Use toggle() in the jQuery example to open AND close on click
jQuery:
$(".button").on("click", function(e) {
$(".content").hide();
$("#" + $(this).data("id")).show(); // or .toggle()
});
.button {
width: 50px;
height: 50px;
background: lightblue;
margin: 5px;
cursor: pointer;
}
.content {
width: 100px;
height: 50px;
background: blue;
color: white;
margin: 5px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="button" data-id="content1">button 1</div>
<div class="button" data-id="content2">button 2</div>
<div class="button" data-id="content3">button 3</div>
<div class="content" id="content1">content 1</div>
<div class="content" id="content2">content 2</div>
<div class="content" id="content3">content 3</div>
Vanilla JS
document.getElementById("nav").addEventListener("click", function(e) {
var tgt = e.target;
if (tgt.matches(".button")) {
document.querySelectorAll(".content").forEach(function(div) { // a simple for loop is needed for older IE
div.style.display = "none";
});
// Here I just show. If you want to toggle, you could use classList.toggle
document.getElementById(tgt.getAttribute("data-id")).style.display = "block";
}
});
.button {
width: 50px;
height: 50px;
background: lightblue;
margin: 5px;
cursor: pointer;
}
.content {
width: 100px;
height: 50px;
background: blue;
color: white;
margin: 5px;
display: none;
}
<div id="nav">
<div class="button" data-id="content1">button 1</div>
<div class="button" data-id="content2">button 2</div>
<div class="button" data-id="content3">button 3</div>
</div>
<div class="content" id="content1">content 1</div>
<div class="content" id="content2">content 2</div>
<div class="content" id="content3">content 3</div>

You can even create a tab system without any javascript at all, using the radio button css trick.
If a radio button is checked, then the next div is displayed, using the sibling selector: ~.
input{
display: none;
}
label{
display: inline-block;
padding: 3px;
border: 1px solid #aaa;
}
label:hover{
cursor: pointer;
}
.display{
display: none;
}
[type=radio]:checked ~ .display{
display: block;
}
<section>
<label for="div1">Show div 1</label>
<label for="div2">Show div 2</label>
<label for="div3">Show div 3</label>
</section>
<section>
<input type="radio" id="div1" name="tab-nav" checked />
<div class="display">
Text from div 1.
</div>
</section>
<section>
<input type="radio" id="div2" name="tab-nav" />
<div class="display">
Text from div 2. It's cool.
</div>
</section>
<section>
<input type="radio" id="div3" name="tab-nav" />
<div class="display">
Text from div 3. Definitely a cool css trick.
</div>
</section>
Here's another src and it's demo.

//find all buttons
document.querySelectorAll("button[data-target]").forEach(el => {
//put a click event on each button
el.addEventListener("click", ev => {
//when clicked, hide all divs
let divs = document.getElementsByClassName("my-div");
for (let div of divs) {
div.style = "display: none;";
}
//then show the div that this button should be showing
//by grabbing it's id from the data-target attribute and setting it's style
document.getElementById(el.getAttribute("data-target")).style = "display: block;";
});
});
.my-div {
display: none;
}
<button data-target="div1">div1</button>
<button data-target="div2">div2</button>
<button data-target="div3">div3</button>
<div class="my-div" id="div1">content 1</div>
<div class="my-div" id="div2">content 2</div>
<div class="my-div" id="div3">content 3</div>

Please refer to Accordion, if that is what you are ultimately trying to achieve.
Remove the condition in the button's click event if you do not want to hide the same content on second click.
SOLUTION:
button1.addEventListener("click", () => activeDiv = (activeDiv === "content1") ? "": "content1");
button2.addEventListener("click", () => activeDiv = (activeDiv === "content2") ? "": "content2");
button3.addEventListener("click", () => activeDiv = (activeDiv === "content3") ? "": "content3");
button1.addEventListener("click", openDivGroup);
button2.addEventListener("click", openDivGroup);
button3.addEventListener("click", openDivGroup);
var activeDiv = '';
function openDivGroup ($event) {
var contentIdArray = jQuery ("[id^=content]");
for (var i = 0; i < contentIdArray.length; i++) {
if (activeDiv === contentIdArray[i].id) contentIdArray[i].style.display = 'block';
else contentIdArray[i].style.display = 'none';
}
}
CODE SNIPPET:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
#button1,
#button2,
#button3 {
width: 50px;
height: 50px;
background: lightblue;
margin: 5px;
cursor: pointer;
}
#content1,
#content2,
#content3 {
width: 100px;
height: 50px;
background: blue;
color: white;
margin: 5px;
}
</style>
</head>
<body>
<div id="button1">button 1</div>
<div id="button2">button 2</div>
<div id="button3">button 3</div>
<div id="content1">content 1</div>
<div id="content2">content 2</div>
<div id="content3">content 3</div>
<script>
var button1 = document.getElementById("button1");
var button2 = document.getElementById("button2");
var button3 = document.getElementById("button3");
var content1 = document.getElementById("content1");
var content2 = document.getElementById("content2");
var content3 = document.getElementById("content3");
content1.style.display = "none";
content2.style.display = "none";
content3.style.display = "none";
button1.addEventListener("click", () => activeDiv = (activeDiv === "content1") ? "": "content1");
button2.addEventListener("click", () => activeDiv = (activeDiv === "content2") ? "": "content2");
button3.addEventListener("click", () => activeDiv = (activeDiv === "content3") ? "": "content3");
button1.addEventListener("click", openDivGroup);
button2.addEventListener("click", openDivGroup);
button3.addEventListener("click", openDivGroup);
var activeDiv = '';
function openDivGroup ($event) {
var contentIdArray = jQuery ("[id^=content]");
for (var i = 0; i < contentIdArray.length; i++) {
if (activeDiv === contentIdArray[i].id) contentIdArray[i].style.display = 'block';
else contentIdArray[i].style.display = 'none';
}
}
</script>
</body>
</html>

Related

How to Delete Element that has no ID? Select Element after hover?

I have a list with several boxes with the class (.box), these boxes cannot have an id attribute, when hovering over them it will show the Delete button (#btnDel) to remove the Element, the question is: How to select this element on hover, the delete button is a specific element, but this element does not have an id attribute, how do I make this selection (document.....)?
When hovering over the div.box, show the delete button and include the onclick=deleteElem('?') function to remove the specific div.box.
const list = document.getElementById('list');
//--Select Delete Button id(btnDel) --//
const btnDel = document.getElementById('btnDel');
list.addEventListener('mouseenter', e => {
if (e.target.matches('.box')) {
//-- coordinates ---//
let rect = e.target.getBoundingClientRect();
//-- Show Delete Button --//
btnDel.style.top = rect.top + 'px';
btnDel.style.display = 'block';
//- How to Delete Element that has no ID? Is there another way to Select the Element Mouse Hover class(.box) ? -- ///
btnDel.setAttribute('onclick', "deleteElem('?')");
}
}, true);
function deleteElem(id) {
var elem = document.getElementById(id);
elem.remove();
}
#list {
max-width: 200px;
}
#list div {
padding: 10px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
margin: 10px;
font-weight: 600;
}
#btnDel {
cursor: pointer;
position: absolute;
display: none;
left: 204px;
}
#btnDel div {
background-color: #ffdfdf;
padding: 7px;
border-radius: 7px;
color: red;
font-size: 15px;
}
<div id="list">
<div class="box">Box 01</div>
<div class="box">Box 02</div>
<div class="box">Box 03</div>
<div class="box">Box 04</div>
<div class="box">Box 05</div>
</div>
<div id="btnDel">
<div>
(X) Delete
</div>
</div>
You can store the current hovered element and remove that.
const list = document.getElementById('list');
const btnDel = document.getElementById('btnDel');
let hoveredEl;
list.addEventListener('mouseenter', e => {
if (e.target.matches('.box')) {
let rect = e.target.getBoundingClientRect();
btnDel.style.top = rect.top + 'px';
btnDel.style.display = 'block';
hoveredEl = e.target;
}
}, true);
document.getElementById('btnDel').addEventListener('click', e => {
hoveredEl?.remove();
e.currentTarget.style.display = '';
});
#list{max-width:200px}#list div{padding:10px;background-color:#fff;border:1px solid #ccc;border-radius:5px;margin:10px;font-weight:600}#btnDel{cursor:pointer;position:absolute;display:none;left:204px}#btnDel div{background-color:#ffdfdf;padding:7px;border-radius:7px;color:red;font-size:15px}
<div id="list">
<div class="box">Box 01</div>
<div class="box">Box 02</div>
<div class="box">Box 03</div>
<div class="box">Box 04</div>
<div class="box">Box 05</div>
</div>
<div id="btnDel">
<div>
(X) Delete
</div>
</div>

Hide and show DIV with javascript parameter

I am trying to do an event for hide and show with pure Javascript string parameters. I want to hide the other div once one of them is displayed (Let's say there are multiple div).
I tried to do it my own but I only managed to display once clicked. I had no idea how to hide the rest and only show that specified div.
Below is my code:
function show(id) {
if (document.getElementById('div_'+id).style.display == 'none') {
document.getElementById('div_'+id).style.display = 'block';
}
return false;
}
.title {
border:1px solid red;
display: inline-block;
font-size: 16px;
}
.content {
border: 1px solid blue;
display: inline-block;
font-size: 16px;
width: 300px;
}
<div class="title" onclick="show('first');">Title 1</div>
<div class="content" id="div_first" style="display:none;">Content 1
</div>
<div class="title" onclick="show('sec');">Title 2</div>
<div class="content" id="div_sec" style="display:none;">Content 2
</div>
You can use data-* attribute to store the target selector.
Don't use inline on* handlers. Keep your JS in one place.
Use CSS .is-active to manipulate the visibility state like display: block;
const showBtn = document.querySelectorAll('[data-show]');
const content = document.querySelectorAll('.content');
function show(ev) {
const selector = ev.currentTarget.getAttribute('data-show');
const elToShow = document.querySelectorAll(selector);
content.forEach(el => el.classList.remove('is-active'));
elToShow.forEach(el => el.classList.add('is-active'));
}
showBtn.forEach(el => el.addEventListener('click', show));
.title {
border:1px solid red;
display: inline-block;
font-size: 16px;
}
.content {
border: 1px solid blue;
display: inline-block;
font-size: 16px;
width: 300px;
display: none; /* ADD THIS */
}
.content.is-active{ /* ADD THIS */
display: block;
}
<div class="title" data-show="#content-1">Title 1</div>
<div class="title" data-show="#content-2">Title 2</div>
<div class="content" id="content-1">Content 1</div>
<div class="content" id="content-2">Content 2</div>
Just keep track of the id or element that is being displayed so that you can hide it if another one is selected. There's no need to iterate over them to hide them all, as you will know which one is being displayed, or to query the DOM each time to get the current one, as you can just keep a reference to it the first time.
I have updated the logic to toggle them if you click the same one twice and removed the inline event listeners, which I've moved to JS.
Note I have also replaced the <div>s for the .title elements with <button>s, as they will work better with keyboard navigation, mouse events and screen readers. You could also use <a>s instead.
let currentContentTab = null;
function show(e) {
// Using e.target you can get a reference to the clicked button:
const contentTab = document.getElementById(`div${ e.target.id.substring(3) }`);
const isHidden = contentTab.style.display === 'none';
// Toggle the panel we have just clicked (assuming you want to allow closing all of them again):
contentTab.style.display = isHidden ? 'block' : 'none';
// Hide the previous one, if any:
if (currentContentTab) {
currentContentTab.style.display = 'none';
}
// Keep track of the one we are currently displaying:
currentContentTab = isHidden ? contentTab : null;
}
// No need to have inline JS, you can bind the event listeners from JS:
for (const button of document.querySelectorAll('.title')) button.onclick = show;
body {
font-family: monospace;
font-size: 16px;
}
.title {
font-family: monospace;
font-size: 16px;
border: 1px solid red;
background: transparent;
padding: 8px;
outline: none;
}
.content {
border: 1px solid blue;
width: 300px;
padding: 8px;
margin-top: 8px;
}
<button class="title" id="tab1">Title 1</button>
<button class="title" id="tab2">Title 2</button>
<button class="title" id="tab3">Title 3</button>
<button class="title" id="tab4">Title 4</button>
<div class="content" id="div1" style="display:none; ">
Content 1...
</div>
<div class="content" id="div2" style="display:none; ">
Content 2...
</div>
<div class="content" id="div3" style="display:none; ">
Content 3...
</div>
<div class="content" id="div4" style="display:none; ">
Content 4...
</div>
If accessibility is important for you, you might want to add some ARIA attributes and the HTML hidden attribute:
let currentTab = null;
let currentPanel = null;
function show(e) {
const tab = e.target;
const id = tab.getAttribute('aria-controls');
const panel = document.getElementById(id);
// Toggle the panel we have just clicked:
tab.toggleAttribute('aria-selected');
panel.toggleAttribute('hidden');
// Hide the previous one, if any:
if (currentTab) {
currentTab.removeAttribute('aria-selected');
currentPanel.setAttribute('hidden', true);
}
// Keep track of the one we are currently displaying:
if (currentTab === tab) {
currentTab = null;
currentPanel = null;
} else {
currentTab = tab;
currentPanel = panel;
}
}
for (const button of document.querySelectorAll('.title')) button.onclick = show;
body {
font-family: monospace;
font-size: 16px;
}
.title {
font-family: monospace;
font-size: 16px;
border: 1px solid red;
background: transparent;
padding: 8px;
outline: none;
}
.content {
border: 1px solid blue;
width: 300px;
padding: 8px;
margin-top: 8px;
}
<button class="title" role="tab" aria-selected="true" aria-controls="div1" id="tab1">Title 1</button>
<button class="title" role="tab" aria-selected="true" aria-controls="div2" id="tab2">Title 2</button>
<button class="title" role="tab" aria-selected="true" aria-controls="div3" id="tab3">Title 3</button>
<button class="title" role="tab" aria-selected="true" aria-controls="div4" id="tab4">Title 4</button>
<div class="content" id="div1" role="tabpanel" aria-labelby aria-labelledby="tab1" hidden>
Content 1...
</div>
<div class="content" id="div2"role="tabpanel" aria-labelby aria-labelledby="tab2" hidden>
Content 2...
</div>
<div class="content" id="div3"role="tabpanel" aria-labelby aria-labelledby="tab3" hidden>
Content 3...
</div>
<div class="content" id="div4"role="tabpanel" aria-labelby aria-labelledby="tab4" hidden>
Content 4...
</div>
This JS code will grab all .content divs and will hide them unless it's the one we clicked.
function show(id) {
const el = document.getElementById('div' + id);
if (el.style.display == 'none') {
el.style.display = 'block';
}
const otherEls = document.querySelectorAll('.content');
otherEls.forEach(function (elItem) {
if (el !== elItem) {
elItem.style.display = 'none';
}
});
return false;
}
My solution as the following:
function show(id)
{
var divs=document.getElementsByClassName("content");
for (i=0;i<divs.length;i++)
{
divs[i].style.display='none';
}
document.getElementById('div_'+id).style.display = 'block';
}
.title {
border:1px solid red;
display: inline-block;
font-size: 16px;
}
.content {
border: 1px solid blue;
display: inline-block;
font-size: 16px;
width: 300px;
}
<div class="title" onclick="show('first');">Title 1</div>
<div class="content" id="div_first" style="display:none;">Content 1
</div>
<div class="title" onclick="show('sec');">Title 2</div>
<div class="content" id="div_sec" style="display:none;">Content 2
</div>

Hide & show content with javaScript

So, on my example I have 2 div-buttons (named btn1 and btn2) and 2 div elements (named content1 and content2).
What I would want, is that when you click the btn1, content1 shows. If you click btn2, content2 should show.
Content1 and content2 elements are currently placed in the same position, and by default, none of the content elements shouldn't be open before you have clicked anything. I would like to achieve this with pure javaSript.
Here is the example code:
var btn1 = document.getElementById("btn1");
var content1 = document.getElementById("content1");
content1.style.opacity = "0";
btn1.addEventListener("mouseover", showContent1);
function showContent1(){
if(content1.style.opacity === "0") {
content1.style.opacity = "1";
} else {content1.style.opacity = "0";}
}
var btn2 = document.getElementById("btn2");
var content2 = document.getElementById("content2");
content2.style.opacity = "0";
btn2.addEventListener("mouseover", showContent2);
function showContent2(){
if(content2.style.opacity === "0") {
content2.style.opacity = "1";
} else {content2.style.opacity = "0";}
}
#btn1, #btn2 {
width:100px;height:20px;text-align:center;background:grey;cursor:pointer;margin:10px 0px;
}
#contents {
width: 200px;height:200px;border: 2px solid black;
}
#content1, #content2 {
width: 200px;height:200px;position:absolute;background:lightblue;
}
<div id="btn1">show1</div>
<div id="btn2">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
You can add click event to the buttons and based on the button clicked you can show or hide the respective div.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<style>
#btn1, #btn2 {
width:100px;height:20px;text-align:center;background:grey;cursor:pointer;margin:10px 0px;
}
#contents {
width: 200px;
height:200px;
border: 2px solid black;
}
#content1, #content2 {
width: 200px;
height:200px;
position:absolute;
background:lightblue;
display:none;
}
</style>
</head>
<body>
<script>
function showDiv(div){
if(div == 'btn1'){
document.getElementById('content1').style.display = 'block';
document.getElementById('content2').style.display = 'none';
}else{
document.getElementById('content1').style.display = 'none';
document.getElementById('content2').style.display = 'block';
}
}
</script>
<div id="btn1" onclick="showDiv('btn1')">show1</div>
<div id="btn2" onclick="showDiv('btn2')">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
</body>
Plunker For the same: https://plnkr.co/edit/brxoF2ClW2TeJOVMxn8d?p=preview
Check this, i've made it dynamic so you can create unlimited buttons and contents.
function toogleContent(id){
var toogleContent = document.getElementsByClassName('toogleContent');
var i = toogleContent.length;
while (i--) toogleContent[i].style.display = "none";
document.getElementById(id).style.display = "block";
}
#btn1, #btn2 {
width:100px;
height:20px;
text-align:center;
background:grey;
cursor:pointer;
margin:10px 0px;
}
#contents {
width: 200px;
height:200px;
border: 2px solid black;
}
#content1, #content2 {
width: 200px;
height:200px;
position:absolute;
background:lightblue;
display:none;
}
<div id="btn1" class="toogleBtn" onclick="toogleContent('content1')">show1</div>
<div id="btn2" class="toogleBtn" onclick="toogleContent('content2')">show2</div>
<div id="contents">
<div id="content1" class="toogleContent">content 1</div>
<div id="content2" class="toogleContent">content 2</div>
</div>
Whilst the above answers are all correct insofar as they will get you from A to B (based on the code you have provided), there are also a few 'best practice' changes you should use in your code, to avoid common pitfalls (and allow better maintainability and code reuse).
Firstly, you should avoid using IDs for styling. Whilst using an ID to apply styles is perfectly valid to do (and won't break anything) it is discouraged. An ID for a page must always be unique within a document, so using it to style potentially multiple similar elements means that you will very quickly have either broken HTML (by reusing an ID) or unwieldy and non-maintainable stylesheets (by having multiple identical selectors). You should prefer using classes to add styles to elements, as you can reuse classes, and even extend or use multiple classes per element.
In my snippet, I have also used a dataset with a number in it to help identify which element is being 'selected'. Datasets are intended to store custom data, and are extremely useful for storing and retrieving data in JavaScript. By using a dataset to store an ID that is independent of the ID or class of an element, you can infinitely add/remove tabs without having to change your CSS or JavaScript to fit. After all, I can add in a dataset for an ID of 3 (e.g. <div class="button" data-id="3">) and the button styling won't be affected.
Other good practices include using separate class names or selectors for JavaScript compared to those used to style an element (again so that you can change the name of a JavaScript selector without affecting the look of an element - you can also prepend a JavaScript selector with js- as I have done, so that it is more obvious that the selector is used by JavaScript, and not used to style an element).
I have also used a BEM styleguide to name my classes (though this is a preference thing - in short though, it is good practice to pick and then use some sort of naming convention or style guide for naming/styling elements).
A final recommendation (not shown) <button> element instead of a <div> for buttons. This will improve your disability access for a website, as screen reader technology can then distinguish between what is a button and what is merely a block of content (after all, a screen reader might not pick up that the <div> has a click event handler added, and so a disabled user might not be aware they can click on the 'button' to switch tabs).
// Select all buttons using querySelectorAll
let buttons = document.querySelectorAll('.js-toggle');
// Loop through each button and add an event listener
Array.from(buttons).forEach(button => {
// Click event listener
button.addEventListener('click', function() {
// Select all elements to hide/show
let tab_contents = document.querySelectorAll('.js-content');
// Hide all elements
hideElems(tab_contents);
// Get ID of button
let id = this.dataset.id;
// Select relevant tab using the ID above
document.querySelector(`.js-content-${id}`).style.display = 'block';
});
});
// Function for hiding all elements
let hideElems = (elems) => {
Array.from(elems).forEach(elem => elem.style.display = 'none');
}
.button {
width: 100px;
height: 20px;
text-align: center;
background: grey;
cursor: pointer;
margin: 10px 0;
}
.tabs {
width: 200px;
height: 200px;
border: 2px solid black;
}
.tabs__content {
width: 200px;
height: 200px;
background: lightblue;
display: none;
}
<div class="button js-toggle" data-id="1">show1</div>
<div class="button js-toggle" data-id="2">show2</div>
<div class="tabs">
<div class="tabs__content js-content js-content-1">content 1</div>
<div class="tabs__content js-content js-content-2">content 2</div>
</div>
document.getElementById('btn1').addEventListener('click', ()=>{
document.getElementById('content2').style.display = "none";
document.getElementById('content1').style.display = "block";
});
document.getElementById('btn2').addEventListener('click', ()=>{
document.getElementById('content1').style.display = "none";
document.getElementById('content2').style.display = "block";
});
#btn1, #btn2 {
width:100px;height:20px;text-align:center;background:grey;cursor:pointer;margin:10px 0px;
}
#contents {
width: 200px;height:200px;border: 2px solid black;
}
#content1, #content2 {
width: 200px;height:200px;position:absolute;background:lightblue;display:none;
}
<div id="btn1">show1</div>
<div id="btn2">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
You need onClick event and 2 conditions. Please check this,
function showContent(content_id) {
if (content_id == 'content1') {
document.getElementById('content1').style.display = 'block';
document.getElementById('content2').style.display = 'none';
} else if (content_id == 'content2') {
document.getElementById('content1').style.display = 'none';
document.getElementById('content2').style.display = 'block';
}
}
#btn1, #btn2 {
width:100px;height:20px;text-align:center;background:grey;cursor:pointer;margin:10px 0px;
}
#contents {
width: 200px;height:200px;border: 2px solid black;
}
#content1, #content2 {
width: 200px;height:200px;position:absolute;background:lightblue; display:none;
}
<div id="btn1" onClick='showContent("content1")'>show1</div>
<div id="btn2" onClick='showContent("content2")'>show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
This is a simple way to do it with vanilla javascript, just add a method that hides/shows the element based on which button you click
function toogle(showelem, hideelem) {
document.getElementById(showelem).style.display = "block";
document.getElementById(hideelem).style.display = "none";
}
#btn1, #btn2 {
width:100px;height:20px;text-align:center;background:grey;cursor:pointer;margin:10px 0px;
}
#contents {
width: 200px;height:200px;border: 2px solid black;
}
#content1, #content2 {
width: 200px;height:200px;position:absolute;background:lightblue;
}
<div id="btn1" onClick="toogle('content1','content2');">show1</div>
<div id="btn2" onClick="toogle('content2','content1');">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
function myFunction() {
var element = document.getElementById("myDIV");
element.classList.remove("displayblock");
}
function myFunctionShow(){
var element = document.getElementById("myDIV");
element.classList.add("displayblock");
}
.mystyle {
width: 100%;
padding: 25px;
background-color: coral;
color: white;
display:none;
}
.displayblock{
display:block;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Click the "Try it" button to remove the "mystyle" class from the DIV element:</p>
<button onclick="myFunction()">Hide</button>
<button onclick="myFunctionShow()">Show</button>
<div id="myDIV" class="mystyle displayblock">
This is a DIV element.
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#btn1,
#btn2 {
width: 100px;
height: 20px;
text-align: center;
background: grey;
cursor: pointer;
margin: 10px 0px;
}
#contents {
width: 200px;
height: 200px;
border: 2px solid black;
}
#content1,
#content2 {
width: 200px;
height: 200px;
position: absolute;
background: lightblue;
}
</style>
</head>
<body>
<div id="btn1" onclick="showdiv1()">show1</div>
<div id="btn2" onclick="showdiv2()">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
</body>
<script>
function showdiv1(){
console.log( document.getElementById('content1'))
document.getElementById('content1').style.display='block';
document.getElementById('content2').style.display='none';
}
function showdiv2(){
document.getElementById('content1').style.display='none';
document.getElementById('content2').style.display='block';
}
</script>
</html>
Here We Go
You can you this for any element to hide and show
element.style.display = 'none'; // Hide
element.style.display = 'block'; // Show
element.style.display = 'inline'; // Show
element.style.display = 'inline-block'; // Show
If I understand you right, you should set "display: none" by default and then handle click on button to toggle "open" class. See example below.
const btn1 = document.getElementById("btn1"),
btn2 = document.getElementById("btn2"),
content1 = document.getElementById("content1"),
content2 = document.getElementById("content2");
const map = new Map()
.set(btn1, content1)
.set(btn2, content2);
const closeMapContent = _ =>
map.forEach((value, key) => value.classList.remove("open"));
map.forEach((value, key) => {
key.addEventListener("click", event => {
closeMapContent();
value.classList.add("open");
})
});
#btn1, #btn2 {
width: 100px;
height: 20px;
text-align: center;
background: grey;
cursor: pointer;
margin: 10px 0px;
}
#contents {
width: 200px;
height: 200px;
border: 2px solid black;
}
#content1, #content2 {
width: 200px;
height: 200px;
position: absolute;
background: lightblue;
display: none;
}
.open {
display: block !important;
}
<div id="btn1">show1</div>
<div id="btn2">show2</div>
<div id="contents">
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
function show() {
const h = document.getElementById('hidden1');
h.style.display = 'block' ;
const s =document.getElementById('showed');
s.style.display = 'none';
}
function hide() {
const h = document.getElementById('hidden1');
h.style.display = 'none' ;
const s =document.getElementById('showed');
s.style.display = 'block';
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div >
<button id="showed" onclick="show()" >click to show</button>
<div id="hidden1" style="display: none">
<button onclick="hide()" >click to close</button>
<h1 >Content1</h1>
</div>
</div>
</body>
</html>
see with snippet
Another way to approach this is to use data-* attribute with little bit of styling. You can change the attribute of the parent div then the changes are reflected on children using CSS.
Also, you don't need to loops through elements if know the number of children elements.
See this example:
function toogleContent(target) {
document.querySelector("#contents").setAttribute("data-show", target);
}
#btn1,
#btn2 {
width: 100px;
height: 20px;
text-align: center;
background: grey;
cursor: pointer;
margin: 10px 0px;
}
#contents {
width: 200px;
height: 200px;
border: 2px solid black;
}
#content1,
#content2 {
width: 200px;
height: 200px;
position: absolute;
background: lightblue;
opacity: 0;
}
#contents[data-show='1']>#content1 {
opacity: 1;
}
#contents[data-show='2']>#content2 {
opacity: 1;
}
<div id="btn1" onclick="toogleContent(1)">show1</div>
<div id="btn2" onclick="toogleContent(2)">show2</div>
<div id="contents" data-show=''>
<div id="content1">content 1</div>
<div id="content2">content 2</div>
</div>
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
(function() {
const buttons = document.querySelectorAll('.button');
const content = document.querySelector('.content__wrapper');
hideAll();
setUpClickHandlers();
function hide(element) {
element.classList.add('hide');
}
function show(element) {
element.classList.remove('hide')
}
function hideAll() {
Array.from(content.children).forEach(hide);
}
function toggle(element) {
hideAll();
show(element)
}
function onClick(content) {
return () => toggle(content)
}
function setUpClickHandlers() {
const handler = element => {
const show = content.querySelector(`.${element.dataset.for}`);
element.addEventListener('click', onClick(show));
};
Array.from(buttons).forEach(handler);
}
})()
.hide {
display: none
}
.button {
height: 30px;
line-height: 30px;
border-radius: 5px;
border: 1px solid grey;
padding: 0 10px;
display: inline-block;
margin: 10px 0;
cursor: pointer;
}
.content__wrapper {
background-color: aqua;
padding: 16px;
}
<button class="button" data-for="content_1">content 1</button>
<button class="button" data-for="content_2">content 2</button>
<button class="button" data-for="content_3">content 3</button>
<button class="button" data-for="content_4">content 4</button>
<div class="content__wrapper">
<div class="content content_1">Content 1</div>
<div class="content content_2">Content 2</div>
<div class="content content_3">Content 3</div>
<div class="content content_4">Content 4</div>
</div>

Javascript in need of simplification - collapsible tabs

I've coded some tabs and it seems to work well, although I'm sure I can achieve this with much cleaner code! I'm just not sure how to do that at the moment. I would really appreciate some help with this one.
I'm not sure if its loops I want to use or something completely different?
The way I've done it obviously works but it just seem unnecessary and messy, after this the next step is to add in a transition effect as the tabs come down. I'm not sure if this will even allow me to do that.
function myFunction() {
var a = document.getElementById("results1");
var b = document.getElementById("results2");
var c = document.getElementById("results3");
var d = document.getElementById("title1");
var e = document.getElementById("title2");
var f = document.getElementById("title3");
if (a.style.display === "none") {
a.style.display = "block";
b.style.display = "none";
c.style.display = "none";
d.style.backgroundColor = "#005FAA";
e.style.backgroundColor = "lightgrey";
f.style.backgroundColor = "lightgrey";
}
else {
a.style.display = "none";
d.style.backgroundColor = "lightgrey";
}
}
function myFunction1() {
var a = document.getElementById("results1");
var b = document.getElementById("results2");
var c = document.getElementById("results3");
var d = document.getElementById("title1");
var e = document.getElementById("title2");
var f = document.getElementById("title3");
if (b.style.display === "none") {
a.style.display = "none";
b.style.display = "block";
c.style.display = "none";
d.style.backgroundColor = "lightgrey";
e.style.backgroundColor = "#005FAA";
f.style.backgroundColor = "lightgrey";
}
else {
b.style.display = "none";
e.style.backgroundColor = "lightgrey";
}
}
function myFunction2() {
var a = document.getElementById("results1");
var b = document.getElementById("results2");
var c = document.getElementById("results3");
var d = document.getElementById("title1");
var e = document.getElementById("title2");
var f = document.getElementById("title3");
if (c.style.display === "none") {
a.style.display = "none";
b.style.display = "none";
c.style.display = "block";
d.style.backgroundColor = "lightgrey";
e.style.backgroundColor = "lightgrey";
f.style.backgroundColor = "#005FAA";
}
else {
c.style.display = "none";
f.style.backgroundColor = "lightgrey";
}
}
body{
margin: 10px;}
.title{
background-color:lightgrey;
width: 32%;
float: left;
text-align: center;
text-decoration:none;
color:white;
margin-right: 2%;
padding: 30px;
box-sizing: border-box;
}
.title:last-child{
margin-right:0px;
width:32%;}
.results{
background-color:#005FAA;
float:left;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
<div class="container">
<div id="title1" class="title" onclick="myFunction()">
<h4>Item 1</h4>
</div>
<div id="title2" class="title" onclick="myFunction1()">
<h4>Item 2</h4>
</div>
<div id="title3" class="title" onclick="myFunction2()">
<h4>Item 3</h4>
</div>
</div>
<div class="results" id="results1" style="display:none;">Item 1</div>
<div class="results" id="results2" style="display:none">Item 2</div>
<div class="results" id="results3" style="display:none">Item 3</div>
Maybe something like this? You are already using JQuery, so maybe make it modular and use it to help with your transition down effects (you can transition them up too if you'd like).
const tabs = {
animating: false,
toggleResults: function(thatTab) {
const thatResult = $(`[data-title="${thatTab.attr('id')}"]`);
thatTab.toggleClass('activeTab');
thatResult.toggleClass("openedResult");
tabs.animating = true;
thatResult.slideToggle("fast", function() {
tabs.animating = false;
});
},
init: function() {
$(".title").click(function() {
const thatTab = $(this);
const openedResult = $('.openedResult');
const thatTabId = thatTab.attr("id");
const openedResultTitle = openedResult.data('title');
if (!tabs.animating) {
$('.activeTab').removeClass('activeTab');
openedResult.removeClass('openedResult').hide();
if (thatTabId !== openedResultTitle) {
tabs.toggleResults(thatTab);
}
}
});
}
};
$(function() {
tabs.init();
});
body {
margin: 0;
}
.container {
display: flex;
justify-content: space-between;
width: 100%;
}
.title {
background-color: lightgrey;
flex-basis: 32%;
transition: background-color 0ms;
text-align: center;
color: white;
padding: 30px;
box-sizing: border-box;
}
.activeTab {
background-color: #005faa;
transition: background-color 100ms;
}
.results {
background-color: #005faa;
display: none;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div id="title1" class="title">
<h4>Item 1</h4>
</div>
<div id="title2" class="title">
<h4>Item 2</h4>
</div>
<div id="title3" class="title">
<h4>Item 3</h4>
</div>
</div>
<div class="results" data-title="title1">Item 1</div>
<div class="results" data-title="title2">Item 2</div>
<div class="results" data-title="title3">Item 3</div>
Try this , you can call same function on all three divs with passing their ids to find the current id.
<!DOCTYPE html>
<style type="text/css">
body{
margin: 10px;}
.title{
background-color:lightgrey;
width: 32%;
float: left;
text-align: center;
text-decoration:none;
color:white;
margin-right: 2%;
padding: 30px;
box-sizing: border-box;
}
.title:last-child{
margin-right:0px;
width:32%;}
.results{
background-color:#005FAA;
float:left;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
.active{
display = "block"
}
.inactive{
display : "none"
backgroundColor:"#005FAA"
}
</style>
<div class="container">
<div id="title1" class="title" onclick="ActivateTab(1)">
<h4>Item 1</h4>
</div>
<div id="title2" class="title" onclick="ActivateTab(2)">
<h4>Item 2</h4>
</div>
<div id="title3" class="title" onclick="ActivateTab(3)">
<h4>Item 3</h4>
</div>
<button onclick="ActivateTab(2)">Test</button>
</div>
<div class="results" id="results1" style="display:none;">Item 1</div>
<div class="results" id="results2" style="display:none">Item 2</div>
<div class="results" id="results3" style="display:none">Item 3</div>
<script>
function ActivateTab(id){
let results = document.querySelectorAll(".results")
let titles = document.querySelectorAll(".title")
results.forEach((elementResut,index) =>{
let elementTitle = titles[index];
if(elementResut.id === "results"+id
&& elementResut.style.display === "none")
{
elementResut.style.display = "block";
elementTitle.style.backgroundColor = "#005FAA";
}
else{
elementResut.style.display = "none";
elementTitle.style.backgroundColor = "lightgrey";
}
});
}
</script>
Here is one possible clean-up:
function myFunction(title) {
var results = [...document.getElementsByClassName("results")]
results.forEach(function(r) {
if (title.dataset.for == r.id) {
r.style.display = "block";
} else {
r.style.display = "none";
}
});
var titles = [...document.getElementsByClassName("title")]
titles.forEach(function(t) {
if (t == title) {
t.style.backgroundColor = "#005FAA"
} else {
t.style.backgroundColor = "lightgrey"
}
});
}
body{
margin: 10px;}
.title{
background-color:lightgrey;
width: 32%;
float: left;
text-align: center;
text-decoration:none;
color:white;
margin-right: 2%;
padding: 30px;
box-sizing: border-box;
}
.title:last-child{
margin-right:0px;
width:32%;}
.results{
background-color:#005FAA;
float:left;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
<div class="container">
<div id="title1" data-for="results1" class="title" onclick="myFunction(this)">
<h4>Item 1</h4>
</div>
<div id="title2" data-for="results2" class="title" onclick="myFunction(this)">
<h4>Item 2</h4>
</div>
<div id="title3" data-for="results3" class="title" onclick="myFunction(this)">
<h4>Item 3</h4>
</div>
</div>
<div class="results" id="results1" style="display:none;">Item 1</div>
<div class="results" id="results2" style="display:none">Item 2</div>
<div class="results" id="results3" style="display:none">Item 3</div>
I replaced your three functions with one function that accepts a parameter representing the title element. In the event handler, we just pass this to that function. Then in the function, we loop over the things that might have to change (the title and results nodes) testing as we do whether we're working with the matching element or a different one and choosing behavior based on that.
To link the title elements with the results one, I add a data-for attribute to it. There are many other ways this could be done, including using regular expressions to find the basic id (title2 ~> 2, results2 ~> 2 for instance) and matching on those. But this should get you going.
There is more clean-up I would probably do on this, but this should offer significant simplification.
Update
A comment pointed out that the above did not allow for total tab deselection. Given that, it seems better to refactor a bit more and use the shared base id approach. Here is another version written that way:
function myFunction(title) {
var id = title.id.match(/^\D*(\d+)$/)[1]
var hidden = document.getElementById(`results${id}`).style.display !== 'block';
[...document.getElementsByClassName("results")].forEach(function(r) {
r.style.display = "none";
});
[...document.getElementsByClassName("title")].forEach(function(t) {
t.style.backgroundColor = "lightgrey";
});
if (hidden) {
document.getElementById(`results${id}`).style.display = 'block';
document.getElementById(`title${id}`).style.backgroundColor = '#005FAA';
}
}
body{
margin: 10px;}
.title{
background-color:lightgrey;
width: 32%;
float: left;
text-align: center;
text-decoration:none;
color:white;
margin-right: 2%;
padding: 30px;
box-sizing: border-box;
}
.title:last-child{
margin-right:0px;
width:32%;}
.results{
background-color:#005FAA;
float:left;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
<div class="container">
<div id="title1" class="title" onclick="myFunction(this)">
<h4>Item 1</h4>
</div>
<div id="title2" class="title" onclick="myFunction(this)">
<h4>Item 2</h4>
</div>
<div id="title3" class="title" onclick="myFunction(this)">
<h4>Item 3</h4>
</div>
</div>
<div class="results" id="results1" style="display:none;">Item 1</div>
<div class="results" id="results2" style="display:none">Item 2</div>
<div class="results" id="results3" style="display:none">Item 3</div>

Toggle visibility of 2 divs with 2 buttons

I am having issues with my code
I am trying to show 1 div (show_1) by default and then hide it and show a second div (show_2) when button 2 is clicked. And then when button 1 is clicked hide show_2 and show show_1 again
https://jsfiddle.net/mgzurjgL/4/
It is not working though, nothing happens when I click either buttons.
function switch_div(show_1, show_2) {
var a = document.getElementById(show_1);
var a2 = document.getElementById(show_2);
if (a.style.display == 'block') {
a.style.display = 'block';
a2.style.display = 'none';
} else {
a.style.display = 'none';
a2.style.display = 'block';
}
}
.button {
width: 100px;
height: 30px;
display: inline-block;
background-color: black;
margin: 0 10px 10px 0;
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.button:hover {
background-color: red;
}
.content {
width: 400px;
height: 100px;
display: block;
background-color: gray;
}
.hide {
display: none;
}
<div class="button" onclick="switch_div('show_1', 'show_2');">
1
</div>
<div class="button" onclick="switch_div('show_1', 'show_2');">
2
</div>
<div class="content" id="show_1">
Show by default (and when button 1 is clicked)
</div>
<div class="content hide" id="show_2">
Show this div when button 2 is clicked
</div>
You had your settings wrong in JSFiddle, you need to run the script in the head not onload. Also you passed in the same parameters twice. Also why dont you try something simpler like this.
https://jsfiddle.net/mgzurjgL/5/
function switch_div(show) {
document.getElementById("show_"+show).style.display = "block";
document.getElementById("show_"+((show==1)?2:1)).style.display = "none";
}
.button {
width: 100px;
height: 30px;
display: inline-block;
background-color: black;
margin: 0 10px 10px 0;
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.button:hover {
background-color: red;
}
.content {
width: 400px;
height: 100px;
display: block;
background-color: gray;
}
.hide {
display: none;
}
<div class="button" onclick="switch_div(1);">
1
</div>
<div class="button" onclick="switch_div(2);">
2
</div>
<div class="content" id="show_1">
Show by default (and when button 1 is clicked)
</div>
<div class="content hide" id="show_2">
Show this div when button 2 is clicked
</div>
Two items: script placement and a typo. Working version at JSFiddle, tested in Google Chrome.
The script has to run before the divs. In the JSFiddle Javascript settings, I changed "Load Type" to "No wrap - in <head>." This way the switch_div function exists when the divs are loaded.
There was a typo:
if (a.style.display == 'block')
should be
if (a.style.display == 'none')
Otherwise you are setting block display on an element that's already block :) .
Edit: This code still doesn't do what you appear to want, because the function you have written toggles the div visibility regardless of which button is pressed. What you really want is in this fiddle:
<div class="button" onclick="switch_div('show_1', 'show_2', true);">
and
<div class="button" onclick="switch_div('show_1', 'show_2', false);">
together with
function switch_div(show_1, show_2, should_show_1) {
var a = document.getElementById(show_1);
var a2 = document.getElementById(show_2);
if(should_show_1) {
a.style.display = 'block';
a2.style.display = 'none';
}
else {
a.style.display = 'none';
a2.style.display = 'block';
}
}
That way you get only the div you want.
You need to switch the statements in if-else or change the condition in the if to "if (a.style.display !== 'block') "
When a.style.display is 'block' then you have to set it to 'none' to hide it.
function switch_div(show_1, show_2) {
var a = document.getElementById(show_1);
var a2 = document.getElementById(show_2);
if (a.style.display !== 'block') {
a.style.display = 'block';
a2.style.display = 'none';
} else {
a.style.display = 'none';
a2.style.display = 'block';
}
}
.button {
width: 100px;
height: 30px;
display: inline-block;
background-color: black;
margin: 0 10px 10px 0;
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.button:hover {
background-color: red;
}
.content {
width: 400px;
height: 100px;
display: block;
background-color: gray;
}
.hide {
display: none;
}
<div class="button" onclick="switch_div('show_1', 'show_2');">
1
</div>
<div class="button" onclick="switch_div('show_1', 'show_2');">
2
</div>
<div class="content" id="show_1">
Show by default (and when button 1 is clicked)
</div>
<div class="content hide" id="show_2">
Show this div when button 2 is clicked
</div>
I changed the js function and the "call" for buttons.
function switch_div(show_1, show_2) {
var a = document.getElementById(show_2);
var a2 = document.getElementById(show_1);
a.style.display = 'none';
a2.style.display = 'block';
}
.button {
width: 100px;
height: 30px;
display: inline-block;
background-color: black;
margin: 0 10px 10px 0;
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
}
.button:hover {
background-color: red;
}
.content {
width: 400px;
height: 100px;
display: block;
background-color: gray;
}
.hide {
display: none;
}
<div class="button" onclick="switch_div('show_1', 'show_2');">
1
</div>
<div class="button" onclick="switch_div('show_2', 'show_1');">
2
</div>
<div class="content" id="show_1">
Show by default (and when button 1 is clicked)
</div>
<div class="content hide" id="show_2">
Show this div when button 2 is clicked
</div>
This also works with:
<div class="button" onclick="switch_div(1,2);">
1
</div>
<div class="button" onclick="switch_div(2,1);">
2
</div>
<div class="content" id="show_1">
Show by default (and when button 1 is clicked)
</div>
<div class="content hide" id="show_2">
Show this div when button 2 is clicked
</div>
<script>
function switch_div(n1,n2) {
document.getElementById("show_"+n1).style.display = 'block';
document.getElementById("show_"+n2).style.display = 'none';
}
</script>

Categories