views:

410

answers:

3

I have a tree of ul's that I want to search with jQuery and apply styles to those matching

so this:

Regional
    |-InternetAccessGroup
    |-Wasters
    |-Packaging
        |-Users
            |-Students
                |-Hello Fred
                |-Package Student
            |-Teachers
                |-Package Teacher
            |-Admins
                |-Package Admin

is coded as this:

<ul id="browser" class="filetree">
    <li ><span class="folder" id="Regional">Regional</span>
        <ul id="browser" class="filetree">
            <li class="closed" ><span class="group" id="InternetAccessGroup">InternetAccessGroup </span></li>
            <li class="closed" ><span class="group" id="Wasters">Wasters </span></li>
            <li class="closed" ><span class="folder" id="Packaging">Packaging</span>
                <ul id="browser" class="filetree">
                    <li class="closed" ><span class="folder" id="Users">Users</span>
                        <ul id="browser" class="filetree">
                            <li class="closed" ><span class="folder" id="Students">Students</span>
                                <ul id="browser" class="filetree">
                                    <li class="closed" ><span class="person" id="helloFred"id="Hello Fred ">Hello Fred </span></li>
                                    <li class="closed" ><span class="person" id="student"id="Package Student ">Package Student </span></li>
                                </ul>
                            </li>
                            <li class="closed" ><span class="folder" id="Teachers">Teachers</span>
                                <ul id="browser" class="filetree">
                                    <li class="closed" ><span class="person" id="teacher"id="Package Teacher ">Package Teacher </span></li>
                                </ul>
                            </li>
                            <li class="closed" ><span class="folder" id="Admins">Admins</span>
                                <ul id="browser" class="filetree">
                                    <li class="closed" ><span class="person" id="packageadmin"id="Package Admin ">Package Admin </span></li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

I want to (say) search for any entries containing the word "Package" (i assume with $("someselector:search('"+mysearch+"')"), and add the class "collapsible" to all parent li entries, and add the class "highlighted" to the actual matching entries. I know > is the jQuery child selector, but that seems to be only direct children, and what I'm doing as a jQuery newbie seems much harder. thing.addClas() is ok to me, but the selector part I cannot quite grasp.

+2  A: 

Well, jQuery uses (more or less) CSS-style selection. > means direct child--to get any child, you just need to go 'ul li'. This is a great tutorial on CSS selection: http://css.maxdesign.com.au/selectutorial/

D_N
+2  A: 

Try a custom selector

$(document).ready(function() { 
    $.extend($.expr[':'], { 
        hasWordPackage: function(el) { 
            return ($(el).val().indexOf("Package") > -1);
        } 
    }); 
}); 

So you can say (if I understand you correctly)

$("ul:hasWordPackage").addClass("highlighted").parents("li").addClass("collapsible");
James Wiseman
I'm going to give this a try, but ... If I am getting the thing to search from an input field, say using mysearch=getElementById('userinput').value;how do I plug that into hasWordPackage ? Sorry if I'm sounding very noob-ish.
WaveyDavey
@WaveyDavey - My answer below shows how to do this in a generic way, give it a shot if you're searching dynamically.
Nick Craver
+1  A: 

A few things, first you have multiple id="borwser", IDs have to be unique.

Here's a full sample:

<script type="text/javascript">
  jQuery.expr[':'].Contains = function(a, i, m) { return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0; };

  $(function() {
    $("#files li span:Contains(Package)").addClass("highlighted").parents("li").addClass("collapsible");
  });
</script>
<div id="files">
  <ul class="browser filetree">
      <li><span class="folder" id="Regional">Regional</span>
          <ul class="browser filetree">
              <li class="closed" ><span class="group" id="InternetAccessGroup">InternetAccessGroup </span></li>
              <li class="closed" ><span class="group" id="Wasters">Wasters </span></li>
              <li class="closed" ><span class="folder" id="Packaging">Packaging</span>
                  <ul class="browser filetree">
                      <li class="closed" ><span class="folder" id="Users">Users</span>
                          <ul class="browser filetree">
                              <li class="closed" ><span class="folder" id="Students">Students</span>
                                  <ul class="browser filetree">
                                      <li class="closed" ><span class="person" id="helloFred"id="Hello Fred ">Hello Fred </span></li>
                                      <li class="closed" ><span class="person" id="student"id="Package Student ">Package Student </span></li>
                                  </ul>
                              </li>
                              <li class="closed" ><span class="folder" id="Teachers">Teachers</span>
                                  <ul class="browser filetree">
                                      <li class="closed" ><span class="person" id="teacher"id="Package Teacher ">Package Teacher </span></li>
                                  </ul>
                              </li>
                              <li class="closed" ><span class="folder" id="Admins">Admins</span>
                                  <ul class="browser filetree">
                                      <li class="closed" ><span class="person" id="packageadmin"id="Package Admin ">Package Admin </span></li>
                                  </ul>
                              </li>
                          </ul>
                      </li>
                  </ul>
              </li>
          </ul>
      </li>
  </ul>
</div>

First, we're declaring a case insensitive search which you'll probably want with :Contains, the default :contains selector is case sensitive. Wrap the entire tree in a div just to be clean, but you can do the same with the <ul>. We're searching for spans that contain the text, applying class="highlighted" and crawling parent <li> adding class="collapsible".

To put this in say a searchbox, which I'm guessing is your ultimate goal, just make a function that calls the onload code above, like this:

$(function() {
  $('#myTextbox').keydown(function() {
    //Clear last search
    $("#files li").removeclass("collapsible").find("span").removeClass("highlighted");
    //Search again
    $("#files li span:Contains(" + $(this).val() + ")")
      .addClass("highlighted").parents("li").addClass("collapsible");
  });
});
Nick Craver
You people (on Stackoverflow) are amazing, awesome, generous folks. Many thanks.
WaveyDavey