Autonomous Machine

Posts tagged with jQuery

Apply jQuery event handlers once with $.fn.safe()

Today I was in this situation:

  • I had a page that could mutate in a lot of different ways (AJAX, user interaction, etc)
  • I needed a way to execute a block of code against only the new DOM elements on the page (to avoid duplicating the event handlers on the already existing elements)
  • I didn't want to use livequery (delegation would have created its own set of problems)

This is what I came up with:

$('ul.choices a').safe('choices').click(function(event) {
  // code to only execute once for any DOM element
};

$.fn.safe works similarly to jQuery's filter. It returns a jQuery object containing only DOM elements that haven't already been returned for the specified key ('choices' in the above example). So it's safe to execute the code above multiple times without repercussions. Obviously, looping through a large set of elements can be costly, but for smaller sets this simple solution works great.

Here's what's going on behind the scenes:

var $$ = function(param) {
    var node = jQuery(param)[0];
    var id = jQuery.data(node);
    jQuery.cache[id] = jQuery.cache[id] || {};
    jQuery.cache[id].node = node;
    return jQuery.cache[id];
};

$.fn.safe = function(name) {
  return this.filter(function(i, element) {
    $$(this).unsafe = $$(this).unsafe || [];
    if ($.inArray(name, $$(this).unsafe) == -1) {
      $$(this).unsafe.push(name);
      return true;
    } else {
      return false;
    }
  });
};

I'm using the $$ helper I first saw on Yahuda Katz's blog- you should too. It makes working with jQuery's data cache much easier.

See Also

LowPro for Prototype will only apply a given behavior to a DOM element once, but I haven't used it since moving to jQuery for all new projects.

  • November 20, 2009
  • Article
  • Code, JavaScript, jQuery

Use valid markup in your jQuery DOM creation

I just spent almost an hour trying to figure out why some really basic DOM creation/insertion and JavaScript-initiated form submission wasn't working in IE7 (everything was OK in FireFox). I could have saved a lot of time by checking everything from the beginning, but I noticed a form element wasn't getting appended to the DOM and so I tried debugging that for a while before checking if I even had a valid DOM element to append. I didn't, and after a few minutes of troubleshooting I found the root cause of all my troubles- I had been using invalid markup to create the form element. I changed:

f = $('<form>');

to

f = $('<form />');

and everything started working. I was using the (admittedly invalid) lone opening tags without a thought after seeing that form in several jQuery tutorials and, not being that familiar with jQuery, thinking it was a supported syntax.

So, always use valid markup everywhere and avoid this kid of bug.

  • October 08, 2008
  • Article
  • JavaScript, jQuery