21

If I assign a handler to the OnClick event of an element twice, the handler will be executed twice. But I want to change this so even if I assign it twice, the handler will only execute one time.

Nonsensical example to demonstrate issue:

$('.button').click(
    function(){
       alert('here');
});
$('.button').click(
    function(){
       alert('here');
});

So I've added the handler twice. Now when I click an element with that class, I'd get two alert boxes.

The question is, how do I restrict it so I would only get one alert box?

msigman
  • 4,474
  • 2
  • 20
  • 32
  • 1
    Why would you need to add the event twice? – root Apr 02 '12 at 02:53
  • 1
    There is a function executed on this page every time there is a postback, in order to add the handler to dynamically created elements. However any element which previously existed now has the handler twice... – msigman Apr 02 '12 at 02:54
  • 3
    I think you need to rethink your approach to avoid binding twice, but if you're in a crunch, I suppose you could use `$('.button').off('click').on('click', function(){...});` like here: http://jsfiddle.net/SsRxv/ – hyperslug Apr 02 '12 at 03:10

8 Answers8

27

If .one() is in fact what you're after (removing the event handler after it has been triggered once) then I believe that's the correct answer. If not, you can unbind the event before binding it:

var myEventHandler = function () {alert('hello')};
$('a').unbind('click', myEventHandler);
$('a').bind('click', myEventHandler);

Should work.

Edit: since this reply keeps getting up votes, I'll add another (better in most cases) solution that will work at least in the OP's case. When dealing with dynamically added content simply use jQuery's on() on a parent element instead of applying the event handler directly on the element.

http://api.jquery.com/on/

powerbuoy
  • 12,460
  • 7
  • 48
  • 78
6

You can also remove any existing click events in the function with function off('click'):

$('.button').off('click').click(function() {
    ...
});
Justin Ipson
  • 481
  • 9
  • 6
5

a little trick that can help:

jQuery(".button:not(.clickadded)").click(function(){

     alert('here');

).addClass("clickadded");
Miquel
  • 59
  • 1
  • 2
5

To have the events triggered only once, bind them only once. When dynamically adding elements, bind the event handler to the parent element using on():

See this jsfiddle:

<div id="container">
 <p>Paragraph #1</p>
</div>

<div>
 <button id="add">Add Elements</button>
</div>

<script type="text/javascript">
 var n = 1;
 $('#add').click(function() {
   $('#container').append('<p>Paragraph #' + ++n + '</p>');
 });
 $('#container').on('click', 'P', function() {
   alert($(this).text());
 });
</script>

Note how the event handlers are registered with on() only once. The code that dynamically adds elements does not register the event handlers.

leepowers
  • 37,828
  • 23
  • 98
  • 129
4

Use one. http://api.jquery.com/one/

$( ".button" ).one( 'click', function(){
    alert( '....' )
});
Larry Battle
  • 9,008
  • 4
  • 41
  • 55
1

Here is a method I'm using, similar to Miquel's method in some ways.

$.prototype.once = function() {
    var ret = this.not(function() {
        return this.once;
    });
    this.each(function(id, el) {
        el.once = true;
    });
    return ret;
};

Use it like this,

$('#footer')
    .once()
    .click(function(){
        console.log('click the footer');
    });

Once also supports a parameter so you can have different types

areve
  • 518
  • 4
  • 4
0

I solved it by a flag, I know it is not the best by just an idea

if (!alreadyBound) {
     $('.button').bind('click', submitEvtHandler);
     alreadyBound = true;
}
Muhammad Hewedy
  • 29,102
  • 44
  • 127
  • 219
-1

I think there is no point to add function twice. However if you have to then you can do add return false to one of the function.

$('.button').click(
    function(){
       return false;
       alert('here');
});
$('.button').click(
    function(){
       alert('here');
});​
Dips
  • 3,220
  • 3
  • 20
  • 21