The variables username
and password
do not retain their original value (as defined in the script tag) or are not accessible from the onclick event, however making a function call that outputs the variables does. It seems as though the variables are being redefined inside that scope because they are not undefined even if I don't define them.
It appears to be due to the variables being named username
and password
, as shown in the code sample below (usr
and passwd
work as expected.)
There is reason to believe this behaviour has been introduced into recent versions of the browser as older Firefox doesn't exhibit it.
Here is a reproducible code sample (tested in Google Chrome 32 / Firefox 26 - however some users are reporting that it does not work for them):
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var username = "Administrator";
var password = "AdminPass";
var usr = "Jordan";
var passwd = "JordanPass";
function printCredentials() {
$("#out").append("username is: " + username + "<br/>");
$("#out").append("password is: " + password + "<br/>");
$("#out").append("usr is: " + usr + "<br/>");
$("#out").append("passwd is: " + passwd + "<br/>");
}
</script>
</head>
<body>
<a href="#" onclick="printCredentials()">This works</a><br/>
<a href="#" onclick="$('#out').append('username is: ' + username + '<br/>'); $('#out').append('password is: ' + password + '<br/>'); $('#out').append('usr is: ' + usr + '<br/>'); $('#out').append('passwd is: ' + passwd + '<br/>');">But this doesn't (properly)</a><br/>
<div id="out" style="background: yellow"></div>
</body>
</html>
JSFiddle demo
Using jQuery is optional, the same happens with regular JS.
Clicking the second link prints out usr
and passwd
as expected but username
and password
are blank. Curiously, it works as expected (all fields printed) in Internet Explorer.
What is going on here?
On submit javascript posts the username and password to a php script on the server which returns 'true' or 'false'. When the authentication returns true the app changes the html5 page and stores the username and password in html5 local storage.
An event handler is a JavaScript function that runs when an event fires. An event listener attaches responsiveness to a given element, which allows the element to wait or “listen” for the given event to fire. Events can be assigned to elements via inline event handlers, event handler properties & event listeners.
You can register event handlers for either phase, bubbling or capturing, by using the function addEventListener(type, listener, useCapture) . If useCapture is set to false , the event handler is in the bubbling phase. Otherwise it's in the capture phase. The order of the phases of the event depends on the browser.
Here's a break down why you can't see username
and password
attribute
First of all, <a>
tag is capable of parsing the url
in href
attribute and make the parsed values into its own property.
NOTE URL syntax <protocol>://<user>:<password>@<host>:<port>/<url-path>
var a = document.createElement('a');
a.setAttribute('href', 'http://john:[email protected]');
// Do you get the idea now?
a.username // prints "john"
a.password // prints "doe"
That's it, your inline onclick
is being executed against a
's scope which already has both username
and password
property defined (with "" values)
+----------------+
| window.username| <-- your "Administrator"
| |
| +------------+ |
| | a.username | | <-- empty by default ""
| +------------+ |
+----------------+
EDIT: In case you would like to see the Chrome's source code where it defines username/password interface & implementation
Interface: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/dom/DOMURLUtils.h&l=47&rcl=1391416355
Implementation: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/dom/DOMURLUtils.cpp&l=48&rcl=1391416355
Explanation: When I answer this question I assumed that everyone already knows about this
keyword in onclick
event and Scope
in javascript, but looks like it's not clear enough (my bad).
This line "is being executed against <a>'s scope"
means that,
onclick="alert(username)" === onclick="alert(this.username)"
That is, you can think of anything in onclick
is an anonymous function which is bound to <a>
tag so
onclick = function() {
log(this); // 1. bound to `<a>` not `window`
log(username); // 2. implies `this.username` unless you explicitly declare 'var username`
}
How Javascript scope works is, if it can't find that variable (username
) in local scope, it will look at the outer scope for it window.username
.
Hope that should make it more clearer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With