views:

1892

answers:

5

I have created a jQuery content switcher. Generally, it works fine, but there is one problem with it. If you click the links on the side multiple times, multiple pieces of content sometimes become visible.

The problem most likely lies somewhere within the click event. Here is the code:

$('#tab-list li a').click(
    function() {
        var targetTab = $(this).attr('href');
        if ($(targetTab).is(':hidden')) {
            $('#tab-list li').removeClass('selected');
            var targetTabLink = $(this).parents('li').eq(0);
            $(targetTabLink).addClass('selected');
            $('.tab:visible').fadeOut('slow',
                function() {
                    $(targetTab).fadeIn('slow');
                }
            );
        }
        return false;
    }
);

I have tried adding a lock to the transition so that further clicks are ignored as the transition is happening, but to no avail. I have also tried to prevent the transition from being triggered if something is already animating, using the following:

if ($(':animated')) {
    // Don't do anything
}
else {
   // Do transition
}

But it seems to always think things are being animated. Any ideas how I can prevent the animation being triggered multiple times?

+1  A: 

One idea would be to remove the click event at the start of your function, and then add the click event back in when your animation has finished, so clicks during the duration would have no effect.

If you have the ability to execute code when the animation has finished this should work.

Brian Ramsay
A: 

one way would be this:

$('#tab-list ul li').one( 'click', loadPage );
var loadPage = function(event) {
    var $this = $(this);
    $global_just_clicked = $this;
    var urlToLoad = $this.attr('href');
    $('#content-area').load( urlToLoad, pageLoaded );
}
$global_just_clicked = null;
var pageLoaded() {
    $global_just_clicked.one( 'click', loadPage );
}

As you can see, this method is fraught with shortcomings: what happens when another tab is clicked before the current page loads? What if the request is denied? what if its a full moon?

The answer is: this method is just a rudimentary demonstration. A proper implementation would:

  1. not contain the global variable $global_just_clicked
  2. not rely on .load(). Would use .ajax(), and handle request cancellation, clicking of other tabs etc.

NOTE: In most cases you need not take this round-about approach. I'm sure you can remedy you code in such a way that multiple clicks to the same tab would not affect the end result.

jrh.

Here Be Wolves
+1  A: 

Add a variable to use as a lock rather than is(:animating).

On the click, check if the lock is set. If not, set the lock, start the process, then release the lock when the fadeIn finishes.

var blockAnimation = false;

$('#tab-list li a').click(
    function() {
        if(blockAnimation != true){
        blockAnimation = true;
        var targetTab = $(this).attr('href');
        if ($(targetTab).is(':hidden')) {
            $('#tab-list li').removeClass('selected');
            var targetTabLink = $(this).parents('li').eq(0);
            $(targetTabLink).addClass('selected');
            $('.tab:visible').fadeOut('slow',
                function() {
                    $(targetTab).fadeIn('slow', function(){ blockAnimation=false; });
                }
            );
        }
        }
        return false;
    }
);
Ben
I tried this approach but couldn't seem to get it working. It passed the lock test every time.
pmckenna
+1  A: 

I toyed around with the code earlier and came up with the following modification which seems to work:

$('#tab-list li a').click(
    function() {
        $('.tab:animated').stop(true, true);
        var targetTab = $(this).attr('href');
        if ($(targetTab).is(':hidden')) {
            $('#tab-list li').removeClass('selected');
            var targetTabLink = $(this).parents('li').eq(0);
            $(targetTabLink).addClass('selected');
            $('.tab:visible').fadeOut('slow',
                function() {
                    $(targetTab).fadeIn('slow');
                }
            );
        }
        return false;
    }
);

All that happens is, when a new tab is clicked, it immediately brings the current animation to the end and then begins the new transition.

pmckenna
A: 

Well this is how i did it, and it worked fine.

$(document).ready(function() {
    $(".clickitey").click(function () {
        if($("#mdpane:animated").length == 0) {
            $("#mdpane").slideToggle("slow"); 
            $(".jcrtarrow").toggleClass("arrow-open");
        }
    });
});

this is not doing what your code does ofcourse this is a code from my site, but i just like to point how i ignored the clicks that were happening during the animation. Please let me know if this is inefficient in anyway. Thank you.

Asad Hasan