2

I often need to register a single-purpose event listener to multiple HTML elements (e.g. change, click), in a loop. I need a way to differentiate between the target elements when the event fires. Ideally the listener should have a variable that changes depending on which element fires the event.

A straight-forward solution would be to set the id attribute in the loop (jsfiddle), and refer to this.id within the handler. Or if additional fields are required, the data-* attributes, and instead accessing this.dataset.id.

However these end up adding to the actual markup of the page, and can only store strings. If you have a lot of data to assign, of specific types other than string, it can be impractical, and require unnecessary type checking, or integer parsing.

I got around this by defining a new property called param on each HTML element, and I could access it in the handler like so: this.param.address. But that turns out to be a bad idea - a 'feature' not to be relied on due to browser consistencies and a lack it being in any standard.

Another way is supplying arguments to the listener through a closure (jsfiddle). The downside of this method is that it returns a unique listener for each element, which might affect performance versus just a single handler.

Yet another method I had thought of was storing the actual element references with data in an array, and performing a lookup of this from the event handler (JSFiddle).

So my question is: Is there a better (and correct/future-proof) way to pass/assign data to element event handlers, without having to store it as an attribute string?

P.S. I don't want to have to rely on jQuery for this either.

With jQuery it's possible to use $(el).bind("click", {foo:i}, buttonClicked) and $.data(el, "param", {foo:i}) to accomplish the task. However it seems to rely on being able to set a custom property to the element's object, much what I proposed for using param as a custom property for my purposes. Does that mean it's fine as long as the property name is unique enough?...

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
bryc
  • 12,710
  • 6
  • 41
  • 61
  • What do you think could possibly be more efficient than just referring to a custom attribute on each element? Unless you can infer whatever you need to know from the parent/children of the clicked element in the DOM, then a custom attribute is the preferred solution. If this is programmatically generated data, then put it in a closure when you assign the event handler. We can't really be more specific without you showing what the data actually looks like and how you're trying to use it. – jfriend00 Jul 14 '15 at 05:58
  • something like http://jsfiddle.net/arunpjohny/dshkb17f/1/ ? – Arun P Johny Jul 14 '15 at 06:00
  • @jfriend00 Example: 7 checkboxes in a loop would be assigned this object: `{ type: "bitfield", bitno: j, address: i }`. I want the flexibility of JS objects. When you click each checkbox, it knows its type, address and bitno. HTML attributes convert everything to strings, which is not ideal when working with other types. I don't want to have to put in three attributes on each element in the markup. – bryc Jul 14 '15 at 06:34
  • A custom attribute can be JSON which you parse into whatever. Since we have no idea where this custom data comes from if it's not going to be in the HTML, then we really have no idea how to use it. You're just not showing enough of the problem. The only generic answer is to put the custom data in the HTML. Beyond that, we need to know where the data comes from and what you're trying to do with it. Basically, you're asking way too theoretical a question without enough context. Show us your actual code and situation details and we could probably be more helpful. – jfriend00 Jul 14 '15 at 06:38
  • FYI, it's not very many lines of code to implement something like jQuery's `.data()` too if you want a map-like way to store and retrieve custom data for a DOM element without using jQuery. But, without more context, I have no idea if that's appropriate or better than just putting JSON in the HTML and parsing as needed. – jfriend00 Jul 14 '15 at 06:41
  • 1
    It really doesn't matter what the data looks like. Just that I need to retain *types*: number, null, undefined, booleans, etc, and assign *any number* of them to each element. Can't go with attributes. – bryc Jul 14 '15 at 07:30

0 Answers0