Johny
Johny

Reputation: 359

How to make event click event fire only once when element is clicked multiple times

I have a link that the user clicks on to delete a record (class="delMail"). When they click this link, a new div shows up with 2 more links [Y and N]. clicking on Y will delete their email, clicking on N will cancel the request.

The problem is that if the user clicks 10 times on the delMail link prior to clicking on either Y/N, the code will try to delete the email 10 times also?

I've updated my code to my working version, here it is:

$(function(){ //delete Message
    $("a.delMail").click(function(e) {
        e.preventDefault();
        //get divs to show and hide
        var $confirmDelDiv = $(this).parents("tr").next().find(".confirmDelete");
        var $replyDiv = $(this).parents("tr").next().next().find(".replyDiv");

            $replyDiv.fadeOut(); //hide reply div
            $confirmDelDiv.fadeIn("slow"); //show confirm message

            //get id
            var $id = $(this).attr("href"); //get id value of email
            var dataString = "id="+$id;

            $("a.delLinkYes").click(function(y){//if user confirms delete, send id to php page
                y.preventDefault(); $(this).unbind("click");
                    $.ajax({
                            type: "POST",
                            url:  "process.php",
                            action: "deleteEmail",
                            data:  dataString,
                            dataType: "JSON",
                            cache: false,
                            success: function(data){
                                if(data == "true"){//if email was successfully deleted
                                    $confirmDelDiv.delay(60).append("Email deleted!");
                                    $confirmDelDiv.fadeOut("slow");
                                }else{$confirmDelDiv.delay(60).append("Error deleting this email. Please try again!"); return false;}
                            }
                    });
                    return false;
                });

            $("a.delLinkNo").click(function(n){//if user cancels request, stop.
                $(this).unbind("click");alert("cancel"); return false; 
                //$confirmDelDiv.fadeOut("slow"); return false;
            });
    });
});

Is this ok? I mean efficiency wise?

Upvotes: 2

Views: 2006

Answers (3)

Zack The Human
Zack The Human

Reputation: 8481

I would look into using jQuery.fn.one() rather than jQuery.fn.click() for this. From the documentation it shows that you can:

Attach a handler to an event for the elements. The handler is executed at most once per element.

So it should be as simple as replacing:

$("a.delMail").click(function(e) ...

With:

$("a.delMail").one('click', function(e) ...

Upvotes: 2

leepowers
leepowers

Reputation: 38298

As Kranu noted this is just how click handling works in jQuery - though it's not specific to jQuery, but the JavaScript onclick event that fires.

There's several possible workarounds. Use unbind (scroll down to the section "Using the Event Object") to remove the click handler when the delete button is pressed for that element. You will need to re-bind the click handler whenever the user selects 'no'.

Another option would be to keep a global lookup object such as window.pendingDeletes = {} (keyed by message_id) to track when a delete has been triggered, but not confirmed, and have the click handler return false whenever an message has a pending yes/no decision about a delete.

Upvotes: 0

Kranu
Kranu

Reputation: 2567

That's how jQuery functions. You should unbind and rebind the click event handler to stop users from spamming the results. Here is the basic structure:

$(function() {
  var delHandler=function(e) {
    e.preventDefault();

    //Ignore additional clicks until otherwise stated
    $('a.delMail').unbind('click');

    //Do your stuff
    $.ajax({
      //...
      success:function(data) {
        //...
        //Start listening to user clicks again
        $('a.delMail').bind(delHandler);
      }
    });

    $("a.delLinkNo").click(function(n){
      alert("cancel");
      //Start listening to user clicks again
      $('a.delMail').bind(delHandler);                
      return false;
    });
  }
});

I hope the code example makes sense to you. I omitted several parts to try to make it more clear of what I added. Basically, you stop jQuery from caring if the user clicks the button up until it is done processing the second Y/N box.

Upvotes: 1

Related Questions