55

I'm sure there are a million posts about this out there, but surprisingly I'm having trouble finding something.

I have a simple script where I want to set the onClick handler for an <A> link on initialization of the page.

When I run this I immediately get a 'foo' alert box where I expected to only get an alert when I click on the link.

What stupid thing am I doing wrong? (I've tried click= and onClick=)...

<script language="javascript">

    function init(){

        document.getElementById("foo").click = new function() { alert('foo'); };
    }

</script>

<body onload="init()">
    <a id="foo" href=#>Click to run foo</a>
</body>

Edit: I changed my accepted answer to a jQuery answer. The answer by 'Már Örlygsson' is technically the correct answer to my original question (click should be onclick and new should be removed) but I strongly discourage anyone from using 'document.getElementById(...) directly in their code - and to use jQuery instead.

Community
  • 1
  • 1
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • 26
    why strongly discourage? It's pure isn't it? – tetris11 Jan 04 '13 at 18:53
  • 14
    I strongly discourage anyone from using jQuery for such a simple task as doing `document.getElementById(...)`... – DividedByZero Jul 21 '15 at 18:45
  • 1
    Strange decision indeed, I arrived here looking for a JS solution, not jQ... – brasofilo Jun 09 '19 at 16:19
  • @brasofilo it’s perfectly fine if you’re already using jquery, which 10 years ago a lot more people were. The jquery syntax is just a lot nicer to look at too so when I was already using it I would always favour jquery syntax. – Simon_Weaver Jun 09 '19 at 17:25
  • That's not the point. The question indicates one thing, your choice of answer goes on the opposite direction. Anyway, most answers really tackle the issue you posted, so, it's all good at the end, I guess :) – brasofilo Jun 10 '19 at 14:02
  • @brasofilo oh sorry I missed your point completely somehow that you meant the decision on my answer. Yes I agree! – Simon_Weaver Jun 10 '19 at 16:25
  • Yeah, the community agrees too, lol. Should've been more verbose on my 1st comment... – brasofilo Jun 10 '19 at 23:16

11 Answers11

73

Try:

document.getElementById("foo").onclick = function (){alert('foo');};
nickf
  • 537,072
  • 198
  • 649
  • 721
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 3
    I didn't realize that new would call the function on page init. Good to know. – discorax Oct 30 '08 at 04:54
  • @discorax neither did i. in fact not until just now! a year later – Simon_Weaver Dec 05 '09 at 19:58
  • 3
    i definitely would not use any getElementbyId stuff anymore. come a LONG way in my javascript experience in the past year. definitely recommend jQuery - or some other such framework. getElementById is just out of date now. see @darryl's answer below – Simon_Weaver Dec 05 '09 at 20:00
  • 15
    Since when is knowing pure javascript out of date. – KingOfHypocrites May 24 '14 at 17:36
  • I'm a complete newcomer to JS, but I learned the jQuery selection way first and then the getElementById. While I do like the 'queriness', I think it may be overkill and a little less readable. Of course, most of it is just preference anyway :) – Script Kitty Jun 06 '16 at 00:55
37

Use .onclick (all lowercase). Like so:

document.getElementById("foo").onclick = function () {
  alert('foo'); // do your stuff
  return false; // <-- to suppress the default link behaviour
};

Actually, you'll probably find yourself way better off using some good library (I recommend jQuery for several reasons) to get you up and running, and writing clean javascript.

Cross-browser (in)compatibilities are a right hell to deal with for anyone - let alone someone who's just starting.

Már Örlygsson
  • 14,176
  • 3
  • 42
  • 53
23

jQuery:

$('#foo').click(function() { alert('foo'); });

Or if you don't want it to follow the link href:

$('#foo').click(function() { alert('foo'); return false; });
Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
  • should be wrapped in $(function() { ... }; so that it runs (and looks in the dom for 'foo' only after the DOM is complete) – Simon_Weaver Dec 05 '09 at 20:01
  • 4
    This DOES NOT Chante the link only but call it. $('#foo').onclick= is the good way to do it. – Patrick Desjardins Dec 05 '09 at 20:06
  • 3
    You should use preventDefault() to stop the link's default action rather than return false because return false also stops propagation as well (when used as above in jQuery.) $('#foo').click(function(e) { e.preventDefault(); alert('foo'); }); [More Info](http://stackoverflow.com/questions/1357118/javascript-event-preventdefault-vs-return-false) – LocalPCGuy Jun 23 '11 at 14:54
  • 2
    Be sure to first do $('#foo').unbind() if you don't want multiple events stacking up if your doing this a lot. – Ally Jul 05 '12 at 13:51
  • How about `event.preventDefault()` instead of `return false;` – Ouadie Mar 25 '13 at 09:55
  • @PatrickDesjardins Could you please explain what do you mean in your comment? – Piotr Dobrogost Apr 11 '14 at 14:11
  • This does not replace an existing action on the click event, it only adds to it. To replace the existing action use the solution provided by CMS. document.getElementById("foo").onclick = function (){alert('foo');}; – Vincent Dec 16 '14 at 19:31
13

I tried more or less all of the other solutions the other day, but none of them worked for me until I tried this one:

var submitButton = document.getElementById('submitButton');
submitButton.setAttribute('onclick',  'alert("hello");');

As far as I can tell, it works perfectly.

Nic
  • 6,211
  • 10
  • 46
  • 69
Selin Ebeci
  • 131
  • 1
  • 2
11

If you want to pass variables from the current function, another way to do this is, for example:

document.getElementById("space1").onclick = new Function("lrgWithInfo('"+myVar+"')");

If you don't need to pass information from this function, it's just:

document.getElementById("space1").onclick = new Function("lrgWithInfo('13')");
yuttadhammo
  • 5,069
  • 6
  • 34
  • 45
  • 1
    Not sure why you were downvoted. Your first example is a good way to pass a variable when you don't want a closure. – mhenry1384 Feb 13 '12 at 18:08
  • This worked nicely for me in 2021 - I am trying to change an onclick with a function + a var passed from AJAX and couldn't get this to work at all.. Probably not the most ideal solution but for what I need does the trick – orgg Mar 06 '21 at 13:20
5

OMG... It's not only a problem of "jQuery Library" and "getElementById".

Sure, jQuery helps us to put cross-browser problems aside, but using the traditional way without libraries can still work well, if you really understand JavaScript ENOUGH!!!

Both @Már Örlygsson and @Darryl Hein gave you good ALTARNATIVES(I'd say, they're just altarnatives, not anwsers), where the former used the traditional way, and the latter jQuery way. But do you really know the answer to your problem? What is wrong with your code?

First, .click is a jQuery way. If you want to use traditional way, use .onclick instead. Or I recommend you concentrating on learning to use jQuery only, in case of confusing. jQuery is a good tool to use without knowing DOM enough.

The second problem, also the critical one, new function(){} is a very bad syntax, or say it is a wrong syntax.

No matter whether you want to go with jQuery or without it, you need to clarify it.

There are 3 basic ways declaring function:

function name () {code}

... = function() {code} // known as anonymous function or function literal

... = new Function("code") // Function Object

Note that javascript is case-sensitive, so new function() is not a standard syntax of javascript. Browsers may misunderstand the meaning.

Thus your code can be modified using the second way as

 = function(){alert();}

Or using the third way as

 = new Function("alert();");

Elaborating on it, the second way works almost the same as the third way, and the second way is very common, while the third is rare. Both of your best answers use the second way.

However, the third way can do something that the second can't do, because of "runtime" and "compile time". I just hope you know new Function() can be useful sometimes. One day you meet problems using function(){}, don't forget new Function().

To understand more, you are recommended read << JavaScript: The Definitive Guide, 6th Edition >>, O'Reilly.

Eric
  • 121
  • 2
  • 2
  • `document.getElementById("foo").onclick = function() { alert('foo'); };` // based on answer by Eric, only one line of code needs to change. here's the whole thing: `Click to run foo` – Jonathan Apr 11 '16 at 14:17
2

I agree that using jQuery is the best option. You should also avoid using body's onload function and use jQuery's ready function instead. As for the event listeners, they should be functions that take one argument:

document.getElementById("foo").onclick = function (event){alert('foo');};

or in jQuery:

$('#foo').click(function(event) { alert('foo'); }
kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
1

Here is the YUI counterpart to the jQuery posts above.

<script>
  YAHOO.util.Event.onDOMReady(function() {   
    document.getElementById("foo").onclick =  function (){alert('foo');};
  });
</script>
blak3r
  • 16,066
  • 16
  • 78
  • 98
0

I think you want to use jQuery's .bind and .unBind methods. In my testing, changing the click event using .click and .onclick actually called the newly assigned event, resulting in a never-ending loop.

For example, if the events you are toggling between are hide() and unHide(), and clicking one switches the click event to the other, you would end up in a continuous loop. A better way would be to do this:

$(element).unbind().bind( 'click' , function(){ alert('!') } ); 
lamarant
  • 3,243
  • 2
  • 25
  • 30
0

Nobody addressed the actual problem which was happening, to explain why the alert was issued.

This code: document.getElementById("foo").click = new function() { alert('foo'); }; assigns the click property of the #foo element to an empty object. The anonymous function in here is meant to initialize the object. I like to think of this type of function as a constructor. You put the alert in there, so it gets called because the function gets called immediately.

See this question.

Community
  • 1
  • 1
Steven Lu
  • 41,389
  • 58
  • 210
  • 364
0

The YUI example above should really be:

<script>
  YAHOO.util.Event.onDOMReady(function() {   
     Dom.get("foo").onclick =  function (){alert('foo');};
  });
</script>