How to hide div when it's already open? - javascript

I couldn't think of any better title, so I will try to explain my question here as clear as possible. I'm quite a newbie in JQuery so this is probably a very easy question.
I have some divs with a button on it. When you click the button, another div should pop-up.
My question is: How can I make the div, which is already open, close when clicking on another button?
I made a fiddle with some example code: http://jsfiddle.net/zuvjx775/1/
And the example code here:
HTML:
<div class="wrapper">
<div class="test">
<input type='button' class='showDiv' id="1" value='click!' />
</div>
<div class="show_1">
</div>
</div>
<br>
<div class="wrapper">
<div class="test">
<input type='button' class='showDiv' id="2"value='click!' />
</div>
<div class="show_2">
</div>
</div>
JQuery:
$('.showDiv').on('click', function(){
var id = $(this).attr('id');
$('.show_'+id).show();
});
When show_1 for example is visible, and I click on the button in div2, I want show_2 to come up, which it does, but show_1 to dissapear.
Can someone point me in the right direction?

You can hide all divs that their class starts with 'show' before show the one you want. For example:
$('.showDiv').on('click', function() {
var id = $(this).attr('id');
$("div[class^='show']").hide();//find div class starts with 'show' and hide them
$('.show_' + id).show();
});
.test {
border: 1px solid black;
height: 100px;
width: 450px;
float: left;
}
.show_1 {
width: 50px;
height: 50px;
background-color: yellow;
float: left;
display: none;
}
.show_2 {
width: 50px;
height: 50px;
background-color: green;
float: left;
display: none;
}
.wrapper {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="test">
<input type='button' class='showDiv' id="1" value='click!' />
</div>
<div class="show_1">
</div>
</div>
<br>
<div class="wrapper">
<div class="test">
<input type='button' class='showDiv' id="2" value='click!' />
</div>
<div class="show_2">
</div>
</div>

Is the structure of the document fixed?
is so... I guess the easiest way of doing this is to just do the following:
$('.showDiv').on('click', function(){
var id = $(this).attr('id');
if(id == 1){
$('.show_1').show();
$('.show_2').hide();
}else{
$('.show_2').show();
$('.show_1').hide();
}
})

Related

Two Column Accordion with Separate Full Width Divs

The intension is to have a two column accordion, without limiting the "expand" field to the left or right column. The catch is that there will be multiple on one page. This is already created, but only button 1 is working. With the way my JS is going, it will get very very repetitive - I am looking for assistance with re-writing the JS to be multiple click friendly. Fiddle: https://codepen.io/ttattini/pen/abLzaaY
EDIT: It would also be perfect if one dropdown would close as the next is opened
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="row">
<div id="column">
<button id="button">I am Button #1</button>
<button id="button">I am Button #3</button>
</div>
<div id="column">
<button id="button">I am Button #2</button>
<button id="button">I am Button #4</button>
</div>
</div>
<div id="hidden">
<p id="content"> So here I am #1</p>
</div>
<div id="hidden">
<p id="content"> So here I am #2</p>
</div>
<div id="hidden">
<p id="content"> So here I am #3</p>
</div>
<div id="hidden">
<p id="content"> So here I am #4</p>
</div>
CSS
#hidden {
background: #ccc;
margin-top: 2%;
overflow: hidden;
transition: height 200ms;
height: 0; /* <-- set this */
}
#button {
padding: 10px;
margin-top: 5px;
width:50%;
margin-left: 10%;
cursor: pointer;
}
#row {
display: flex;
}
#column {
flex: 50%;
}
JS
$(function() {
var b = $("#button");
var w = $("#hidden");
var l = $("#content");
b.click(function() {
if (w.hasClass('open')) {
w.removeClass('open');
w.height(0);
} else {
w.addClass('open');
w.height(l.outerHeight(true));
}
});
});
The biggest issue is that you're using IDs when you should be using classes. IDs must be unique to each element in a page. When you repeat an ID, JS will only target the first element using that ID. That's why only the first one is working.
The second issue is that, because of the way the script is written, it will only target a single element. What you need to do is get all the elements you want to target by something like their class name and then loop through them, applying the event listener to each one and its appropriate children.
EDIT: Here is an example from some code I wrote for a page with multiple accordions a few weeks ago in vanilla JS
//Below I establish a counting variable and find all the accordions on the page
const acc = document.getElementsByClassName( 'accordion' );
let i;
//Looping through each accordion
for ( i = 1; i <= acc.length; i++ ) {
//Identify target for the event listener. In this case, a heading for each accordion, which I've numbered e.g. "title-1"
const title = 'title-' + i;
const label = document.getElementById( title );
//Identify target content, in this case a list that has a unique ID e.g. "list-1"
const listNum = 'list-' + i;
const list = document.getElementById( listNum );
//Add event listener to heading that toggles the active classes
label.addEventListener( 'click', function() {
label.classList.toggle( 'accordion--active' );
});
}
Of course, there's more than one way to skin a cat, but this is a working example.
I have tracked the clicked event of each button and showed the corresponding hidden content with the use of data- attribute.
I have used vanilla JavaScipt instead of jQuery.
const buttons = document.querySelectorAll('.button');
const hiddens = document.querySelectorAll('.hidden');
buttons.forEach((btn) => {
btn.addEventListener('click', btnClicked)
function btnClicked(e) {
hiddens.forEach((hidden) => {
if(e.target.dataset.btn == hidden.dataset.content) {
hidden.classList.toggle('height')
} else {
hidden.classList.remove('height')
}
})
}
})
.hidden {
background: #ccc;
margin-top: 2%;
padding-left:2%;
overflow: hidden;
transition: height 200ms;
height: 0; /* <-- set this */
}
.hidden.height {
height: 50px;
}
.button {
padding: 10px;
color: white;
background-color: #2da6b5;
border: none;
margin-top: 5px;
width:90%;
margin-left: 5%;
cursor: pointer;
}
.button:hover {
filter: brightness(.9);
}
#row {
display: flex;
}
.column {
flex: 50%;
}
<div id="row">
<div class="column">
<button class="button" data-btn="one">I am Button #1</button>
<button class="button" data-btn="three">I am Button #3</button>
</div>
<div class="column">
<button class="button" data-btn="two">I am Button #2</button>
<button class="button" data-btn="four">I am Button #4</button>
</div>
</div>
<div class="hidden" data-content="one">
<p class="content"> So here I am #1</p>
</div>
<div class="hidden" data-content="two">
<p class="content"> So here I am #2</p>
</div>
<div class="hidden" data-content="three">
<p class="content"> So here I am #3</p>
</div>
<div class="hidden" data-content="four">
<p class="content"> So here I am #4</p>
</div>
Also, please do not use the same ID at multiple elements.

Issue on Injecting Data Attribute to an existing Element

Can you please take a look at this demo and let me know why I am not able to inject clicked element attribute data data-css to data attribute of color-box? as you can see I am able to print it out in the console by
console.log(jQuery(this).data('css'));
But the
jQuery('.current-color').data('css', jQuery(this).data('css'));
is not setting the data attribute for target element .current-color
jQuery(".color").on('click', function() {
jQuery('.current-color').css('background', jQuery(this).data('color'));
jQuery('.current-color').data('css', jQuery(this).data('css'));
console.log(jQuery(this).data('css'));
jQuery('.current-color-name').text(jQuery(this).find('.color-name').text());
});
.color-box {
width: 100px;
height: 100px;
cursor: pointer;
background:#eee;
border:2px solid #444;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="current-color" data-css="">
<div class="color-box current-color-name">Orane</div>
</div>
<div class="colors">
<div class="color-box color" data-css="red.css" data-color="#f44336">
<div class="color-name">red</div>
</div>
</div>
Try to use .attr('data-anything') instead of .data('anything') It works here
$(".color").on('click', function() {
$('.current-color').css('background', $(this).attr('data-color'));
$('.current-color').attr('data-css', $(this).attr('data-css'));
console.log($(this).attr('data-css'));
$('.current-color-name').text($(this).find('.color-name').text());
});
.color-box {
width: 100px;;
height: 100px;
cursor: pointer;
background:#eee;
border:2px solid #444;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="current-color" data-css="">
<div class="color-box current-color-name"></div>
</div>
<div class="colors">
<div class="color-box color" data-css="red.css" data-color="#f44336">
<div class="color-name">red</div>
</div>
<div class="color-box color" data-css="orange.css" data-color="orange">
<div class="color-name">Orange</div>
</div>
<div class="color-box color" data-css="blue.css" data-color="blue">
<div class="color-name">Blue</div>
</div>
</div>
The reason why 'data-' atrribute could not work was that when you first used the $('..').data(' ') method to get the attribute value after you set it by
$('..').data(' ',' ') method,jquery stored the value so that when you clicked again,the value had not changed.
I thought reason was more important than solution for a developer.I hoped this could help.

Background image div clickable

I have a div with a background image. How can i make the div (the background image) clickable? I want to unhide an other div when clicked on the div (image). Onclick code: onclick="javascript:unhide('kazen')"
var clickit = document.getElementsByClassName("fh5co-grid")[0];
var kazen = document.getElementById("kazen");
clickit.addEventListener("click", function(){
if (kazen.style.display === "none") {
kazen.style.display="block";
} else {
kazen.style.display="none";
}
});
kazen.addEventListener("click", function(){
this.style.display="none";
});
#kazen {
background-color: #cc9;
display: none;
width: 100px;
height: 100px;
position: absolute;
top: 15px;
left: 15px;
}
.fh5co-grid {
}
<div class="col-md-4 col-sm-6 ">
<div class="fh5co-grid" style="background-image: url(images/PREVIEW_Shop_02-29.jpg);">
<a class="image-popup text-center" >
<div class="prod-title ">
<h3>Kaas</h3>
<h4>in ons aanbod hebben we verse en harde kazen - binnenkort meer hierover</h4>
</div>
</a>
</div>
</div>
<div id="kazen" >
<div class="col-md-12">
<div class="fh5co-grid" style="background-image: url(images/Melkerhei_Dag2-16-4.jpg);">
<a class="image-popup text-center" >
<div class="prod-title ">
</div>
</a>
</div>
</div>
</div>
You can have a look at the fiddle I created if this is what you want.
$(document).ready(function() {
$("div.fh5co-grid").click(function() {
$("div.next").css("display", "block");
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-4 col-sm-6 ">
<div class="fh5co-grid" style="background-image: url(http://placehold.it/350x150);">
<a class="image-popup text-center">
<div class="prod-title ">
<h3>cheese</h3>
<h4>tekst</h4>
</div>
</a>
</div>
</div>
<div style="background-color: #000; display:none" class="next">Next div</div>
From what you're describing, this seems pretty close. The background image isn't clickable, it's the div itself. And this could be done with jQuery, yes, but it's trivial enough that pure javascript is pretty easy here. Clicking in the red-boxed area will display the div with the id kazen, and clicking in either kazen or the red-boxed area again will hide it.
Note, there was a weird glitch to my solution. I changed the display if/else to check if it's currently displayed and hide it, rather than if it's currently hidden to display it. That was causing a strange effect of re-hiding the kazan div on the first click.
Within stackoverflow, you'll need an absolute url to display an image. If you aren't seeing your image here, that may be why.
var clickit = document.getElementsByClassName("fh5co-grid")[0];
var kazen = document.getElementById("kazen");
clickit.addEventListener("click", function(){
if (kazen.style.display === "block") {
kazen.style.display="none";
} else {
kazen.style.display="block";
}
});
kazen.addEventListener("click", function(){
this.style.display="none";
});
#kazen {
background: url("https://static.pexels.com/photos/6832/waterfall-beauty-lets-explore-lets-get-lost.jpg");
background-size: 100%;
display: none;
width: 100px;
height: 100px;
position: absolute;
top: 15px;
left: 15px;
color: #fff;
}
.fh5co-grid {
border: 1px dotted red;
}
<div class="col-md-4 col-sm-6 ">
<div class="fh5co-grid" style="background-image: url(images/PREVIEW.jpg);">
<a class="image-popup text-center">
<div class="prod-title ">
<h3>cheese</h3>
<h4>tekst</h4>
</div>
</a>
</div>
</div>
<div id="kazen">
Click me to hide!
</div>

Changing the function of a button in a website

So below I have some code of what I'm working with. Right now, if you just launch the website, the #picture div has a background image, and if you press any of the buttons, that picture is replaced with something else.
So what I can't figure out is how the buttons would change what they do after pressing a button. Let's say you click on Button 1 and the background image is replaced. I want the buttons to recognize what background image is in that div and change functions accordingly, in my case, I want them to change what pictures they replace the current one with.
If the current background of #picture is X, you have ABC choices, if the background of #picture is Y, you have DEF choices, would be a TLDR explanation maybe.
<div id="adventure">
<div class="picture">
</div>
<div id="choice">
<button class="button1">Val 1</button>
<button class="button2">Val 2</button>
<button class="button3">Val 3</button>
</div>
</div>
$('.button1').click(function() {
$('.picture').css('background-image',
'url("image1")'
);
});
$('.button2').click(function() {
$('.picture').css('background-image',
'url("image2")'
);
});
$('.button3').click(function() {
$('.picture').css('background-image',
'url("image3")'
);
});
I've probably gone about doing this in a bad way but I'm really at a loss on how I would do this. I can only think up of one way of doing it and that is to have a bunch of if statements depending on what background is in the #picture div but I don't know how to implement that.
This demo relies on the class .active which determines which set of buttons (called .group) are visible, whilst the other .groups remain absent. The #switch button will toggle through each group.
You must name your images according to the id of the button it belongs to.
Example:
HTML of Button
<button id="image_of_sky.png">D</button>
URL to Image
http://domain.com/path/to/image_of_sky.png
jQuery img variable
var img = "http://domain.com/path/to/"+btn;
Snippet
$('.button').click(function() {
var btn = $(this).attr('id');
var img = "https://placehold.it/330x150?text=" + btn;
$('.picture').css('background-image',
'url(' + img + ')'
);
});
$('#switch').click(function() {
var act = $('.group.active');
var next = act.next();
act.removeClass('active');
next.addClass('active');
if (act.attr('id') == "choiceGHI") {
$('#choiceABC').addClass('active');
}
});
#adventure {
width: 395px;
}
.picture {
width: 330px;
height: 150px;
border: 1px outset grey;
}
.group {
width: 330px;
display: none;
padding: 0;
}
.button {
width: 32.5%;
margin: 0;
}
.active {
display: block;
}
#switch {
float: right;
margin: -20px 0 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="adventure">
<div class="picture"></div>
<div id="choiceABC" class="group active">
<button id="Image1" class="button">A</button>
<button id="Image2" class="button">B</button>
<button id="Image3" class="button">C</button>
</div>
<div id="choiceDEF" class="group">
<button id="Image4" class="button">D</button>
<button id="Image5" class="button">E</button>
<button id="Image6" class="button">F</button>
</div>
<div id="choiceGHI" class="group">
<button id="Image7" class="button">G</button>
<button id="Image8" class="button">H</button>
<button id="Image9" class="button">I</button>
</div>
<button id="switch">Switch</button>
</div>

Hide Previous div and toggle next div on click a button?

I have a number of buttons in my html. Each button referring to a particular DIV. I want an easy way to hide the previously open DIV when another button is clicked. So far I have written a code in jquery, but I have a strange feeling that am putting in a lot of code into a simply achievable task. Is there a simpler way to do this than what I have tried to accomplish?
Here is what I have done so far.
My HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TODO supply a title</title>
<meta name="viewport" content="width=device-width"/>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'></script>
</head>
<body>
<div id="body">
<input type="button" name="division1" value="div1" class="buttons" id="button1"/>
<input type="button" name="division2" value="div2" class="buttons" id="button2"/>
<input type="button" name="division3" value="div3" class="buttons" id="button3"/>
<input type="button" name="division4" value="div4" class="buttons" id="button4"/>
<input type="button" name="division5" value="div5" class="buttons" id="button5"/>
<input type="button" name="division6" value="div6" class="buttons" id="button6"/>
<div id="div1" class="divs"></div>
<div id="div2" class="divs"></div>
<div id="div3" class="divs"></div>
<div id="div4" class="divs"></div>
<div id="div5" class="divs"></div>
<div id="div6" class="divs"></div>
</div>
</body>
</html>
My CSS:
#body{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #000;
}
.buttons{
width: 10%;
height: 5%;
position: relative;
left: 10%;
cursor: pointer;
z-index: 500;
}
.divs{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: none;
}
#div1{
background-color: #377D9F;
}
#div2{
background-color: #02B0E6;
}
#div3{
background-color: #4b9500;
}
#div4{
background-color: #aaa;
}
#div5{
background-color:#aa0000;
}
#div6{
background-color: aquamarine;
}
My Jquery:
$(document).ready(function () {
$("#button1").click(function () {
$('#div1').toggle(100);
$("#div2,#div3,#div4,#div5,#div6").hide();
});
$("#button2").click(function () {
$("#div2").toggle(100);
$("#div1,#div3,#div4,#div5,#div6").hide();
});
$("#button3").click(function () {
$("#div3").toggle(100);
$("#div1,#div2,#div4,#div5,#div6").hide();
});
$("#button4").click(function () {
$("#div4").toggle(100);
$("#div1,#div2,#div3,#div5,#div6").hide();
});
$("#button5").click(function () {
$("#div5").toggle(100);
$("#div1,#div2,#div3,#div4,#div6").hide();
});
$("#button6").click(function () {
$("#div6").toggle(100);
$("#div1,#div2,#div3,#div4,#div5").hide();
});
});
I kind of have around 50 DIV's in my html like the above ones. And I think using the above JQUERY is a waste of coding lines. I know there will be a better way to do this. My code seems to work well, but is there any way in jquery to just hide the previous DIV, no matter which button user clicks?
$(document).ready(function(){
$(".buttons").click(function () {
var divname= this.value;
$("#"+divname).slideToggle().siblings('.divs').hide("slow");
});
});
Going with this sentence I kind of have around 50 DIV's in my html like the above ones
This would be a lot more clean as well as convenient if you use a select tag, instead of using button to show and hide each div
Demo
HTML
<select id="show_divs">
<option>Select to show a div</option>
<option value="1">Show 1</option>
<option value="2">Show 1</option>
</select>
<div class="parent">
<div id="show1">This is the first div</div>
<div id="show2">This is the second div</div>
</div>
jQuery
$('#show_divs').change(function() { //onChange execute the function
var showDiv = $(this).val(); //Store the value in the variable
$('div.parent > div').hide(); //Hide all the div nested inside .parent
$('#show' + showDiv ).show(); //Fetch the value of option tag, concatenate it with the id and show the relevant div
});
CSS
div.parent > div {
display: none; /* Hide initially */
}
If you want to avoid using id's, you can also create your custom attribute, like data-show="1" and data-show="2" so on...
Try this
$(document).ready(function() {
$(".divs").hide();
$(".buttons").click(function() {
$(".divs").hide().eq($(this).index()).show();
});
});
DEMO
<input type="button" value="div1" class="buttons" id="button1" />
<input type="button" value="div2" class="buttons" id="button2" />
<input type="button" value="div3" class="buttons" id="button3" />
<input type="button" value="div4" class="buttons" id="button4" />
<input type="button" value="div5" class="buttons" id="button5" />
<input type="button" value="div6" class="buttons" id="button6" />
<div id="div1" class="divs">div1</div>
<div id="div2" class="divs">div2</div>
<div id="div3" class="divs">div3</div>
<div id="div4" class="divs">div4</div>
<div id="div5" class="divs">div5</div>
<div id="div6" class="divs">div6</div>
<script language="javascript">
$(document).ready(function () {
$(".buttons").click(function () {
$('.divs').hide();
$('#div'+$(this).attr('id').replace('button','')).toggle(100);
})
})
</script>

Categories