views:

65

answers:

2

i have this jQuery file, but the vote_up click handler keeps conflicting with the vote_down click handler, when i click the vote_down element it changes the vote_up element:

jQuery script:

$(document).ready(function () {
    $("a.vote_up").click(function () {
        //get the id
        var the_id = this.id.split('_').pop();
        //the main ajax request
        $.ajax({
            type: "POST",
            data: "action=vote_up&id=" + the_id,
            url: "ajax/votes.php",
            success: function (msg) {
                $("span.vote_count#" + the_id).html(msg).fadeIn();
                $("#" + the_id + " img").attr("src", "img/uparrowActive.png");
            }
        });
    });
});
$(document).ready(function () {
    // the vote down function
    $("a.vote_down").click(function () {
        //get the id
        var vote_id = this.id.split('_').pop();
        //the main ajax request
        $.ajax({
            type: "POST",
            data: "action=vote_down&id=" + vote_id,
            url: "ajax/votes.php",
            success: function (msg) {
                $("span.vote_count#" + vote_id).html(msg).fadeIn();
                $("#" + vote_id + " img").attr("src", "img/downarrowActive.png");
            }
        });
    });
});

html:

<a href='#' class='vote_up' id="id_23"><img src="img/uparrow.png" /></a>
<a href='#' class='vote_down' id="id_23"><img src="img/downarrow.png" /></a>

the jQuery and ajax request is wokring fine, but the change of src is the problem, because when i click vote down, it changes the vote_up image!!

+5  A: 

You can't use the same "id" value for two different elements.

Pointy
so shall i change the vote_down id to `votedown_23`
getaway
@getaway - You can change it to `van_halen_1984` if you want, as long as it is unique. :o)
patrick dw
Things will improve if you change it to something other than "id_23". An "id" value **must** be unique across the whole page if you want things to work properly. That's what it's called "id" ("identity").
Pointy
I always thought it was 'identification'?
colinmarc
now the whole jquery thing is not working only the ajax bit? :(( i think i need to go to sleep
getaway
@colinmarc well whatever; something that means "unique in all the world like a perfect snowflake or a precious duck baby".
Pointy
@patrick - +1 for the gratuitous hair metal reference.
Peter Ajtai
@Peter - Oh, it could've been [so much worse](http://dietrichthrall.files.wordpress.com/2008/03/poison_group.jpg). :o)
patrick dw
+1  A: 

If you're looking for some sort of strategy for focusing events to a repeating piece of data, utilizing IDs with the number appended to reference the various elements may work, but may not be the best approach.

I assume each repeating item has its own container that repeats. You may be better off placing a unique ID on that container, and finding the elements from there.

Take this for example:

<div id='outerContainer'>
    <div id='set_123' class='someContainer'>
        <a href='#' class='vote_up'><img src="img/uparrow.png" /></a>
        <span class='vote_count'></span>
        <a href='#' class='vote_down'><img src="img/downarrow.png" /></a>
    </div>
    <div id='set_124' class='someContainer'>
        <a href='#' class='vote_up'><img src="img/uparrow.png" /></a>
        <span class='vote_count'></span>
        <a href='#' class='vote_down'><img src="img/downarrow.png" /></a>
    </div>
    <div id='set_125' class='someContainer'>
        <a href='#' class='vote_up'><img src="img/uparrow.png" /></a>
        <span class='vote_count'></span>
        <a href='#' class='vote_down'><img src="img/downarrow.png" /></a>
    </div>
</div>

You could use .delegate() to place click handlers on the #outerContainer that fire when you click the appropriate up/down elements.

Something like:

$(document).ready(function() {
    $('#outerContainer').delegate('.vote_up', 'click', function() {
       //get the id
        var the_id = $(this).closest('.someContainer').attr('id').split('_').pop();
        //the main ajax request
        $.ajax({
            type: "POST",
              // Make sure "this" in the callback refers to the element clicked
            context: this,
            data: "action=vote_up&id=" + the_id,
            url: "ajax/votes.php",
            success: function (msg) {
                  // Not sure where your vote_count is. See the HTML for my placement
                $(this).siblings("span.vote_count").html(msg).fadeIn();
                  // get the child <img> and set its src
                $(this).children("img").attr("src", "img/uparrowActive.png");
            }
        });
    });
    $('#outerContainer').delegate('.vote_down', 'click', function() {
       //get the id
        var the_id = $(this).closest('.someContainer').attr('id').split('_').pop();
        //the main ajax request
        $.ajax({
            type: "POST",
              // Make sure "this" in the callback refers to the element clicked
            context: this,
            data: "action=vote_down&id=" + the_id,
            url: "ajax/votes.php",
            success: function (msg) {
                  // Not sure where your vote_count is. See the HTML for my placement
                $(this).siblings("span.vote_count").html(msg).fadeIn();
                  // get the child <img> and set its src
                $(this).children("img").attr("src", "img/downarrowActive.png");
            }
        });
    });
});

So the ID with the number you need is on each .someContainer. You traverse up to that container to get the ID, and do your .split().pop().

Then in the AJAX request, I set the context: property for $.ajax() so that this will still refer to the element that was clicked in your callback.

Inside the callback, you find the .siblings() that have the class .vote_count, and set its .html() content.

Finally you use .children() to get the img element, and set its src attribute.

This should give the general idea. You'll need to adjust for your HTML.

patrick dw
thanks for the answer, i have chnaged evrything to fit my html, but i tried to read about the context bit, but i dnt get it, im already sending the ajax to votes.php aint i, i was thinking shall i put this `$(this).attr("id")`
getaway
@getaway - I don't understand your last sentence, but with regard to context, the reason I added that property to the AJAX request is because *inside the callback* I wanted `this` to refer to the element that was clicked. When you have an AJAX callback, like your `success:` callback, the meaning of `this` magically changes inside the callback, so that it no longer refers to the element that was clicked. To make it refer to that element once again, you pass `this` via the `context:` property of the request. That's only one approach, but is probably the cleanest.
patrick dw
...if I hadn't done that, `$(this).siblings(...` and `$(this).children(...` would have not worked, because `this` would no longer be a reference to the `.vote_up` or `.vote_down` element that was clicked.
patrick dw
thanks, but why dnt i just remove the context then
getaway
@getaway - What do you mean by "remove the context"? In the code I posted, I want `this` to refer to the element that was clicked for the `success:` callback. If I don't have `context:this`, it will not. In other words, *before* the AJAX request (in the click handler), `this` is a reference to the element that was clicked. But *inside* the `success:` callback for the AJAX request, `this` no longer refers to that element. But we want it to. So setting the `context:` property to `this` makes it so that `this` continues to be a reference to the element in the callback.
patrick dw
thanks i solved the question :))
getaway
oh my god patrick, what about if i wanted to implent a toggle on the votes, basically reverse the action, just like stackoverflow! i was thinking i have to create another script obviously dealing with reverse votes!! :))
getaway