开发者

slideToggle executing twice in one call

开发者 https://www.devze.com 2023-01-18 17:43 出处:网络
I can\'t show a live example at this point, but i don\'t s开发者_StackOverflow中文版ee how the slideToggle is being called twice. it is called on click of a link.

I can't show a live example at this point, but i don't s开发者_StackOverflow中文版ee 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.


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.


Prologue

The answer to your questions points out something quite strange about jQuery. I ran into this problem when I tried to hide/slide divs and show/slide another one (in a jquery/Ajax navigation site), not knowing which divs were already visible.

Possible Answer

When a jquery calls more than one element in the same call, the function is executed more than once.

Exemple

$("#div_one, #div_two").hide("slow", function() {
   $("#div_two").show("slow");
});

--> #div_two will appear, disappear, and then appear again, because the chained function will trigger twice.

Additionnal info

Same thing happen with a call to a class with multiple elements.

Solution

In my case, I simply decided to do things differently. The first divs only disappear (no slide effect), and the new one can have a slide effect. This way, I don't need to wait for the first divs to slide before triggering the new div, so I don't have to encapsulate the second command into a chained function.

In this exemple, the alert only trigger once :

$("#div_one, #div_two").hide();
$("#div_two").show("slow");
});

It changes the user experience, but it works...


I'm pretty late, but the slideToggle() function will call the complete function for every elements that it's toggling.

There's probably more than one $(this).parent().siblings('div.remaining-comments').


Just using e.stopPropagation(); at the start (and function(e){) fixed it for me.


Just wanted to add that I encountered the same problem. Due to a faulty resolution to a merge conflict, a .js file was included in the page twice. Because of that, the change event on a checkbox fired twice.

So, check to make sure that the code that hooks up event handlers (or calls .ready()) isn't referenced twice.


watch out for moving or wrapping elements containing script blocks in them. This can cause the code there to be executed twice. unbind is a workaround but better to move your js into the head or bottom of the page.

0

精彩评论

暂无评论...
验证码 换一张
取 消