0

My page displays posts stored in my database and pairs a like/dislike button to each post. I am trying to make it so that when a user clicks like or dislike, the value is sent to my database for later recollection.

I have a complex loop that I hope to explain: On page load, an ajax call is made to an external php file to fetch data from my database. The result is an object array which holds "postID":value. Inside a for loop, I am storing the value inside var postID for easy access. I'm obviously going about this wrong because the code does execute, but only sends the value and postID of the last occurrence in the loop no matter which pair of buttons I press: If I have 11 posts in my database and I press "like" on post 3 it will store the value 'like' but for post 11. If I press dislike on post 7 it will store the value 'dislike' but for post 11.

So the question is, how do I fix this so when I press like or dislike for post x, it will store the value for that same post and not the last post in my database?

The array looks like this:

{"s":0,"d":[{"postID":"1"},{"postID":"2"},{""pos‌​tID":"3"},{""pos‌​tID":"4"},{""pos‌​tID":"5"},{""pos‌​tID":"6"},{""pos‌​tID":"7"},{""pos‌​tID":"8"},{""pos‌​tID":"9"},{""pos‌​tID":"10"},{""pos‌​tID":"11"}]}

The post divs are the following format:

<div id="post_#"> //# representing the postID in the database
    <div id="like_#"></div> //# repesenting the postID in the database
    <div id="dislike_#"></div> //# representing the postID in the database
</div>

My jQuery (includes only the like button):

$(document).ready(function() {
    $.ajax({
        url: 'postID.php', //fetch the above array
        type: 'POST',
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        cache: false,
        success: function (post) {
                    if (post.s == 0) {
                    //Loop through returned data array using: post.d
                        for (var key in post.d) {
                            var obj = post.d[key];
                            for (var prop in obj) {
                                var postID = obj[prop];

                                //When like button is clicked do this
                                $('#like_' + postID).click(function() {

                                    // Declare variables
                                    var value = '1';

                                    // Send values to database
                                    $.ajax({
                                        url: 'check.php', //check.php receives the values sent to it and stores them in the database
                                        type: 'POST',
                                        data: 'postID=' + postID + '&value=' + value,
                                        success: function(result) {
                                            $('#Message_'+ contestID).html('').html(result).prependTo('#post_' + postID);
                                        }
                                    });
                                 });
                             }
                         }
                     }
                  }
     });
});

So again, my problem is that the second ajax loop is only sending the last instance of var postID instead of sending the postID of the post that was actually clicked.

Any ideas?

Sweepster
  • 1,829
  • 4
  • 27
  • 66
  • Classic JavaScript function-in-a-loop problem. Has been asked many times - probably thousands - on SO. See http://stackoverflow.com/questions/7399411/settimeout-only-sees-last-value-in-array – Matt Ball Nov 06 '11 at 22:38
  • I don't see how the solution above can help me. I'm not creating the loop with an i variable and increasing it's value each time it loops. I'm going through an already established array so I don't know what event to place in the function or where to place in within the series of for loops that I have. – Sweepster Nov 06 '11 at 23:47
  • The problem is fundamentally the same, though. The innermost `success` callback only sees the very last value of `postID` because (1) there is no block scope, only function scope, in JavaScript and (2) `postID` is part of the closure formed by the `success` callback. – Matt Ball Nov 06 '11 at 23:50
  • so then would the solution be to place (function(postID){ just above $('#like...? I've tried inserting it everywhere but everything results in killing the entire mechanism - it doesn't send any values anywhere. – Sweepster Nov 07 '11 at 00:33

1 Answers1

1

*updated to use .on() instead of .live() as its deprecated since 1.7 try this instead:

html

<div id="post_#" class="post"> //# representing the postID in the database
    <div id="like_#" class="like">test</div> //# repesenting the postID in the database
    <div id="dislike_#" class="dislike"></div> //# representing the postID in the database
</div>

jquery

$(document).ready(function() {

//When like button is clicked do this
$('.like').on('click', function() {

    var postID = $(this).attr('id').replace('like_', '');

    // Declare variables
    var value = '1';

    // Send values to database
    $.ajax({
        url: 'check.php',
        //check.php receives the values sent to it and stores them in the database
        type: 'POST',
        data: 'postID=' + postID + '&value=' + value,
        success: function(result) {
            $('#Message_' + contestID).html('').html(result).prependTo(this);
        }
    });
});

});

Here is the link to a sample http://jsfiddle.net/TXwZk/

Victor
  • 4,721
  • 1
  • 26
  • 31
  • 1
    .live() is deprecated as of version 1.7 of jQuery. Is there another way? – Sweepster Nov 06 '11 at 23:39
  • Your code sends the following values to check.php: PostID: like Value: 1 It should be send: PostID:# Value: 1 With # being the ID of the post I clicked on. – Sweepster Nov 07 '11 at 00:55
  • did you make sure the markup is the same structure as above? Post your code to jsfiddle.net and post a link – Victor Nov 07 '11 at 02:12
  • success! The problem I had was I forgot a php variable to set the postID to the like div. It works perfectly, thank you! – Sweepster Nov 07 '11 at 22:52