Selecting Elements by Properties and DOM Expandos
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.
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:
[js] $('[@events]'); [/js]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:
[js]$('[@events]') .filter( function(index) { return !!(this.events['click']); }); [/js]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.