Why don't we just use element IDs as identifiers in JavaScript? - javascript

All browsers I've come to work with allow accessing an element with id="myDiv" by simply writing:
myDiv
See here: http://jsfiddle.net/L91q54Lt/
Anyway, this method seems to be quite poorly documented, and in fact, the sources I come across don't even give it a mention and instead assume that one would use
document.getElementById("myDiv")
or maybe
document.querySelector("#myDiv")
to access a DOM element even when its ID is known in advance (i.e. not calculated at runtime). I can tell that the latter approaches have the advantage of keeping the code safe if someone inadvertedly attempts to redefine myDiv in a wider scope (not such a brilliant idea though...), overwrites it with some different value and goes on without noticing the clash.
But other that that? Are there any concerns in using the short form above other than code design, or what else am I missing here?

Anyway, this method seems to be quite poorly documented, and In fact, the sources I come across don't even give it a mention [...]
Reliance on implicitly-declared global variables aside, the lack of documentation is a great reason not to use it.
The apparent promotion of id values into global variables isn't standards compliant (the HTML5 spec for the ID attribute doesn't mention it) and, therefore, you shouldn't assume future browsers will implement it.
EDIT: It turns out this behaviour is standards compliant - In HTML5, window should support property access to "Named Elements":
Named objects with the name name, for the purposes of the above algorithm, are those that are either:
child browsing contexts of the active document whose name is name,
a, applet, area, embed, form, frameset, img, or object elements that have
a name content attribute whose value is name, or
HTML elements that have an id content attribute whose value is name.
Source: HTML 5 spec, 'Named access on window object", emphasis mine.
Based on this, standards compliance is not a reason to avoid this pattern. However, the spec itself advises against its use:
As a general rule, relying on this will lead to brittle code. Which
IDs end up mapping to this API can vary over time, as new features are
added to the Web platform, for example. Instead of this, use
document.getElementById() or document.querySelector().

Great question. As Einstein probably didn’t say, things should be as simple as possible, and no simpler.
the latter approaches have the advantage of keeping the code safe if someone inadvertedly attempts to redefine myDiv in a wider scope (not such a brilliant idea though...), overwrites it with some different value and goes on without noticing the clash
That’s the main reason why this is a bad idea, and it’s quite enough. Global variables aren’t safe to rely on. They can be overwritten at any time, by any script that ends up running on the page.
In addition to that, just typing in myDiv isn’t a “short form” of document.getElementById(). It’s a reference to a global variable.document.getElementById() will happily return null if the element doesn’t exist, whilst attempting to access a non-existent global variable will throw a reference error, so you’d need to wrap your references to the global in a try/catch block to be safe.
This is one reason why jQuery is so popular: if you do $("#myDiv").remove(), and there is no element with an id of myDiv, no error will be thrown — the code will just silently do nothing, which is often exactly what you want when doing DOM manipulation.

There are a few reasons:
You don't want your code and your markup that coupled.
By using a specific call to access a div, you don't have to worry about the global space being corrupted. Add a library that declares myDiv in global space and you're in a world of pain that will be hard to fix.
You can access elements, by ID, that aren't part of the DOM
They can be in a fragment, a frame, or an element that has been detached and not re-attached to the DOM yet.
EDIT: Example of accessing a non-attached elements by ID
var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.id = "span-test";
frag.appendChild(span);
var span2 = frag.getElementById("span-test");
alert(span === span2);

In my case I had an iframe inside my page. I was confused by id attribute vs name attribute, both of which affected a variable named inner_iframe, accessible from window!
If I used only the id attribute, like id="inner_iframe", window.inner_iframe is a HTMLIFrameElement. Properties include inner_iframe.contentDocument and inner_iframe.contentWindow as described here*
In this case, I assume the variable appears on window because of the reason quoted by #joew in the accepted answer:
HTML elements that have an id content attribute whose value is name
If I used only the name attribute, like name="inner_iframe" then window.inner_iframe is a "frame", aka a "window object". contentWindow, therefore the name-attribute inner_iframe does not have properties contentDocument or contentWindow.
I assume the inner_iframe variable appears on window because of the reason quoted by #joew in the accepted answer
child browsing contexts of the active document whose name is name
If I used both name and id attributes, and I gave both attributes the same value name="inner_iframe" id="inner-iframe"; the name attribute trumped/clobbered the id attribute; I was left with the "window object", not the HTMLIFrameElement!
So my point is to be careful about ambiguity; the conflict between name and id attributes on the same object with two different APIs: is just a specific case where implicit behavior and attachment to a window variable may confuse you.
*(and only if the <script> was loaded after/beneath the <iframe> in the HTML, or the <script> waited until window.onload before trying to access by id attribute)
**this "frame" vs DOM Element distinction is described in Mozilla documentation as:
Each item in the window.frames pseudo-array represents the window object corresponding to the given 's or 's content, not the (i)frame DOM element (i.e., window.frames[0] is the same thing as document.getElementsByTagName("iframe")[0].contentWindow).

As someone that has been developing Web-based applications for over 25 years, I can say with certainty that the only reason for this quirky behavior is backwards compatibility.
The method getElementById wasn't even part of DOM Level 1. However, the earlier DOM Level 0 allowed direct access to most elements on the page:
https://docstore.mik.ua/orelly/webprog/dhtml/ch02_04.htm
As you can see, browsers like Netscape 6 and MSIE 5 continued to support the old convention, even after getElementById was adopted as a "standard"
The earliest DHTML capable browsers like Netscape Navigator and MSIE frequently pushed their own DOM specs into the marketplace. So you ended up with a lot of bad design decisions which ultimately became standardized by virtue of "that's how it was done before".
https://www.quirksmode.org/js/dom0.html
For reasons of backward compatibility the more advanced browsers, even
those who support the Level 1 DOM, still also support the old,
faithful Level 0 DOM. Not supporting it would mean that the most
common scripts suddenly wouldn't work any more. So even though the
Level 0 DOM doesn't entirely fit into the new DOM concepts, browsers
will continue to support it.
When Netscape introduced Level 0 DOM, it was likely assumed that Web-based applications would never amount to more than auto-filling a few form fields and moving some images around the screen. So there was no concern about polluting the global window object with a handful of element IDs.
Obviously that solution didn't scale well at all. But we're stuck with this archaic Level 0 DOM convention just so as not to break legacy Javascript code.

Related

get value of TD to show in modal Javascript [duplicate]

Under what circumstances is it illegal for an HTML page to contain elements with duplicate ID attributes?
As a developer who has worked with HTML for many years, I am aware that the intention is that element ids should be unique - what I am asking is for the practical negative effects of duplicate ids.
Granted, getElementByID()-like functions in some libraries might return arrays rather than a single element and this could cause issues when the developer had not anticipated this case. However, as far as I know, such functions will continue to operate so clearly they are not a breaking-effect of id duplicates.
So why is it that duplicate ids are said to be not allowed?
EDIT: The driver for the question was that I saw some templating libraries when generating list/repeated items, producing elements with duplicate ids and I wondered what the impact of that might be in practical terms and how to decide whether to adopt those libraries.
I also wondered about the effect of modal plugins, or any other, that might clone an existing hidden node and thereby create a duplicate via code, and then what the browser would do in that case.
It's always "illegal". Against the spec = illegal. Just because something "seems to work" due to a fluke or overly generous compiler doesn't mean it is valid code.
Another way to think about it: juhst becuse u kan reed ths duzint mayke it korrect Englesh. You have a generous compiler/brain which can understand that (e.g Google Chrome), but someone with more limited English knowledge (e.g. new to the market Browser X) or someone with a mental incapacity (e.g. Internet Explorer) might not understand it at all...but would be able to understand it if each word was spelled correctly/according to spec.
https://softwareengineering.stackexchange.com/questions/127178/two-html-elements-with-same-id-attribute-how-bad-is-it-really
A few reasons I can find:
According to the DOM spec, "If more than one element has an ID attribute with that value, what is returned is undefined"
And:
Incorrect doesn't come in shades of grey. This code violates the standard and is therefore incorrect. It would fail validation checking, and it should. That said, no browser currently on the market would complain about it, or have any problem with it at all. Browsers would be within their rights to complain about it, but none of the current versions of any of them currently do. Which doesn't mean future versions might not treat this code badly.
And:
Behavior trying to use that ID as a selector, either in css or javascript, is unguessable and probably varies from browser to browser.
And:
Many javascript libraries will not work as expected
And:
Experience says that getElementById in major browsers will return the first matched element in the document. But this may not always be the case in the future.
Specification says UNIQUE
HTML 4.01 specification says ID must be document-wide unique.
HTML 5 specification says the same thing but in other words. It
says that ID must be unique in its home subtree, which is basically
the document if we read the definition of it.
Avoid duplication
But since HTML renderers are very forgiving when it comes to HTML
rendering they permit duplicate IDs. This should be avoided if at all
possible and strictly avoided when programmatically accessing
elements by IDs in JavaScript. I'm not sure what getElementById
function should return when several matching elements are found?
Should it:
return an error?
return first matching element?
return last matching element?
return a set of matching elements?
return nothing?
But even if browsers work reliably these days, nobody can guarantee
this behavior in the future since this is against specification.
That's why I recommend you never duplicate IDs within the same
document.
This is an answer by Robert Koritnik at Software Engineering asked by danludwig
Question: Two HTML elements with same id attribute: How bad is it really?
Duplicate ids not allowed in HTML
That code is incorrect. Incorrect doesn't come in shades of grey. This
code violates the standard and is therefore incorrect. It would fail
validation checking, and it should. That said, no browser currently
on the market would complain about it, or have any problem with it at
all. Browsers would be within their rights o complain about it, but
none of the current versions of any of them currently do. Which
doesn't mean future versions might not treat this code badly.
~From Dan Ray
Duplicate ids and JavaScript
So if you use duplicate ids in your HTML many libraries will not work as expected. The most libraries will get the first id they find and return that element. When we look at pure JavaScript: the document.getElementById("idName"); should return in the case of multiple elements with the same id. It says it must return the first element, in tree order.
Under what circumstances is it illegal for an HTML page to contain
elements with duplicate ID attributes?
It is illegal in any circumstances as per the specification:
When specified on HTML elements, the id attribute value must be unique amongst all the IDs in the element's tree [...].
As a developer who has worked with HTML for many years, I am aware
that the intention is that element ids should be unique - what I am
asking is for the practical negative effects of duplicate ids.
The CSS selector specification does not define how to handle documents with non-unique ids, as far as I can tell. So you cannot safely use id selectors in CSS in those cases.
The id attribute is also used to navigate to fragments (aka "anchors"). According to the specification, the browser should navigate to the "first such element in tree order". But that might conflict with which element actually comes first from top to bottom. I.e. your layout could conflict with the actual fragment link.
Granted, getElementByID() style functions in jquery etc might return
arrays rather than a single element and this could cause issues when
the developer had not anticipated this case. However, as far as I
know, such functions will continue to operate so clearly they are not
a breaking-effect of id duplicates.
That is clearly wrong, getElementByID() never returns an array. As per the specification:
The getElementById(elementId) method, when invoked, must return the first element, in tree order, within context object’s descendants, whose ID is elementId, and null if there is no such element otherwise.
Your expectation is also wrong in the case of jQuery:
Each id value must be used only once within a document. If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM. This behavior should not be relied on, however; a document with more than one element using the same ID is invalid.
There is really no reason to violate the specification in this case, you don't gain anything by doing it. While your pages won't completely break, you could run into problems with CSS, fragment links, and probably other things. In addition, your documents will be invalid and duplicate ids might confuse other people that have to maintain your code.

Access HTML elements based on id identifier [duplicate]

This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 9 years ago.
I was playing with javascript, and I don't understand how this little snippet can works:
html > <div id="foo_bar"></div>
javascript > foo_bar.textContent = "Hello, world!";
result > <div id="foo_bar">Hello, world!</div>
foo_bar is not a variable defined before in the code. I only have this one line in my javascript code.
Check the jsFiddle demo : http://jsfiddle.net/6W25e/
So what really happend?
I always thought that was impossible to access dom elements without dom methods like element.getElementById().
Is there any documentation on this behavior? (my searches have been unsuccessful on mdn)
Taken from bobInce
What is supposed to happen is that ‘named elements’ are added as apparent properties of the document object. This is a really bad idea, as it allows element names to clash with real properties of document.
IE made the situation worse by also adding named elements as properties of the window object. This is doubly bad in that now you have to avoid naming your elements after any member of either the document or the window object you (or any other library code in your project) might want to use.
Read more: Do DOM tree elements with ids become global variables?
This means it's very bad practice to do that, and some browsers don't support it, the good ones that don't fall into the trick.
What happens is that some browsers will make them global variables as classes of window, making them immediately accessible when the window loads.

Is getElementById optional in some browsers? [duplicate]

This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 8 years ago.
When accessing elements by window.someThing, the "someThing" should be the name of html element. But what I see now, is that I can access an element by id in the same way, without document.getElementById. When has this been changed? It looks like it works in Chrome, IE, Firefox 13, but not in Firefox 12.
For example:
<div id="MyDiv">Content</div>
<script>
MyDiv.innerHTML = "New Content";
</script>
Why does the example above work? Why don't I have to do:
var MyDiv = document.getElementById('MyDiv');
Is it something new, or has it always been possible and I just didn't know it?
http://www.quirksmode.org/dom/w3c_core.html#gettingelements
It's been (mostly) implemented since IE 5.5
I can't really find any info on using the ID as variable name. I'd suggest on sticking to getElementById("MyDiv").doSomething instead of MyDiv.doSomething, to improve compatibility.
Especially when you're writing larger scripts, you may mix up variable names with id's used in the page. getElementById ensures you "get" the DOM element.
This is not standard behavior in JavaScript. When adding a variable as you did with var MyDiv, the variable was added to the window object so that it could be accessed directly as if it were a property, but DOM elements were never added. I don't personally know the reasons for the new behavior, but my guess would be that it's just an expansion of the language engine's capability. If you really want to know what the behavior is supposed to be, you could always read the standard: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Edit: Also, note that the method that is used to get the element is document.getElementById() which comes from the document object model. The method you're referring to is placing an id into the window object which can create conflicts by id. The standard defined method is to get the element from document and avoid putting things into the window. Using the window object in this manner would be similar to using a global variable (which is a bad practice re: http://www.javascripttoolbox.com/bestpractices/#namespace)
You can find your answer here: Can I Use an ID as a Variable Name?
In short, avoid it.
The reason it works is because the browser actually creates a variable window.document.myDiv
AVOID IT!
It seems like an amazing feature but I would recommend not using it because if you have divs with id same as that of some global JS variables, it would be conflicting and will also mess-up stuff in some other third party JS files that you include.
But You always have jQuery selectors always with you and not to forget the new querySelector feature in modern browsers :)

Purpose of element.setAttribute()?

If there is an element like this:
var c = document.createElement('a');
Then one can add the attribute name simply by doing:
c.name = "a1";
What is the purpose of setAttribute() if one can just use the dot notation?
An attribute is not the same thing as a property.
Attributes are usually created in your HTML, and will become an object member of element.attributes. Some will also set a corresponding property.
There are some attributes that update when you change the property, but others that do not. For example, the .value property will not change the attribute on input elements. Or custom properties do not become custom attributes.
Most of the time you probably want to set the property, but if you want to change the attribute, then in some cases you must use setAttribute
Who says you can do either?
Well, okay you can. But seriously, "who says?", because it mostly comes down to that.
In the beginning, there was Netscape Navigator 2, the first web browser to support Javascript, and indeed being a few months prior to server-side use in Netscape Enterprise Server, the first anything to support Javascript (called "Livescript" in a beta version but quickly renamed "Javascript" because it was 1995 and putting the word "java" in anything was a sure-fire way to get about 20,000 column-inches out of tech journalists who spent the rest of their time wondering confused around coffee wholesalers wondering where the press releases and promotional schwag was).
The object model at the time was pretty small, to the point that you could learn it to the point where you could hold the entire model in your head in a couple of days. For most elements, you couldn't actually do very much with them. A lot of things were quite fiddly (where you can find the current value of a <select id="selId" name="selName"> today with document.getElementById('selId').value and a few other ways, then you would need document.forms[0]["selName"].options[document.forms[0]["selName"].selectedIndex].value.
Then IE3 came out with Javascript too, NN 3 upped the ante by letting you change an image's src attribute. The browser wars had begun in earnest. Many veterans are still haunted by the memories of what they did.
The really obvious way to make a browser's document model better, was to have more and more things reflected by properties - preferably writable rather than read-only. The next-best thing was to have a slightly simpler and easier to remember way of changing something than the other browser (then they might make more web pages that worked in the latest version of your browser and didn't in your rival's).
Through keeping up a rapid pace of development, it was clear that Netscape would develop a new middleware platform that would make the position of Microsoft and Apple irrelevant, while the jury was out on whether yahoo or alta-vista had the approach to search and/or directory that would dominate the web. (Don't make long-term predictions about technology).
During the general trend of make-script-able-to-do-everything-to-everything, a lot of properties got named after the corresponding attribute when there was one, which is after all a pretty sensible way.
This is a bit inconsistent though. For one thing, most properties that correspond to attributes map string values to string values in a straight-forward way. One or two do not, such as the href attribute on anchor elements which gives you a richer object with properties reflecting parts of the URI (mostly because it was available from the early days before make-script-able-to-do-everything-to-everything). Which is both useful (if you want to break the URI down) and a nuisance because there's no good way of telling which is which.
At the height of this, they had something called DHTML, and something called dHTML, which were two ways to do pretty much the same thing in completely incompatible ways.
There's also the fact that javascript is loose in letting you add a new property to anything, and HTML lets you add in new attributes (debatable, depending on how strictly you stay to which standard, but this was the browser wars and new proprietary attributes were seemingly added by one browser or another every 4 minutes). Knowing whether a property would have any real effect on any given browser was a nuisance.
Meanwhile, in a distant International Standards Consortium, something called XML was being developed. It let you add all sorts of elements with all sorts of attributes in all sorts of ways. Ways of dealing with this in script were also added.
We needed a way to more consistently change the attributes of elements than that currently existing, and since it was obvious that all future versions of HTML would be XML applications (Don't make long-term predictions about technology) it made sense for it to be at least relatively consistent between the two.
It was also dawning on everyone, that having a more popular browser than everyone else wasn't going to turn anyone into the next Bill Gates (not even the current Bill Gates) so the advantages of having greater support for standard approaches rather than greater flashy-stuff-the-other-guy-can't-do became more apparent.
The W3C DOM became more and more finalised and more and more supported. It gave us a more consistent way of setting attributes. It was more verbose, but you could know consistently what it was going to do, and it was also more powerful in creating, copying, changing and deleting parts of a document.
But old sites had to be kept going if possible, along with the fact that it does remain a useful shorthand for a lot of attributes to just set the corresponding property, so people weren't going to stop using it. Still, the DOM approach is supported to some extent by all browsers, giving much more consistency between them.
And then half the developers started using JQuery anyway.
This is to make some custom attribute:
while its all fine to make el.name='aaa';
if you make el.customsttr='a' it will not work.
-- (unless it has been already defined, as pointed out below)
http://jsfiddle.net/sXdHB/
Application:
For example you have an img, with attr 'src', then you might want to add a custom atribute 'big_src' and then read it through some script to display a bigger one;
I'd use getAttribute/setAttribute to make it clear that you're working with DOM elements. Minimizing ambiguity is a plus!
However, this is what quirksmode.org has to say about atrributes:
Attributes
A bloody mess. Try influencing attributes in this order:
Try getting or setting a specific property, like x.id or y.onclick.
If there is no specific property, use getAttribute() or
setAttribute().
If even that doesn't work, try any other method or
property in the table below. Most have horrible browser
incompatibility patterns, though.
Avoid attributes[]. It's worse
than anything else.

Storing custom data in dom elements

Is this wrong? If so why?
var elm = document.getElementById("myElm");
elm.customValue = {attr1 : "test", attr2 : "test"};
I understand how to use the data attributes, but I don't want to muddy up my dom with all those attributes.
This introduces a memory leak in some browsers because you bind a native C object (the DOM element) and a JS object together and some garbage collection algorithms cannot deal with this. IE is one of them.
Here is an MSDN article about IE memory leaks: http://msdn.microsoft.com/en-us/library/ie/bb250448(v=vs.85).aspx
Bottom line, why wouldn't you use the proper tools available? You have no idea if in the future, near or far, whatever custom property name you are using will be added to the w3c specifications for that particular element. Now, suddenly your code is broken.
Never mind that adding custom properties to elements which already have defined properties makes your code a maintenance nightmare. Whether it's you or someone else maintaining it in the future, there's going to be a "wtf" moment where the developer is trying to igure out if a) a custom property was added to the element or b) the element itself is in fact a custom object.
Finally, what if that element is replaced in the dom via Ajax or dynamic HTML? Now the property is gone and your code is broken.
You should consider HTML5 data-attributes.
From the man himself: http://ejohn.org/blog/html-5-data-attributes/

Categories