我正在编写一个脚本,其中包含一个搜索输入框,用于隐藏那些不包含搜索文本的项目(这些项目分布在几个无序列表中)。目前该脚本基本按照预期工作,之前我也做过类似的功能并且运行良好。
然而,这次除了隐藏与输入文本不匹配的项目之外,我还想实现一个功能:如果某个父容器的所有子列表项都被隐藏(因为它们都不包含搜索文本),那么也隐藏该父容器。
但是现在出现了问题,当我添加了隐藏父容器的功能时,有些实际与输入文本相匹配、应当显示的项目却被隐藏了,而另外一些匹配项却没有被隐藏,我无法找出原因所在。
下面是基本的脚本示例:
// 获取过滤器元素及其名称
let filterList = [];
let filters = document.querySelectorAll('ul.list-filters a');
// 添加搜索输入框
let tEl = document.querySelector('#productListLeft');
let nEl = document.createElement('input');
nEl.setAttribute('id', 'filterSearch');
nEl.setAttribute('type', 'text');
nEl.setAttribute('placeholder', 'Search for filters');
tEl.prepend(nEl);
// 根据搜索文本过滤/隐藏项目
let filtersSearch = document.querySelector('#filterSearch');
for (let i = 0; i < filters.length; i++) {
let filterName = filters[i].querySelector('span:first-of-type').textContent.toLowerCase();
filterList.push(filterName);
}
filtersSearch.addEventListener('keyup', (e) => {
let text = filtersSearch.value.toLowerCase();
for (let i = 0; i < filters.length; i++) {
if (filterList[i].indexOf(text) < 0) {
filters[i].style.display = 'none';
} else {
filters[i].style.display = 'block';
}
}
// 隐藏所有子元素均被隐藏的父容器(此处功能出现不一致的问题)
let parentFilter = document.querySelectorAll(".filterSet");
let visCheck = true;
for(let i = 0; i < parentFilter.length; i++) {
let children = parentFilter[i].querySelectorAll('ul.list-filters a');
// 更新每个父容器内是否有可见子元素的标志
visCheck = children.some(child => child.style.display !== "none");
if (!visCheck) {
parentFilter[i].style.display = "none";
} else {
parentFilter[i].style.display = "block";
}
}
});
从描述来看,您提到当仅输入字符r
时,脚本表现正常,但如果只输入字符f
时,会出现误隐藏含有f
的项目,如第一个项目'foo'。
jQuery解决方案如下,您希望将其转换为纯JavaScript版本:
$('.filterSet').map(function(){
let visCheck = true;
$(this).find("ul.list-filters a").map(function(){
if ( $(this).css("display") != "none" ) {
visCheck = false;
}
});
if ( visCheck == true ) {
$(this).css("display", "none");
} else {
$(this).css("display", "block");
}
});
非常感谢,无论是帮助解决原始JavaScript脚本中的问题,还是将其转换为纯JavaScript版本以复制jQuery实现,都将非常感激。