3

In my HTML there are number of divs each having names inside. I have to implement alphabetic filter in it. If user clicks on button 'A-J' the list will make only divs where first letter of name is between A-J and similarly for other letter groups. I have written following piece of code till now :

        $("#jfmfs-filter-selected-aj").click(function(event) {
            event.preventDefault();
            for (i = 0; i < all_friends.length ; i++)
            {
                var aFriend = $( all_friends[i] );
                if(!(/^[a-jA-J]+$/.test(aFriend.find(".friend-name").html().charAt(0)))){
                    aFriend.addClass("hide-filtered");
                }
            }
            $(".filter-link").removeClass("selected");
            $(this).addClass("selected");
        });

This Code works fine but hides div in a loop and hence it takes time. Is there a way i can write the above code in single line to add "hide-filtered" class to all divs which meets my criteria in one go Something like this?

all_friends.not( {divs with inner html starting with letters a-j} ).addClass("hide-non-selected");
all_friends.not( /^[a-jA-J]+$/.test(all_friends.find(".friend-name").html().charAt(0)) ).addClass("hide-non-selected");

Final Solution I used using jquery filter (Barmar's answer):

all_friends.filter(function() {
                      return(!(/^[a-fA-F]+$/.test($(this).find(".friend-name").html().charAt(0))))
                    }).addClass("hide-non-selected");
Vishwesh Shetty
  • 687
  • 9
  • 27
  • Looks like [this][1] is the kind of stuff you're looking for.. [1]: http://stackoverflow.com/questions/190253/jquery-selector-regular-expressions – Aidan Ewen Dec 01 '12 at 09:04
  • @AidanEwen jQuery regex selectors can only be applied to attributes, not to text. – Barmar Dec 01 '12 at 09:07

2 Answers2

2

Try this:

var AJ_regex = /^[a-jA-J]/;
$('.friend-name', aFriend).filter(function() {
    return !(AJ_regex.test($(this).html()));
}).addClass("hide-filtered");
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks I have updated my question with the final solution I used. – Vishwesh Shetty Dec 01 '12 at 09:19
  • The simplest and biggest efficiency saving you could make is to create the regular expression outside the loop (and `.filter()` is effectively a loop). – Beetroot-Beetroot Dec 01 '12 at 09:28
  • @Beetroot-Beetroot Thanks for the suggestion, I made that change to my answer. This also suggests that if he has different filters, he could use a single function and pass the RE as a parameter. – Barmar Dec 01 '12 at 09:31
  • By the way, your solution (before moving the regexp out of the loop), although concise, is probably *less* efficient than the OP's original in that it loops three times - once to apply the selector, once to filter, and once to apply the class. Only the first is a big deal. On efficiency grounds, it is better to use a preformed collection rather than make a new one, especially when making/changing the selection involves the DOM. – Beetroot-Beetroot Dec 01 '12 at 09:39
  • @Beetroot-Beetroot That's probably true of many chained jQuery operations, since each step in the chain is another loop over the collection, and this is a common idiom. It's not usually a problem if the collection is small. – Barmar Dec 01 '12 at 09:48
  • Indeed Barmar, all these issues can be safely ignored for small collections. – Beetroot-Beetroot Dec 01 '12 at 09:56
0

Have a look at this jquery filter by James Padolsey. It looks like you could use this to do the kind of thing you're looking for.

For your purposes it would look something like -

$('div.friend-name').filter('div:regex(innerHTML, ^[a-jA-J])').addClass("hide-non-selected");

(that will probably need tweaking - I've not tested it).

Aidan Ewen
  • 13,049
  • 8
  • 63
  • 88