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 :)
Related
Please be nice. My first question here. I'm learning JavaScript and jQuery. Google isn't much help because I don't know how to ask the right question. Need human intervention please. I'm trying to figure out what is going on with this simple bit of code:
var myVar = $("<p>");
This creates an opening and closing <p> tag and I don't understand why.
Next, I'll add this paragraph to an existing element #myDiv. For example:
$("myDiv").html(myVar); results in the following:
<div id="myDiv"><p></p></div>
Continuing...
$("myDiv").html(myVar.text("A string for the paragraph"));
Results in:
<div id="myDiv"><p>A string for the paragraph</p></div>
Why does that first snippet create an opening and closing <p> tag? What is this called?
It's simply a more concise method of this in pure JavaScript:
var myVar = document.createElement("p");
And that goes to jQuery like this:
var myVar = $("<p></p>");
And because it's jQuery, and it gets more and more concise, it eventually becomes:
var myVar = $("<p>");
This is the right kind of question to be asking while you learn, so good for you! That being said, one SO post won’t be able to completely answer it, at least in the way that I think you're asking it, but I (we) will give you what I can.
To begin, the way that JavaScript interacts with HTML is through the Document Object Model (DOM). This is like taking an entire HTML document and cutting it up into the individual elements, tags, attributes, etc., and then constructing a representation of that document in "plain" JavaScript as a (very large) Object. The variable name assigned to this Object is document. This special Object has all sorts of magical properties and methods (functions) that can be used to read and update any piece of the DOM (which ultimately translates into the HTML you see in your browser).
What I've described so far has nothing to do with jQuery, and all of that manipulation can be done with plain JavaScript (like Jack Bashford's answer, for example). However, due to the way that browsers and other web technologies have evolved over the years, many "gotchas" exist (or used to exist) when it comes to doing any of this stuff in "plain" JavaScript. jQuery is an incredibly important tool, historically speaking, because it provided a "standard" way to write very direct code to do all of this DOM reading or manipulation, and the jQuery library would make sure that all of the "gotchas" were avoided.
So, what is jQuery (in code, that is)? Well, there could be many technical answers to that, and one important technical answer is that it is an Object, because in JavaScript, (almost) EVERYTHING is an Object. However, let's focus on the question at hand, and the code you provided:
$("<p>");
Here, the dollar sign IS jQuery (or a variable pointing to the jQuery Object). The parentheses that follow indicate that the jQuery Object is being called as a function. It is like saying, in code, "do the jQuery thing with this string of characters: '<p>'." Taking a step back, the full statement
var myVar = $("<p>");
is saying "this variable 'myVar' is now pointing to the results of whatever doing the jQuery thing with '<p>' will give us."
The "magical" thing about writing in jQuery is that the syntax almost always feels the same (and gives it an intuitive feel).
Grab the jQuery Object. This is usually the variable $, but jQuery will also work.
Call the function ($()). There are cases where you don't, like ajax requests, but that's a separate topic and use case.
Supply it with any kind of selector ($('#myDiv')), which is a way of referring to specific HTML elements based on their properties and location in the document (here we are looking up a specific element based on it's id).
Work with the result ($('#myDiv').html(...etc))
I'll point out at this point that the jQuery documentation should be handy so you know what you're getting as a result of any specific function call, but in almost all cases, this function will return another jQuery Object that holds references to whatever elements you selected or manipulated during that function call.
In the latter example, we will receive a reference to the #myDiv element, on which we then call another function (.html()) that will either read or update the contents of that html element.
In the case of the line you specifically asked about, the syntax used to "select" a 'p' tag will be interpreted by jQuery not to look up all 'p' elements in the document (that syntax would be $("p")), but rather to create a single new 'p' element and store it in memory as a jQuery Object that points to this newly created element. Read more about that syntax and its possibilities here.
Well, I hope that was helpful. I sure enjoyed writing it, and even learned a few things along the way myself.
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.
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.
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
Following up on my question about jQuery.get() I was wondering if there is a list of DOM properties and methods that aren't available in jQuery that can only be accessible if you were working with the raw DOM object (i.e. $("#someID").get().scrollHeight; )
I haven't encountered a list but if one existed it would probably be quite lengthy. In addition to browser-specific (proprietary) properties there's a bunch of other less useful properties and methods not currently abstracted by jQuery. But then, I don't really see this as a problem, or even a valid point of discussion because jQuery IS JavaScript; if you need access to something beyond what jQuery provides then you can use get() or access a specified element within one of your "jQuery collections" like an array:
jQuery(elem)[0].someDOMProperty;
Plus jQuery provides absolutely no support for non-element nodes within the DOM. If, for whatever reason, you need direct access to comment nodes, text nodes etc. then you'll need to use the "raw" DOM.
I don't know of a compiled list of DOM operations/properties that are NOT available in jQuery (and a quick google search didn't turn anything up), but if you go to http://api.jquery.com/ you can see the entire API, and even download it as an Adobe AIR app in case you don't have internet when you need it.
No. JQuery is just JavaScript. If you can do it in JavaScript, you can do it in jQuery. Some properties and methods are overwritten in the context of a jQuery object and that's where you would want to us the get() method--to 'get' (i.e. access) the standard property/method.
That's really as complicated as it is.
Every attribute of every element is accessible through the attr() function. If you could do a document.getElementById() on that element and then access a property, you can also do it using the attr() function. However, some properties are accessed more easily in other ways when using jquery. For example, to see if an element is hidden or visible, you could do:
var isVisible=$("#el").is(":visible");
instead of using the attr() method. Similarly, you can find the selectedIndex of dropdowns and the text of the selected option, in easier ways than using the attr() method. This pdf outlines some of these easier approaches.
To access a css property, you are better off doing:
var fontWeight=$("#el").css("fontWeight");
rather than using get() or attr(). You can also set the css properties in this way, e.g:
$("#el").css("fontWeight","bold");
I could be wrong, but I think you can access any properties via the attr method.