0

Stopping jQuery Slideshow on Youtube Click How do I get my slideshow of videos to stop when I play one of the videos?

I have a simple jQuery slideshow that slides through a list of 3 videos:

jQuery(document).ready(function ($) {
    $('#videoSlides > div').hide();
    $('#videoSlides > div:first').show();
    var doTheSlide = function () {
        $('#videoSlides > div:first')
            .fadeOut(0)
            .next()
            .fadeIn(2000)
            .end()
            .appendTo('#videoSlides');
    };
    var delay = 5000;
    interval = setInterval(doTheSlide, delay);
});

Then, when one of the videos is clicked, the slideshow is supposed to stop:

function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
    clearInterval(interval);
}
}

The slideshow works perfectly, but the slideshow doesn't successfully stop when I've clicked on one of the videos to play it. It just keeps on sliding through. How do I stop this?

The complete code is found here: http://jsfiddle.net/8b5r2fa9/4/

OneHoopyFrood
  • 3,829
  • 3
  • 24
  • 39
alloy
  • 756
  • 1
  • 13
  • 23

1 Answers1

0

You have three problems. One, your event isn't firing. Two, messing with intervals is tricky and should be avoided where possible. Three, you'll lose your event attachments when the video element is moved and re-appended.

Ready? Lets go.

According to this: YouTube API Change Event Not Firing the API may be buggy, so loading the videos with JS is a better option.

(function setupPlayers() {
    if(window['YT'].loaded == 1){
        // Sets up the players via script due to the Iframe API being buggy
        var player01 = new YT.Player('player01', {
            height: '390',
            width: '640',
            videoId: 'nCgQDjiotG0',        
            events: {      
              'onStateChange': onPlayerStateChange
            }
        });
        var player02 = new YT.Player('player02', {
            height: '390',
            width: '640',
            videoId: 'V70ruRzEGOI',        
            events: {      
              'onStateChange': onPlayerStateChange
            }
        });
        var player03 = new YT.Player('player03', {
            height: '390',
            width: '640',
            videoId: 'xgrcK9Ozb_Q',        
            events: {      
              'onStateChange': onPlayerStateChange
            }
        });
    }
    else {
        setTimeout(setupPlayers, 100);
    }
})();

Note: to make sure the API is loaded you have to check window['YT'].loaded until it's all there.

This is a bit of a round-about technique to get what you want done but its far easier than messing with the interval itself. Javascript Timeouts and Intervals are tricky at best.

What we're making here is a primary loop (like for a game, if you've ever done that) and putting a global condition on the action of that loop. This way the code is only executed while your condition is true, but it just keeps running that loop and you don't have to worry about stopping or starting it back up. I've also changed the setInterval to a setTimeout that's repeatedly called in the doTheSlide function, this seems more stable to me and has fixed some issues in chrome I've dealt with before.

Also in this next snippet is the fix for the final issue. You cannot use appendTo on the element so instead you must move through the nodes and detect the end of the list. I've used a little jQuery extention method you can see in the final code.

var slideDelay = 5000;
var currentSlide = $('#videoSlides > div:first');

function doTheSlide() {
    if(window.slide === true){
        currentSlide.hide();
        if(currentSlide.next().exists()){
            currentSlide = currentSlide.next();
        }
        else {
            currentSlide = $('#videoSlides > div:first');
        }
        currentSlide.fadeIn(2000);
    }
    setTimeout(doTheSlide, slideDelay);
};

$(function() {
    //  Add a nifty helper
    $.fn.exists = function () {
        return this.length !== 0;
    };

    // Set up the slideshow (Runs once)
    var interval;
    window.slide = true;
    jQuery(document).ready(function ($) {
        $('#videoSlides > div').hide();
        $('#videoSlides > div:first').show();
        setTimeout(doTheSlide, slideDelay);
    });
});

Here is the final working code: fiddle

I've also included code to restart the slider when the video ends or pauses.

Community
  • 1
  • 1
OneHoopyFrood
  • 3,829
  • 3
  • 24
  • 39