Question

I'm using below jscript code to filter unordered list. I'm trying to remove <h3> Tag for the results while searching. Example if search for Batman My current output is

Action    
   Batman

Adventure

I need to remove heading Adventure coz no result under this category.

    <script type="text/javascript"> 
(function ($) {
  jQuery.expr[':'].Contains = function(a,i,m){
      return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
  };  
  function listFilter(header, list) {
    var form = $("<form>").attr({"class":"filterform","action":"#"}),
        input = $("<input>").attr({"class":"filterinput","type":"text"});
    $(form).append(input).appendTo(header); 
    $(input)
      .change( function () {
        var filter = $(this).val();
        if(filter) {
          $(list).find("a:not(:Contains(" + filter + "))").parent().slideUp();    
          $(list).find("a:Contains(" + filter + ")").parent().slideDown();          
        } else {
          $(list).find("li").slideDown();
        }
      })
    .keyup( function () {
        $(this).change();
    });
  } 
  $(function () {
    listFilter($("#header"), $("#list"));
  });
}(jQuery)); 
  </script>

And my html is

<div id="wrap"> 
    <h1 id="header">DVD Collection<form class="filterform" action=""><input class="filterinput" type="text"></form></h1> 
    <h3>Action</h3>
    <ul id="list"> 
        <li><a href="#">Batman</a></li>
        <li style="display: list-item;"><a href="#">Star Trek (2009)</a></li> 
        <li style="display: list-item;"><a href="#">Tremors</a></li> 
    </ul> 
    <h3>Adventure</h3>
    <ul id="list">  
        <li style="display: list-item;"><a href="#">Ice Age</a></li> 
        <li style="display: list-item;"><a href="#">Avathar</a></li> 
    </ul> 

</div>
Was it helpful?

Solution

Hers the code modified. works perfectly. i have changed the HTML too.

HTML:

<div id="wrap"> 
<h1 id="header">DVD Collection</h1> 
<ul id="list">   
  <li>
<h3>Action</h3>
<ul>
    <li><a href="#">Batman</a></li>
    <li style="display: list-item;"><a href="#">Star Trek (2009)</a></li> 
    <li style="display: list-item;"><a href="#">Tremors</a></li> 
  <li style="display: list-item;"><a href="#">Amnts</a></li> 
  </ul>
  </li>
  <li>
<h3>Adventure</h3>
<ul>
    <li style="display: list-item;"><a href="#">Ice Age</a></li> 
    <li style="display: list-item;"><a href="#">Avathar</a></li> 
</ul> 
  </li>
  </ul>
</div>

Javascript:

(function ($) {
  jQuery.expr[':'].Contains = function(a,i,m){
      return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
  };  
  function listFilter(header, list) {
    var form = $("<form>").attr({"class":"filterform","action":"#"}),
        input = $("<input>").attr({"class":"filterinput","type":"text"});
    $(form).append(input).appendTo(header); 
    $(input)
      .change( function () {
        var filter = $(this).val();
        if(filter) {
          $(list).find("a:not(:Contains(" + filter + "))").parent().slideUp(function(){$(list).find("ul").each(function(){
            console.log($(this).children("li:visible").length); if($(this).children("li:visible").length===0)$(this).parent().slideUp();
          });});    
          $(list).find("a:Contains(" + filter + ")").parent().slideDown();  

        } else {
          $(list).find("ul, li").slideDown();
        }
      })
    .keyup( function () {
        $(this).change();
    });
  } 
  $(function () {
    listFilter($("#header"), $("#list"));
  });
}(jQuery)); 

Heres the demo http://jsbin.com/welcome/71807/

Updated Code

Add a li to list

<li class="noresult">No Result Found</li>

CSS:

.noresult {
  display: none;
}

JS: Another chained function to the slideUp

function(){
              if($(list).find("ul:visible").length === 0)
                $(".noresult").show();
              else
                $(".noresult").hide();
            });

Demo and full code here http://jsbin.com/welcome/71862/

OTHER TIPS

Try putting your collections in a <ul>, like below:

<div id="wrap"> 
<h1 id="header">DVD Collection<form class="filterform" action=""><input class="filterinput" type="text"></form></h1> 
<ul id="dvd-collections">
    <li>
        <h3>Action</h3>
        <ul id="list"> 
            <li><a href="#">Batman</a></li>
            <li style="display: list-item;"><a href="#">Star Trek (2009)</a></li> 
            <li style="display: list-item;"><a href="#">Tremors</a></li> 
        </ul>
    </li> 
    <li>
        <h3>Adventure</h3>
        <ul id="list">  
            <li style="display: list-item;"><a href="#">Ice Age</a></li> 
            <li style="display: list-item;"><a href="#">Avathar</a></li> 
        </ul> 
    </li>
</ul>

And in your script if there are no results in the ul[id=list], slideUp its parent li.

Hope it helps.

I've added something in your script. Below is the whole script:

<script>
(function ($) {
  jQuery.expr[':'].Contains = function(a,i,m){
  return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};

function listFilter(header, list) {
   var form = $("<form>").attr({"class":"filterform","action":"#"}),
   input = $("<input>").attr({"class":"filterinput","type":"text"});
   $(form).append(input).appendTo(header);

   $(input).change( function () {
    var filter = $(this).val();
    if(filter) {
      $(list).find("a:not(:Contains(" + filter + "))").parent().slideUp(function(){
          jQuery.each($(list).find('ul'),function(){
              if(!$(this).find('li:visible').length){
                 $(this).parent().slideUp();
              }
           });
      });
      $(list).find("a:Contains(" + filter + ")").parent().slideDown();
    } else {
      $(list).find("li").slideDown();
    }
    return false;
  })
.keyup( function () {
    $(this).change();
  });
  }

$(function () {
    listFilter($("#header"), $("#list"));
});
}(jQuery));

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top