Related
I am wondering if the html class attribute should only be used for styling. Is there any drawback to using the class attribute as a variable. The W3 spec http://www.w3.org/TR/html5/dom.html#classes does not specify one way or another but, all examples and training point in the direction of styling only for multiple objects.
In my case I want to use the class attribute as variable that matches the key value in a object array. For example in my Javascript code I have an object that has a number of key/value pairs. On my web app I have a number of save buttons. When a save button is clicked I grab the parents class attribute value and use it as the key for the object to know which value to change. The class attribute on the parent has not other value than to let me know which key value pair to change in my object
While I'm sure it's possible to use classes that way, it's certainly not their intended purpose. html has data attributes that provide the functionality you want, for example
<button data-key="some value" name="" id="">click me</button>
You can then get that value (onClick if you like) and use it as a key for your object/data structure. Theres a good overview here
While it is not bad, it neither is best practice.
You can, instead of using the class attribute, define explicit data attributes. Using the class attribute would mean that you could not use several classes (because that would be a weird key to search for in an object, right?).
For instance:
<div class="any classes you like" data-mykey="searchforthiskey">
<button></button>
</div>
In jQuery:
$('button').click(function() {
var key = $(this).closest('div').attr('data-mykey');
});
From a functional perspective, there's no reason to NOT use the class attribute to store information about that element. You can access a class attribute as easily as you can a data attribute.
From a standards perspective, it is probably better to use a data attribute. Why? Well, if you are the only person working on your front-end, no big deal. If you are one of many on a team of front-end developers, who works specifically on the javascript side of things, you may run into a conflict with another front-end developer who works on the HTML/CSS side of things. They may remove a class from the element, not realizing that its also being used as your javascript hook into that element. In that case, you're better off creating your own data attribute, which then makes it clear that this attribute is probably data related and won't be molested by someone just trying to fix the styling of that element.
I am complete beginner in JS, so pardon my ignorance. I also didn't manage to find the answer to my question, although, undoubtedly, someone must have asked it before... so I'm posting here.
Here is a simple form I wrote:
<head>
<title>wowzy</title>
<link href="stylesheet.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<form name="forma" id="prvaForma" action="/nonsense.php" method="POST">
<label for="first">1st Value</label>
<input id="first" type="text" name="firstField" value="1st Value here" onClick = 'check();'>
<label for="second">2nd Value</label>
<input id="second" type="text" name="2ndField" value="2nd Value here">
<input type="submit" value="SUBMIT!">
</form>
</body>
and here is the JS function inside the scripts tag following the body
function check() {
var v1 = document.body.prvaForma.first.value;
alert("this is the value: " + v1);
}
Now, this doesn't work and I have been told what to do to make it work, e.g.
var v1 = document.getElementById("first").value
however, I would like to know why does it not work. I just imagined the DOM model in my head, and contructed the path that leads toward the element I want to select, i.e.
document.body.prvaForma.first.value
You can clearly see the DOM hierarchy here, and in the end, selecting the member "value" of the element.
I've been mostly programming in MATLAB and C, and I have some OO background in C++. JS seems awfully confusing right now, so any help is appreciated.
I just imagined the DOM model in my head, and constructed the path that
leads toward the element I want to select, i.e.
document.body.prvaForma.first.value
But DOM nodes do not have properties on them that match such paths! They only would collide with regular properties.
DOM nodes do have properties that allow them to access parent and child nodes (which builds up the DOM tree), and they do store some information about the node itself (tagname, attributes such as id or class).
Usually, you would use methods on them to find nodes in the tree, the most prominent of which is by using DOM selectors (you know them from CSS). Including shortcut methods like getElementById or getElementsByClassName.
And then there are some shortcut properties on the nodes, like .children which yields a collection of all element-typed child nodes. Similarly, there is a .body shortcut on the document which accesses the <body> node in the document. But these are exceptions!
The exception you might be looking for is the .forms collection, which holds all the <form> elements in a document by their name (attribute). And each form has an .elements collection, which holds inputs in that formular by their name (attribute). So you might use
document.forms["forma"].elements["firstField"]
but accessing the input by its id is much cleaner.
As you are taking your first steps in JS, I recommend using the developer console to debug and explore the language. Open in with the F12 key.
Now, being specific to your question, take a look at the documentation of document.forms, you might find it useful to select values inside forms.
This is what DOM level 0 looks like (DOM2 and 3 are almost identical) - http://www.technologyuk.net/the_internet/web/document_object_model.shtml
So to access your form items you would use
var ele = document.forms['prvaForma'].elements;
var val = ele['firstField'].value
Is there an agreed set of "best practices" for use of the DOM Level 0 collections in modern JavaScript applications? (document.forms, document.images, etc.)
In applications using jQuery, I've noticed a tendency to, say, change the contents of a drop-down using $(...).html() to switch out the underlying nodes, rather than using element.options[]. Is this because the DOM 0 collections are best avoided, or because jQuery makes it much easier to change the underlying DOM structure?
Edit: I guess part of the question includes if the older features are reliable cross-browser. I remember that, once upon a time, IE would add <tbody> tags automatically to your table, while firefox would not. That made walking the dom tree painful cross-browser. Similarly, element.options[] had problems when changing the options in the collection. Are these guys reliable cross-browser?
First off, great question.
DOM Level 0-1 functionality is my favorite toolbox to work with. The support is tremendous. I'll highlight the pros and cons for each subset of DOM Level 0 below:
DOM Level 0 Events
Since these are added as properties of an ElementNode, you can only have one handler. For some instances (eg: event delegation), this is burdensome. However, I feel that the DOM is diverse enough (especially as your project gets bigger) to have enough room for DOM level 0 handlers. DOM Level 2 listeners are painful to implement without a library/framework to smooth over older browsers. Even as a Flash developer (listeners are used everywhere), the DOM 0 events are far easier to me. One of the highlights is the fact that the this value is set for you (without IE hacking and coughing like the other model). For example, consider this markup:
<div id="foo">Cick Me!</div>
Now, all that needs to be done is selection and attachment of a DOM Level 0 handler.
var foo = document.getElementById("foo");
function bar()
{
console.log(this); //<div id="foo">
}
foo.onclick = bar;
That's a very easy way of selecting elements and an alternative to Event.currentTarget;
There's a great discussion on DOM Level 0 events vs. DOM Level 2 events here: [link]
DOM Level 0 HTMLCollections
Bar none, HTMLCollections are my favorite feature of the DOM. Because nodes are selected for you, there's no need to run queries. In my opinion, they're the most overlooked DOM feature today. Name traversal such as: collection["name"] is very handy and certainly helps when traversing forms. For example, consider this bit of markup:
<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
<fieldset>
<legend>Dummy Form</legend>
<input type="text" name="bar">
<select name="baz">
<option selected value="1">1</option>
</select>
</fieldset>
</form>
There are many DOM Level 0 ways to tackle this.
var foo = document.forms.foo; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
Demo: http://jsbin.com/udozoz/0edit#preview
var foo = document.forms[0]; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
Demo: http://jsbin.com/udozoz/2/edit#preview
var foo = document.getElementById("foo"); //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
Demo: http://jsbin.com/udozoz/3/edit#preview
Certainly, method 3 is more preferable. It's DOM Level 1, and not DOM Level 0. However, name traversal fits naturally for the HTMLFormElement.elements HTMLCollection. Since you're supposed to use name attributes on form elements, you can easily access them without an id attribute.
Ex: var baz = foo.elements.baz;
When using radio buttons that share the same name (to make only one selectable at a time), you can use the HTMLFormElement.elements HTMLCollection to select all of the radio buttons. That's very powerful. Consider this markup:
<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
<fieldset>
<legend>Radio Buttons</legend>
<label for="select_1">1</label>
<input id="select_1" type="radio" name="selectable" value="a">
<label for="select_2">2</label>
<input id="select_2" type="radio" name="selectable" value="b">
<label for="select_3">3</label>
<input id="select_3" type="radio" name="selectable" value="c">
</fieldset>
</form>
You could use this simple code and have every radio button with the name attribute value of "selectable":
var foo = document.forms.foo;
var selectables = foo.elements.selectable;
console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
Demo: http://jsbin.com/upiyom/edit#preview
var foo = document.forms.foo;
var selectables = foo.selectable;
console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
Demo: http://jsbin.com/upiyom/2/edit#preview
Option 2 enables you to bypass the elements HTMLCollection completely. While certainly not as clear as Option 1, it's still used today.
HTMLCollections have become more populous and far more diverse since the introduction of DOM Level 0. For example, take a look at the HTMLCollections available for a table. It's staggering. There's HTMLTableElement.rows, HTMLTableElement.tBodies, HTMLTableSectionElement (thead, tbody, tfoot).rows, and HTMLTableRowElement.cells. Those collections are very powerful, and have made DOM traversal far simpler with tables (permitting you use them).
DOM Level 0 Properties
While the properties on ElementNodes weren't as diverse in DOM Level 0 as they are now, there's still a couple of gems to note:
HTMLInputElement.defaultChecked
defaultChecked enables you to bypass searching through an HTMLInputElement's checked attribute completely because it stores a boolean based on that attribute's value. This means you don't have to kludge through sloppy solutions for IE builds related to get/set/removeAttribute. Later on, the defaultValue property would also be added to fill a similar need.
document.lastModified [non-standard]
lastModified will store the last time the document was changed. It's a cool little feature that has limited use.
HTMLDocument.title
title will snag the document's title for you. Its usage is a small niche at best.
In regards to your tbody question, browsers today do add an HTMLTableSectionElement (tbody) if you don't to promote proper DOM structure. You should get to know proper table markup so this won't be a problem in the future :).
Example markup:
Wrong:
<table>
<!-- tbody will be inserted here and will wrap the tr -->
<tr>
<td>Hello, World!</tr>
</tr>
</table>
Right:
<table>
<tbody>
<tr>
<td>Hello, World!</td>
</tr>
</tbody>
</table>
Demo: http://jsbin.com/exomub/edit#preview
Summary
The main point that needs to be driven home is that most of DOM Level 0 is standardized in DOM Levels 1 and 2. This means the browser support is extensive (since it's really old). There shouldn't be too much apprehension to using it—aside from some edge cases in older browser builds. At the end of the day, it's your choice.
I'd like to add that I've only very briefly—in the past—been employed to develop with HTML/JavaScript. I do it as a hobby, so I'm not privy to "horror stories" about browsers/projects gone wrong.
I hope this cleared a few things up.
-Matt
ElementNode - Node with nodeType == 1
HTMLCollection - Live array-like NodeList collected by the browser
That's a very interesting question. Here are my two cents.
First, it might go without saying, but it depends on whose code you're working on. Professional programmers aim to follow company-wide (or, for larger companies, team-wide) best practices, and if DOM Level 0 is discouraged or forbidden by these guidelines, then you should not use it. If it's either allowed or not mentioned at all, then the decision resolves to a personal choice, like for your own code.
Now, there's no obvious technical drawback that prevents you from using Level 0 if you wish to do so. For instance, I would be surprised if iterating over element.options was any slower than over element.getElementsByTagName("option") or $("option", element). The first syntax is also arguably more readable than the alternatives.
Browser support is not a problem either. Level 0 is older than dirt and has been supported for more than a decade by every script-aware browser under the sun.
However, the above is about choice, not efficiency, which is what the second half of your question is concerned with. Indeed, you can iterate over element.options or $("option", element) or $(element).children("option") with more or less the same efficiency, but if you have to do heavy work (for instance, wipe out the existing <option> elements and add new ones), then using element.innerHTML or $(element).html() will definitely be faster.
That's because the innerHTML Level 0 property and the html() jQuery method (which uses innerHTML internally) both delegate all the markup parsing and DOM manipulation to the browser, which is usually written in a lower-level language and heavily optimized for these tasks. Removing the <option> elements one by one in a Javascript loop will always be slower in comparison, and in this situation, using DOM Level 0 or all the bells and whistles of jQuery makes absolutely no difference.
I'll start by saying that I don't know of any "official" statements like "DOM Level 0 considered harmful". This is just my own opinion.
I think it depends on the case.
The issue I have is that it is problematic, especially with dynamically generated/modified documents, to target specific elements using the collections like documents.forms or documents.images. Every time I see someone write document.forms[0], I cringe.
Current, and even not-so-current browsers provide the ability via functions like getElementsByTagName to simulate the same behaviour, but in a more generic and reusable way. Of course, when you add jQuery into the mix, then there's no reason at all to use those collections.
The exceptions I have though, are when you are working in a non-jQuery environment and you're accessing things like selectElement.options or tbodyElement.rows. In those cases, it really is simpler when you're doing basic stuff like adding or removing items.
In jQuery-using applications, I've noticed a tendency to, say, change the contents of a drop-down using $(...).html() to switch out the underlying nodes, rather than using element.options[]. Is this because the dom0 collections are best avoided, or because jQuery makes it much easier to change the underlying DOM structure?
That can be explained quite easily. 95% of jQuery developers are ignorant of the fact the DOM API exists or can be used.
The fact that jQuery is abused for things the DOM can do more easily is simply caused by people not learning the DOM.
Personally I'd say use DOM 0, but then again, personally I would say use a DOM shim and don't use jQuery. It's all a matter of choice.
Do whatever is the most maintainable
For better or for worse, I use pure DOM level 0 features mainly for debugging. It is sometimes faster to inspect document.forms[0].elements for inputs.
I also use such features when I'm inspecting some page which use some esoteric (or simply unknown to me) framework. I have no time to dig into those abstractions and just inspecting collections directly.
I do believe you'd better know all this DOM zero arsenal, but it's even better if you know about all this modern pure DOM don't-know-which-level-it-is-exaclty level APIs. ClassList collections are nice, for example. I mean, if you are using a framework, you should always know, why do you exactly need it.
As any seasoned JavaScript developer knows, there are many (too many) ways to do the same thing. For example, say you have a text field as follows:
<form name="myForm">
<input type="text" name="foo" id="foo" />
There are many way to access this in JavaScript:
[1] document.forms[0].elements[0];
[2] document.myForm.foo;
[3] document.getElementById('foo');
[4] document.getElementById('myForm').foo;
... and so on ...
Methods [1] and [3] are well documented in the Mozilla Gecko documentation, but neither are ideal. [1] is just too general to be useful and [3] requires both an id and a name (assuming you will be posting the data to a server side language). Ideally, it would be best to have only an id attribute or a name attribute (having both is somewhat redundant, especially if the id isn't necessary for any css, and increases the likelihood of typos, etc).
[2] seems to be the most intuitive and it seems to be widely used, but I haven't seen it referenced in the Gecko documentation and I'm worried about both forwards compatibility and cross browser compatiblity (and of course I want to be as standards compliant as possible).
So what's best practice here? Can anyone point to something in the DOM documentation or W3C specification that could resolve this?
Note I am specifically interested in a non-library solution (jQuery/Prototype).
Give your form an id only, and your input a name only:
<form id="myform">
<input type="text" name="foo">
Then the most standards-compliant and least problematic way to access your input element is via:
document.getElementById("myform").elements["foo"]
using .elements["foo"] instead of just .foo is preferable because the latter might return a property of the form named "foo" rather than a HTML element!
[1] document.forms[0].elements[0];
"No-omg-never!" comes to mind when I see this method of element access. The problem with this is that it assumes that the DOM is a normal data structure (e.g.: an array) wherein the element order is static, consistent or reliable in anyway. We know that 99.9999% of the time, that this is not the case. Reordering or input elements within the form, adding another form to the page before the form in question, or moving the form in question are all cases where this code breaks. Short story: this is very fragile. As soon as you add or move something, it's going to break.
[2] document.myForm.foo;
I'm with Sergey ILinsky on this:
Access arbitrary elements by referring to their id attribute: document.getElementById("myform");
Access named form elements by name, relative to their parent form element: document.getElementById("myform").foo;
My main issue with this method is that the name attribute is useless when applied to a form. The name is not passed to the server as part of the POST/GET and doesn't work for hash style bookmarks.
[3] document.getElementById('foo');
In my opinion, this is the most preferable method. Direct access is the most concise and clear method.
[4] document.getElementById('myForm').foo;
In my opinion, this is acceptable, but more verbose than necessary. Method #3 is preferable.
I just so happened to be watch a video from Douglas Crockford and he weighed in on this very subject. The point of interest is at -12:00. To summarize:
Document collections (document.anchor, document.form, etc) are obsolete and irrelevant (method 1).
The name attribute is used to name things, not to access them. It is for naming things like windows, input fields, and anchor tags.
"ID is the thing that you should use to uniquely identify an element so that you can get access to it. They (name and ID) used to be interchangeable, but they aren't anymore."
So there you have it. Semantically, this makes the most sense.
To access named elements placed in a form, it is a good practice to use the form object itself.
To access an arbitrary element in the DOM tree that may on occasion be found within a form, use getElementById and the element's id.
I much prefer a 5th method. That is
[5] Use the special JavaScript identifier this to pass the form or field object to the function from the event handler.
Specifically, for forms:
<form id="form1" name="form1" onsubmit="return validateForm(this)">
and
// The form validation function takes the form object as the input parameter
function validateForm(thisForm) {
if (thisform.fullname.value !=...
Using this technique, the function never has to know
- the order in which forms are defined in the page,
- the form ID, nor
- the form name
Similarly, for fields:
<input type="text" name="maxWeight">
...
<input type="text" name="item1Weight" onchange="return checkWeight(this)">
<input type="text" name="item2Weight" onchange="return checkWeight(this)">
and
function checkWeight(theField) {
if (theField.value > theField.form.maxWeight.value) {
alert ("The weight value " + theField.value + " is larger than the limit");
return false;
}
return true;
}
In this case, the function never has to know the name or id of a particular weight field, though it does need to know the name of the weight limit field.
It’s not really answering your question, but just on this part:
[3] requires both an id and a name... having both is somewhat redundant
You’ll most likely need to have an id attribute on each form field anyway, so that you can associate its <label> element with it, like this:
<label for="foo">Foo:</label>
<input type="text" name="foo" id="foo" />
This is required for accessibility (i.e. if you don’t associate form labels and controls, why do you hate blind people so much?).
It is somewhat redundant, although less so when you have checkboxes/radio buttons, where several of them can share a name. Ultimately, id and name are for different purposes, even if both are often set to the same value.
This is a bit old but I want to add a thing I think is relevant.
(I meant to comment on one or 2 threads above but it seems I need reputation 50 and I have only 21 at the time I'm writing this. :) )
Just want to say that there are times when it's much better to access the elements of a form by name rather than by id. I'm not talking about the form itself. The form, OK, you can give it an id and then access it by it. But if you have a radio button in a form, it's much easier to use it as a single object (getting and setting its value) and you can only do this by name, as far as I know.
Example:
<form id="mainForm" name="mainForm">
<input type="radio" name="R1" value="V1">choice 1<br/>
<input type="radio" name="R1" value="V2">choice 2<br/>
<input type="radio" name="R1" value="V3">choice 3
</form>
You can get/set the checked value of the radio button R1 as a whole by using
document.mainForm.R1.value
or
document.getElementById("mainForm").R1.value
So if you want to have a unitary style, you might want to always use this method, regardless of the type of form element. Me, I'm perfectly comfortable accessing radio buttons by name and text boxes by id.
Being old-fashioned I've always used the 'document.myform.myvar' syntax but I recently found it failed in Chrome (OK in Firefox and IE). It was an Ajax page (i.e. loaded into the innerHTML property of a div). Maybe Chrome didn't recognise the form as an element of the main document. I used getElementById (without referencing the form) instead and it worked OK.
OLD QUESTION, NEW INSIGHTS (2021)
After reading and learning from some of the excellent answers to this question, is needed to go back to basics and try to get more data how id and name are defined in their origins.
The result was simple and enlightening. I'm summarizing it below:
The most important fact is, by far, that id and name are so different and have so different purposes, that they are defined in separate sections of the W3/WHATWG specifications. In short:
id:
defined as part of the DOM (web document standards) specification and NOT as an HTML (markup language) thing. So, id is DOM (document), not HTML (language).
its purpose is directly related to the unique identification of a node in the document. Therefore, very suitable to access nodes.
must be unique
name:
defined as part of the HTML specifications and NOT as and DOM. Therefore, name is HTML (language), not DOM (web document).
its purposes is directly related to form submission - how a form is structured, its enctype, the data sent to the server (eg. via https), and so on.
Based on the above data and some accumulated experience as a developer, my main conclusions are:
The confusion about using id or name to access an element is caused by some main factors:
while the very term element is clearly defined in the DOM specification, it doesn't have a very clear definition on the HTML specification - which refers to DOM, xhtml namespace, etc.
we, developers, don't like to dig into the technicalities of definitions (maybe I don't need to detail this assumption here), which can cause further misunderstandings.
as a result, the term element is widely used to refer both to a HTML tag (eg, a form) and a DOM node (despite the fact that a form is a node in the DOM, but not vice-versa.)
JavaScript provides a number of ways to access things in the DOM, including the ones based on its own stuff, like (getElementsByTagName, getElementsByName) which requires some behind-the-scenes actions to retrieve the actual nodes from the DOM.
on one hand, it makes easier for the developers to access these elements; on other hand, it hides the concepts and structures that are playing important roles in that particular context.
ultimately, the above factors generate confusions that lead to necessary and clever questions like the one that originates this whole thread.
after having read the answers and comments, gathered data, burned some neurons by analyzing the data and making conclusions, my answer to the question is:
if you want to keep it strictly technical (and probably have some gain in performance), then go for id wherever is possible and makes sense - for example, it doesn't make sense to add the id everywhere; probably it doesn't make sense to use the id attribute in radio input types.
if you want to use the flexibility offered by JavaScript, but keeping the best from both worlds, I would suggest the solution provided by #Doin in this thread.
I also appreciated the Accessibility factor brought by #paul-d-waite. The same factor is explored in this answer as well.
keep in mind that not everything you can you should.
References:
HTML - name
HTML - element
DOM - id
DOM - element
HTML - Living Standard — Last Updated 5 November 2021
DOM - Living Standard — Last Updated 18 October 2021
It's also worth it to take a look at The form element
Other references in Stackoverflow:
was the name attribute really needed in html?
Difference between id and name attributes in HTML
Bonus: Short and cool distinction between id and name, for the impatient.
Just to add to everything already said, you may access the inputs either with the name or id using preferably the elements property of the Object form, because without it you may get a property of the form named "foo" rather than an HTML element. And according to #Paul D. Waite it's perfectly ok to have both name and id.
var myForm = document.getElementById("myform")
console.log(myForm.foo.value) // hey
console.log(myForm.foo2.value) // hey
//preferable
console.log(myForm.elements.foo.value) // hey
console.log(myForm.elements.foo2.value) // hey
<form id="myform">
<input type="text" name="foo" id="foo2" value="hey">
</form>
According to MDN on the HTMLFormElement.elements page
The HTMLFormElement property elements returns an
HTMLFormControlsCollection listing all the form controls contained in
the element. Independently, you can obtain just the number of
form controls using the length property.
You can access a particular form control in the returned collection by
using either an index or the element's name or id.
I prefer this one:
document.forms['idOfTheForm'].nameOfTheInputFiled.value;
The name attribute works well. It provides a reference to the elements.
parent.children - Will list all elements with a name field of the parent.
parent.elements - Will list only form elements such as input-text, text-area, etc.
var form = document.getElementById('form-1');
console.log(form.children.firstname)
console.log(form.elements.firstname)
console.log(form.elements.progressBar); // undefined
console.log(form.children.progressBar);
console.log(form.elements.submit); // undefined
<form id="form-1">
<input type="text" name="firstname" />
<input type="file" name="file" />
<progress name="progressBar" value="20" min="0" max="100" />
<textarea name="address"></textarea>
<input type="submit" name="submit" />
</form>
Note: For .elements to work, the parent needs to be a <form> tag. Whereas, .children will work on any HTML-element - such as <div>, <span>, etc.
To supplement the other answers, document.myForm.foo is the so-called DOM level 0, which is the way implemented by Netscape and thus is not really an open standard even though it is supported by most browsers.
Form 2 is ok, and form 3 is also recommended.
Redundancy between name and id is caused by the need to keep compatibility. In HTML5 some elements (such as img, form, iframe and such) will lose their "name" attribute, and it's recommended to use just their id to reference them from now on :)
Check out this page: Document.getElementsByName()
document.getElementsByName('foo')[0]; // returns you element.
It has to be 'elements' and must return an array, because more than one element could have the same name.
My answer will differ on the exact question.
If I want to access a certain element specifically, then will I use document.getElementById().
An example is computing the full name of a person, because it is building on multiple fields, but it is a repeatable formula.
If I want to access the element as part of a functional structure (a form), then will I use:
var frm = document.getElementById('frm_name');
for(var i = 0; i < frm.elements.length;i++){
..frm.elements[i]..
This is how it also works from the perspective of the business. Changes within the loop go along with functional changes in the application and are therefore meaningful. I apply it mostly for user friendly validation and preventing network calls for checking wrong data. I repeat the validation server side (and add there some more to it), but if I can help the user client side, then is that beneficial to all.
For aggregation of data (like building a pie chart based on data in the form) I use configuration documents and custom made JavaScript objects. Then is the exact meaning of the field important in relation to its context and do I use document.getElementById().
Because the case [2] document.myForm.foo is a dialect from Internet Explorer.
So instead of it, I prefer document.forms.myForm.elements.foo or document.forms["myForm"].elements["foo"].
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.