views:

921

answers:

3

Hi,

I find myself doing this repeatedy.

$jq("button").filter(function(){
    return this.id.match(/^user_(\d+)_edit$/);
}).click(function(){
    var matches = this.id.match(/^user_(\d+)_edit$/);
    var user_id = matches[1];

    alert('click on user edit button with ID ' + user_id);
});

So I want to apply a click event to some buttons and in the click event handler I need the user ID. Is there a way I can avoid the second match?

$jq("button").filter(function(){
    return this.id.match(/^user_(\d+)_edit$/);
}).click(function(){
    var user_id = some_magic_variable;

    alert('click on user edit button with ID ' + user_id);
});

Thanks.

+3  A: 

You could store the ID on the element itself (using jQuery's data method) when you do the filter, and then retrieve that value in the click handler.

$jq("button").filter(function(){
    var $this = $jq(this);
    var matches = $this.attr('id').match(/^user_(\d+)_edit$/);

    if (matches) {
        $this.data('idNumber', matches[1]);
    }

    return matches;
}).click(function(){
    var user_id = $(this).data('idNumber');

    alert('click on user edit button with ID ' + user_id);
});
bdukes
+9  A: 

How about avoiding the first match?

$jq("button[id^=user][id$=edit]").click(function() {

});

Would select all buttons that have an ID that starts with user and ends with edit.

Although honestly, looking at your use case, it would be WAY better to simply give all buttons that are meant to edit a user a class of "edit_user" and then just do:

$jq('button.edit_user').click(function() {

});

It is cleaner, faster, and the jQuery way of getting all elements that serve a similar purpose.

As far as getting the user id there's been some lively discussion on custom attributes on this site (Custom attributes - Yay or nay?) and I personally do data-userid='5' in my elements and then just do var id = $(this).attr('data-userid'); to get the ID. Nice and easy. Won't validate as XHTML, though.

Paolo Bergantino
+1 Prettier than regex matching, and useful suggestion.
karim79
I agree with use of a 'edit_user' class, but I need a user_id link to each button. I could do this <button id="user_12" class="edit_user"/> but I stll need to do match to get the user ID.
Rohan Almeida
+1 Darn you Paolo...Upvoting you brought me into my last ten votes for the day - 2 or 3 of which were yours. Stop providing insight!
Jonathan Sampson
You can take away the upvote if you'd like, I hit my daily cap like 2 hours ago. I just can't stop! :P
Paolo Bergantino
A: 

Personally, I would preprocess the DOM:

$(function() {

$("button").each(function() { 
      var matches = $(this).attr("id").match(/^user_(\d+)_edit$/);

      if (matches) {
         $(this).data("user_edit_id",matches[1]);
      }
   }
});

Then you can simply:

$("button").filter(function(){
    return $(this).data("user_edit_id");
}).click(function(){
    var user_id = $(this).data("user_edit_id");

    alert('click on user edit button with ID ' + user_id);
});

It's not a perfect solution to what you want, but it's one way...

Philippe Leybaert
Not really a big fan of this solution as it still takes a bunch of sweeps of all the buttons unnecessarily. At the very least you could add a class on the each if there's matches, chain that together with the click, and avoid the filter function altogether. So: $('button').each(...).filter('.user_edit').click(...);
Paolo Bergantino
True, but I was proposing a solution within the context of the current problem (without changing markup)
Philippe Leybaert