Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Associate Data With HTML Element (without jQuery)

I need to associate some data with an HTML Element, hopefully avoiding any memory leaks. Obviously a simple solution would be to throw some kind of identifier on the element, and then create a dictionary mapping that identifier to the data I need. However, this is in a javascript library that users will add to their page, thus I don't have control over when elements are added or removed.

What I'm looking to do is associate data with an HTML element while it's on the page, while allowing for that data to be GC'd when/if the element is removed. Is there a way to do this that doesn't involve writing my own periodic GC to clean up orphaned data? Is it safe to add properties to HTML elements?

like image 475
Colin M Avatar asked Feb 21 '15 19:02

Colin M


2 Answers

Attribute approach

You can store data in elements using custom data-* attributes.

This has the limitation that you can only store strings, but you can use JSON to store plain objects or arrays (not by reference).

To avoid conflicts with other code, it would be a good idea to include the name of your library in the attribute.

They can be set directly in the HTML:

<div data-mylibrary-foo="bar"></div>

And they can be read or written with JavaScript:

element.getAttribute('data-mylibrary-foo');        // read  (old way)
element.setAttribute('data-mylibrary-foo', 'bar'); // write (old way)
element.dataset.mylibraryFoo;                      // read  (new way)
element.dataset.mylibraryFoo = 'bar';              // write (new way)

They can also be read by CSS, using some attribute selector.

Property approach

This is much more flexible than the attribute approach, allowing to store arbitrary data in your element.

To avoid conflicts with other code, better wrap all properties in an object with the name of your library:

element.mylibrary = {};
element.mylibrary.foo = 'bar';

The problem is that a future HTML standard could define mylibrary as a native property, so there could be problems.

Symbol approach

ECMAScript 6 introduces symbols, which can be used as properties. The advantage is that each symbol has an unique identity, so you don't need to worry about some other library or a future standard using the same properties as your code.

var foo = Symbol("foo");
element[foo] = 'bar';

WeakMap approach

ECMAScript 6 introduces WeakMaps, which allow you to associate data with objects in a way that, if the objects are no longer referenced anywhere else, they will be garbage collected.

Like the property approach, they allow you to store arbitrary data.

Since the data is not stored in the elements themselves, there is no risk of conflicts.

var allData = new WeakMap();
var data1 = allData.get(element1) || {}; // read
data1.foo = "bar";
allData.set(element1, data1);            // write
like image 136
Oriol Avatar answered Sep 25 '22 20:09

Oriol


An HTML element in JavaScript is just a JavaScript object, so you can certainly add arbitrary properties to it. JavaScript will handle the garbage collection just fine.

The data- attribute is another option and might be a better choice if your properties are strings; their values will be visible in the DOM (which might be a good thing for debugging). If your properties are themselves objects, then you'd have to stringify them (and reverse the process to retrieve their values).

like image 34
Stephen Thomas Avatar answered Sep 24 '22 20:09

Stephen Thomas