This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Do you ever need to specify javascript: in an onclick?
To execute JavaScript on a DOM event, you could use something like this:
<div onclick="alert('Alert');">Alert</div>
Something like this seems to work as well:
<div onclick="javascript: alert('Alert');">Alert</div>
However, I've heard that the second example is "bad" and that the first example should be used over the second.
Is this bad? If so, why is this bad? What is the difference between alert('Alert') and javascript: alert('Alert')?
What about using it in <a> tags (if it is any different)?
Alert
Edit: To clarify, I am asking about the javascript: part specifically, and not how I have inline JavaScript mixed in with my markup. Sorry about the confusion.
Oh the wonderful confusing world of JavaScript. The code you posted probably doesn't do what most programmers think it's doing.
There is a difference between each of the following lines:
<a onclick="alert('Hello World!')"...>example</a> //V1
<a href="javascript: alert('Hello World!')"...>example</a> //V2
<a onclick="javascript: alert('Hello World')"...>example</a> //V3
although they all will alert Hello World!.
The first (V1) has an inline click event bound via the [onclick] attribute. It may also contain an [href] attribute that navigates to another location after the [onclick] attribute has executed, or any number of other click events bound in the code, assuming the default behavior hasn't been prevented.
The second (V2) has an executable javascript: url set as the [href] attribute. It might also contain an [onclick] attribute or other click events bound in external scripts.
The first and second examples (V1 & V2) have identical code executed, which is:
alert('Hello World!')
The third example (V3) has an inline click event bound via the [onclick] attribute, just like V1, however the code being executed is different. The executed code is:
javascript: alert('Hello World')
Although it looks like a javascript: url, it's actually just using a label in javascript.
Labels in JavaScript are useful for skipping out of nested loops, as in the following example code:
label: for (i = 0; i < 5; i++) { //labeled line
for (j = 0; j < 5; j++) {
console.log(i, j);
if (i === 2 && j === 3) {
break label; //this jumps out of both for loops
}
}
}
In most inline JavaScript, it's misused because the author doesn't understand the difference between the three formats.
Why is using javascript: <code> bad?
That's a leading question. It assumes that using javascript: <code> is bad.
javascript: <code> isn't bad. It's a tool. Tools aren't inherently good or bad, only the people using the tools are. You wouldn't call a hammer "bad", even if someone used it as a weapon.
javascript: <code> has some nice uses. You shouldn't use it for most cases because it's the wrong tool for the job, however if you're writing a bookmarklet, you'd be required to use the javascript: <code> format.
Additionally, there are a few niche contexts where it could make sense to leave javascript inline. An example of this would be to add a simple print button to the page:
Print
Although even this example could be easily replaced by a class and externalizing the javascript:
Print
<script>
//jQuery used for brevity
$(document).on('click', '.print', function () {
window.print();
return false;
});
</script>
There's no real problem with using the javascript: labels. It's just considered bad style most of the time.
an onclick-handler already is JavaScript, so repeating that is just senseless, redundant information (in fact, it's chaging the code thats executed by adding a label named javascript - but in most cases this shouldn't have any effect).
JavaScript code in a href attribute would be placed more appropriately in an onclick handler, so you can use the href to provide a link for users that have JavaScript disabled. This is called Progressive Enhancement.
For more detailed information, you may want to take a look at this great blog-post about "The useless javascript: pseudo-protocol"
Related
Newer to javascript and trying to learn why this works, searching Google has led to no answers (although I maybe searching using the incorrect terms).
I'm am making a call to a function during an onclick event within an <a></a>. I was able to get the function finally working (with a suggestion from a coworker) by adding in 'javascript:' before making the function. Without the javascript: portion in the onclick, my function was not being called upon.
It now works but I don't understand what that is doing, the other programmer who suggested putting it in the call also isn't sure what exactly it does.
Here is a simplified version of the code used:
#1 .jspf higher up which includes page #2 to display it's contents
function createTagging(1, 2) {
cmCreateElementTag(1 + ", " + 2,"TagName");
}
HTML in .jspf file #2 further down website makes the call to function in file #1
<a id="CatEntry" href="https://aurl"
onclick="javascript: createTagging('parameter1', 'parameter2');"
title="atitle" aria-label="alabel">
<img id="ThumbNailImage_59244" src="https://image.jpg"
alt="" border="0"/>
</a>
-Troy
Why do I need 'javascript:' in the call to my javascript function?
You don't. It's an onclick handler. You use the javascript: pseudo-protocol where a URL is expected (for instance, if you'd used href instead of onclick). onclick expects JavaScript code.
In fact, it only works because JavaScript has labelled statements, and javascript: is a valid label. It's completely ignored.
Without the javascript: portion in the onclick, my function was not being called upon.
With respect, that must have been observational error. Again, in an onclick handler, it makes no difference whether you have javascript: in front of it or not. If it wasn't working, and then it was working, you changed something else at the same time you added javascript:.
onclick attribute is always calling javascript in HTML.
onclick="createTagging('parameter1', 'parameter2');"
It is only necessary if you use not an event, but href. There you need to add the protocoll as well for Javascript.
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 2 years ago.
First off I want to say I am quite new to JavaScript, but not entirely new to programming. I am familiar with python and just finished last semester at my college taking c++ and got an A. Now this semester I am taking JavaScript. I feel a bit silly asking this question because it seems quite stupid to me, but please be nice to me... Anyway, the very first part of my assignment is to write a function to count the hyperlinks on a webpage which the teacher provides. There should be 20. So, the teacher provides 2 lines of code to create an array of links and then console.log them. I copied and pasted them exactly as the teacher has them on the assignment page. The two lines are:
var myLinks = document.getElementsByTagName("a");
console.log("Links", myLinks.length);
Firstly, I typed these two lines directly into the console on chrome with the provided website open, the output is 20. Correct! So I happily copied and pasted the two lines into the linked JavaScript file and reload the page and it produces 0. I don't understand why... I hope this is not a silly question, but coming from c++ last semester, this really seems like a silly problem to me... Thank you for any help!
update: That was the whole JavaScript file. And I am only 3 weeks into the semester and still feel like this is all a bit over my head... Anyway, yes the script tag needed to be at the end of the body tag I guess. I did not realize it mattered... I apologize for the silly question... But thank you all, I appreciate the help.
<script>
function getAnchorLinkCount() {
var myLinks = document.getElementsByTagName("a");
console.log("Links", myLinks.length);
}
</script>
then
<body onload="getAnchorLinkCount()">
You suppose to get count when your DOM entirely loaded
Most likely, the function executed before the html was completely loaded. To avoid such problems, always wrap your JS in a ready handler. With JQuery, use:
$(document).ready(function(){
// your code here
});
For a pure JS equivalent, have a look at this thread.
The problem is, it's likely (we can't see all of your code) that the javascript is executing before DOM has finished loading.
Consider:
<script>
var myLinks = document.getElementsByTagName("a");
alert("Links" + myLinks.length);
</script>
<body>
foo
bar
</body>
Output: Links0
vs:
<body>
foo
bar
</body>
<script>
var myLinks = document.getElementsByTagName("a");
alert("Links" + myLinks.length);
</script>
Output: Links2
To avoid this issue there's a few suggestions:
Put javascript code after the <body> tag, not in the head.
Use something like jQuery's $(document).ready(...)
Put the javascript in the head, but call the onload method in the body tag <body onload = "myInitFunction()">
If you are dealing with DOM which is programming interface for HTML. You must wait for DOM structure to load so that it can be accessed in JavaScript
Use DOMContentLoaded, The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed.
Another solution could be including your script right before closing body tag which will be executed when all the DOM is loaded and parsed.
Try this:
document.addEventListener("DOMContentLoaded", function(event) {
var myLinks = document.getElementsByTagName("a");
console.log("Links", myLinks.length);
});
Note: As per the docs, A very different event - load - should be used only to detect a fully-loaded page. It is an incredibly popular mistake to use load where DOMContentLoaded would be much more appropriate, so be cautious.
There is no problem with the code that you have written but the problem can be when you are executing it.
First you need to wait until DOM is ready then you can call the js methods. That is why it is document.... which mean from the DOM tree get my element.
There can multiple ways to execute once DOM is ready
window.load
DOMContentLoaded
Put your script just before closing body tag. This ensure that your entire DOM is ready.
If your are using jquery you can use $(document).ready(function(){})
Below is a snippet where the all js codes are at the bottom of the page.
<body>
Link 1
Link 2
Link 3
Link 4
Link 5
Link 6
<script>
// Will give a Collection of a tags
var getListTagName = document.getElementsByTagName('a');
console.log('document.getElementsByTagName ',getListTagName.length);
// Does same but but document.querySelectorAll is preferred to match a css selector
var getListQuery = document.querySelectorAll('a');
console.log('document.querySelectorAll ',getList.length)
</script>
</body>
Hope this post will be helpful for you.
I know this is bad practice. Don't write code like this if at all possible.
Of course, we'll always find ourselves in situations where a clever snippet of inline Javascript can address an issue quickly.
I am pursuing this query in the interest of fully understanding what happens (and the potential pitfalls) when something like this is written:
Click Me
As far as I can tell this is functionally the same as
<script type="text/javascript">
$(function(){ // I use jQuery in this example
document.getElementById('click_me').onclick =
function () { alert('Hi'); };
});
</script>
Click Me
Extrapolating from this it seems that the string assigned to attribute onclick is inserted within an anonymous function which is assigned to the element's click handler. Is this actually the case?
Because I'm starting to do things like this:
Display my next sibling <!-- Return false in handler so as not to scroll to top of page! -->
Which works. But I don't know how much of a hack this is. It looks suspicious because there is no apparent function that is being returned from!
You might ask, why are you doing this, Steve? Inline JS is bad practice!
Well to be quite honest I'm tired of editing three different sections of code just to modify one section of a page, especially when I'm just prototyping something to see if it will work at all. It is so much easier and sometimes even makes sense for the code specifically related to this HTML element to be defined right within the element: When I decide 2 minutes later that this was a terrible, terrible idea I can nuke the entire div (or whatever) and I don't have a bunch of mysterious JS and CSS cruft hanging around in the rest of the page, slowing down rendering ever so slightly. This is similar to the concept of locality of reference but instead of cache misses we're looking at bugs and code bloat.
You've got it nearly correct, but you haven't accounted for the this value supplied to the inline code.
Click Me
is actually closer to:
Click Me
<script type="text/javascript">
document.getElementById('click_me').addEventListener("click", function(event) {
(function(event) {
alert(this);
}).call(document.getElementById('click_me'), event);
});
</script>
Inline event handlers set this equal to the target of the event.
You can also use anonymous function in inline script
Click Me
What the browser does when you've got
<a onclick="alert('Hi');" ... >
is to set the actual value of "onclick" to something effectively like:
new Function("event", "alert('Hi');");
That is, it creates a function that expects an "event" parameter. (Well, IE doesn't; it's more like a plain simple anonymous function.)
There seems to be a lot of bad practice being thrown around Event Handler Attributes. Bad practice is not knowing and using available features where it is most appropriate. The Event Attributes are fully W3C Documented standards and there is nothing bad practice about them. It's no different than placing inline styles, which is also W3C Documented and can be useful in times. Whether you place it wrapped in script tags or not, it's gonna be interpreted the same way.
https://www.w3.org/TR/html5/webappapis.html#event-handler-idl-attributes
The best way to answer your question is to see it in action.
<a id="test" onclick="alert('test')"> test </a>
In the js
var test = document.getElementById('test');
console.log( test.onclick );
As you see in the console, if you're using chrome it prints an anonymous function with the event object passed in, although it's a little different in IE.
function onclick(event) {
alert('test')
}
I agree with some of your points about inline event handlers. Yes they are easy to write, but i don't agree with your point about having to change code in multiple places, if you structure your code well, you shouldn't need to do this.
It looks suspicious because there is no apparent function that is being returned from!
It is an anonymous function that has been attached to the click event of the object.
why are you doing this, Steve?
Why on earth are you doi.....Ah nevermind, as you've mentioned, it really is widely adopted bad practice :)
Try this in the console:
var div = document.createElement('div');
div.setAttribute('onclick', 'alert(event)');
div.onclick
In Chrome, it shows this:
function onclick(event) {
alert(event)
}
...and the non-standard name property of div.onclick is "onclick".
So, whether or not this is anonymous depends your definition of "anonymous." Compare with something like var foo = new Function(), where foo.name is an empty string, and foo.toString() will produce something like
function anonymous() {
}
using javascript:
here input element is used
<input type="text" id="fname" onkeyup="javascript:console.log(window.event.key)">
if you want to use multiline code use curly braces after javascript:
<input type="text" id="fname" onkeyup="javascript:{ console.log(window.event.key); alert('hello'); }">
can you write javascript that produces/writes/etc. functioning javascript?
for example, have a link that has a function tied to it that when clicked produces a functioning javascipt snippet? The snippet could deal with a completely other elements.
For example
Link #1(has the javascript function that produces javascript) Link #2(does absolutely nothing for now)
Click on link #1(produces javascript snipped that says "when link #2 is clicked document.write('hello')"
Clicking on link #2 now produces "hello" whereas it previously did nothing. Is that possible?
Yes, you can dynamically assign event handlers described in text.
However, dynamic code generation is far more difficult than it sounds unless you're just following basic patters and replacing certain variables. Writing programs that write programs has long been a fascination of the computer industry, and this gave way to functional programming, which can be done in javascript.
Create the input/delete keys on the onClick handler for the datepicker, you can attach date information (or other data) when the input(s) are created. Now, you should look into $.delegate() for how to bind handlers to those inputs created. $.delegate can bind handlers to elements that are not created yet, so when they are created they will fire a handler. By storing date relevant information in the inputs via $.data() or data- attributes you will have context aware handlers for dealing with things.
If I understand your question correctly, you could do what you want with the code below.
Not sure why you'd want to do this, though.
can you write javascript that produces/writes/etc. functioning javascript?
You can do this the way I did it, or by using eval -- though, as many coders have pointed out, eval is evil!
<html>
<head>
<script type="text/javascript">
function initLinks(){
document.getElementById("link1").addEventListener("click", function(){
document.getElementById("link2").addEventListener("click", function(){
document.write("hello");
}, false);
}, false);
}
</script>
</head>
<body onload="initLinks()">
<a id="link1">Link 1</a>
<a id="link2">Link 2</a>
</body>
</html>
I never seen this before but you can invoke the HREF attribute of a link using javascript if the HREF contains javascript:;//code......;
On my example below click on both links. they do the same thing even though they have different javascript in the HREF.
for example:
<script type="text/javascript">
function clickme()
{
var link = document.getElementById("clickme");
eval(link.href);
}
</script>
<a id="clickme" href="javascript:alert('hello');">I will alert hello</a>
<br />
click me
I tested this on IE8, Firefox 3.6.8, Safari 5.0.1, and Chrome 6.0.472.55. Is this standardized, so I will not have to worry about this feature being deprecated in the future?
You don't have to worry about it being deprecated in the future. It's a bad idea now.
What's really happening there is this: There's a link using the javascript: protocol, which is respected by browsers. It means that everything following the javascript: is JavaScript and should be executed by the JS interpreter.
When you retrieve the link's href, you receive it as a string, e.g. "javascript:clickme()". You can use eval on strings to execute JavaScript. Now, you'd think that would fail (because of the javascript: protocol thing at the front), but it doesn't, because JavaScript has labels and that looks like a label when you treat it as JavaScript code.
So it works, but it's a bad idea. It's also disallowed (because of the eval) in the new "strict" mode of the latest version of JavaScript, ECMAScript 5th edition.
In general, when we think we need to use eval for something, it indicates that there's a problem with our code and that some refactoring is in order. The exceptions to that rule are very edgey edge cases that most of us will never run into. In this case, rather than having the href attribute contain the code that we want to execute, it should just use the code we want to execute. Your example, for instance, has a clickMe function as the only thing being used. Rather than evaling it, we should just call that function directly.
It won't be deprecated but I don't see the use of it.
If you do want to stream line this more do:
<script type="text/javascript">
function clickme()
{
clicked();
}
function clicked()
{
alert("hello");
}
</script>
<a id="clickme" href="javascript:clicked();">I will alert hello</a>
<br />
click me
Or better yet do:
Click Me
Or even better:
<span onclick="clicked();" class="MakeMeLookLIkeLInk">Click Me</a>
Anchor controls are mainly used for navigation, and as a good practice to keep it that way. if you have functionality that needs to take place, use a span/div with an onclick. You can use a button as well.
I think your question is whether the line
eval(link.href);
is valid.
The answer to that is yes, it is. There's no reason you can't evaluate code that's stored in some property, the same way you could evaluate the contents of an input box.
That said, this looks like a VERY bad way to code things. If you're not careful, you could end up in a circular loop. Additionally, code like this will be very hard to maintain.