views:

186

answers:

7

Hi guys,
When I want some link to not do anything but only respond to javascript actions what's the best way to avoid the link scrolling to the top edge of the page ?
I know several ways of doing it, they all seem to work fine :

<a href="javascript:void(0)">Hello</a>

or

<a id="hello" href="#">Hello</a>
<script type="text/javascript>
  $(document).ready(function() {
    $("#toto").click(function(){
      //...
      return false;
    });
  });
</script>

and even :

<a id="hello" href="#">Hello</a>
<script type="text/javascript>
  $(document).ready(function() {
    $("#toto").click(function(event){
      event.preventDefault();          
      //...
    });
  });
</script>

Do you have any preference ? why ? in which conditions ?

PS: of course the above examples assume you're using jquery but there's equivalents for mootools or prototype.

A: 

Dreamweaver uses a nice little trick by default that I've started using.

<a href='javascript:;'></a>

It's small, it doesn't trip and anchors and it's library agnostic.

Whit
I think this is the same example as my first one. The browser is waiting for an url and in both case the expression will be evaluated to null or undefined (null == undefined).
Mike
@Mike: It actually evaluates to `undefined` in both cases. `null` is a valid JavaScript value and is not the same as `undefined`.
casablanca
+3  A: 

The only advantage that I can think of to using javascript:void(0) is that it will be supported even by the oldest browsers. That said, I would use one of the other unobtrusive approaches you have mentioned:

  • For most uses, event.preventDefault() and return false can be used interchangeably.
  • event.preventDefault() will prevent the page from reloading, as desired, but will allow the click event to bubble up to the parent. If you want to stop the bubbling, you can use it in conjunction with event.stopPropagation.
  • return false will additionally stop the event from bubbling up to the parent.

I say 'interchangeably' in the first point above because much of the time we do not care whether or not an event bubbles up to the parent(s). However, when do we need some fine-tuning, we should consider points two and three.

Consider the following example:

<div>Here is some text <a href="www.google.com">Click!</a></div>​

$("a").click(function(e) {
    e.preventDefault();
});

$("div").click(function() {
    $(this).css("border", "1px solid red");
});
​

Clicking on the anchor will prevent the default action of the event from being triggered, so the browser will not redirect to www.google.com. However, the event will still 'bubble up' and cause the div's click event to fire, which will add a border around it. Add e.stopPropagation() or just return false and the div's click event will not fire. You can mess with it here: http://jsfiddle.net/cMKsN/1/

karim79
Out of interest: is calling `event.precentdefault()` at the top of your handler effective if an exception occurs after that in your handler code?
sje397
@sje397 Yeah, if you have `event.preventDefault(); someFunction();` and something breaks with someFunction(), the default event is still stopped.
Robert
A: 

I tend to prefer using return false, as that gives the option to give the user a choice whether to continue that action, such as shown here, in quirksmode:

http://www.quirksmode.org/js/events_early.html#default

It's simple, it's old, but it works well, cross-browser, regardless of the version of javascript.

James Black
+1  A: 

event.preventDefault() and return false; are one thing - they instruct the browser not to process the default action for the event (in this case, navigating to the href of the anchor tag that was clicked). href=javascript: and its ilk are something else - they're causing the default action to be 'do nothing'.

It's a question of style. Do you want to do all your work in the onclick, or do you want to be able to put actions in both the onclick and the href and rely on the capabilities of the browser to modulate between the two?

DDaviesBrackett
A: 

I'd rather not put JavaScript into the href because that's not what it's meant for. I prefer something like

<a href="#" onclick="return handler();">Link</a>
casablanca
+1  A: 

I like using href="javascript:void(0)" in the link as # implies jumping to the top of the page and that may in fact happen if for some reason your jQuery event does not load e.g. jQuery fails to load.

I also use event.preventDefault(); as it will not follow the link even if an error is encountered before return false; for example:

HTML:

<a id="link" href="http://www.google.com"&gt;Test&lt;/a&gt;

jQuery Example 1:

$("#link").click(
    function(){
        alert("Hi");
        invalidCode();
        return false;
    }
);

jQuery Example 2:

$("#link").click(
    function(event){
        event.preventDefault();
        alert("Hi");
        invalidCode();
        return false;
    }
);

Since invalidCode(); will throw an error return false is never reached and if jQuery Example 1 is used the user will be redirected to Google whereas in jQuery Example 2 he will not.

Adam
+15  A: 

Binding:

  • javascript: URLs are a horror to be avoided at all times;
  • inline event handler attributes aren't brilliant either, but OK for a bit of rapid development/testing;
  • binding from script, leaving the markup clean, is typically considered a best practice. jQuery encourages this, but there is no reason you can't do it in any library or plain JS.

Responses:

  • return false means both preventDefault and stopPropagation, so the meaning is different if you care about parent elements receiving the event notification;
  • jQuery is hiding it here but preventDefault/stopPropagation have to be spelled differently in IE usually (returnValue/cancelBubble).

However:

  • You have a link that isn't a link. It doesn't link anywhere; it's an action. <a> isn't really the ideal markup for this. It'll go wrong if someone tries to middle-click it, or add it to bookmarks, or any of the other affordances a link has.
  • For cases where it really does point to something, like when it opens/closes another element on the page, set the link to point to #thatelementsid and use unobtrusive scripting to grab the element ID from the link name. You can also sniff the location.hash on document load to open that element, so the link becomes useful in other contexts.
  • Otherwise, for something that is purely an action, it would be best to mark it up like one: <input type="button"> or <button type="button">. You can style it with CSS to look like a link instead of a button if want.
  • However there are some aspects of the button styling you can't quite get rid of in IE and Firefox. It's usually not significant, but if you really need absolute visual control a compromise is to use a <span> instead. You can add a tabindex property to make it keyboard-accessible in most browsers although this isn't really properly standardised. You can also detect keypresses like Space or Enter on it to activate. This is kind of unsatisfactory, but still quite popular (SO, for one, does it like this).
  • Another possibility is <input type="image">. This has the accessibility advantages of the button with full visual control, but only for pure image buttons.
bobince
+1 but I disagree with "inline event handler attributes aren't brilliant either". Unless you need multiple handlers, tag attributes such as `onclick` are by far the simplest and cleanest way of attaching an event handler to an element.
casablanca
@bobince Thanks for the complete reply. I never really think of it this way ... but it now looks clear to me it shouldn't be a link. I'll try the above techniques input/span and see what fits better.@casablanca I don't really agree, I wrote the first example but I never actually use it. The same way I hate seeing css in my html I really think javascript code should always be unobtrusive and remain to external files.
Mike
I totally agree with "inline event handler attributes aren't brilliant either". They may be simple for quick prototyping but when you have to add that 2nd handler you quickly become inconsistent in how you attach handlers, and inconsistency leads to errors. The link should work on its own, as bobince states, and enhancing it to perform fancy feats should be part of the *controller*, which should be kept separate from the *model* and *view*
Stephen P
Stephen P - totally agree, except with the implication that MVC is 'the right thing' :) It's just one way of organising things (admitedly popular), and has it's down sides like everything else.
sje397
If you're never going to need more than one listener function for a particular event and element and know your own mind then there's nothing wrong with event handler attributes. In fact, they have the advantage over every other method of event binding of working immediately, without having to wait for other script to load and do the binding.
Tim Down