This question already has answers here:
Do DOM tree elements with IDs become global properties?
(5 answers)
Closed 9 years ago.
i have the following index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript">
</script>
<script type="text/javascript">
jQuery(document).ready(function($) {
console.log(foo); // jQuery assumes foo is an id?
});
</script>
</head>
<body>
<div id="foo">i'm a div</div>
</body>
</html>
the console outputs:
<div id="foo">i'm a div</div>
why?
This has got nothing to do with jQuery.
This is because named elements(elements with an ID or name attribute) become properties of the window object.
console.log(foo) is identical to console.log(window.foo);
Since your div is a named element(id="foo"), it is added to window.
Named access on window
It's not a jQuery behavior, it's (originally) an Internet Explorer behavior. IE has always created global variables for each DOM element that has an id attribute. The variable is named after the id and references the DOM element. Lately, other browsers have been following suit.
http://www.west-wind.com/weblog/posts/2009/Mar/22/Internet-Explorer-Global-Variable-Blow-ups
http://blogs.msdn.com/b/alvar/archive/2009/10/22/internet-explorer-creates-global-variables-for-each-object-in-the-dom.aspx
http://www.shanison.com/2010/06/17/ie-id-and-javascript-global-variable/
http://www.2ality.com/2012/08/ids-are-global.html
JQuery doesn't assume that, but rather JavaScript does. Your foo is unquoted, so it must either be an identifier or undefined. The element with id foo happens to be in the scope of your script, so the element identified by it is logged.
If you renamed it to bar, then you'd be able to reference bar as it'd be a top-level id.
Note that such usage is frowned upon because it is unclear what you're doing in the code without referencing the html. Using document.getElementById(...) or a variant thereof is generally preferred because it is clear what you're doing.
Related
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 3 years ago.
I'm trying to use function closure in my javascript as follows:
In my html file:
<head>
<script src="myscript.js"></script>
</head>
<body>
<section id="mysectionId"></section>
</body>
In myscript.js:
(function() {
var id = document.getElementById('mysectionId');
console.log(id);
}());
However, id seems to equal null. I'm not sure what I've done wrong - does function closure scope exclude globals like 'document'? If so, how come I can still use 'console.log()' inside the function closure?
You're javascript is running before your html loads. Put your script tag after your html content at the very bottom of the body
<head>
// put css here
</head>
<body>
<section id="mysection"></section>
<script src="myscript.js"></script>
</body>
This question already has answers here:
JS function named `animate` doesn't work in Chrome, but works in IE
(3 answers)
Closed 6 years ago.
In my HTML I define the lang function in the script tag and add the "Test Fire!" button which has to call lang on click:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Functions</title>
<script type="text/javascript">
function lang() {
alert("Hello, World! It's JavaScript this time");
}
</script>
</head>
<body>
<form action="">
<input type="button" value="Test Fire!" onclick="lang();">
</form>
</body>
</html>
However, if I click the button I get this error:
Uncaught TypeError: lang is not a function
But if I change the function name from lang to anything else this code works fine.
Consider this code:
<input type="button" value="Debugger Test" onclick="debugger;" />
<input type="button" value="Prototype Test" onclick="console.log(__proto__);" />
When you click on “Debugger Test” and open your debugger, you’ll see that there seems to be an implicit with scope wrapped around the onclick, making all the <input>’s properties accessible without needing to refer to the button.
Clicking on “Prototype Test” logs the prototype of the current scope. You’ll see that it’s the HTMLInputElement’s prototype, making all the scopable properties of this entire prototype chain available to the scope.
Interestingly, the scopable part of the prototype chain of the current HTMLDocument is included as well.
All this means that all global attributes (lang is one of them) and several others specific to buttons are overridden. E.g. value, type also wouldn’t work. Similarly, variables like createElement (from document) also wouldn’t work, but the unscopable append (from ParentNode.prototype) would.
All this is also explained in this answer to a related question about global variables clashing with window properties.
Your best bet is to use the standard way of adding event listeners: addEventListener.
<input type="button" value="Test" />
<script>
function lang() {
alert("Hello, World! It’s not an HTML event handler attribute this time");
}
document.querySelector("input").addEventListener("click", lang);
</script>
There is no reason to complicate (I really do not know why it does not work), but you can use:
Add the alert directly in the input.
Result: https://jsfiddle.net/cmedina/h4m1qcoq/6/
or
Add listener to input
function lang() {
alert("Hello, World! It's JavaScript this time");
}
document.getElementById('test').onclick = lang
Result: https://jsfiddle.net/cmedina/h4m1qcoq/7/
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 6 years ago.
I don't understand why simple code is not working is my browser.
<head>
<script src="../static/js/jquery-1.12.3.min.js" ></script>
<script src="../static/js/jquery-ui.min.js"></script>
<link href="../static/js/jquery-ui.min.css" rel="stylesheet"/>
<script>
$("#totalCart").html("99,75");
</script>
</head>
<body>
<div id="totalCart">Total </div>
</body>
when I start this code in Chrome I see nothing, why?
You're using a selection before DOM is loaded.
The good practice is to include all script at the end of your body.
Or you can use
$(document).ready(function(){
//your code
});
Try putting
<script>
$("#totalCart").html("99,75");
</script>
just before
</body>
Explanation:
For jQuery to grab an element via $("#totalCart") - and, likewise, for non-library javascript to grab an element via document.getElementById('totalCart') - that element has to first exist.
In your original structure, the script runs as soon as it is parsed - but this happens before the element is parsed... effectively, at the moment the script runs, the element does not yet exist.
By the time the element is parsed and does exist, the script has already run and it is not invoked a second time.
If you place the <script> at the very end of the document (just before <body>) then all elements will already have been parsed by the browser rendering engine and they will exist.
This question already has answers here:
JS function named `animate` doesn't work in Chrome, but works in IE
(3 answers)
Closed 6 years ago.
In my HTML I define the lang function in the script tag and add the "Test Fire!" button which has to call lang on click:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Testing Functions</title>
<script type="text/javascript">
function lang() {
alert("Hello, World! It's JavaScript this time");
}
</script>
</head>
<body>
<form action="">
<input type="button" value="Test Fire!" onclick="lang();">
</form>
</body>
</html>
However, if I click the button I get this error:
Uncaught TypeError: lang is not a function
But if I change the function name from lang to anything else this code works fine.
Consider this code:
<input type="button" value="Debugger Test" onclick="debugger;" />
<input type="button" value="Prototype Test" onclick="console.log(__proto__);" />
When you click on “Debugger Test” and open your debugger, you’ll see that there seems to be an implicit with scope wrapped around the onclick, making all the <input>’s properties accessible without needing to refer to the button.
Clicking on “Prototype Test” logs the prototype of the current scope. You’ll see that it’s the HTMLInputElement’s prototype, making all the scopable properties of this entire prototype chain available to the scope.
Interestingly, the scopable part of the prototype chain of the current HTMLDocument is included as well.
All this means that all global attributes (lang is one of them) and several others specific to buttons are overridden. E.g. value, type also wouldn’t work. Similarly, variables like createElement (from document) also wouldn’t work, but the unscopable append (from ParentNode.prototype) would.
All this is also explained in this answer to a related question about global variables clashing with window properties.
Your best bet is to use the standard way of adding event listeners: addEventListener.
<input type="button" value="Test" />
<script>
function lang() {
alert("Hello, World! It’s not an HTML event handler attribute this time");
}
document.querySelector("input").addEventListener("click", lang);
</script>
There is no reason to complicate (I really do not know why it does not work), but you can use:
Add the alert directly in the input.
Result: https://jsfiddle.net/cmedina/h4m1qcoq/6/
or
Add listener to input
function lang() {
alert("Hello, World! It's JavaScript this time");
}
document.getElementById('test').onclick = lang
Result: https://jsfiddle.net/cmedina/h4m1qcoq/7/
I know there are a few answers to this question.
Usually the answers given online involve doing this...
document.getElementById (<%=myElementID.ClientID %>);
rather than this...
document.getElementById("myElementID");
However, even when I do it the first way, my JavaScript code still cannot find the element. It tells me the element is undefined.
So...just for testing...I tried to strip out all my JavaScript code and access the element with an alert box like this...
<script type="text/javascript">
alert(document.getElementById('<%=searchHyperLink.ClientID %>').value);
</script>
It still tells me its undefined.
But its not freaking undefined! When I view the page source, the id rendered by <%=searchHyperLink.ClientID %> exactly matches the id of the control I want to find.
Any suggestions?
To expand on Evan's comment, if you're doing the document.getElementById in a script tag that's before the element in the ordering of the document, it will return undefined. Try this instead:
<html>
<head>
<script>
function postLoadFn() {
alert(document.getElementById('<%=searchHyperLink.ClientID %>').innerHTML);
}
</script>
</head>
<body onload="postLoadFn();">
<!-- Your markup here -->
</body>
</html>
I've used parent to access a higher level in my project asp.net masterpage(home.master).
Instead of:
document.getElementById (<%=myElementID.ClientID %>);
Use:
parent.window.document.getElementById (<%=myElementID.ClientID %>);