thank_you
thank_you

Reputation: 11107

One() not working with AJAX?

I have three div boxes on my pageIn each div box there is a delete button I press that removes the div box from the code. An ajax request in that same event sends an unique number based on which div box was pressed to the server. In order to prevent multiple click events to be called on the delete button, I used the one() event. But in rare events where I click the button quickly it will fire the event twice and I see that the database received duplicate numbers. I thought one() prevents that from happening. What could be wrong with my jquery code to cause it to fire twice? My code is below.

Sample button from HTML

<input id="delete_post_3" type="button" value="X">

jQuery Code

$('#delete_post_1').one('click', function() {
    var session_user_id = <? php echo $session_user_id; ?> ;
    var number = 1;
    $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: number
    }, function() {
        $('#post_1').remove();
    });
});

$('#delete_post_2').one('click', function() {
    var session_user_id = <? php echo $session_user_id; ?> ;
    var number = 2;
    $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: number
    }, function() {
        $('#post_2').remove();
    });
});

$('#delete_post_3').one('click', function() {
    var session_user_id = <? php echo $session_user_id; ?> ;
    var number = 3;
    $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: number
    }, function() {
        $('#post_3').remove();
    });
});

Update: Per request, I'm going to give a brief explanation on my code for the entire page.

<script>

//when document is ready, loads jquery code that allows any div boxes that currently   
//exist on the page to have a click event that will delete the box. this is the same 
//code seen above in my example.

</script>

<form>
//form to fill out info
</form>

<script>
//ajax post sent when form button clicked
$.post('ajax_file.php', {data: data}, function(data){

//in here div box is created

<script>

//duplicated jquery code from top of page. without it the div box delete button does 
//not work

</script>

});

</script>

Upvotes: 9

Views: 1341

Answers (9)

Dean L
Dean L

Reputation: 1240

I know your question was about finding out why your one() wasn't working. But it looks like, over the course of discussion, we've all determined that you've ended up creating multiple one() declarations. We also now know that you'll get one execute for each one() you declare and that is undesired for your situation. While that finding technically answers your question, I believe your problem isn't solved. I was thinking that maybe your approach to your problem could be modified and ended up making this JS fiddle:

http://jsfiddle.net/sEvAn/45/

The gist of my suggestion:

  1. Bind your click event to the OUTER div wrapper ("#post_list" in my example). This allows you to always detect delete button clicks, even if a post was newly created/added to your DOM via an ajax call.
  2. Include a custom data-postid attribute on each of your buttons to make it easy to determine which post ID you need to delete.
  3. In my example, I use a slow fadeOut to simulate a slow ajax call. But the point of that is to show how to use the completion callback function to do something else (like remove the DOM element that's been successfully deleted.

That's pretty much it. This is my first attempt ever to answer a question on stackoverflow, so I hope you'll find this helpful!

Upvotes: 0

Kevin B
Kevin B

Reputation: 95018

Stop binding the events every time you add more buttons and instead bind them only once using event delegation.

var session_user_id = <? php echo $session_user_id; ?> ;
$("#someparentelement").on( "click", "button[id^=delete_post]:not(.handled)", function(){
    var theid = this.id.replace(/delete_post_/i,"");
    $(this).addClass("handled");
    $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: theid
    }, function() {
        $('#post_' + theid).remove();
    });
});

Small note though, I suspect you don't need to pass user_id, php should be able to pull that out of the session.

Edit: Oops, .one delegeated still only fires one event overall, not one per child. Updated to similar .on functionality.

http://jsfiddle.net/JPULH/

Important
Do not put this code in a location where it will execute more than once.

Upvotes: 0

Ivan Schrecklich
Ivan Schrecklich

Reputation: 499

You should lock your post and maybe get everything into one function like that:

            var locker = 0;
        $('.delete_post').on('click', function() {
        if (locker == 0)
        {
        locker = 1;
        var session_user_id = <? php echo $session_user_id; ?> ;
        var number = $(this).attr('id');
        $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: number
        }, function() {
        $('#'+number).remove();
        locker = 0
        });
        }
        });

Your input thing should of course look like that then:

<input id="3" class="delete_post" type="button" value="X">
 <input id="2" class="delete_post" type="button" value="X">
  <input id="1" class="delete_post" type="button" value="X">

Upvotes: 0

Zahid Riaz
Zahid Riaz

Reputation: 2889

It seems like you are using synchronous call issue. remove all the code from click function to a new function. call that function on click. also use asynchronous ajax request.

Upvotes: 0

LeGEC
LeGEC

Reputation: 51870

From what I understand in your document :

<script>
   //if #delete_post_1 exists in the page, it receives a "once" event handler to delete #post_1
</script>

<form>
</form>

<script>
$.post('ajax_file.php', {data: data}, function(data){
   //if the request succeeds, this html code is loaded into the DOM
<script>
       //are you sure that you do not bind a *second* "once" event handler to #delete_post_1 ?
</script>
});

</script>

Upvotes: 0

Nope
Nope

Reputation: 22339

I can't tell if this issue is sorted or not, but given all the feedback in the comments it seems you are binding one twice and it also seems based on the comments you left in user23875's answer that you are aware of that.

If you bind the event twice it executes twice, simple as that.

If you are fully aware of the fact that you are binding the event twice, why not try unbinding any previous attached event first.

$('#delete_post_1').off('click').one('click', function() {
...
$('#delete_post_2').off('click').one('click', function() {
...
$('#delete_post_3').off('click').one('click', function() {

Unless you are also re-rendering your complete HTML twice the above will make sure you are only ever having attached a single click event.

As user23875 had pointed out, you are certainly doing something funky in your scripts.

You should be separating your code as much as possible to ensure code you only intent to run ones only gets called ones and so on.

Hopefully the above will fix this issue.

Upvotes: 3

AlbertEngelB
AlbertEngelB

Reputation: 16436

How about you add a '.disabled' class to the button on click, and have the click event have a :not(.disabled) on the event selector?

EXAMPLE:

$('#delete_post_1:not(.disabled)').one('click', function() { $(this).addClass('disabled'); var session_user_id = <? php echo $session_user_id; ?> ; var number = 1; $.post('ajax_delete_post.php', { user_id: session_user_id, number: number }, function() { $('#post_1').remove(); }); });

Upvotes: 0

yodog
yodog

Reputation: 6232

could you try this code and check the console if it fires twice?

$('#delete_post_3').on('click', function(event) {
    var session_user_id = <?php echo $session_user_id;?> ;
    var number = 3;
    $.post('ajax_delete_post.php', {
        user_id: session_user_id,
        number: number
    }, function() {
        $('#post_3').remove();
    })
    $(this).off(event);
})

EDIT

try one last thing: quotes

"user_id": session_user_id,
"number": number

Upvotes: 0

Max Allan
Max Allan

Reputation: 640

Well, first check that you do not have a space between < and php where you echo the session_user_id... This might be an possible solution, the rest seams to be right.

Upvotes: 0

Related Questions