malsup / cycle2

2nd gen cycling
899 stars 237 forks source link

Before/After events not firing on first load #383

Open robnero opened 10 years ago

robnero commented 10 years ago

This may seem like a repeated issue, but I can't get any other fixes to help in my context.

The slideshow is working correctly, but only after all slides are run through the first time. The before and after "on" events are not triggering the first run through.

Below is a cycle of 3 banners, each with an image and colored box on the right side. I'm trying to get the text in the colored box to fade in after the banner changes.

<div class="container" style="position:relative;">
    <div class="row">
        <div class="span12">
            <div id="slideshow">
                <div class="row">
                    <div class="span8"><img src="banner1.jpg"></div>
                    <div class="span4 carouselCallOut" style="background-color:#A7B742;">
                        <div class="callOutText" id="textone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pretium enim ut velit ultrices, vel tempor mauris laoreet. Pellentesque tincidunt.</div>
                    </div>
                </div>

                <div class="row">
                    <div class="span8"><img src="banner2.png"></div>
                    <div class="span4 carouselCallOut" style="background-color:#FF821F;">
                        <div class="callOutText" id="texttwo">In pretium enim ut velit ultrices, vel tempor mauris laoreet. Pellentesque tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
                    </div>
                </div>

                <div class="row">
                    <div class="span8"><img src="banner3.jpg"></div>
                    <div class="span4 carouselCallOut" style="background-color:#87CCE6;">
                        <div class="callOutText">Pellentesque tincidunt. In pretium enim ut velit ultrices, vel tempor mauris laoreet. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
                    </div>
                </div>

            </div>
            <div class="cycle-pager"></div>
        </div>
    </div>
</div>

<script src="js/jquery-1.8.3.min.js"></script>
<script src="jquery.cycle2.min.js"></script>
<script>
    $('#slideshow').cycle({
        slides: '> div',
        fx: 'fade',
        timeout: 4000,
        speed: 1000,
        pager: '.cycle-pager'
    });

    $('#slideshow').on('cycle-before', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag){
        $('.callOutText', outgoingSlideEl).fadeOut();
        //alert('before');
    });

    $('#slideshow').on('cycle-after', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag){
        $('.callOutText', incomingSlideEl).delay(250).fadeIn(500);
        //alert('after');
    });
</script>

The alerts included are firing correctly every time. But the text is not fading-in correctly until all 3 slides have cycled through. Any thoughts?

(I love this plugin! Thank you!)

robnero commented 10 years ago

You can view the issue here: http://jsfiddle.net/L92G5/3/

If you let the cycle go through all the slides, you don't see the desired effect until the second cycle of slides onward.

Any thoughts?

robnero commented 10 years ago

Initially, I found this page that expressed the same issue, but had a solution: http://stackoverflow.com/questions/15209213/jquery-cycle2-cycle-before-after-only-works-on-first-transition

I now think that the proposed solution is wrong. I changed the script at the end and now it works correctly:

<script>
    $('#slideshow').cycle({
        slides: '> div',
        fx: 'fade',
        timeout: 4000,
        speed: 1000,
        pager: '.cycle-pager'
    });

    $('#slideshow').on('cycle-before', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag){
        $('.callOutText').fadeOut();
    });

    $('#slideshow').on('cycle-after', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag){
        $('.callOutText').delay(250).fadeIn(500);
    });

    $('.callOutText').delay(1000).fadeIn(500);
</script>

Anyone care to verify?

albell commented 10 years ago

Yep that works.

It might have been that your fadeIn and fadeOut were bumping into each other. Executing a precautionary show() or hide() before a fadeIn() or fadeOut() is often a best practice. It's also sometimes useful when troubleshooting to call a stop() before any animation. Lastly it's cleaner if you can do things in one handler instead of two.

(It does however make sense that cycle-after doesn't fire on the initial load of the first slide. It only fires on transitions.)

How I would do it:

// First load.
// This init listener must come before init or the event will already have fired.
$('#slideshow').on('cycle-post-initialize', function(event, optionHash) {
    $('.callOutText').hide()
                     .delay(1000)
                     .fadeIn(1000);
});

// all subsequent
$('#slideshow').on('cycle-before', function(event, optionHash, outgoingSlideEl, incomingSlideEl, forwardFlag){
   $(incomingSlideEl).find('.callOutText')
                     .hide()
                     .delay(1000) 
                     .fadeIn(1000);
});

$('#slideshow').cycle({
   slides: '> div',
   fx: 'fade',
   timeout: 4000,
   speed: 1000,
   pager: '.cycle-pager'
});

http://jsfiddle.net/Q5MZ4/