I have a page that sorts things if you choose one of the options. The list of filters was too long so I added a div that shows/hides options. On page load some of the options are hidden via CSS with display: hidden
. Code below just changes display
from display: none
to display: inline-block
based on number of clicks.
var timesClicked = 0;
window.onload = function(){
document.getElementById("filter_attribute_217").onclick = function(){
timesClicked ;
if (timesClicked%2==0){
hide();
} else {
show();
}
};
This is show() function
function show(){
document.getElementById("filter_attribute_69").style.display="inline-block";
document.getElementById("filter_attribute_70").style.display="inline-block";
document.getElementById("filter_attribute_72").style.display="inline-block";
//all those other options
document.getElementById("filter_attribute_217").innerHTML = "less";
document.getElementById("filter_attribute_217").style.borderTop = "1px dashed #e1e4e6";
document.getElementById("filter_attribute_68").style.borderBottom = "none";
document.getElementById("filter_attribute_87").style.borderBottom = "none";
}
And this is hide() function
function hide(){
document.getElementById("filter_attribute_217").innerHTML = "more";
document.getElementById("filter_attribute_217").style.borderTop = "1px dashed #e1e4e6"
document.getElementById("filter_attribute_69").style.display="none";
document.getElementById("filter_attribute_70").style.display="none";
//all those other options
document.getElementById("filter_attribute_103").style.display="none";
}
This is working perfectly until I choose one of the options which means that some other disappear. Then when trying to use more/less button I will get errors like this one:
Uncaught TypeError: Cannot read properties of null (reading 'style')
at hide (user.js?sci=481:68:50)
at document.getElementById.onclick (user.js?sci=481:58:9)
Clicking it again shows the same error just with show()
function.
I've tried checking if element exist in DOM structure with document.body.contains(YOUR_ELEMENT_HERE);
but it always shows that all of the options exists. Checked it with
if(document.body.contains(element){
console.log("exists")
} else {
console.log("doesn't exist")
}
Console was always outputting "exists".
I then tried just ignoring the problem to see if others options will show with
function stoperror() {
return true;
};
window.onerror = stoperror;
But with the same result just without the error. I'm at my wit's end and I don't know why this is happening and how can I fix it. I need to add that all I can edit here is JavaScript and CSS. Thats why I made another option (filter_attribute_217) and made it into my show more/less button.
Any help is appreciated even if you tell me it's not possible so I won't think about it.
EDIT: Here's HTML code for basically every option. They only thing that is changing from option to option is id and href.
<div data-limit="3" id="filter_attribute_104">
<h5>
Transparent
</h5>
<ul>
<li style="margin-right:15px;">
<a title="tak" href="/pl/c/Balls/119/1/default/1/f_at_104_0/1">
<i src="/libraries/images/1px.gif" alt="" ></i>
<span>tak </span>
<em>(56)</em>
</a>
</li>
</ul>
<div data-limit="3" id="filter_attribute_68">
<h5>
White
</h5>
<ul>
<li style="margin-right:15px;">
<a title="tak" href="/pl/c/Balls/119/1/default/1/f_at_68_0/1">
<i src="/libraries/images/1px.gif" alt="" ></i>
<span>tak </span>
<em>(208)</em>
</a>
</li>
</ul>
I also have this in my JS code
window.addEventListener("DOMContentLoaded",(event) => {
document.getElementById("filter_attribute_217").innerHTML = "więcej";
document.getElementById("filter_attribute_217").style.borderTop = "1px dashed #e1e4e6";
});
CodePudding user response:
This is an example with the code you provided. However your question is still not properly stated. I assume the HTML is getting generated dynamically? If so, I would make sure that the elements I'm trying to use are existing for sure while I call my JS. So I got rid of the window.onload
you are using. Also, if you want to apply global changes, do not repeat the same things for each ID, just use a querySelectorAll('.classname')
with a .forEach
. Example:
let timesClicked = 0;
let show = () => {
document.querySelector('.group-filter').innerHTML = 'LESS';
document.querySelectorAll('.group-filter').forEach(elem => {
elem.style.display = 'flex';
// Other things...
});
}
let hide = () => {
document.querySelector('.group-filter').innerHTML = 'MORE';
document.querySelectorAll('.group-filter').forEach(elem => {
elem.style.display = 'none';
// Other things...
});
// Restore the first element's display
document.querySelector('.group-filter').style.display = 'flex';
}
document.getElementById('filter_attribute_104').addEventListener('click', () => {
timesClicked ;
if (timesClicked % 2 == 0) hide();
else show();
});
.hidden {display:none;}
<div data-limit="3" id="filter_attribute_104">
<h5>Transparent</h5>
<ul>
<li style="margin-right:15px;">
<a title="tak" href="#">
<i src="/libraries/images/1px.gif" alt="" ></i>
<span>tak </span>
<em>(56)</em>
</a>
</li>
</ul>
</div>
<div data-limit="3" id="filter_attribute_68">
<h5>White</h5>
<ul>
<li style="margin-right:15px;">
<a title="tak" href="#">
<i src="/libraries/images/1px.gif" alt="" ></i>
<span>tak </span>
<em>(208)</em>
</a>
</li>
</ul>
</div>
<div data-limit="3" id="filter_attribute_168">
<h5>Red</h5>
<ul>
<li style="margin-right:15px;">
<a title="tak" href="#">
<i src="/libraries/images/1px.gif" alt="" ></i>
<span>tak </span>
<em>(332)</em>
</a>
</li>
</ul>
</div>