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>
1
  • 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, 2016 at 11:21

1 Answer 1

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>
6
  • 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, 2016 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, 2016 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, 2016 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, 2016 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, 2016 at 10:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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