5

So I've built this theme so the client can add Properties to their WordPress website.

Within this theme I've built a favouriting system but I seem to be having a problem with making the favourite button work on the Custom Post Type list page.

The Problem: Every time I hit the favourite button it will always favourite the first post in the list and not the one I clicked. Image Explain below:

First Image

In this Image it displays 3 of the Properties side by side with the star icon being the favourite button.

Second Image

In this Image the first star is gone but I clicked the star on the far right Property.

My only thought is that in the jQuery I am not finding that Property ID and just finding an <i> element and hiding it.

The jQuery code:

$('a#add-to-favorite').click(function(eve){
    eve.preventDefault();
    eve.stopPropagation();
    var $star = $(this).find('i');
    var add_to_fav_options = {
        target:        ('#fav-target'),   // target element(s) to be updated with server response
        beforeSubmit:  function(){
            $star.addClass('fa-spin');
        },  // pre-submit callback
        success: function(){
            $star.removeClass('fa-spin');
            $('#add-to-favorite').hide(0,function(){
                $(this).find('#fav-output').delay(200).show();
            });
        }
    };

    $('#add-to-favorite-form').ajaxSubmit( add_to_fav_options );
});

The favourite code:

<span class="add-to-fav">
    <?php
    $property_id = get_the_ID();
    if(is_added_to_favorite($property_id)) {
        ?>
        <div id="fav-output" class="show">
            <i class="fa fa-star"></i>&nbsp;
            <span id="fav-target">Added to Favourites</span>
        </div>
        <?php
    } else {
        ?>
        <form action="<?php echo admin_url('admin-ajax.php'); ?>" method="post" id="add-to-favorite-form">
            <input type="hidden" name="property_id" value="<?php echo $property_id; ?>">
            <input type="hidden" name="action" value="add_to_favorite">
        </form>
        <div id="fav-output">
            <i class="fa fa-star"></i>&nbsp;
            <span id="fav-target">Added To Favourites</span>
            <span id="property-target-<?php echo $property_id; ?>" data-property-id="<?php echo $property_id; ?>"></span>
        </div>
        <a href="#add-to-favorite" id="add-to-favorite">
            <i class="fa fa-star-o"></i>&nbsp;
            <span class="add-to">Add to Favourites</span>
        </a>
        <?php
    }
    ?>
</span>
  • an html identifier has to be unique in a HTML page. then you have to change "fav-target" because there is several of these – mmm Aug 4 '16 at 11:21
4

You should not be using element IDs more than once, instead you should be using classes.

Without going into to much detail try the adjustments below...

Change the following:

<a href="#add-to-favorite" id="add-to-favorite">
    <i class="fa fa-star-o"></i>&nbsp;
    <span class="add-to">Add to Favourites</span>
</a>

...to

<a href="#add-to-favorite" class="add-to-favorite">
    <i class="fa fa-star-o"></i>&nbsp;
    <span class="add-to">Add to Favourites</span>
</a>

Change your JS to:

$('a.add-to-favorite').click(function(eve){
    eve.preventDefault();
    eve.stopPropagation();
    var $context = $(this); //cache the click context here
    var $star = $context.find('i');
    var add_to_fav_options = {
        target:        ('#fav-target'),   // target element(s) to be updated with server response
        beforeSubmit:  function(){
            $star.addClass('fa-spin');
        },  // pre-submit callback
        success: function(){
            $star.removeClass('fa-spin');
            $context.hide(0,function(){
                //find the #fav-output element based on click context
                $context.find('#fav-output').delay(200).show();
            });
        }
    };

    $('#add-to-favorite-form').ajaxSubmit( add_to_fav_options );
});

note: untested

Update #2:

JavaScript...

$('.add-to-fav').click(function(eve){
    eve.preventDefault();
    eve.stopPropagation();
    var $context = $(this); //cache the click context here
    var $add_to_favorite = $context.find('a.add-to-favorite');
    var $star = $add_to_favorite.find('i');
    var add_to_fav_options = {
        target: $context.find('.fav-target'), // target element(s) to be updated with server response
        beforeSubmit:  function(){
            $star.addClass('fa-spin');
        },  // pre-submit callback
        success: function(){
            $star.removeClass('fa-spin');
            $add_to_favorite.hide(0,function(){
                //find the #fav-output element based on click context
                $add_to_favorite.find('.fav-output').delay(200).show();
            });
        }
    };

    $context.find('.add-to-favorite-form').ajaxSubmit( add_to_fav_options );
});

HTML...

<span class="add-to-fav">
    <?php
    $property_id = get_the_ID();
    if(is_added_to_favorite($property_id)) {
        ?>
        <div class="fav-output show">
            <i class="fa fa-star"></i>&nbsp;
            <span class="fav-target">Added to Favourites</span>
        </div>
        <?php
    } else {
        ?>
        <form action="<?php echo admin_url('admin-ajax.php'); ?>" method="post" class="add-to-favorite-form">
            <input type="hidden" name="property_id" value="<?php echo $property_id; ?>">
            <input type="hidden" name="action" value="add_to_favorite">
        </form>
        <div class="fav-output">
            <i class="fa fa-star"></i>&nbsp;
            <span class="fav-target">Added To Favourites</span>
            <span class="property-target-<?php echo $property_id; ?>" data-property-id="<?php echo $property_id; ?>"></span>
        </div>
        <a href="#add-to-favorite" class="add-to-favorite">
            <i class="fa fa-star-o"></i>&nbsp;
            <span class="add-to">Add to Favourites</span>
        </a>
        <?php
    }
    ?>
</span>
| improve this answer | |
  • Okay I'll remember the ID thing for the future - but I still have the same problem of click the last one favourites the first one :/ – Stephen Aug 4 '16 at 11:39
  • Try solution #2, it appears that you had more context based issues because of further usage of IDs instead of classes and you were not containing some of your modifications to the DOM within the click context. – Adam Aug 4 '16 at 11:47
  • Updated solution #2 again, yet more ID classes (this time on the "form" tag). Changed the HTML and JS to reflect. – Adam Aug 4 '16 at 11:50
  • 1
    Actually yeah it will go a long way to helping you solve your problems... because you are not capturing the "click" event in a context relevant manner. This has nothing to do with HTML5 standards. You are trying to enact upon a click event without specifying context, so the elements you are selecting in the DOM are not descendants or direct siblings of the element or element parent in which was clicked. – Adam Aug 5 '16 at 2:52
  • 1
    Yeah I managed to fix my problem in the end - I just had to change the $add_to_favourite.find() to $context.find() – Stephen Aug 5 '16 at 10:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.