Can't bind script to new elements in DOM

So, I did a little work on this, but I still can't figure it out.

I have a page here: http://taste.fourseasons.com/ingredients/

The Show More button at the bottom brings up additional messages on the page with the following script:

$("a.view-more").bind('click',function(event){
        event.preventDefault();
        if($('.post-holder').hasClass('ingredients')) { posttype = 'ingredient'; }
        if($('.post-holder').hasClass('recipe')) { posttype = 'recipe'; }
        if($('.post-holder').hasClass('cmed')) { posttype = 'cmed'; }
        filter = 'none';
        morePosts(posttype,filter);
});

      

And the ability for people to vote works with this:

$.post('http://taste.fourseasons.com/wp-admin/admin-ajax.php', data,
           function(response){
                   if(response!="-1") {
                           el.find('.vote-sm').removeClass('vote-sm').addClass('unvote-sm');
                           el.find('.vote-text').html("VOTED");
                           el.unbind("click");
                           if(response!="null") {
                                   el.find(".vote-count").html(response);
                           }
                           var cookie = getCookie("better_votes_"+postID);
                           if(!cookie) {
                                   var newcookie = postID;
                           } else {
                                   var newcookie = postID;
                           }
                           setCookie("better_votes_"+postID, newcookie, 365);
                   } else {
                   }
           });
           return false;
   });

      

But when the user clicks the button more and these elements are added to the DOM, the voting options don't work with these new elements. I assumed I could just add them together:

$("a.view-more").bind('click',function(event){
        event.preventDefault();
        if($('.post-holder').hasClass('ingredients')) { posttype = 'ingredient'; }
        if($('.post-holder').hasClass('recipe')) { posttype = 'recipe'; }
        if($('.post-holder').hasClass('cmed')) { posttype = 'cmed'; }
        filter = 'none';
        morePosts(posttype,filter);

        $(".vote").bind('click',function(event) {
               event.preventDefault();
               postID = $(this).attr('data-post');
               var el = $(this);
               //el.html('<span id="loader"></span>');
               var nonce = $("input#voting_nonce_"+postID).val();
               var data = {
                       action: 'add_votes_options',
                       nonce: nonce,
                       postid: postID,
                       ip: '66.252.149.82'                        
               };
               $.post('http://taste.fourseasons.com/wp-admin/admin-ajax.php', data,
               function(response){
                       if(response!="-1") {
                               el.find('.vote-sm').removeClass('vote-sm').addClass('unvote-sm');
                               el.find('.vote-text').html("VOTED");
                               el.unbind("click");
                               if(response!="null") {
                                       el.find(".vote-count").html(response);
                               }
                               var cookie = getCookie("better_votes_"+postID);
                               if(!cookie) {
                                       var newcookie = postID;
                               } else {
                                       var newcookie = postID;
                               }
                               setCookie("better_votes_"+postID, newcookie, 365);
                       } else {
                       }
               });
               return false;
       });
    });

      

But that doesn't work, and it also creates a script that adds two votes to the total instead of one, every time you vote.

Thanks for any help.

This code is in the wp function page:

function add_votes_options() {
    $postid = $_POST['postid'];
    $ip = $_POST['ip'];

    if (!wp_verify_nonce($_POST['nonce'], 'voting_nonce_'.$postid))
        return;

    $voter_ips = get_post_meta($postid, "voter_ips", true);
    if(!empty($voter_ips) && in_array($ip, $voter_ips)) {
        echo "null";
        die(0);
    } else {
        $voter_ips[] = $ip;
        update_post_meta($postid, "voter_ips", $voter_ips);
    }   

    $current_votes = get_post_meta($postid, "votes", true);
    $new_votes = intval($current_votes) + 1;
    update_post_meta($postid, "votes", $new_votes);
    $return = $new_votes>1 ? $new_votes : $new_votes;
    echo $return;
    die(0);
}

      

+3


source to share


1 answer


You are facing a fairly common problem with event binding.

$("a.view-more").bind('click',function(event){

      

The above line of code you wrote attaches an event listener to the DOM elements available at the time. This is why new elements added to the DOM do not respond to the event; because they are not connected to an event listener.

To get around this, we can use something called event delegation. This works by attaching the event to the parent DOM element that you want to listen to for the event. We can then determine which child event the event happened with when the event eventually propagates to the parent.

jQuery makes this very easy. You can use a method delegate()

, but I suggest you use a method on()

, which is a method that handles all event operations in jQuery. Others, such as click()

, mouseover()

and bind()

, are just aliases.on()



In any case, in order to delegate an event, we need to specify a selector for the parent to which the event will be attached, and a selector for the elements of interest. Thus, the line of code will now look like this:

$("body").on('click', "a.view-more", function(event){

      

You should really use something other than the body, but this is just an example.

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

+3


source







All Articles