2

I am trying to filter a UL for specific LIs with a keyup text input. Problem is, the LIs are nested within a tree, and the filter only sees the top most LI and doesn't appear to be filtering correctly. Typing Pennsylvania should show ONLY Pennsylvania, and nothing above it. Any ideas? Thanks in advance.

http://www.jsfiddle.net/CDAVZ/412

HTML

<input type='text' value='[Enter search term followed by Return]' class='allW treeSearch' />
  <ul id="treeview">
    <li data-expanded="true"><span class="icon-location-7 md-moon delBlue treeSpace" data-icon="&#xe6b5;"></span>
    <span class="icon-location-7 md-moon white treeSpace" data-icon="&#xe6b5;"></span>Root
        <ul>
            <li data-expanded="true"><span class="icon-stack-6 md-moon delLtBlue treeSpace" data-icon="&#xe6a0;"></span>
            <span class="icon-stack-6 md-moon white treeSpace" data-icon="&#xe6a0;"></span>Gas Model
              <ul>
                  <li data-expanded="true"><span class="glyphicon glyphicon-globe md-moon delGreen treeSpace"></span>
                  <span class="glyphicon glyphicon-globe md-moon white treeSpace"></span>United States
                    <ul>
                        <li data-expanded="true"><span class="icon-pie md-moon delBlue treeSpace" data-icon="&#xe708;"></span>
                        <span class="icon-pie md-moon white treeSpace" data-icon="&#xe708;"></span>Pennsylvania

                        </li>
                    </ul>
                  </li>
              </ul>
            </li>
         </ul>
      </li>
  </ul>

jQuery

$('.treeSearch').click(function(){
    $(this).val(''); 
});

$('.treeSearch').keyup(function(){

    var searchText = $(this).val();

    $('#treeview ul').each(function(){

        var currentLiText = $(this).text(),
            showCurrentLi = currentLiText.indexOf(searchText) !== -1;

        $(this).toggle(showCurrentLi);

    });     
}); 
triplethreat77
  • 1,276
  • 8
  • 34
  • 69

2 Answers2

2

Note: This make extensive dom manipulations.... please beware about the cost associated with it

From what I can understand, you need to make dom structure changes to achieve this

$('.treeSearch').click(function () {
    $(this).val('');
});

RegExp.quote = function (str) {
    return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
};

$('#treeview li').each(function () {
    var $this = $(this);
    var text = $this.contents().map(function () {
        return this.nodeType == 3 && $.trim($(this).text()) != '' ? $.trim($(this).text()) : undefined;
    }).get().join(' ');

    $this.data('parent', $this.parent()).data('text', text);
})


$('.treeSearch').keyup(function () {

    var regex = new RegExp(RegExp.quote(this.value), 'i');

    var $selected = $('#treeview li').removeClass('selected').hide().filter(function () {
        return regex.test($(this).data('text'));
    }).addClass('selected').show();

    $selected.each(function () {
        var $this = $(this),
            $parent = $this.parent(),
            $ul = $this.data('parent');

        var $li = $this;
        while ($ul.is(':not(#treeview)') && !$ul.parent().hasClass('selected')) {
            $li = $ul.parent();
            $ul = $li.parent();
        }
        $this.appendTo($ul)
    })

});
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
2

if you do not want to change the html you can change .toggle() for .css("visibility")

$('.treeSearch').click(function(){
    $(this).val(''); 
});
$('.treeSearch').keyup(function(){
    var searchText = $(this).val();
$('#treeview li').contents().filter(function() {
    return this.nodeType == 3;
}).each(function(){
var currentLiText = $(this).text();
    if(currentLiText.replace(/\s+/g, '')!=""){
        if(currentLiText.indexOf(searchText) !== -1){
            $(this).parent("li").css({"visibility": "visible"});
        }
        else{
         $(this).parent("li").css({"visibility": "hidden"});
        }
    }
});     
});    

http://jsfiddle.net/HLWMv/1/
this will only show the actual "li"
to remove the if(currentLiText.replace(/\s+/g, '')!=""){ part you need to remove the extra spaces and new lines in your html
UPDATE
case insensitive

$('.treeSearch').click(function(){
$(this).val(''); 
});
$('.treeSearch').keyup(function(){

var searchText = $(this).val();

$('#treeview li').contents().filter(function() {
    return this.nodeType == 3;
}).each(function(){

    var currentLiText = $(this).text().toLowerCase();
        if(currentLiText.indexOf(searchText.toLowerCase()) !== -1){
            $(this).parent("li").css({"visibility": "visible"});
        }
        else{
         $(this).parent("li").css({"visibility": "hidden"});
        }
});     
}); 

http://jsfiddle.net/HLWMv/2/
I removed the spaces in the HTML

Abraham Uribe
  • 3,118
  • 7
  • 26
  • 34