How to convert a <div> to collapsable panel? - javascript

As shown in the image below I want to collapse left blue panel
I am trying to create left Blue panel using HTML. But I do not have any idea, how to create collapsable panel?

Concept used
Execute a function when button is clicked.
Explanation of Code
First there are 2 buttons present on same location : myButton1 and myButton2
myButton2 which shows the div is currently invisible (display:none;).
when mybutton1 is clicked it reduces the width of "menu" div and also hides itself while making myButton2 visible. When myButton2 is clicked it restores the width of "menu" div and hides itself while making button1 visible.
function toggle1() {
document.getElementById("menu").style.width = "2px";
document.getElementById("myButton1").style.display = "none";
document.getElementById("myButton2").style.display = "block";
};
function toggle2() {
document.getElementById("menu").style.width = "100px";
document.getElementById("myButton2").style.display = "none";
document.getElementById("myButton1").style.display = "block";
};
#menu {
width: 100px;
height: 500px;
background: blue;
}
#myButton1 {
position: absolute;
}
#myButton2 {
position: absolute;
display: none;
}
<div id="container">
<input onclick="toggle1()" type="button" value="hide" id="myButton1"></input>
<input onclick="toggle2()" type="button" value="show" id="myButton2"></input>
<div id="menu">
</div>
</div>

This will give you a div and a button. By default, the div is collapsed but when you click the button, the div will expand to reveal the content. Clicking the button again will collapse it again.
HTML:
Panel Button
<div class="blue-panel">a blue panel</div>
CSS:
.blue-panel{overflow:hidden; max-height: 0;}
.blue-panel.active{max-height: 1000px;}
JS:
jQuery('.panel-toggle').click(function() {
jQuery('.blue-panel').toggleClass('active');
});

Related

Toggle or Show/Hide

I need help toggling overlays with multiple divs. I don't want to have a separate function for each one (there's 6 with 6 different overlay popups). The onclick div will reveal the overlay popup. Help is appreciated!
I need help toggling overlays with multiple divs. I don't want to have a separate function for each one (there's 6 with 6 different overlay popups). The onclick div will reveal the overlay popup. Help is appreciated!
function on() {
document.getElementById("overlay").style.display = "block";
}
function off() {
document.getElementById("overlay").style.display = "none";
}
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.8);
z-index: 2;
cursor: pointer;
}
#text{
position: absolute;
top: 50%;
left: 50%;
font-size: 1rem;
color: white;
transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
}
<!-- //DIV -->
<div class="row ">
<div class="col-md-6 col-lg-4 d-flex align-items-stretch" onclick="on()">
<div class="card mb-3">
<img src="img/ballet.jpg" class="embed-responsive w-100 classpic" alt="...">
<div class="card-body">
<h5 class="card-title">BALLET</h5>
</div>
</div>
</div>
<!-- //POPUP -->
<div id="overlay" onclick="off()">
<div id="text">
<h3>Ballet</h3>
<p>Ballet is an artistic dance form performed to music using precise and highly formalized set steps and gestures.
Classical ballet, which originated in Renaissance Italy and established its present form during the 19th century,
is characterized by light, graceful, fluid movements and the use of pointe shoes.
</p>
<h4>Shedule:</h4>
<p>Ages 4-8: Thursdays • 4PM<br>
Ages 9-14: Fridays • 7PM</p>
</div>
</div>
There's a problem with your approach, namely, when an element has display:none it is removed from the html tree and cannot receive a click event. Also, no two elements can share the same id attribute and so your function cannot be applied by reference to an id directly.
I've made a working snippet that achieves what I think you are after. There are undoubtedly others that would work but it's quite straight forward and works.
Firstly, arrange each of your alternative div pairs (one hidden, one visible) inside a parent div and give it a class name. This has the advantage that, if you size the container div appropriately, the content will not jump about when you swap the hidden div for visible and vice versa. Next, give classes to distinguish the (initially) hidden content from the visible div. Your markup pattern then will be repeats of:
<div class='container'>
<div class='main'>my first main content</div>
<div class='hidden'>my first hidden content </div>
</div>
In the style sheet, set the class display properties:
.hidden {
display: none;
}
.main {
display: block;
}
Then, set up a click event listener in javascript. This will take a click event from anywhere on the page.
document.addEventListener('click', event => {
})
inside the event listener, place an if block to test whether the click event was received by an element that was inside a div of .container class:
if (event.target.parentElement.className=='container') {
}
I slightly modified this, see edit note and bottom.
If the click event got that far, the click must have been recieved by the visible div inside that container (since the hidden one cannot receive click events and they are the only two elements present.
So you can go ahead and swap the classes applied to the visible div that received the click:
event.target.classList.add('hidden');
event.target.classList.remove('main');
You now have to do the opposite to the other div in the container class to make that sibling visible. The problem is, you don't know whether the hidden class was the first child, or the second child of the container div. What you do know for sure, is that the other div is a sibling of the div you just made invisible.
So we can test to see if there is a next sibling using a conditional:
if (event.target.nextElementSibling) {
event.target.nextElementSibling.classList.add('main');
event.target.nextElementSibling.classList.remove('hidden');
}
If the hidden div followed the visible one, a nextElementSibling will be found and the classes swapped. If no nextElementSibling was found, we know the other div had to come before the one we already hid.
so, an else extension of that if block can be added to switch the classes on the previousElementSibling:
...} else {
event.target.previousElementSibling.classList.add('main');
event.target.previousElementSibling.classList.remove('hidden');
} // end else;
And you're done!
I wanted to explain the logic in detail to make sure you know what's going on, but it's not that complicated.
The advantage of an approach like this is that the single event listener will cope with 1, 2, or 1,000 pairs of divs and none need any special IDs or anything other than an initial class of .main or .hidden (and that they be grouped inside a .container div.
document.addEventListener('click', event => {
if (event.target.parentElement && event.target.parentElement.className=='container') {
event.target.classList.add('hidden');
event.target.classList.remove('main');
if(event.target.nextElementSibling) {
event.target.nextElementSibling.classList.add('main');
event.target.nextElementSibling.classList.remove('hidden');
} else {
event.target.previousElementSibling.classList.add('main');
event.target.previousElementSibling.classList.remove('hidden');
} // end else;
} // end parentElement if;
}) // end click listener;
.hidden {
display: none;
border: 1px solid red;
margin: 5px;
}
.main {
display: block;
border: 1px solid black;
margin: 5px;
}
<div class='container'>
<div class='main'>my first main content</div>
<div class='hidden'>my first hidden content </div>
</div>
<div class='container'>
<div class='main'>my second main content</div>
<div class='hidden'>my second hidden content </div>
</div>
Edit the conditional to detect whether the parent element of the click event was a .container div was modified to check that the event target has a parent AND that the parent is a .container div. This prevents an error if a click is received anywhere outside of the container div.
** Displaying an Opaque Overlay in Response to Click **
Again, this solution allows the functionality to be applied to limitless div elements without the need for independent ids. Again, two classed .main and .hidden are used to decide which div has been clicked from a single event listener applied to the document rather than to multiple divs.
The basic process of displaying, and then re-hiding the (originally hidden) .overlay div is very simple:
if (element.className == 'main') {
element.parentElement.getElementsByClassName('overlay')[0].classList.remove('hidden');
}
if (element.className == 'overlay') {
element.classList.add('hidden');
}
However, a problem arises because of the use of class names, rather than ids. Namely, when the overlay is displayed, a click on it may be received by a descendent element that does not have the class name .hidden. To work properly, every descendent of the overlay div would have to be given the .hidden class and the class swapped applied for ever element inside the .hidden div. This could get very complicated if the div had many child elements (perhaps with their own descendents).
Instead, when a click is received, the target element is inspected to see if it has a relevant class (main or hidden). If it does, the script flows to the simple class switching blocks. If it has no, or a different class name however, a do-while loop examined the parent element of the click to see if it was contained in a relevant (main or hidden) class. The loop continues searching up the document tree until either a relevant element is found, or there are no more parent elements to examine.
If a parent is found to have the required class name, a reference to the element is passed onto the class switching block.
do {
if (element && (element.className == 'overlay' || element.className == 'main')) {
// foundElementClassName = element.className;
break;
} // end if;
if (element.parentElement) {
element = element.parentElement;
} else {
break;
}
} while (element.className != "overlay" || element.className != "main");
The following working snippet demonstrates the functionality. In it, three divs (coloured pink) have an associated (initially) hidden overlay div, while a fourth div has no associated overlay and should ignore clicks.
If a click is made on a pink div, it's specific overlay appears. A click anywhere on the overlay dismisses it, regardless of whether the click was received by the overlay div itself, or by a child element or deeper descendent (e.g. clicking on the text of the overlay (which is in a child h2 element still allows the correct .overlay div to have its styles switched to hide it again.
document.addEventListener('click', (event) => {
let element = event.target;
do {
if (element && (element.className == 'overlay' || element.className == 'main')) {
// foundElementClassName = element.className;
break;
} // end if;
if (element.parentElement) {
element = element.parentElement;
} else {
break;
}
} while (element.className != "overlay" || element.className != "main");
// end do-while loop;
// if a relevant element was found, the element object is stored in element variable;
if (element.className == 'main') {
element.parentElement.getElementsByClassName('overlay')[0].classList.remove('hidden');
}
if (element.className == 'overlay') {
element.classList.add('hidden');
}
}) // end click event listener;
.main {
display: block;
width: 50%;
margin: 10px;
border: 1px solid black;
background: pink;
}
.overlay {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0px;
left: 0px;
width: 100%;
min-height: 100%;
bottom: auto;
z-index: 1;
background: rgba(255,255,0,0.7);
padding: 20px;
}
.hidden {
display: none;
}
.other {
display: block;
width: 50%;
margin: 10px;
border: 1px solid black;
background: yellow;
}
<div class="container">
<div class="main">Content of div 1. Content of div 1. Content of div 1. Content of div 1. Content of div 1. Content of div 1. Content of div 1. Content of div 1 </div>
<div class="overlay hidden"><h1>overlay for first pink div</h1> </div>
</div>
<div class="other">
some other content that doesn't have an associated overlay and that should ignore clicks.
</div>
<div class="container">
<div class="main">Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2. Content of div 2.</div>
<div class="overlay hidden"><h1>overlay for SECOND pink div</h1> </div>
</div>
<div class="container">
<div class="main">Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. Content of div 3. </div>
<div class="overlay hidden"><h1>overlay for Third pink div</h1> </div>
</div>

How to hide a popup by clicking outside using javascript

There are so many questions like my one,even I go through this link also.But I didnt get a proper solution yet.So Im posting my issue here.
I have to popup a message when click an icon and when I click the same div where the icon is reside,it should disappear. This is working fine.But when I click outside the div also, the popup should disappear.How can I modify this javascript function to achieve it
<div>
<h5 class="haead">Search for a product title
<div class="popup" onclick="myFunction5()"> <img class="qnicon" src="question.png">
<span class="popuptext" id="myPopup5">Search product.</span>
</div>
</h5>
</div>
<script>
function myFunction5() {
var popup = document.getElementById("myPopup5");
popup.classList.toggle("show");
}
</script>
The easiest way I've found that avoids any number of other problems you could encounter, is to put the popup on top of a 100% width/height div. That "disabler" div has the same click handler as the button that would ordinarily close the popup. So if the user clicks the "X" to close, the "Ok" button (or whatever you've got set up) or the area outside the popup, same effect, it closes.
That "disabler" div (it effectively disables the entire app except for the popup) can be completely clear, or translucent, by setting the opacity.
You put the "disabler" div at z = 9998, the popup at z = 9999 (just more CSS), and they'll always be on top. Note that this may not be necessary if all your content loads into a div that is already underneath the disabler (e.g. the router-outlet div in Angular), but I usually do it anyway.
Complete basic example. I typically make a component out of this and hook it into an event bus so I can pass data in and out of it (so I can change the position, style, messages, even what happens when you click the close button). If you get this code you should be able to use some approximation of it in any framework, etc.
<html>
<head>
<style>
.button {
text-align: center;
width: 100px;
height: 30px;
background-color: green;
border: 2px solid grey;
color: white;
margin: auto;
position: relative;
}
.disabler {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 99998;
background-color: #000000;
opacity: 0.5;
}
.popup {
position: relative;
/* Center with whatever voodoo you like */
top: calc(50% - 150px);
left: calc(50% - 150px);
width: 300px;
height: 300px;
background-color: blue;
border: 2px solid grey;
z-index: 99999;
}
</style>
</head>
<body>
<div class="button" onclick="togglePopup ( )">
Show Popup
</div>
<div class="button" onclick="showAlert ( )">
Show Alert
</div>
<!-- This div is on top of everything except the popup div -->
<!-- It effectively disables the entire app except for the popup -->
<div id="disabler" class="disabler" onclick="togglePopup ( )"></div>
<!-- This div holds the popup -->
<!-- You can only close the popup by clicking the close button, or the disabler background -->
<!-- Clicking in the blue popup area doesn't do anything (intentionally) -->
<!-- Even though you can see other widgets through the disabler, they're all inaccessible -->
<!-- Try the show alert button to confirm -->
<div id="popup" class="popup">
<div class="button" onclick="togglePopup ( )">
Close Popup
</div>
</div>
<script type="text/javascript">
togglePopup ( ); // Hide them to start.
function togglePopup ( ) {
let disabler = document.getElementById ( 'disabler' );
disabler.style.display = disabler.style.display ? '' : 'none';
let popup = document.getElementById ( 'popup' );
popup.style.display = popup.style.display ? '' : 'none';
}
function showAlert ( ) {
alert ( 'Hey there!' );
}
</script>
</body>
</html>
Here is the way to do this:
Javascript
popup.addEventListener('click',function(e) {
// This is important to prevent the popup from inheriting the event since it
// is inside the body
e.stopPropagation();
});
var body = document.body;
body.addEventListener('click', function(e){
if(popup.classList.contains('show')) {
popup.classList.remove("show");
}
);
I wish this solves your problem
Edit
That didn't work because you have to structure your code properly like this:
HTML
<div id='popup-container'>
<!-- This all inside the popup -->
<h5 class="haead">Search for a product title</h5>
<div class="popup-data">
<img class="qnicon" src="question.png">
<span class="popuptext" id="myPopup5">Search product.</span>
</div>
Show Popup
</div>
Javascript
var popupContainer = document.getElementById('popup-container');
var body = document.body;
var showPopup = document.getElementById('show-popup');
showPopup.addEventListener('click', function(e) {
e.preventDefault();
popupContainer.classList.add('show');
});
popupContainer.addEventListener('click', function(e) {
e.stopPropagation();
});
body.addEventListener('click', function(e) {
if(popupContainer.classList.contains('show'))
popupContainer.classList.remove('show');
);

How do I get a currently visible (default hidden) slideToggle() .div to close when another is opened?

So I have close to what I would like to achieve, including having my slideToggle .divs close when I click anywhere off of the "link" divs (.click, .click2) with one glaring exception...
When I click "Link 1" it does what I'd like and displays .showup then if I click "Link 2" it also initially does what I'd like and displays .showup2 over .showup BUT I need .showup to close so that they aren't both open at the same time.
As you can see with my provided code this presents a problem bc with both "showup" divs already open if I then directly click "Link 1" again .showup remains hidden behind .showup2
Similarly, in the above example if I click "Link 2" first, .showup2 opens but when I then directly click "Link 1", .showup does not appear over .showup2
So ultimately I would like my slideToggle divs to hide when I click ANYWHERE outside of my "Link" divs (.click and .click2) - which it currently does - however that ANYWHERE should include my other script instructed "Link" divs!! And that is where I am stumped.
Here is code that demonstrates in a very simplified example :
HTML
<div class="click">Link 1</div> <div class="click2">Link 2</div>
<div class="showup">something I want to show</div>
<div class="showup2">something else I want to show</div>
SCRIPT
$(document).ready(function(){
$('.click').click(function(event){
event.stopPropagation();
$(".showup").slideToggle("fast");
});
});
$(document).on("click", function () {
$(".showup").hide();
});
$(document).ready(function(){
$('.click2').click(function(event){
event.stopPropagation();
$(".showup2").slideToggle("fast");
});
});
$(document).on("click", function () {
$(".showup2").hide();
});
CSS
body{margin:50px;}
.showup,
.showup2 { width:100%;height:100px; background:red; display:none; position: fixed;}
.click,
.click2 { cursor:pointer; display:inline-block; padding: 0 15px;}
Thanks so much for any help! Jorie
You could do with same class name of the button and boxes .data-target attr used for target the which element to toggling .
Updated
Toggle function with each button
Bold text toggle function added
$(document).ready(function() {
$('.click').click(function(event) {
event.stopPropagation();
if($(".showup").eq($(this).attr('data-target')).css('display') == 'block'){
$(".showup").eq($(this).attr('data-target')).slideUp();
$('.click').removeClass('bold')
}
else{
$(".showup").hide();
$('.click').removeClass('bold')
$(".showup").eq($(this).attr('data-target')).slideToggle("fast");
$(this).toggleClass('bold')
}
});
}).on('click',function(){
$(".showup").hide();
$('.click').removeClass('bold')
})
body {
margin: 50px;
}
.showup{
width: 100%;
height: 100px;
background: red;
display: none;
position: fixed;
}
.bold{
font-weight:bold;
}
.click{
cursor: pointer;
display: inline-block;
padding: 0 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click" data-target="0">Link 1</div>
<div class="click" data-target="1">Link 2</div>
<div class="showup">something I want to show</div>
<div class="showup">something else I want to show</div>

Close lightbox on click outside of the child div

I'm creating a lightbox without using a jquery plugin, and now I'm trying to close it by clicking on the close button or by clicking anywhere else outside of the white area (.white_content)
Jsfiddle Example
<button onclick="document.getElementById('lightbox').style.display='inline';">
Show lightbox
</button>
<!-- LIGHTBOX CODE BEGIN -->
<div id="lightbox" class="lightbox" style="display:none">
<div class="white_content">
Close
<p>Click anywhere to close the lightbox.</p>
<p>Use Javascript to insert anything here.</p>
</div>
</div>
<!-- LIGHTBOX CODE END -->
Although it's not just like I want it. I want it to close only if I click on the dark area of the lightbox and not on the white container (.white_content), I've heard that event.propagation can be a bad thing to use, so here's how I'm closing the lightbox
$(document).on('click', function(event) {
if (!$(event.target).closest('button').length) {
$(".lightbox").hide();
}
});
you can change you condition bit like below
$(document).on('click', function(event) {
if ($(event.target).has('.white_content').length) {
$(".lightbox").hide();
}
});
Most lightbox scripts are using two div-s, content and overlay. Overlay is there for background and to prevent users to click on page content, and also click on overlay can be used to close lightbox.
HTML:
<div id="lightbox"> LIGHTBOX CONTENT </div>
<div id="overlay"></div>
JS:
$( '#overlay, #close').on('click', function(event) {
$("#lightbox, #overlay").hide();
});
$( '#show').on('click', function(event) {
$("#lightbox, #overlay").show();
});
EXAMPLE
You want to close the lightbox on any click that isn't targeting the lightbox or one of its children. Your existing code is pretty close:
$(document).on('click', function(event) {
if (!$(event.target).closest('button').length &&
!$(event.target).closest('.white_content').length) {
$(".lightbox").hide();
}
});
$(document).on('click', function(event) {
if (!$(event.target).closest('button').length &&
!$(event.target).closest('.white_content').length) {
$(".lightbox").hide();
}
});
.textright {
float: right;
}
.lightbox {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background:rgba(0, 0, 0, .8);
}
.white_content {
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
padding: 16px;
border: 5px solid gray;
background-color: white;
z-index:1002;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="document.getElementById('lightbox').style.display='inline';">
Show lightbox
</button>
<!-- LIGHTBOX CODE BEGIN -->
<div id="lightbox" class="lightbox" style="display:none">
<div class="white_content">
Close
<p>Click anywhere to close the lightbox.</p>
<p>Use Javascript to insert anything here.</p>
</div>
</div>
<!-- LIGHTBOX CODE END -->
I'd also recommend using a class to denote whether the lightbox is visible or not, rather than changing the display property directly; that way it's more clear when you check it. Compare $el.is('.active') with $(el).css('display') == 'inline'

Onclick, only parent div not subdiv

I'm playing around with building a basic modal window and i want it do dissapear when i click the edges. So my problem in it's most basic form:
<div style="width:100%;height:100%;" onclick="hideAll()">
Hide all onclick.
<div style="width:100px;height:100px;">
does not hide all onclick
</div>
</div>
What is the best way to achieve this? To use unnested divs? html/css magic?
HTML:
<div style="width:100%;height:100%;" class="outerModal">
Hide all onclick.
<div style="width:100px;height:100px;">
does not hide all onclick
</div>
</div>
JavaScript:
$(document).on("click", ".outerModal", function(evt) { //listen for clicks
var target = $(evt.target ||evt.srcElement); //get the element that was clicked on
if (target.is(".outerModal")) { //make sure it was not a child that was clicked.
//hide dialog
}
});
Example:
JSFiddle
When you hide the parent tag, it automatically hides the childen tag as well, You should first contain the child div into variable and after that hide the parent div and append that stored child div into parent tag something like this.
HTML
<div id="result">
<div style="width:100%;height:100%;" id="parentDiv" onclick="hideAll()">
Hide all onclick.
<div style="width:100px;height:100px;" id="childDiv">
does not hide all onclick
</div>
</div>
</div>
javaScript
function hideAll(){
var childDiv = document.getElementById('childDiv'); //contain child div
var parDiv = document.getElementById('parentDiv');
parDiv.style.display = 'none'; //hide parent div
parDiv.parentNode.appendChild(childDiv); //append child div
}
DEMO
Assuming that "parentDiv" is to be the background and "childDiv" is to be the actual modal content, the best way I have found is to separate the divs entirely.
HTML
<div id="parentDiv" onclick="hideAll()"> </div>
<div id="childDiv" >
does not hide all onclick
</div>
Javascript using jQuery
function hideAll(){
/* The Parent Div will hide everything when clicked, but the child won't */
$('#childDiv').fadeOut(1000, function(){
$('#parentDiv').fadeOut(1000);
});
}
CSS
#parentDiv {
background: black;
display: block;
position: fixed;
top: 0;
left: 0;
z-index: 100;
height: 100%;
width: 100%;
}
#childDiv {
display: block;
position: relative;
background: white;
height: 200px;
width: 200px;
z-index: 101
}
Here is a working example.
Hope this helps at all.
See this fiddle:
http://jsfiddle.net/eZp9D/
$(document).ready(function () {
$('#parentDiv').click(function (e) {
if ($(e.target).prop('id') == "parentDiv") {
$(this).hide();
}
});
});
You can use basic jQuery and style it accordingly with CSS.
Check this example.
If you want to have it disappear by clicking outside of the dialog window, make sure that onClick you perform this action:
$( "#dialog_id" ).dialog( "close" );

Categories

Resources