Opinion: in HTML, Possible Duplicate IDs or Non-Standard Attributes? - javascript

It seems pretty common to want to let your javascript know a particular dom node corresponds to a record in the database. So, how do you do it?
One way I've seen that's pretty common is to use a class for the type and an id for the id:
<div class="thing" id="5">
<script> myThing = select(".thing#5") </script>
There's a slight html standards issue with this though -- if you have more than one type of record on the page, you may end up duplicating IDs. But that doesn't do anything bad, does it?
An alternative is to use data attributes:
<div data-thing-id="5">
<script> myThing = select("[data-thing-id=5]") </script>
This gets around the duplicate IDs problem, but it does mean you have to deal with attributes instead of IDs, which is sometimes more difficult. What do you guys think?

Note that an ID cannot start with a digit, so:
<div class="thing" id="5">
is invalid HTML. See What are valid values for the id attribute in HTML?
In your case, I would use ID's like thing5 or thing.5.

<div class="thing" id="myapp-thing-5"/>
// Get thing on the page for a particular ID
var myThing = select("#myapp-thing-5");
// Get ID for the first thing on the page
var thing_id = /myapp-thing-(\d+)/.exec ($('.thing')[0].id)[1];

You'll be giving up some control of the DOM
True, nothing will explode, but it's bad practice. If you put duplicate ids on the page you'll basically loose the ability to be sure about what you're getting when you try to access an element by its id.
var whoKnows = document.getElementById('duplicateId');
The behavior is actually different, depending on the browser. In any case, you can use classNames for duplicate values, and you'll be avoiding the problem altogether.
The browser will try to overlook faults in your markup, but things become messy and more difficult. The best thing to do is keep your markup valid. You can describe both the type of the element and its unique database id in a className. You could even use multiple classNames to differentiate between them. There are a lot of valid possibilities:
<div class="friend04"/>
<div class="featuredFriend04" />
or
<div class="friend friend04" />
<div class="featuredFriend friend04" />
or
<div class="friend objectId04" />
<div class="groupMember objectId04" />
or
<div class="friend objectId04" />
<div class="friend objectId04" id="featured" />
These are all completely legitimate & valid snippets of XHTML. Notice how, in the last snippet, that I've still got an id working for me, which is nice. Accessing elements by their id is very quick and easy, so you definitely want to be able to leverage it when you can.
You'll already spend enough of your time in javascript making sure that you've got the right values and types. Putting duplicate ids on the page will just make things harder for you. If you can find ways to write standards-compliant markup, it has many practical benefits.

IDs should be unique according to the standards and whilst most browsers don't barf when handed duplicate IDs it would not be a good idea to rely on that always being the case.
Making the ID unique by adding a type name to the ID would work but you need to ask why you need it. Giving an element an id is very useful when the element needs to be found, getElementById is very fast. The reason its fast it that most browsers will build an index of IDs as its loads the DOM. However if you have zillions of IDs that you never actually need to use in something like getElementById then you've incurred a cost that is never paid back.
I think you may find most of the time you want the object ID in an event fired by the element or one of its children. In which case I would use an additional attribute on the element and not the ID attribute.
I would leave class attribute to do what its meant to do and not overload it with identification duties.

Considering the fact that you can have multiple classes per element, couldn't you create a unique identifier as an additional class per element? That way, there could be more than one element with the same "id" without HTML ID attribute collisions.
<div class="thing myapp-thing-5" />
<div class="thing myapp-thing-668" />
<div class="thing myapp-thing-5" />
It would be easy to then find these nodes, and find their corresponding DB record with a little string manipulation.

In HTML5, you could do it like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
window.addEventListener("DOMContentLoaded", function() {
var thing5 = document.evaluate('//*[#data-thing="5"]',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE ,null);
alert(thing5.singleNodeValue.textContent);
}, false);
</script>
</head>
<body>
<div data-thing="5">test</div>
</body>
</html>

If you set non-standard properties, be sure to either set them programmatically (as everything will be legal that way) or go through the trouble of revising the dtd !-)
But I would use an ID with a meaningful word prepending the DB-id and then use .getElementById, as every necessary informtion is at hand ...

Non-standard attributes are fine, if you're using XHTML and take the time to extend the DTD you're using to cover the new attributes. Personally, I'd just use a more unique id, like some of the other people have suggested.

I don't like John Millikin's solution. It's gonna be performance-intensive on large datasets.
An optimization on his code could be replacing the regular expression with a call to substring() since the first few characters of the id-property are constant.
I'd go with matching class and then a specific id though.

Keeping track of your data via the DOM seems shaky to me; remember, those IDs are global variables, so if there's any chance somebody else's script can find its way onto your page, it's vulnerable. For best results, load your data into an object within an anonymous function and write the table (or the big nested list of DIVs) afterwards.

Related

document.object Vs. document.getElementById()

What is the difference between these two syntaxes below-
document.object and document.getElementById().
I want to know when to use which syntax???
e.g.-
CODE1(Implementation with <form>)
<body onload="document.forms[1].innerHTML='hi';">//Alt: onload="document.getElementById('f1').innerHTML='hi';"
<form id=f1>
<input />
</form>
<form id=f2>
<input />
</form>
</body>
both the syntax in onload works the same way. But this doesn't work for the following-
CODE2(Implementation with <div>)
<body onload="document.getElementById('div1').innerHTML='hi';">//cannot use the syntax: onload="document.divs[1].innerHTML='hi';"
<div id=div1>hello</div>
<div id=div2>hello</div>
</body>
So definitely the syntax: document.object does not work with <div>-elements but works with <form>'-element. But **document.getElementById()`** works for both. So when should I use which one???
Someone please highlight the differences between the two syntaxes.
Thanx in advance...
document.forms is a very old method of accessing stuff, along with document.images and document.all, and possibly a few others that I don't remember.
The number one flaw in accessing document.forms[1] is simple: what if another form is added to the page, before the target one? Suddenly you have to search through all your code for references to anything, and change them.
This is where IDs come in. By only allowing one of each ID on a page, getElementById can accurately retrieve it, every time, without caring about what happens to the document in the meantime. The only change that matters is the element being removed altogether.
you can use document.object_name to find anchors, applets, embeds, forms, images, links, plugins.
to find HTML Elemets like div, span, etc. you have to use selectors. you can get this elements by element name, id, class, etc.
The easiest way to access the div in your example is via the "named access on window object" functionality (http://www.whatwg.org/specs/web-apps/current-work/#named-access-on-the-window-object):
Instead of
<body onload="document.getElementById('div1').innerHTML='hi';">
you can use
<body onload="div1.innerHTML='hi';">
Note that "div1" is a property of the window object, not of the document object.

JQuery "#id.class" Selector Mashup

I have some bullet points which I want to show more text below them on clicking them. They are both two separate Ps that are paired together by sharing a common id. So, what I am trying to do below is to find the element with (id_same_as_this.class), so that the element with the class "expand" as well as the id that matches the clicked on P is toggled. Does that make sense?
$(document).ready(function(){
$(".expandable").click(function(){
$(this.attr('id')+"."+"expand").toggle(800);
});
});
I only ask if the above code could be made to work because it would make the expandable bullet points in my web page significantly less code intensive than a lot of the examples I have read about.
$(this.attr('id')+"."+"expand").toggle(800);
Must be
$("#" + this.id +".expand").toggle(800);
You missed the # there. That said, you shouldn't ever have a common ID. By definition IDs are meant to be unique. If you have the same ID on multiple elements, while it may work now on the browsers you try, you have no guarantee it won't break in the next rev of jQuery (or Chrome, or Konqueror, or iOS Safari). There's also no reason to do it. You could just use classes or data-* attributes.
Yes this will work but you need a # before the ID
They are both two separate Ps that are paired together by sharing a common id.
IDs are unique. Two elements can't share a common ID, as that defeats the whole purpose of having a unique identifier. JavaScript assumes that you're using valid HTML, so document.getElementById() will return only the first element with a matching id. By using non-unique IDs, things will start breaking in unpredictable ways:
$('#foo').find('.bar') // Won't search past first #foo
$('#foo .bar') // Will search past first #foo in IE8+
Try restructuring your HTML to make this task easier. Maybe you could do something like this:
<ul id="bullets">
<li>
<h2>Title</div>
<div>Text</div>
</li>
</ul>
And then use a simple event handler:
$('#bullets h2').click(function() {
$(this).next().toggle(800);
});
You don't need id values for this at all (which is good, as from the comments on hungerpain's answer, you're using the same id value on more than one element, which is invalid).
Just do this:
$(document).ready(function(){
$(".expandable").click(function(){
$(this).find(".expand").toggle(800);
});
});
That will find the element with the class expand within the expandable that was clicked. No relying on unspecified behavior of selectors.
If you really need that data on the expandable, just put it in a data-* attribute. So instead of this invalid structure:
<!-- INVALID -->
<div id="foo27" class="expandable">
<div class="expand">...</div>
</div>
<div id="foo27" class="expandable">
<div class="expand">...</div>
</div>
Do this
<!-- VALID -->
<div data-id="foo27" class="expandable">
<div class="expand">...</div>
</div>
<div data-id="foo27" class="expandable">
<div class="expand">...</div>
</div>
Use the above code to do the expansion. If you need the value, use .attr("data-id") or .data("id") to get it.

access child DOM object from parent in dotted notation

Is there a way to select a child DOM object by treating it as data member of its parent DOM object? Imagine I have this code:
<div id=div1>
<div id=innerdiv1></div>
<div id=innerdiv2></div>
</div>
<div id=div2>
<div id=innerdiv1></div>
<div id=innerdiv2></div>
</div>
This example won't work in real life because both pairs of child divs have the same id's (innerdiv1, innerdiv2), but that's exactly what bothers me about the "id" thing.
Is there some way in javascript to access a child element as a data member, something like document.getElementById('div1.innerdiv1'), which would return a different object from document.getElementById('div2.innerdiv1').
I can't stand that each id has to be unique throughout the document. It becomes a major issue when you have a lot of code and you accidentally use the same id twice. It makes for really nasty bugs that are difficult to squash.
You can use document.querySelector in modern browsers. document.getElementById is pretty much obsolete.
document.querySelector('#div1 #innerdiv1')
You can use classes for the inner divs instead of ids, which do not need to be unique.
The document object has a getElementById method, but the returned elements do not have this method, and it couldn't take a string that isn't exactly the id of an element [if that's what you want try a library, like jQuery or Pumbaa80's suggestion of document.querySelector].
In some browsers you can try:
document.getElementById('div1').getElementsByTagName('div')[0]
As a side note, try dropping these two html documents into html5.validator.nu or http://validator.w3.org/#validate_by_input
<!DOCTYPE html><head><title>t</title></head><body>
<div id=div1><div id=d1>one</div><div id=d2>two</div>three</div>
<div id=div2><div id=d1>four</div><div id=d2>five</div>six</div>
</body>
Now you can totally avoid using the same id twice by just using classes instead.
<!DOCTYPE html><head><title>t</title></head><body>
<div id=div1><div class=d1>one</div><div class=d2>two</div>three</div>
<div id=div2><div class=d1>four</div><div class=d2>five</div>six</div>
</body>
For the first one, you could use document.querySelector('#div2 #d1') or $('#div2 #d1')
but I don't think the result would be guaranteed across all browsers due to the fact that this should be equivalent to writing document.querySelector('#d1') which you can see returns the first occurring id that matches, or $('#d1') which returns both id matching elements in an array.
And for the second one you could use document.querySelector('#div2 .d1') or $('#div2 .d1') or the other statements for very similar results, except that your html is valid this time. You don't even have to have css that defines d1 and d2 and if you used an attribute like class="d1 mySubHeading" and class="d2 mySubHeading" you could style both with mySubHeading and leave d1 and d2 there purely for selection via these methods.

Is it's a good pracice to give same id's to multiple tags?

The first thing that comes to my mind when i hear the word ID is that it's something which is unique, Well it is in the case of ASP.NET server tags. But it seems that there is nothing wrong using same id's for multiple tags if it's not a server tag. So is it a problem at all?
Your DOM selectors will fail. document.getElementById will only return the first match, and different javascript libraries might to their own funky stuff depending on the parsing they do on your selectors. plus, different browsers might also do their own when using querySelectorAll.
I'd recommend to use a class attribute instead of an id, even if you do not intend to address the elements with javascript. Repeating the same id on a page is still invalid code and will lead to uncertain results.
So is it a problem at all?
It wouldn't validate: the IDs of HTML elements are supposed to be unique. It would be difficult to hyperlink to an element whose ID is not unique.
No , you shouldn't reuse the tags even though they are serverside, they add the clientid to the server but again it should be unique.
anyway why do you want to reuse them??
Please see the below code , we can make it unique like this
<li id="userID<%# Eval("UserId")%>">
other example
<asp:Repeater ID="idtest" runat="server">
<ItemTemplate>
<div id="catID<%# Eval("Id")%>" class="Content">
<ul id="someotherRandom<%# Eval("Id").ToString()%>" style="width:364px;">
</ul>
</div>
</ItemTemplate>
</asp:Repeater>
IDs should be unique. If you need to identify a tag that repeats then you need to give it a class. The class attribute is intended to identify multiple items on a page.

Is it normal to have two elements with same id in two div elements with other id?

I know, that two elements can't hav the same id. But it's happens so, that in my project I have two elements with same id in other divs, like this
<div id="div1">
<img id="loading" />
</div>
<div id="div2">
<img id="loading" />
</div>
And CSS:
#div1 #loading
{
some style here...
}
#div2 #loading
{
another style here...
}
Works fine for me, but maybe it is not reccomended to do by so?
Yes, I know, thet I can use classes, and it's strongly recomended to do by so, but I want to know is there any potential risk in this usage of id?
I think no, because when I wrote for example
$("#div1 #loading")... it becomes a unique element.
Isn't it?
Change your id to class. It is not a good idea to give duplicate id.
Think two students having same roll no in a class. Imagine them getting examination result. How will the school be able to recognise the marksheet?
Your way is not cross browser compatible, and will affect a lot while coding JavaScript, and posted form etc
You can get the same effect using class
see
<div id="div1">
<img class="loading" />
</div>
<div id="div2">
<img class="loading" />
</div>
and css:
#div1 .loading
{
some style here...
}
#div2 .loading
{
another style here...
}
an id must (should) be unique!!
you will have troubles selecting it via JS in most browsers -
better use class
The big reason is for JavaScript DOM manipulation. In your case, if you do something like this...
document.getElementById("loading")
... JavaScript will return the first element, and the first element only. You'll have no way to access the rest of them without some serious DOM walking.
Just because no-one else has posted it - the HTML spec, section on ID, which says:
id = name [CS]
This attribute assigns
a name to an element. This name must
be unique in a document.
Yes you are right, it is not recommened to do so. An ID should always be unique (e.g. if you want to select the element with javascript).
If you just want to add the same style to the divs, just use css class.
Unique:
In mathematics and logic, the phrase "there is one and only one" is used to indicate that exactly one object with a certain property exists.
#div1 #loading does not remedy the fact that you have two instances of #loading in your document. So, no, don't do that.
IDs should be unique, so id1 and id2 are fine, but for many elements with the same style, use an HTML class and CSS class selector:
.loading
{
styles here
}
These are allowed to be repeated as many times as you want on a page :)
Is it normal? No.
Is it recommended? Definitely not! It's actually prohibited (but enforcement is weak).
But it (apparently) works, so ...
Id are used to distinguish elements, they must be unique for different reason, one of them is the use of javascript, function like getElementById won't work well if you have duplicate ID, you won't be able to predict what it'll do on different browser as JS is self-implemented on each browser differently.
If you wish to use a structure like #div loading and #div2 loading it seem clear that both loading have similar uses so they should be classes and would be used like this
#div1.loading and #div2.loading
Also one plus of using this syntax would be to put the common style in .loading like this
.loading{ style common to both the loading }
#div1.loading{ style used only by the loading in div1 }
#div2.loading{ style used only by the loading in div2 }
https://www.w3.org/TR/1999/REC-html401-19991224/struct/global.html#adef-id
BUT!
If you need it in your project, you can use it, like suggested in my Question Final Update!
validation and purist-ism aside, it is perfectly functional. But I would definitely be annoyed if I use that #loading id and find that a jquery effect or a css effect applies to more than 1 element.Do tell me if IE6 or 7 or Firefox 1.x or 2.x ruins that code.
It's bad practice of using I'd on element. Because I'd giving something for understanding unique with their name identification. And second thing we use its in CSS but in JavaScript this bad practice. So good example for this class and student.
So don't do this.
I disagree on people saying to always use a "unique", meaning different ID everytime you label one. Sometimes its acceptable, such as my case where I am making a calculator.
The javascript is doing the math and outputting the result into the div with the id="total". I need that same exact "total" to be in 2 different places however. In this case, why wouldn't I use two different div's with the same ID? I need the same number in both boxes. With jQuery, I perform and output the math once and it populates both div's at the same time, which is what I want.
So long as you understand the risks where if you were PULLING information from those 2 div's with the same ID, then I say feel free. As long as you dont confuse yourself and need 2 different results in the same div ID.

Categories