Access HTML elements based on id identifier [duplicate] - javascript

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.

Related

jQuery, which is best, assigning element to variable or not? [duplicate]

This question already has answers here:
Is storing jQuery elements in variables more efficient?
(5 answers)
Closed 2 years ago.
While reading jQuery and Bootstrap documentation I often see this:
var modal = $('#someid');
modal.find('.something').text('something');
modal.find('.somethingelse').text('somethingelse');
It first assigns the element to a variable, then works from there. However I usually write this:
$('#someid').find('.something').text('something');
$('#someid').find('.somethingelse').text('somethingelse');
My question is, are there reasons for using the first method - assigning to a variable - other than the syntax itself? Is it faster or better regarding the DOM?
The first method is preferred for multiple reasons.
It cuts down on the number of times the DOM has to be accessed, which is a relatively slow operation and so it performs better.
It reduces the number of times your code instantiates a new jQuery object from an existing Element object, which is another performance benefit.
It DRYs up the code so that the same statements are not needlessly repeated.
As such you should always follow this practice, known colloquially as 'caching the selector', where possible.

Why don't we just use element IDs as identifiers in 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.

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 :)

do I really need to call getElementById()? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
IE/Chrome: are DOM tree elements global variables here?
I just stumbled upon an unexpected but useful behavior in the browser: It creates a variable for every element that has an ID in my html code. So when I have:
<div id="ohlala"> ... </div>
the browser seem to run this code behind the scene:
var ohlala = document.getElementById("ohlala");
so I can easily change the text of that element by:
ohlala.innerHTML="test"
Try it online: http://jsfiddle.net/Facby/
The question is: why would I need to write the document.getElementById() bit myself? How portable is that code? I tried in Opera, FireFox and Chrome and it works! Can I rely on this functionality? Does the browser always create variables for every element with id? In that case I have to be more careful about the names that are used in my javascript code not to conflict with similar ids from the HTML, right?
When creating elements with IDs, the "window" object receives the specific attributes, that's why you can use variables directly, this behavior is deprecated and usually is wrote like this: window.ohlala.innerHTML = "...", this behavior is conserved by the browsers for compatibility with some older code on websites, but it is not recommended to use it in modern websites, always use .getElementById() method, this method is part of a W3C Standard, and you can use it in all modern browsers, in some very old browser versions and < IE7 it will not work. Learn more about DOM (Document Object Model) here: https://developer.mozilla.org/en-US/docs/DOM

Is it a bad practice to reference Javascript objects from DOM elements?

As a "best practice" for front-end developers, is it bad to use the "control" property to reference back to the Javascript object?
Here's a link to the property in question:
https://developer.mozilla.org/en/XUL/Property/control
I've seen a lot of Javascript functions that reference DOM elements using selectors and then perform DOM manipulation that way. But what if we started by traversing through the DOM tree and we have the DOM element first?
EDIT 1
Okay, it seems like there are some interest here but no contributions for some reason. This started as a conversation between me and my co-worker. He was concerned about circular references and possible cases of losing references... does that apply here? I thought as long as we don't call delete <javascript object> then we're fine.
EDIT 2 I found this: JQuery methods and DOM properties
In my world right now, I'm using the Microsoft AJAX Library where we created multiple ScriptControls and put them on various pages; which in turn, (the ScriptControls) get "modified" by page's events and sometimes events of other ScriptControls. When pages need to do something with the DOM element, the Javascript would use the respective Javascript Object's methods.
However, it seems in JQuery (based on the other question), it's common to get the DOM element then use .get(0) to grab the JQuery object out of it (if it exists).
So I guess this is a witch hunt so far and there's still no right answer to my question :(
I know I'm still lacking an example but I'm not sure how to approach this.
I am not too sure what exactly you're referring to. Could you provide a simple code example? Otherwise, your question is a bit vague IMHO. I'll give it a shot anyways:
I do not understand why there would be any lost or circular references. The control attribute is just the id (string) of the "controlling" DOM Element, not a reference to the actual DOM Element. If you delete label.control it will no longer be associated with the other DOM Element.

Categories