I'm trying to create a drop down menu that exposes the content when it's hovered over. I didn't know how to do it myself so I referenced W3school's collapsible tutorial's code.
In the tutorial the collapsible opens when clicked on, and I was able to make it open when hovered over, but it's automatically closes when I try and hover over the content within. I need it to stay open when I hover over the internal content. I don't really know any js though so could someone help me?
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("mouseover", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
You need to handle the mouseenter and mouseleave event, but please do a container for both of the elements so that you can refer those events to it (as it includes both elements)
var coll = document.getElementsByClassName("both");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("mouseenter", function() {
var collapser = this.querySelector(".collapsible");
collapser.classList.add("active")
var content = collapser.nextElementSibling;
content.style.maxHeight = content.scrollHeight + "px";
});
coll[i].addEventListener("mouseleave", function() {
var collapser = this.querySelector(".collapsible");
collapser.classList.remove("active")
var content = collapser.nextElementSibling;
content.style.maxHeight = null;
});
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #555;
}
.collapsible:after {
content: '\002B';
color: white;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.content {
padding: 0 18px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
</style>
</head>
<body>
<h2>Animated Collapsibles</h2>
<p>A Collapsible:</p>
<div class="both">
<button class="collapsible">Open Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
<div class="both">
<button class="collapsible">Open Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
</body>
Related
SO,
It has been days that I am investing time on an error that I know could be solved with a line of code but because I am relatively new to coding I couldn't find a fix for this. I have a small piece of code for a collapsible list from W3 Schools, it works perfectly on W3 Schools editor but I get an Uncaught TypeError: content is null error while I push it to my WordPress website.
Here is the JavaScript Code:
window.onload=function() {
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
}
And here is the CSS:
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active, .collapsible:hover {
background-color: #555;
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
And finally here is the HTML:
<button type="button" class="collapsible">Open Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
Below is the console error that I get:
I am trying to make a collapsible div, using javascript, where you can navigate and open the collapsible by using the href="#one" tag. I have tried putting the href inside of the div, but with no result. I've also tried making the inside the div to an anchor text but still no success. However I do the collapsable won't open on the tag, only navigate to it's area while still being hidden.
<div class="box" id="one "> <h1> Object One </h1> </div>
<button type="button" class="collapsible" > Read more </button>
<div class="content" href="#one">
<p> Lorem ipsum dolor sit amet, consectetur adi
pisicing elit, sed do eiusmod tempor incidid
unt ut labore et dolore magna aliqua. Ut enim ad mini
m veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
javascript
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block")
{
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
Jsfiddle: https://jsfiddle.net/wbyux172/1/
Hope I can get some help with this one :)
You can create a link to a named anchor by using the name attribute (or the id attribute).
When linking within the same document, the A element is set as follows.
linked text
(Target point)
<a name="anchorname">a named anchor</a>
click here to see working example with explanation.
Checkout this working example:
var cols = document.querySelectorAll(".collapsible");
cols.forEach((col) => {
col.addEventListener("click", function() {
this.classList.toggle("active");
var contentArea = this.nextElementSibling;
var content = contentArea.querySelector('.content');
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
});
.collapsible {
background-color: #dedede;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.collapsible a{
text-decoration: none;
font-size: 16px;
font-weight: bold;
cursor: pointer;
}
.content-area .content {
border: 1px solid #dedede;
display: none;
padding: 10px;
}
<div class="box" id="one "><h1>Object One</h1></div>
<button type="button" class="collapsible" >
Read more
</button>
<div class="content-area">
<a name="section1"></a>
<div class="content">
<p> Lorem ipsum dolor sit amet, consectetur adi
pisicing elit, sed do eiusmod tempor incidid
unt ut labore et dolore magna aliqua. Ut enim ad mini
m veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
I'm using the code for an animated collapsible on this link:
https://www.w3schools.com/howto/howto_js_collapsible.asp
HTML:
<button type="button" class="collapsible">Open Collapsible</button>
<div class="content">
<p>Lorem ipsum...</p>
</div>
CSS:
/* Style the button that is used to open and close the collapsible content
*/
.collapsible {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .collapsible:hover {
background-color: #ccc;
}
/* Style the collapsible content. Note: hidden by default */
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
JS:
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
I want to implement another collapsible button inside the first collapsible drop down. As of right now my nested button does nothing when I click the + icon other than change to a -. Here is my html:
<button type="button" class="collapsible">Options:</button>
<div class="content">
<button class="collapsible">Check</button>
<div id="content">
TEST
</div>
</div>
CSS and JS are the same as in the link.
I created first loop to calculate all class content heights to be able to use this number as max-height to the main container. you can use css display block and none instead, but i do this to create animation.
var allHeights = 0;
var contents = document.getElementsByClassName("content");
var j;
for (j = 0; j < contents.length; j++) {
var h = document.getElementsByClassName("content")[j].scrollHeight;
allHeights += h;
}
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.maxHeight == allHeights + "px"){
content.style.maxHeight = "0px";
} else {
content.style.maxHeight = allHeights + "px";
}
});
}
.collapsible {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active, .collapsible:hover {
background-color: #ccc;
}
.content {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
.collapsible:after {
content: '\02795'; /* Unicode character for "plus" sign (+) */
font-size: 13px;
color: white;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2796"; /* Unicode character for "minus" sign (-) */
}
<button type="button" class="collapsible">First Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<button type="button" class="collapsible">Second Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button type="button" class="collapsible">Third Collapsible</button>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
You made a mistake in nested content div element. Instead of id="content" there should be class="content" to have it working correctly. Take a look at the snippet below.
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
/* Style the button that is used to open and close the collapsible content */
.collapsible {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .collapsible:hover {
background-color: #ccc;
}
/* Style the collapsible content. Note: hidden by default */
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}
<button type="button" class="collapsible">Options:</button>
<div class="content">
<button type="button" class="collapsible">Check</button>
<div class="content">
TEST
</div>
</div>
I am trying to have an Expand All button on my website. I have two levels of expanding and collapsing links and would like to have an option to Expand All when someone wants to see everything without clicking. I think I know what I need to do - loop through all accordions and set them to display. Could you give me some tips.
This is the code. Please help.
function ExpandAll() {
var acc = document.getElementsByClassName("accordionMain");
var i;
for (i = 0; i < acc.length; i++) {
var panel = this.Children
panel.style.display = "block";
}
}
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
<!DOCTYPE html>
<head>
</head>
<body>
<h2>Accordion</h2>
<button onclick="ExpandAll();">Expand All</button>
<button class="accordion">Section 2</button>
<div class="panel">
<button class="accordion">Section 1</button>
<div class="panel">
<p>
content
</p>
</div>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</body>
</html>
You can ask document to give you all .panel elements to show as below
function ExpandAll() {
var pannels = document.querySelectorAll('.panel');
for (panel of pannels)
panel.style.display = "block";
}
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
<h2>Accordion</h2>
<button onclick="ExpandAll();">Expand All</button>
<button class="accordion">Section 2</button>
<div class="panel">
<button class="accordion">Section 1</button>
<div class="panel">
<p>
content
</p>
</div>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
ExpandAll() should be expandAll() (May not matter but it bothered me)
Make sure to change it for the onclick for your button as well.
<button onclick="expandAll();">Expand All</button>
Then change your code to not look for acordionMain but for the panel. The getElementsByClassName(X) returns and array. So you can just iterate through that array and set the style to display: "block" via JS. The code is below.
<script>
function expandAll ()
{
var elements = document.getElementsByClassName("panel");
for (var i = 0; i < elements.length; i++) {
var panel = elements[i];
panel.style["display"] = "block";
}
}
</script>
EDIT:
Here is a Fiddle: https://jsfiddle.net/CraftingGamerTom/f6y96c2e/
I am new to this forum. I hope I am not breaking any rules. I am trying to include accordion within accordion and after a lot of research found this solution on your website. I thought I would start with this and modify what I need to make it work for my specific situation, but this solution does not seem to work for me and looks like it worked for the person asking. What am I doing wrong here? Please help.
<!DOCTYPE html>
<head>
<style>
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active, button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
</style>
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
</script>
</head>
<body>
<h2>Accordion</h2>
<button class="accordion">Section 2</button>
<div class="panel">
<button class="accordion">Section 1</button>
<div class="panel">
<p>
content
</p>
</div>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</body>
</html>
Include the <script> after the accordeon
<!DOCTYPE html>
<head>
<style>
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active, button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
</style>
</head>
<body>
<h2>Accordion</h2>
<button class="accordion">Section 2</button>
<div class="panel">
<button class="accordion">Section 1</button>
<div class="panel">
<p>content</p>
</div>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
</script>
</body>
</html>
Or else wrap your script in:
document.addEventListener("DOMContentLoaded", function(event) {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
});
Otherwise, when it gets to the part:
var acc = document.getElementsByClassName("accordion");
it cannot get the element by class name that does not yet exist, and acc will be an empty array.
Here you go with a solution using jQuery https://jsfiddle.net/apjnf4xf/1/
$('.accordion').click(function(){
$('.panel').slideUp();
$(this).next('div.panel').slideDown();
});
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active, button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Accordion</h2>
<button class="accordion">Section 2</button>
<div class="panel">
<p>content</p>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
Hope this will help you.
You are running the script before the browser even knows that your document has elements with class accordion. Run the script after the window has loaded or as the other answers here suggest, include the script after the accordion HTML markup.
<!DOCTYPE html>
<head>
<style>
button.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
button.accordion.active, button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
</style>
<script>
window.addEventListener('load',setUpAccordion);
function setUpAccordion(){
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
}
}
}
</script>
</head>
<body>
<h2>Accordion</h2>
<button class="accordion">Section 2</button>
<div class="panel">
<button class="accordion">Section 1</button>
<div class="panel">
<p>
content
</p>
</div>
</div>
<button class="accordion">Section 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</body>
</html>