JS collapse isn't displaying my content correctly - javascript

I've been trying to get this to work but sadly I lack the knowledge in JS.
The content gets behind the collapsible div most of the time
is anyone able to help me fix this?
This is my js file :
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){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + 50 + "px";
}
});
}
https://codepen.io/FGamerNL/pen/qYJOxx

I think you need set maxHeight for parentElement has "content" class when click to children.

The max-height of your outer <div class="content"></div> is not recalculated, when you toggle one of it’s children.

Related

Identifier 'i' has already been declared problem

I try to do a accordion for display content and i get this problem on mi js code, I'm sure it's an easy problem to fix, but I can't see it right now, I need help to see it.
JS code:
var acc = document.getElementsByClassName("servicon-button");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
My html of this:
<button class="servicon-button"> <img src="icons/computer.svg" alt=""> </button>
<div class="panel">
try declaring the i variable inside the for loop, putting the variable inside the for loop ensures that the variable is only used inside the loop which is a good thing, if you put it outside, it will mix with other variables in the code in the global scopes which can cause problems like reassigning or redeclaring variables
const acc = document.getElementsByClassName("servicon-button");
for (let i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
const panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
sidenote : var is not really recommended, use const and let instead
Instead of declaring var i before the loop, declare it inside the for loop like this:
for (let i = 0; i < acc.length; i++) { ... This is where the error is coming from.

I try to make several divs show individually on click

I have 6 divs, and each div when click will show a pop up window, now, the problem is that it is not working. Here is my code, I don't know what i am doing wrong:
var clickMe = document.getElementsByClassName("skill-items__item");
for (i = 0; i < clickMe.length; i++) {
clickMe[i].addEventListener("click", function() {
var ShowMe = this.nextElementSibling;
for (i = 0; i < ShowMe.length; i++) {
if (ShowMe[i].style.display === "block") {
ShowMe[i].style.display = "none";
} else {
ShowMe.style.display = "block";
}
}
});
}
Your problem is that you're using i twice. Your second for loop is overwriting the i variable from the first for loop.
Don't worry, we've all been there. Good luck!

Javascript onClick() Requiring Multiple Clicks

Good Morning --
I have read through multiple posts with a very similar issue to mine but I still am unable to find a feasible solution. My sideNav is requiring an initial click before it begins working on every click and my dropdown boxes are requiring me double click before anything happens. I have been attempting to fix this for a few days now and was hoping someone here could help.
I have attached my code below. Thanks everyone for taking the time out of your day to help.
https://codepen.io/Bryant_Mitchell/pen/KKPbQLy
function sideBar() {
var sideBar = document.getElementById("sideBar"),
main = document.getElementById("main");
sideBar.style.width = sideBar.style.width === "250px" ? '0' : '250px';
main.style.marginLeft = main.style.marginLeft === "250px" ? '0' : '250px';
}
function collapseButton() {
var coll = document.getElementsByClassName("dropdown");
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){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
}
P.S. one additional issues I am having but it does not take any priority, when hiding my sideNav it tends to push the content down and is unsightly. I know I can increase the size of the navigation and it will fix this issue but I was wandering if there was any other way to fix it. Again, this isn't really a priority for me but figured I would ask here instead of making another post later.
Just remove the onclick Attribute of the dropdown Element in your HTML an add following Line at the end of your code:
addEventListener("load", collapseButton);
function sideBar() {
var sideBar = document.getElementById("sideBar"),
main = document.getElementById("main");
sideBar.style.width = sideBar.style.width === "250px" ? '0' : '250px';
main.style.marginLeft = main.style.marginLeft === "250px" ? '0' : '250px';
}
function collapseButton() {
var coll = document.getElementsByClassName("dropdown");
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) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
}
addEventListener("load", collapseButton);
addevntlistner can call your collapseButton function like above .
But remember to remove the onclick statement in your html file as shown below.
<button type="button" class="dropdown" >Projects</button>
The reason this is happening is because the sidebar doesn't have an initial style.width value. You're querying an inline style value, not the computed style value.
This code:
sideBar.style.width === "250px" ? '0' : '250px';
is the issue. On first run, your sidebar doesn't have an inline width value. When you click it the first time, then it gets an inline style value of 250px. You can skip this by calculating the computed width, not the inline width:
function sideBar() {
var sideBar = document.getElementById("sideBar");
var main = document.getElementById("main");
var sidebarWidth = getComputedStyle(sideBar).width;
var mainMargin = getComputedStyle(main).marginLeft;
sideBar.style.width = sidebarWidth === "250px" ? '0' : '250px';
main.style.marginLeft = mainMargin === "250px" ? '0' : '250px';
}
CodePen
You can do something similar for your dropdown.

Javascript find the content of a button (1 content per button)

I have a button
<button class="collapsible"></button>
whose content is
<div class="content"></div>
On a single page there might be multiple buttons, but every button is linked to a single content, so if there are 7 buttons in a page there are 7 contents too.
The content might be placed far away from its button, in fact between them there might be text, images, paragraphs, lists, or even another button, but in this last case the content of the second button is placed after the content of the first one.
So these are the typical cases
• button is simply followed by text
The <button class="collapsible">sky</button> is blue.
<div class="content">it is above our heads</div>
• button is followed by an image and they are both inside a paragraph
<p>I saw a <button class="collapsible">cat</button> like this <img ...></p>
<div class="content">The cat is the most beautiful thing in the universe</div>
• buttons is outside a ul list while content is inside it
The following is a <button class="collapsible">list</button> structure.
<ul>
<li>first item</li>
<li>second item <div class="content">it contains items</div></li>
<li>third item</li>
</ul>
• 2 buttons followed by their contents
There are 2 <button class="collapsible">buttons</button> in this <button class="collapsible">line</button> as you can see.
First <div class="content">are clickable things</div> and second <div class="content">is a straight thing</div>
Initially I was using the following javascript
( function() {
var list = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < list.length; i++) {
list[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.parentElement.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
} )();
Notice how this variable is defined
var content = this.parentElement.nextElementSibling
The parentElement was necessary since wordpress usually adds <p> tags. But later I found out that in some cases the <p> tags were not automatically added, and so I edited the JS content variable to be
var content = this.nextElementSibling;
if (!content) {
content = this.parentElement.nextElementSibling;
}
Now I'd like to place images or another button between a certain button and its content, but its difficult to handle all the cases using if's.
Since every button is linked to a unique content, is it possibile to write a JS which given the button number n it finds the content number n?
I was thinking about defining the variables
var coll = document.getElementsByClassName("collapsible");
var cont = document.getElementsByClassName("content");
(so coll.length == cont.length) and then for a given i associate coll[i] with cont[i]. So I edited the definition of content to be
var content = cont[i];
but I found out that this doesn't work since at that point i is equal to coll.length, that is i is out of range. This is the full JS I was thinking about
( function() {
var coll = document.getElementsByClassName("collapsible");
var cont = document.getElementsByClassName("content");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = cont[i];
console.log(content)
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
} )();
This seems to work in all cases
<script type="text/javascript">
( function() {
coll = document.getElementsByClassName("collapsible");
cont = document.getElementsByClassName("content");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].setAttribute('data-id', 'con' + i);
cont[i].setAttribute('id', 'con' + i);
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = document.getElementById(this.getAttribute('data-id'));
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
} )();
</script>

How do I collapse all extended blocks?

I'm trying to use this collapsible menu. I want to be able to collapse all blocks under the collapsible menu under the header block. Currently, they all keep extended.
The script for the extension of the block -
<script>
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";
}
});
}
</script>
I'd like all extended blocks under the header block to re-collapse once the header block is clicked on again.

Categories