87

I have seen the following methods of putting JavaScript code in an <a> tag:

function DoSomething() { ... return false; }
  1. <a href="javascript:;" onClick="return DoSomething();">link</a>
  2. <a href="javascript:DoSomething();">link</a>
  3. <a href="javascript:void(0);" onClick="return DoSomething();">link</a>
  4. <a href="#" onClick="return DoSomething();">link</a>

I understand the idea of trying to put a valid URL instead of just JavaScript code, just in case the user doesn't have JavaScript enabled. But for the purpose of this discussion, I need to assume JavaScript is enabled (they can't login without it).

I personally like option 2 as it allows you to see what's going to be run–especially useful when debuging where there are parameters being passed to the function. I have used it quite a bit and haven't found browser issues.

I have read that people recommend 4, because it gives the user a real link to follow, but really, # isn't "real". It will go absolutely no where.

Is there one that isn't support or is really bad, when you know the user has JavaScript enabled?

Related question: Href for JavaScript links: “#” or “javascript:void(0)”?.

Community
  • 1
  • 1
Darryl Hein
  • 142,451
  • 95
  • 218
  • 261

7 Answers7

69

I quite enjoy Matt Kruse's Javascript Best Practices article. In it, he states that using the href section to execute JavaScript code is a bad idea. Even though you have stated that your users must have JavaScript enabled, there's no reason you can't have a simple HTML page that all your JavaScript links can point to for their href section in the event that someone happens to turn off JavaScript after logging in. I would highly encourage you to still allow this fallback mechanism. Something like this will adhere to "best practices" and accomplish your goal:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
fcdt
  • 2,371
  • 5
  • 14
  • 26
cowgod
  • 8,626
  • 5
  • 40
  • 57
  • 4
    as the href value will be shown to user in the status bar? (the bar at the bottom) I would consider using a bit more user friendly link eg. "js.html?doSomething" the page can still be static html. This way the user will clearly see a difference between links. – Gene Oct 29 '08 at 07:51
  • 7
    You can override this value with the title attribute, e.g. go – Conspicuous Compiler Jan 25 '10 at 13:56
  • It should be best practice to log the requests to the javascript_required.html page and log the function that caused the error. – Timo Huovinen May 16 '12 at 17:05
  • 2
    Have you thought about the consequences for SEO? – DanielBlazquez Sep 14 '12 at 17:43
  • Matt Kruse's [javascripttoolbox.com](http://javascripttoolbox.com/) appears to be offline and for sale. – showdev Aug 27 '20 at 21:50
10

Why would you do this when you can use addEventListener/attachEvent? If there is no href-equivalent, don't use an <a>, use a <button> and style it accordingly.

eyelidlessness
  • 62,413
  • 11
  • 90
  • 94
  • 10
    using a button instead of a link isn't a feasible option in many cases. – nickf Oct 29 '08 at 05:26
  • 2
    Because it looks ugly. You can add an icon beside the link. They are hard to format the same across browsers. And generally, people are moving to links instead of buttons--look at most of stack over flow. – Darryl Hein Oct 29 '08 at 05:44
  • 2
    It looks ugly? It looks like whatever you want it to look like. In fact, I think buttons actually have more style flexibility than links, in that they're inline but can properly take padding across browsers. Anything that can be done with a link can be done with a button, with regards to CSS. – eyelidlessness Oct 29 '08 at 07:11
  • why button? Why not use a span. The css will be simpler (shorter) than with buttons. – Gene Oct 29 '08 at 07:46
  • 3
    Span can't be keyboard-focused. – bobince Oct 29 '08 at 09:41
  • 3
    And button is (gasp) semantically correct. Span is semantically meaningless. A button is *exactly* what the author intends to use, semantically. – eyelidlessness Oct 29 '08 at 17:09
  • @JKirchartz, I answered the question. The correct answer is to use `addEventListener` (and `attachEvent` for backwards compatibility). Edit: I see you didn't vote down the accepted answer, which says much the same thing. – eyelidlessness Feb 14 '12 at 16:49
  • @YuriKolovsky, HTML5 corrects this to allow any "form element" (``, ` – eyelidlessness Mar 15 '12 at 16:01
  • @eyelidlessness thank you, didn't know that, now the ` – Timo Huovinen Mar 16 '12 at 09:10
  • 1
    @TimoHuovinen, I did not realize until now that you had edited my answer. Unfortunately you edited it with examples that were **expressly discouraged in my answer**. I rolled back to the previous state. In the future, please use care to respect the spirit of other people's posts when editing. – eyelidlessness Jun 01 '14 at 05:34
  • @eyelidlessness yes, I see that now, I remember at that point that I was trying to follow your point, must have been dead sleepy or something. – Timo Huovinen Jun 01 '14 at 06:43
5

You forgot another method:

5: <a href="#" id="myLink">Link</a>

With the JavaScript code:

document.getElementById('myLink').onclick = function() {
    // Do stuff.
};

I can't comment on which of the options has the best support or which is semantically the best, but I'll just say that I much prefer this style because it separates your content from your JavaScript code. It keeps all the JavaScript code together, which is much easier to maintain (especially if you are applying this to many links), and you can even put it in an external file which can then be packed to reduce filesize and cached by client browsers.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 7
    If you have 20 or 30 different links with JS this can get quite tedious and end up with a lot of JS. – Darryl Hein Oct 29 '08 at 05:45
  • it's no more tedious than wading through HTML to change javascript. ...or you could use something like jQuery which can easily change the events on multiple elements at once... $('#menu a').click(function() { .. }) – nickf Oct 30 '08 at 00:24
  • 1
    @JKirchartz I don't see how it's preaching if there's reasons behind the answer. If you read the question, it really is a "which of these 4 is best", and I just pointed out that there's another option he had not considered. – nickf Feb 17 '12 at 16:54
  • Don't care, trololo, when choosing between A B C and D, one does not choose E. – JKirchartz Feb 17 '12 at 21:34
  • 3
    @JKirchartz Yeah, I don't think you really get the purpose of Stack Overflow then. If someone asks "Which is better to build a web app in: Cobol or Fortran?" It's acceptable to tell that person that they haven't considered all the possibilities. The question clearly isn't asking "which out of **only these four things** is the best". – nickf Feb 18 '12 at 00:25
  • @nickf "I understand the idea of trying to put a valid URL instead of just JavaScript code, just in case the user doesn't have JavaScript enabled. But for the purpose of this discussion, I need to assume JavaScript is enabled (they can't login without it)." & "Is there one that isn't support or is really bad, when you know the user has JavaScript enabled?" he already knows and is asking which of these 4 is best. – JKirchartz Feb 20 '12 at 13:56
  • furthermore, I do not see how anybody can question the validity of an opinion, especially on the internet. If @nickf wants to complain about a blemish to his rep, fine, but I don't see why I should care. – JKirchartz Feb 21 '12 at 16:04
3
<a href="#" onClick="DoSomething(); return false;">link</a>

I will do this, or:

<a href="#" id = "Link">link</a>
(document.getElementById("Link")).onclick = function() {
    DoSomething();
    return false;
};

Depending on the situation. For larger apps, the second one is best because then it consolidates your event code.

Anik Islam Abhi
  • 25,137
  • 8
  • 58
  • 80
  • If you have 20 or 30 different links with JS this can get quite tedious and end up with a lot of JS. – Darryl Hein Oct 29 '08 at 05:46
  • and bugs which creep into your code can be VERY hard to debug. These bugs appear very easily, as evidenced by your first example. :) – nickf Oct 29 '08 at 07:22
1

One difference I've noticed between this:

<a class="actor" href="javascript:act1()">Click me</a>

and this:

<a class="actor" onclick="act1();">Click me</a>

is that if in either case you have:

<script>$('.actor').click(act2);</script>

then for the first example, act2 will run before act1 and in the second example, it will be the other way around.

JoelFan
  • 37,465
  • 35
  • 132
  • 205
1

Modern browsers only

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }
    doc.addEventListener('click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault();
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Cross-browser

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var cb_addEventListener = function(obj, evt, fnc) {
        // W3C model
        if (obj.addEventListener) {
            obj.addEventListener(evt, fnc, false);
            return true;
        } 
        // Microsoft model
        else if (obj.attachEvent) {
            return obj.attachEvent('on' + evt, fnc);
        }
        // Browser don't support W3C or MSFT model, go on with traditional
        else {
            evt = 'on'+evt;
            if(typeof obj[evt] === 'function'){
                // Object already has a function on traditional
                // Let's wrap it with our own function inside another function
                fnc = (function(f1,f2){
                    return function(){
                        f1.apply(this,arguments);
                        f2.apply(this,arguments);
                    }
                })(obj[evt], fnc);
            }
            obj[evt] = fnc;
            return true;
        }
        return false;
    };
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }

    cb_addEventListener(doc, 'click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault ? e.preventDefault() : e.returnValue = false;
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

You can run this before the document is ready, clicking the buttons will work because we attach the event to the document.

Sources:

Community
  • 1
  • 1
Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
1

Method #2 has a syntax error in FF3 and IE7. I prefer methods #1 and #3, because #4 dirty the URI with '#' although causes less typing... Obviously, as noted by other responses, the best solution is separate html from event handling.

Pier Luigi
  • 7,871
  • 9
  • 36
  • 46