Selecting Elements by Properties and DOM Expandos

read 4 comments

Sometimes it is very convenient to store information on an element by using custom properties (DOM Expandos). For example, I use DOM Expandos in my Mouse Wheel plugin to store an array of handler methods (_mwHandlers) along with a method (_mwHandler) to call all those handlers when the mouse wheel is used. Storing these methods on the element allows me to write less code, and manage scope easier. It also gives me a function reference for easy removal when needed.

Now, what if I needed to select all elements that have a mouse wheel handler on them?

In jQuery 1.1 the attribute selector has an undocumented feature that will search DOM Expandos and properties as well as actual HTML attributes. Since I know that my handler method is named _mwHandler, I can use the following selector to find all elements in the document that have a mouse wheel event attached to them.

JavaScript:
  1. $('[@_mwHandler]');

Search by Events

Also, since the jQuery event system uses a DOM Expando to store events internally, you could find all elements that have an event attached to them using this selector:

JavaScript:
  1. $('[@events]');

If you are using jQuery Revision 1371 or higher, the DOM Expando name has changed from 'events' to '$events'.

If you combine the previous selector with the filter method, you can find all elements that have a click event like this:

JavaScript:
  1. $('[@events]')
  2.   .filter( function(index) {
  3.     return !!(this.events['click']);
  4.   });

Clean Up

Most importantly, if you are using DOM Expandos, you should clean up after yourself to avoid memory leaks. Some instances of using DOM Expandos will not leak, but others will. So you're better off cleaning up, just in case. For example in the mouse wheel plugin I remove the DOM Expandos on a particular element inside the unmousewheel method. Then during the window unload event I loop through all the elements that still have a mouse wheel handler and call unmousewheel on them. In order to make this process as fast as possible I store a "cache" (just an Array) of elements that I have added DOM Expandos too.

comment feed

4 comments

  1. Since it is changing to $events, could you do the following in your code so that it'll work in both versions?

    $("[@events], [$events]");

  2. Hey Travis. Great idea and yes you could combine the two selectors to insure that it works with both versions. Just make sure to remember to put the @ in there.

    $('[@events], [@$events]');

  3. Frdric

    I hope to see an other article on expandos... This look useful but get little explanations. Particularly, did we can select an item depending of the expando value? I think about something like that:

    listItem = $('<li>item</li>');
    listItem._myData = $i;
    [...]
    $('li[@$_myData=34]');

Sorry, but comments for this entry are now closed.