views:

537

answers:

3

I am building a drag'n'drop gui builder in Javascript. So far so good.

As I add items to the GUI and configure them; I have two mechanisms for addressing them:

  • the 'class' - which I use for doing things to all instances of an item (eg CSS, generic functionality and so on and so forth) and which I can bind javascript libraries to... and I can make full use of polymorphic class names (ie class="name1 name2 name3 name4" with different things bound to each class name...)
  • the 'id' - which refers to this particular instance of a text box or a paragraph and which I can bind javascript libraries to

My problem is this: the 'id' must be unique across all html items on the page (by definition) so how do I ensure this? I need to get all the id's of all the items and then maintain some sort of state table.

Starting from a blank bit of html this is pretty reasonable - but I need to start from a partly created bit of html with a mixture of existing 'id's - some of which will be in my unique scheme and some of which wont be...

The way to do this best ought to be a solved problem.

Suggestions, tips, examples?

+2  A: 
function uniqueId() {
    return 'id_' + new Date().getTime();
}
Darin Dimitrov
Mostly guaranteed to be unique for this session... Would probably be good enough...
Gordon Guthrie
or even easier: increment id (e.g. ID0, ID1, ID2 ... ID130 etc) by one each time you add one element to the page...
dusoft
Yeah, but what happens if I then edit an existing GUI? - I need to know what I have got up to...
Gordon Guthrie
How would you know the ID of a particular element when you want to access it?
Daud
I use a class name to get all the items that I'm interested in and then I generate an array of id's (but I can't have a name class with other id's on the page...)
Gordon Guthrie
s/class/clash/g
Gordon Guthrie
Well I stuck this in as the interim solution to get going and found that Javascript can create HTML fragments under the granularity of Date().getTime() - ie multiple elements where being created with the same ID so caveat lector...
Gordon Guthrie
+2  A: 

The best way to do this will depend entirely upon the structure and organization of your javascript. Assuming that you are using objects to represent each of your GUI elements you could use a static counter to increment your ids:

// Your element constructor
function GuiElement() {
    this.id = GuiElement.getID();
}
GuiElement.counter = 0;
GuiElement.getID = function() { return 'element_' + GuiElement.counter++; };

Of course you probably have more than one type of element, so you could either set each of them up so that they have their own counter (e.g. form_1, form_2, label_1, label_2) or so that they all share a counter (e.g. element_1, element_2, element_3), but either way you will probably want them to inherit from some base object:

// Your base element constructor
function GuiElement(tagName, className) {
    this.tagName = tagName;
    this.className = className;
}
GuiElement.counter = 0;
GuiElement.getID = function() { return 'element_' + GuiElement.counter++; };
GuiElement.prototype.init = function() {
    this.node = document.createElement(this.tagName);
    this.node.id = this.id = GuiElement.getID();
    this.node.className = this.className;
}

// An element constructor
function Form() {
    this.init();
}
Form.prototype = new GuiElement('form', 'form gui-element');

// Another element constructor
function Paragraph() {
    this.init();
}
Paragraph.prototype = new GuiElement('p', 'paragraph gui-element');

You could also go this route if you would rather keep some variables "private":

// Your element constructor constructor
var GuiElement = (function() {
    var counter = 0;
    function getID() {
        return 'element_' + counter++;
    }
    return function GuiElement(tagName, className) {
        return function() {
            this.node = document.createElement(tagName);
            this.node.id = this.id = getID();
            this.node.className = className + ' gui-element';
            this.className = className;
        };
    }
})();

// Create your element constructors
var Form = GuiElement('form', 'form'),
    Paragraph = GuiElement('p', 'paragraph');

// Instantiate elements
var f1 = new Form(),
    f2 = new Form(),
    p1 = new Paragraph();

Update: If you need to verify that an id is not already in use then you could add the check you and of the getID methods:

var counter = 0;
function getID() {
    var id = 'element_' + counter++;
    while(document.getElementById(id)) id = 'element_' + counter++;
    return id;
}
Prestaul
Aah, I see I wasn't clear enough in my statement of the problem. I start with a non-blank bit of html which may already contain ids, some of them conforming to my 'id incrementation' standards, and some not... I have edited the main body to reflect this...
Gordon Guthrie
@Gordon, I've updated my post.
Prestaul
Oh, yeah, and as you run it only on instantiating the gui builder the cost of find the first 'next' id is negligible...
Gordon Guthrie
A: 

If you happen to be using the Prototype library (or want to check it out), you can use the Element.identify() method.

Otherwise, Darin's response is a good idea as well.

Jason
Cool, checking it out...
Gordon Guthrie