Extending Prototype to parse model ID from DOM ID
Posted on November 6th, 2008 No Comments »
Consider a simple list of to-do tasks:
<ol class="tasks">
<li id="task-1">run</li>
<li id="task-2">vote</li>
<li id="task-3">code</li>
</ol>
There are three task instances (with ids 1, 2, 3), each of which is rendered as a list element referenceable by DOM id. Note the id format: <model>-<id>, e.g. "task-1". This pattern is frequently used to avoid collisions with ids for other models because DOM ids are global and cannot be qualified to a particular object type or namespace (e.g. Task v. Group). When using the <model>-<id> format, you'll often want to obtain just the model id portion, say, to send to the server to edit or delete a task. After you've written code like this a few times:
var modelId = element.id.split('-').last();
you'll be overcome by a strong urge to extract a method that hides the ugly and standardizes the approach. I use the Prototype library at work, so I've implemented a utility method as an extension to Prototype's Element, making it available to any html element obtained via $() or $$(). However, the idea is easily implemented in jQuery or a library-agnostic manner. Here's the code:
/*
* Prototype Element extensions
*/
Element.addMethods({
/**
* Returns last delimited portion of dom id for id or element passed where element id is of the form:
* example-<id> OR example_<id>
* Supports hyphen '-' or underscore '_' as delimiter. Returns null if element id is missing or does not
* contain a delimiter. Some example ids:
* task-group-25 // Returns 25
* 25 // Returns null; use element.id instead
*/
modelId: function(element) {
var id = $(element).id;
if (id == null) return null; // Just in case; browsers tested return empty string for missing id.
var idParts = id.split(/[-_]/g);
return (idParts.length > 1) ? idParts.last() : null;
}
});
/*
* Usage
*/
// Get single task id
$('task-1').modelId(); // Returns "1"
// Get all task ids
$$('.tasks li').invoke('modelId'); // Returns ["1","2","3"]