Live search for accordions and its content

£可爱£侵袭症+ 提交于 2021-02-19 03:48:14

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!