Alex B Alex B - 5 months ago 48
jQuery Question

slideToggle executing twice in one call

I can't show a live example at this point, but i don't see how the slideToggle is being called twice. it is called on click of a link.

here:

// initialize the jquery code
$(function(){
$('div.slideToggle a').click(function(){
$(this).parent().siblings('div.remaining-comments').slideToggle('slow',function(){ //'this' becomes the remaining-comments.
var hidden = $(this).siblings('div.slideToggle').find('input').val();
if($(this).siblings('div.slideToggle').find('a').html().substr(0,4) == 'Show'){
$(this).siblings('div.slideToggle').find('a').html('Hide comments');
}
else {
$(this).siblings('div.slideToggle').find('a').html(hidden);
}
});
});
});


it is meant to display and hide extra comments on a blog page.
however, it is displaying and then hiding in one click. I have put an alert in both the 'if' and 'else' and both appear, so how is it invoked twice?

obviously when the link contains the text 'Show' it reveals the hidden div, and when clicked again it will not find 'Show' and will therefore hide the div. The funny thing is, it was working absolutely perfectly. It's on the company intranet so i suppose maybe something else could be affecting it, but i really don't see how.

Answer

It is possible that your document ready is called more than once, when page reinitializes, best thing to do is to unbind the click event before binding a new one to it.

this way you avoid having the click event bound twice on 1 element

try this:

$('div.slideToggle a').unbind('click').click(function(){
  // your code here
});

UPDATE:

The problem with this above situation is that you have to bind it again to every extra element that is added after you bound the click function the first time.

You can fix this issue, by binding 1 click handler on a parent item that stays in the dom. Giving it a sub-selector as argument.

It results in only 1 click handler being added, instead of 1 for each element. So you should win on performance, code execution time, and amount of javascript you were writing.

example:

let say you have a list where you dinamically add new elements

<ul id="ContactList">
    <li>John Doe <a href="#">Like</a></li>
    <li>Jane Doe <a href="#">Like</a></li>
    <li>Josh Doe <a href="#">Like</a></li>
    <li>Jeff Doe <a href="#">Like</a></li>
</ul>

and you bind some functionality on the anchor tag when it is clicked

$(function(){

    $('#ContactList').on('click', 'li a', function(e){
        // do your thing here...
        var el = $(e.currentTarget);
        el.addClass('iLikeYou');
    });

});

now, no matter how many items you add later on, it will work anyway. because it accepts clicks anywhere within the ul#ContactList and will execute the callback only when the clicked element matches the selector li a.

while $('#ContactList li a') would first get all the elements and then bind the click to all selected items. Newly added items afterwards don't have the click event and would need to have it bound to them first.