49

How is this done?

IAdapter
  • 62,595
  • 73
  • 179
  • 242
Daddy Warbox
  • 4,500
  • 9
  • 41
  • 56

5 Answers5

80

This is a good question, and I actually don't think it can be done easily. (Some discussion on this)

If it is super duper important for you to have this functionality, you could hack it like so:

function singleClick(e) {
    // do something, "this" will be the DOM element
}

function doubleClick(e) {
    // do something, "this" will be the DOM element
}

$(selector).click(function(e) {
    var that = this;
    setTimeout(function() {
        var dblclick = parseInt($(that).data('double'), 10);
        if (dblclick > 0) {
            $(that).data('double', dblclick-1);
        } else {
            singleClick.call(that, e);
        }
    }, 300);
}).dblclick(function(e) {
    $(this).data('double', 2);
    doubleClick.call(this, e);
});

And here is an example of it at work.

As pointed out in the comments, there is a plugin for this that does what I did above pretty much, but packages it up for you so you don't have to see the ugly: FixClick.

Xavi López
  • 27,550
  • 11
  • 97
  • 161
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • Well it appears to work, but it has the distinct problem of not detecting regular clicks for .5 seconds. I could shorten the time, of course, but... oh well. I'll figure this out then myself. Thanks anyway. – Daddy Warbox Jul 01 '09 at 06:11
  • Yeah, I'm thinking 250 or even less is probably reasonable to expect as far as double clicks go. I've been doing some serious googling on this and apparently this is the best you're gonna get. I could make a plugin out of it to hide the ugly away if it makes you feel better. :) – Paolo Bergantino Jul 01 '09 at 06:12
  • Interesting, hadn't tried this yet and indeed looks like a hackish way to do it. But from an event -point-of-view it makes sense that the click-event gets called twice – jitter Jul 01 '09 at 06:14
  • 1
    Actually, couldn't I simply block subsequent single click events during the double-click duration? I think that'd solve the delay problem. – Daddy Warbox Jul 01 '09 at 06:17
  • 5
    Btw there already seems to be a plugin for this http://plugins.jquery.com/project/FixClick which solves it similar to Paolo Bergantino – jitter Jul 01 '09 at 06:20
  • Nice find, jitter. Looking at the source code they are doing essentially what I am doing, but they went for a 300ms default timer. That sounds reasonable. – Paolo Bergantino Jul 01 '09 at 06:39
  • For what it's worth, here is the source for another plugin which does this (mentioned one of the other answers) which uses custom/special events: http://bit.ly/diBCkI – balupton Jul 18 '10 at 19:28
  • I know that this might be too late but it seems that using .on('click') instead click() doesn't work – developarvin Jul 09 '12 at 08:17
  • 2
    The jQuery plugins site is down but this neat jQuery extension in GitHub is linked to from the comments section on jQuery site https://gist.github.com/399624 – Martin Belcher - AtWrk Nov 22 '12 at 12:46
  • https://gist.github.com/ncr/399624/#comment-5911 - Spent a day to fix the issue in IE. Thanks Martin! – Babu Dec 26 '13 at 09:26
35

Raymond Chen has discussed some of the implications of single-versus-double clicking - although he's talking in the context of Windows, what he says is relevant to browser-based UI design.

Basically, the action taken on a double click should be a logical thing to do after a single click. So for example, in a desktop UI, single click selects an item, and double click opens it (e.g. opens the file, or launches the application). The user would have to select the file to open it anyway, so it doesn't matter that the single click action is taken before the double click action.

If you have a UI component whose double click action is completely unrelated to the single click action, such that it becomes necessary to prevent the single click action from occurring once the system realises it was actually a double click, then you really ought to rethink your design. Users will find it awkward and counter-intuitive, in that it will not act in the way they are used to things acting.

If you still want to go that way, then you will either have to use the debouncing technique (in which case all single click actions will be delayed) or else implement some mechanism whereby the double click handler undoes the work done by the single click handler.

You should also be aware that some users set a very long double click time. Somebody with, for example, arthritic hands might have a double click time of more than a second set in their system preferences, so the debouncing technique based on some arbitrary time period of your choosing is going to make your UI component inaccessible to those people if taking the single click action precludes taking the double click action. The "undo what just happened on single click" technique is the only viable workaround for this, as far as I know.

NickFitz
  • 34,537
  • 8
  • 43
  • 40
  • good point about users being able to set their own double click time ... i don't want to wait a full second before i execute the single click action, so waiting for the double click with a timeout is practical useless – Hrqls Mar 25 '13 at 07:44
  • sometimes the double click action is a logical follow up after a single click, and it might be ok to execute the single click action before as well (that's how i have it right now), but the single click action might cause some extra load (or, in my case, data traffic) which you would like to prevent (although it wouldn't hurt exactly) – Hrqls Mar 25 '13 at 07:46
8

The technique outlined in the other answers is known as debouncing.

Walter Rumsby
  • 7,435
  • 5
  • 41
  • 36
1

jQuery Sparkle provides a clean elegant solution for this, by implementing a singleclick custom event. By doing this, you can use it just like any other event, so:

$('#el').singleclick(function(){});
// or event
$('#el').bind('singleclick', function(){});

It also provides custom events for the last and first clicks of a series of clicks. And the lastclick custom event actually passes the amount of clicks back! So you could do this!

$('#el').lastclick(function(event,clicks){
    if ( clicks === 3 ) alert('Tripple Click!');
});

You can find the source code for defining the custom event here.

It's open source under the AGPL licence, so you can feel free to grab what you need out of it worry free! :-) It's also actively developed on a day to day basis so you will never be short on support.

But most importantly it is a DRY Plugin/Effect Framework to allow you to develop plugins and extensions much more easily. So hope this helps to achieve that goal!

Chris Frederick
  • 5,482
  • 3
  • 36
  • 44
balupton
  • 47,113
  • 32
  • 131
  • 182
0

If this is for a button submitting a form (which is not necessarily the case for the original poster, but may be the case for other people getting here via Google), an easier option would be to disable the element that is being clicked on in your click event handler:

$(selector).click(function(e) {
    $(this).prop('disable', true);
}
Katie Kilian
  • 6,815
  • 5
  • 41
  • 64