I have a form with checkbox inputs that follow a certain hierarchy. I'm trying to make it so that clicking a button next to the input of a category toggles between showing and hiding the inputs of its subcategories. The toggling itself works just fine but it triggers a scroll to the top of the page. When I comment out the form tags the toggle works perfectly without the scrolling.
For reference, here's my html
function showSubcategories(show_button) {
let category_div = show_button.parentNode;
let subcategories_divs = category_div.querySelectorAll('.subcategory');
for (var i=0; i<subcategories_divs.length; i++) {
subcategories_divs[i].style.height = "32px";
}
show_button.style.display = "none";
category_div.querySelector('.hide-button').style.display = "inline-block";
}
function hideSubcategories(hide_button) {
let category_div = hide_button.parentNode;
let subcategories_divs = category_div.querySelectorAll('.subcategory');
for (var i=0; i<subcategories_divs.length; i++) {
subcategories_divs[i].style.height = "0px";
}
hide_button.style.display = "none";
category_div.querySelector('.show-button').style.display = "inline-block";
}
.subcategory {
padding-left: 20px;
overflow: hidden;
height: 0;
transition: 1s;
}
<form>
<div>
<input type="checkbox" value="category">
<label for="category">category</label>
<button class="show-button" onclick="showSubcategories(this)">∨</button>
<button class="hide-button" onclick="hideSubcategories(this)">∧</button>
<div class="subcategory">
<input type="checkbox" value="subcategory1">
<label for="subcategory1">subcategory1</label>
</div>
<div class="subcategory">
<input type="checkbox" value="subcategory2">
<label for="subcategory2">subcategory2</label>
</div>
</div>
</form>
I'm altering the height of each individual subcategory input separately because there's a variable number of subcategories for each category. I've tried placing all the subcategories within a single div and changing that div's height but I get the same issue. Any thoughts?
The default type of a button is submit:
type = submit|button|reset [CI]
This attribute declares the type of the button. Possible values:
submit: Creates a submit button. This is the default value.
https://www.w3.org/TR/html401/interact/forms.html#h-17.5
So you'd have to use event.preventDefault()
to cancel the submit, or specify type="button"
for the buttons.
function showSubcategories(show_button) {
show_button.parentNode.classList.toggle("open", true);
}
function hideSubcategories(hide_button) {
hide_button.parentNode.classList.toggle("open", false);
}
.subcategory {
padding-left: 20px;
overflow: hidden;
height: 0;
transition: 1s;
}
div.menu:not(.open) > .hide-button,
div.menu.open > .show-button
{
display: none;
}
div.menu.open > .subcategory
{
height: 32px;
}
<form>
<div class="menu">
<input type="checkbox" value="category">
<label for="category">category</label>
<button class="show-button" type="button" onclick="showSubcategories(this)">∨</button>
<button class="hide-button" type="button" onclick="hideSubcategories(this)">∧</button>
<div class="subcategory">
<input type="checkbox" value="subcategory1">
<label for="subcategory1">subcategory1</label>
</div>
<div class="subcategory">
<input type="checkbox" value="subcategory2">
<label for="subcategory2">subcategory2</label>
</div>
</div>
</form>