开发者

Multiple JQuery toggles on one form

I have a form for which some of the fields have expanding boxes attached. It looks a little like this (a few times over with slight variations):

<a class="label toggle" rel="toggle[time_allowed]">
  <label for="file_time_allowed" id="time_allowed_label">
    Time Allowed (mins)
  </label>
</a>
<%= form.text_field :time_allowed, :id => "time_allowed" %>
<div class="clear"></div>开发者_运维知识库
<div class="expand_me" id="time_allowed_toggle" style="display:none;"><br />
  <div class="linkExpand expandDiv">
Set a time limit.<br /><br />
  </div>    
</div>

I have this JQuery to expand the .expand_me div when the user clicks on any .toggle.

<script type="text/javascript">
$(function() {
  $(".toggle").click(function() {
    $(this).nextAll(".expand_me").first().toggle("blind",{},500);
    return false;
  });
});
</script>

Two questions:

  1. If I double- or triple-click on .toggle, 2-3 .expand_me divs toggle underneath it. Apparently, my current function is not always calling the next .expand_me but rather the next one that isn't currently animating. How can I make sure the toggle function always and only targets the next div regardless of its animation state?

  2. I wanted to break the queueing of animations that JQuery natively builds up by adding .stop() to my toggle line, as in:

    $(this).nextAll(".expand_me").first().stop().toggle("blind",{},500);
    

    Since I have the issue with #1 I wasn't able to test if this works. If it doesn't, how can I ensure that a newbie who double-clicks on a div isn't met with a confusing double animation?


Works fine if you use just .next() rather than .nextAll().first():

http://jsfiddle.net/ambiguous/xdH82/3/

Or if you use the standard .toggle() rather than the extended one from jQuery-UI:

http://jsfiddle.net/ambiguous/xdH82/4/

I don't know why there's a difference but a tour of the jQuery internals would probably be revealing. If you play around with single and double clicking in here:

http://jsfiddle.net/ambiguous/Nudkh/

Then you'll see that the .nextAll() list excludes the currently animating element but I don't know why.

In any case, .next('.expand_me') exactly matches your intent so I'd just go with that and move on. OTOH, this difference between .next() and .nextAll().first() is probably going to be bugging me for days, hopefully someone will offer an explanation to ease my mind.

UPDATE: If you watch the animation with a DOM inspector (such as WebKit's "inspect element") you'll see that jQuery-UI's extended .toggle is wrapping the animated element in an extra <div> during the animation. So, if you say .nextAll('.expand_me') it won't find the .expand_me that you want as it won't be a sibling anymore: it will be the child of a temporary sibling. The .next('.clear').next('.expand_me') will conveniently fail to find anything as the temporary wrapper will block the direct path "this -> .clear -> .expand_me" and the click handler won't do anything on the second click of the double click.

I probably should have gone straight into the jQuery-UI source to figure out the odd .nextAll() behavior. Oh well, at least I know what's going on now.

UPDATE 2: A better approach than all this .next business would be to explicitly tie the link to the toggling panel:

<a data-panel="panel-1">
    <!--...-->
</a>
<!--...-->
<div id="panel-1" class="expand_me">
    <!--...-->
</div>

And:

$('.toggle').click(function() {
    $('#' + $(this).data('panel')).stop().toggle('blind', { }, 500);
});

If you have an older jQuery then you might have to use .attr('data-panel') instead of .data('panel').

Example: http://jsfiddle.net/ambiguous/pmQR7/1/

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜