3

Using jQuery's .one event handler to do a setup on the first click and something else on the next/subsequent clicks, is it possible to do write this more elegantly:

$('#start').one('click', function(){
    alert('one');

    // could also be .on for subsequent clicks
    $(this).one('click', function(){
        alert('two');    
    });

});

Example fiddle

Update: I was hoping that there was a jQuery pattern to using .one like this self-defining function, but reading the source for .one() it's just an extension of .on()

PHearst
  • 751
  • 6
  • 29
  • 2
    You might consider http://codereview.stackexchange.com for optimization of working code. – James Montagne Apr 11 '13 at 13:58
  • Perhaps you mean this deprecated function which you can reinstate http://stackoverflow.com/questions/14301935/where-has-fn-toggle-handlereventobject-handlereventobject-gone – mplungjan Apr 11 '13 at 14:00
  • 1
    @JamesMontagne Thanks for that, I wasn't really even aware of the code review site though I wonder how much of SO belongs there. – lucuma Apr 11 '13 at 14:03
  • @lucuma It's still in beta and obviously doesn't have the audience SO has, but if people don't know about it, it never will. – James Montagne Apr 11 '13 at 14:07
  • Yeah, thanks for the link to codereview – PHearst Apr 11 '13 at 19:44

3 Answers3

1
var clickIndex = 0;
$('#start').on('click', function(){
    alert(++clickIndex);
});

you could put a switch statement or an if block in here to run different code depending on how many times the user has clicked. If the .one listener unbinding is key for you, simply use .off when clickIndex indicates you are done with the binding.

Fresheyeball
  • 29,567
  • 20
  • 102
  • 164
  • True, but I was wondering if there was a jQuery logic attached to the .one method. If not, the method almost seems pointless ( you could just use .on() and then off() instead of .one() ) – PHearst Apr 11 '13 at 18:57
  • `.one` is literally just a shorthand for `.on` and `.off` – Fresheyeball Apr 11 '13 at 19:21
  • It does have a point, but very limited point. Personally, it a shorthand I suspect most people rarely use. – Fresheyeball Apr 11 '13 at 19:22
  • The function that I wrote above could also be reworked to be a recursive function with `.one` but it would just be harder to read and kinda pointless compared with whats there now. – Fresheyeball Apr 11 '13 at 19:23
  • Read my update. If nothing else comes along, this is clearly the best, simple solution. Was hoping that .one() was meant to be used for other purposes other than the obvious (!). – PHearst Apr 11 '13 at 19:47
0

I think in this case you could just use a data property or class and use the click event:

$('#start').on('click', function(){
    if (!$(this).data('clicked')) {
      alert('one');
      $(this).data('clicked', 'true');
    }
    else  {
      alert('more than one');
    }
});

or with a class:

$('#start').on('click', function(){
    if (!$(this).hasClass('clicked')) {
      alert('one');
      $(this).addClass('clicked');
    }
    else  {
      alert('more than one');
    }
});
lucuma
  • 18,247
  • 4
  • 66
  • 91
  • Why `jQuery.data`? A local variable is so much simpler. – Bergi Apr 11 '13 at 14:33
  • It really just depends on what the OP wants. On many projects that have rich interfaces there would be some kind of styling based on this condition and the class solution is generally what I'd use. A local variable works but may not be ideal in all cases either. – lucuma Apr 11 '13 at 14:38
  • @mplungjan it is matter of opinion and probably would be implementation Dependant as to what is simpler. Eliminating a call to jquery in a simplistic example is one thing but combining something in the framework of a web app it might not be simple to track a lot of local variables. – lucuma Apr 11 '13 at 15:53
0

Maybe like this:

$('#start').on('click', function(){
    var click = $(this).data('clicked')?$(this).data('clicked'):1;
    alert(click);
    if(click === 2)
        $(this).off('click')
    else $(this).data('clicked',++click);    
});
A. Wolff
  • 74,033
  • 9
  • 94
  • 155