Enforcing unique ID

Working with media API is presenting some unique challenges (pun intended). Looking for thoughts on how to solve, especially the enforcement of unique id’s on htmlmediaelements.

The background: HtmlMediaElements are objects, and we need the instance to play, pause, etc, in JavaScript. I’m not sure if other specialty areas handle this differently, but standard practice is to put a unique id on each element, then us Document,getElementById.

Since we have to send the id out a port to play, pause, load, etc, it’s important to enforce unique ids, and is correctness, or else nothing will happen, or will happen to the wrong media element.

My current solution is to use an opaque MediaState type, which requires a string to create (which is then used as the Id). This enforced using the correct id and makes the api a little nicer, as my play/pause ports take one of these opaque types and get the id out.

However, I haven’t yet figured out a way to enforce uniqueness of ids, except to recommend using a dictionary to hold multiple states if using multiple media elements (with the key for each being the id).

I’m also more worried after an incident yesterday where a colleague copied and pasted some html I had given him previously to put two players on the same page. He ended up with two players with two identical ids. And then he spent really a lot of time trying to figure out what was going on before reaching out to me.

My concern is that the opaque type approach could encourage that kind of behavior…people put one in their model and reuse it.

So any thoughts on both enforcing the creation of unique ids and discouraging their reuse?

PS I’ve thus far been shy about using a Task.random approach, as it feels to me as if it may make the API too complicated. At some point, it feels to me, simply nagging people repeatedly in documentation is better than making them jump through hoops to absolutely enforce it.


My first thought would be to just an increment an integer in the model every time a new element is created. Then use String.fromInt on that.

To prevent misuse I guess make a module with an opaque type and only expose functions that do the right things


So, I had to approach a version of this problem in elm-ui (and Richard has it in elm-css).

Can you generate an id based on the attributes of the Media Element?

Elm UI generates an id based on the value of an attribute. So background-color: blue would encode as a css class .bg-color-blue. Using the src string could also work, classes and ids can be sorta huge before you run into issues with length.

Elm CSS does a version of this, but wraps all the attributes for an element together and hashes them using Robin’s Murmur3 lib.

I also considered generating an id based on an elements position in the DOM, but that turned out to be a bad idea for my situation. However, an id based on position in a data structure might work if the elements are all declared in one place.

You could use UUIDs. You wouldn’t have to perform any kind of coordination and the odds of a collision are statistically negligible.


You can wrap it in a custom element and build a declarative elm api around it. this way, you wouldn’t need ids at all (and ports).

How about enforcing the use of a dictionary, even if the user is only creating one MediaState?

You could wrap a standard Dict up in an opaque type called something like MediaRegistry, which is what the user would store in their model. The user can’t create a MediaState directly, but they can do something like MediaRegistry.add to create a new one and add it to the registry. The registry itself is responsible for assigning some kind of unique ID to each of its internal MediaState instances (whether that means just incrementing an integer or doing something more elaborate with UUIDs, etc). Perhaps MediaRegistry.add could return a tuple containing the new MediaRegistry and the ID of the MediaState that has just been added, so you’d know what the new ID is.

Going one step further (/too far?), you could make all interaction with the MediaStates take place via the registry. If you currently have a function like play : MediaState -> MediaState, for example, it could become play : Id -> MediaRegistry -> MediaRegistry.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.