Assigning dynamic ids to HTML and Script elements – Client Side!
Guest Author: Einar Otto Stangvik
Will Code for Nuts
This question popped up on Twitter yesterday:
How do you usually handle duplicate IDs for html elements and scripts in SharePoint Web Parts, scripts and controls?
Which is a natural concern, with all the different web parts and scripts that’s being injected SharePoint portals these days. To end Monday off (in my neck of the woods anyway), I thought I’d make a quick post on what I do in my projects.
Script naming convention
For scripts, I have a few guidelines. First of all, my scripts follow a naming convention based on my organization handle, library concern, project name and so forth. Looking back to my previous couple of posts, e.g. the Script Loader (http://www.codefornuts.com/2009/10/pieces-of-my-core-javascript-library.html), this name would be grep.scriptloader – as that’s a core piece of script for me. For a script specific to a web part, I’d name it similar to the webpart, e.g. grep.webparts.navigationcontrol.
As for the actual script definitions, two matters apply: is it a class, or a single instance?
For single instances, such as the Script Loader above, I declare it like this:
if (!window.grep) window.grep = {};
if (!grep.someSingleInstanceClass)
{
grep.someSingleInstanceClass=
{
instanceVar: "baz",
foo: function() {},
bar: function() {}
}
}
So basically I check if it’s already been assigned, and if it hasn’t, I assign it to a global variable. The above code would then be accessed such as
grep.someSingleInstanceClass.foo();
For multi instance classes, I follow regular javascript oo syntax, with the same has-it-been-defined-clause, such as:
if (!window.grep) window.grep = {};
if (!grep.someClass)
{
grep.someClass = function(ctorVariable)
{
this.someVar = ctorVariable;
this.DoWhatever();
}
grep.someClass.prototype.DoWhatever = function()
{
// ...
}
grep.someClass.prototype.AnotherFunction = function(input)
{
// ...
}
}
Then access that such as
var foo = new grep.someClass("some value for the ctor");
foo.AnotherFunction(42);
HTML element lookups, and dynamic ids
For elements, I use another trick. Since giving the elements a specific id can easily crash with other web parts of the same kind, or even other web parts / controls, I tend to avoid using ids as much as possible, and rather rely on class lookups (where the class has been named similar to the web part). For such lookups to be possible, however, they must be based somewhere – you can’t just search for all instances of ‘css class foo’ in all of the body tag.
Imagine the following scenario:
This element will be added several times, by other instances of the same web part
The script convention noted further up would make sure that the class’ code will only be added once, and we feed that the id of the div, so that the class can make css class based jQuery (or similar) lookups to find the elements it needs within the frame. But what’s the id of the div? Assigning a static id to it would crash with other instances of the same web part, and using a class would be just as hopeless.
That’s where the trick applies, and the following is a fully functional example:
I want a dynamic ID!
The trick works by looking up the script block’s element in the html dom. This element is the last added element, as the script block executes, even if it’s not at the bottom of the page. Based on this script element, it searches its previous siblings for the first match of a given tag type, then assigns a new id.
You could do a lot better with the actual dynamic id than the millisecond postfix shown here, such as an incrementing (or even random) number which is added to a string, then checking if that already exists (in which case we increment / re-random and try again). I leave that to your imagination, though.
As for the example further up, the frame could be identified and put into action such as:
And that would enable us to avoid any and all name crashes for our component.
Guest Author: Einar Otto Stangvik
Will Code for Nuts
Einar is a SharePoint architect and avid developer based in Oslo, Norway. Once a deep diving C++ programmer, and previous Microsoft MVP for that, he’s now mostly turned to the world of .NET and web frontends, with primary focus on C#, WCF, Silverlight and JavaScript.
- Pieces of my core javascript library: The Script Loader
- Pieces of my core javascript library: The Lambda Framework
- Connecting SharePoint UI Elements: SPDrag and the DropBox
- Assigning dynamic ids to HTML and Script elements - Client Side!