Search code examples
jqueryjquery-pluginsjquery-callback

How to track lists of nodes in a Jquery plugin (if clients may remove those DOM nodes)


I'm writing a jQuery plugin that "points at" a certain number of nodes in the DOM. Yet if I try something like having my plugin hold references to a set of nodes, I worry about them going "stale".

(While I realize that JavaScript is garbage collected and won't crash, I'd like to be able to keep my lists up to date, and not hold on to things that should be GC'd.)

The first thing that occurred to me was that there might be some sort of hook. But there does not seem to be a standard that looks trustworthy:

With JQuery, is it possible to have a function run when a DOM element calls .remove()?

Callback on the removal of an element from the DOM tree?

jQuery remove() callback?

This made me wonder about maintaining lists of nodes by putting a class attribute on them. That way, their membership in the list would travel with them. But as one might fear, this can be pathologically slow to enumerate, and is why you are supposed to formulate your query as tags before classes.

In addition to potential performance concerns, I wonder if it's considered poor form for a plugin to poke classes onto DOM nodes for this kind of purpose, which is not related to styling. (One of the better things about .data() is that it's relatively out-of-band, and with the exception of this list issue that's what I'm using.)

This seems like a common enough problem to have been addressed by other plugins. I'm tempted to use the class solution for it's "correctness" properties, even though it's slower. But is there a faster and more canonical way that gives the best of both worlds?


Solution

  • I would trust in how jQuery UI does it. Specifically Droppables, they maintain a list internally of jQuery objects that they iterate over when something hovers over it. They manage the list in 2 ways,

    1. Add a destroy handler that is fired when jQuery.remove() is run. (They hook into jQuerys remove functions to do this) This won't handle plain javascript removes though so,
    2. Just check if it exists before doing anything.

    They don't remove it, I assume, because its possible for it to be removed from the DOM then put back in.