问题
I have a list of accordions in my html page and i would like to have a search box for filtering the accordions and its contents. Basically i would like to create a search box for all the accordions but i also want to search for the contents inside the accordions. Sorry if my question is not clear but this is my first question on Stackoverflow.
Below the code is for how i am creating the accordions and how i show them when the user press one title. (i have created one accordion in the html and i clone it whenever i want to create more in the javascript file.)
// this is in the html
<input type="search" id="accordion_search_bar" placeholder="Search"/>
<div id="accordions">
<div id="accID1" class="AccordionContainer">
<button id="accID" class="accordion"></button>
<div class="panel" id="panel1">
</div>
//this is the js file
for (a = 0; a < acc.length; a++) {
acc[a].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";
}
});
}
// this is the other js for the search
$(function() {
var searchTerm, panelContainerId;
// Create a new contains that is case insensitive
$.expr[":"].containsCaseInsensitive = function(n, i, m) {
return (
jQuery(n)
.text()
.toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0
);
};
$("#accordion_search_bar").on("change keyup paste click", function() {
searchTerm = $(this).val();
$("#accordions > .AccordionContainer").each(function() {
panelContainerId = "#" + $(this).attr("id");
$(
panelContainerId + ":not(:containsCaseInsensitive(" + searchTerm + "))"
).hide();
$(
panelContainerId + ":containsCaseInsensitive(" + searchTerm + ")"
).show();
});
});
});
Basically i want to the search box to search through the buttons of all accordions and also search in every panel that i created for each accordion.
回答1:
Using the HTML property innerText
we can extract the text content of each accordion and check whether it contains the text for which you are searching. If it does contain the text then we show the accordion, otherwise we hide it. MDN has a great article on innerText
. They state,
It approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied it to the clipboard
You might use innerText
when searching your accordions in the following way: (your accordion script uses vanilla JavaScript whereas your search is using JQuery. I'll use plain JavaScript below to ensure compatibility.)
Get a list of accordions:
accordions = document.querySelectorAll( '.AccordionContainer' );
Assuming your search is in a variable called searchText
, loop through each accordion and look at its text content:
Array.prototype.forEach.call( accordions, function( accordion ) {
if ( accordion.innerText.toLowerCase().indexOf( searchText ) >= 0 ) {
// If the index of searchText is -1 then it is not in the accordion.
// Otherwise it is, so we display the accordion
accordion.style.display = 'block';
}
else {
// We hide the accordion if searchText is not found
accordion.style.display = 'none';
}
} );
I converted both the search and accordion text content to lowercase for case insensitivity.
A complete example that shows an input event listener added to the search bar might look like the following:
var search = document.getElementById( 'accordion_search_bar' ),
accordions = document.querySelectorAll( '.AccordionContainer' );
// Show content on click
Array.prototype.forEach.call( accordions, function( accordion ) {
accordion.querySelector( 'button' ).addEventListener( 'click', function() {
this.nextElementSibling.classList.add( 'active' );
} );
} );
// Apply search
search.addEventListener( 'input', function() {
var searchText = search.value.toLowerCase();
Array.prototype.forEach.call( accordions, function( accordion ) {
if ( accordion.innerText.toLowerCase().indexOf( searchText ) >= 0 ) {
accordion.style.display = 'block';
}
else {
accordion.style.display = 'none';
}
} );
} );
.panel {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s;
}
.panel.active {
max-height: 300px;
}
<input type="text" id="accordion_search_bar">
<div id="accordions">
<div class="AccordionContainer">
<button class="accordion">Show Content</button>
<div class="panel" id="panel1"> This is accordion text</div>
</div>
<div class="AccordionContainer">
<button class="accordion">Show Content</button>
<div class="panel" id="panel1"> This is another lot of accordion text</div>
</div>
</div>
Note that using innerText
will search all text content of the accordion, including the button text. If you just want to search the panel text then get that element and use innerText
on that.
来源:https://stackoverflow.com/questions/55324783/live-search-for-accordions-and-its-content