0

I'm having trouble with a jQuery script for voting on posts. I have a "frontpage" with a list of posts from a mysql db. On each post there is a little votebox you can either vote up or down.

jQuery/ajax script:

<script type="text/javascript">
$(document).ready(function() {

    $('.plus-button').click(function(){
        var postid = <?php echo $postloopid; ?>;
        $('.minus-button').removeClass('disliked');    
        $(this).toggleClass('liked');
        alert(postid);

        $.ajax({
            type:"POST",
            url:"php/votesystem.php",
            dataType : 'html',
            data:'act=like&postid='+postid,
            success: function(data){
                $('.plus-button').html(data);
            }
        });
    });
    $('.minus-button').click(function(){
        var postid = $(this).attr('id');
        $('.plus-button').removeClass('liked');    
        $(this).toggleClass('disliked');

        $.ajax({
            type:"POST",
            url:"php/votesystem.php",
            dataType : 'html',
            data:'act=dislike&postid='+postid,
            success: function(data){
                $('.minus-button').html(data);
            }
        });
    });
});
</script>

Votebox.php

<?php
// If postid is from frontpage use $postloopid as $postid
if(isset($postloopid)){
    $postid = $postloopid;
}
$postid = htmlentities($postid, ENT_QUOTES);;

include("connect.php");


//For test purposes
echo $postid;



// If user logged in show votebox
if(isset($_SESSION['username'])){

    $userid = $_SESSION['userid'];

    $sql2 = mysqli_query($connect,"SELECT * FROM posts WHERE id='$postid' AND deleted=0");

    if($sql2){

        $voterow = mysqli_fetch_assoc($sql2);



         $checkupvote = $voterow['upvoters'];

         $checkdownvote = $voterow['downvoters'];

         $checkupvote = explode(" ",$checkupvote);

         $checkdownvote = explode(" ",$checkdownvote);

         if($checkupvote = array_search($userid,$checkupvote) == true){

            echo '<div class="plus-button liked" name="like">+ ' . $voterow['totalupvotes'] . '</div>';

            echo '<div class="minus-button" name="dislike">- ' . $voterow['totaldownvotes'] . '</div>';


         }

         elseif($checkdownvote = array_search($userid,$checkdownvote) == true){

            echo '<div class="plus-button" name="like">+ ' . $voterow['totalupvotes'] . '</div>';

            echo '<div class="minus-button disliked" name="dislike">- ' . $voterow['totaldownvotes'] . '</div>';


         }

         else{

            echo '<div class="plus-button" name="like">+ ' . $voterow['totalupvotes'] . '</div>';

            echo '<div class="minus-button" name="dislike">- ' . $voterow['totaldownvotes'] . '</div>';

         }

    }
    else {
        echo 'No result <br />';

    }

}
else {
    echo 'Cant find user';
}









?>

Frontpage:

<?php
$sql1 = mysqli_query($connect,"SELECT * FROM posts WHERE totalupvotes < $trendmin AND deleted=0 ORDER BY added DESC LIMIT 0,10");
if($sql1){
    while($row = mysqli_fetch_array($sql1)){
        $postloopid = $row['id'];


        ?>
        <div id="postlist">

        <div style="width:400px; font-size:18px; font-weight:bold;">
        <a target="_blank" href="post.php?id=<?php echo $row['id']; ?>"><?php echo $row['title']; ?></a>
        </div><br />
        <article class="slide"><?php echo nl2br($row['post']); ?></article>





        <br />
        <?php include("php/votebox.php"); ?>
        <br />
        by <a style="font-size:18px;" href="profile.php?id=<?php echo $row['submittedby']; ?>"><?php echo $row['submitteduser']; ?></a>
         at <span style="font-size:12px;"><?php echo $row['added']; ?></span><span style="float:right; margin-right: 10px;"><a target="_blank" href="post.php?id=<?php echo $row['id']; ?>#commentfield"><?php echo $row['totalcomments']; ?> comments</a></span>



         </div>


<?php
    }
}
?>

The problem now is that when I click the votebox buttons it turns out I only get the postid from the first loaded post from the while loop. Another problem I have is that my total up- and downvotes changes in all the posts on the list, not the specific post.

Any ideas?

6
  • 1
    It looks like you're using html_entities to "escape" your $postid, use mysql_real_escape to do this, html_entities is by no means secure. Commented Aug 29, 2014 at 1:20
  • You're selecting all rows from posts, then selecting a single row from posts. That's an additional 10 more queries that don't need to be made (considering the LIMIT clause). Just check if $row is set at the top of Votebox.php, or do this in a single file. Commented Aug 29, 2014 at 1:24
  • @LJ_1102 Thnx for the advice. Commented Aug 29, 2014 at 1:26
  • @myninjaname I'm using another infinite scroll script not included in this problem. Commented Aug 29, 2014 at 1:27
  • 1
    In addition to @LJ_1102 's comment, see stackoverflow.com/questions/60174/… Commented Aug 29, 2014 at 1:30

2 Answers 2

1

The Javascript code isn't in the loop, it can't reference postloopid. Or if it is, you're binding all buttons of the class every time through the loop, and clicking on them will run all the handlers, incrementing all the posts.

You should put the post ID as a data field in the button, and then access that from the Javascript:

echo '<div class="plus-button liked" data-postid="'+$postid+'" name="like">+ ' . $voterow['totalupvotes'] . '</div>';

echo '<div class="minus-button" data-postid="'+$postid+'" name="dislike">- ' . $voterow['totaldownvotes'] . '</div>';

Then your Javascript can do:

$('.plus-button').click(function(){
    var postid = $(this).data('postid');
    $(this).siblings('.minus-button').removeClass('disliked');    
    $(this).toggleClass('liked');
    alert(postid);

    $.ajax({
        type:"POST",
        url:"php/votesystem.php",
        dataType : 'html',
        data:'act=like&postid='+postid,
        context: this,
        success: function(data){
            $(this).html(data);
        }
    });
});

I made the following changes to the JS:

  1. Use $(this).data('postid') to get postid.
  2. Only remove the disliked class from the sibling minus button, not all minus buttons on the page.
  3. Put the returned HTML just in this element, not in all plus buttons. I pass this in the context: parameter, so that the success function can refer to it.
Sign up to request clarification or add additional context in comments.

1 Comment

Actually needed both replies. Got it working now. Thank you very much :)
1

Alright lets go through your jQuery code(just the like function):

Bind click handler to all elements with the class plus-button

$('.plus-button').click(function(){
    var postid = <?php echo $postloopid; ?>;

Remove disliked class from all elements with class minus-button

    $('.minus-button').removeClass('disliked');    
    $(this).toggleClass('liked');
    alert(postid);

    $.ajax({
        type:"POST",
        url:"php/votesystem.php",
        dataType : 'html',
        data:'act=like&postid='+postid,
        success: function(data){

Set inner html of all elements with class plus-button

            $('.plus-button').html(data);
        }
    });
});

What you want is to store the postid as an attribute on the posts, then use

var postid = $(this).attr('postid')

only remove the disliked class from the current element

$(this)
    .parents('{element containing plus and minus button}')
    .find('.minus-button')
        .removeClass('disliked')
;

store reference to the clicked element

var $this = $(this); // Cool guys do this right in the beginning and use only this variable instead of $(this)

then in your ajax success handler you want to set only the html of the button you clicked, so you may use the reference you stored in the parent function scope

$this.html(data);

EDIT in regards to infinite scroll script

When parts of your page are dynamic, you want to bind the click handler to a static parent element of the dynamic content using:

$("#postsParent").on('click', '.plus-button', function () {/*handler*/})

2 Comments

Uhm... I see where this is going and I like it, but what's a click handler to all elements with the class plus-button? You mean like <div onClick="">? And what would that look like?
the "click handler" is the method discussed above, your function handling the click event. No special markup required, also be sure to only include the script once not for every row.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.