Go To Next Slide When Vimeo Finished

Blog

Check Out Useful Squarespace articles here

Go To Next Slide When Vimeo Finished

If you are using Squarespace Gallery block to host Vimeo videos, it makes sense go to next slide when video stops playing. And this actually can be easily done.

So we need to know when exactly Vimeo video ends.

1) We may use their Player.js  for that. Good call, but only if we need some more extra using Vimeo API. Also in this case we need to pass iframe element to Player class and this will be a little bit tricky, because Squarespace Videoloader dynamically adds video iframe in the moment you click Play button by default.  

2) Almost all communication with iframes using window.postMessage() method. And Vimeo iframe already post ready event message to our top window. After ready event we may tell the iframe to push other messages to main window and control the video also.

I found second way more simple and clean. So here is the logic: 

  1. Wait for window.onload ($(document).ready or Y.on('domready')) event to make sure Gallery was initialized.
  2. Subscribe to message event.
  3. Check for ready message and make sure it has vimeo url origin and iframe contentWindow is equal current active slide iframe.contentWindow (to be sure it is not message from some other iframe on page)
  4. Use addEventListener method to make iframe post proper messages to our window
  5. If this is event we are waiting for - call next Slide.
  6. After slide changed, check new slide for video, and play it.

Two words about 5 clause: I saw many code from devs, who trigger next/prev slide from code with simulating 'click'  on gallery controls (arrows). Well, it make sense, even if Squarespace will change something in their gallery code. But while I may retrieve galleries instance (with ability to call all other Gallery methods) from GalleryManager or from Gallery Node with code below, let me use that. 

<script>
    //array with galleries instances on page
    var all_galleries = Y.Squarespace.GalleryManager.getGalleries()
    //gallery instance from first gallery node on page.
    //you may use #gallery-block-id selector to choose the gallery you need
    var gallery = Y.one('.sqs-block-gallery .sqs-gallery').getData('gallery')
</script>

So I need to use this for first gallery on page and here is the full code you may inject to Header/Footer or Page Injection Tab:

<script>
function isVimeoUrl(url) {
    return ( /^(https?:)?\/\/(player.)?vimeo.com(?=$|\/)/.test(url)) ;
}
Y.on('domready', function() {
    var firstGallery = Y.one('.sqs-block-gallery .sqs-gallery');
    var gallery = firstGallery.getData('gallery');
    var autoplay_next_video = false;
    if (gallery) {
        gallery.after('currentIndexChange', function() {
            setTimeout(function() {
                if (firstGallery.one('.sqs-active-slide .sqs-video-wrapper') && autoplay_next_video) {
                    var videoloader = firstGallery.one('.sqs-active-slide .sqs-video-wrapper').videoloader;
                    videoloader.showVideo() && videoloader.play();
                    autoplay_next_video = false;
                }
            }, 500)
        })
    }
    window.addEventListener("message", function(e) {
        if (!isVimeoUrl(e.origin)) {
            return;
        }
        var data = e.data;
        if (JSON.parse(data) && firstGallery) {
            data = JSON.parse(data);
            var activeSlide = firstGallery.one('.sqs-active-slide');
            var video = activeSlide.one('.sqs-video-wrapper iframe');
            if (video) {
                if (video.getDOMNode().contentWindow !== e.source) {
                    return;
                }
                if (data.event == 'ready') {
               video.getDOMNode().contentWindow.postMessage('{"method": "addEventListener", "value": "ended"}', "*");
                    autoplay_next_video = false;
                } else if (video && data.event == 'finish') {
                    autoplay_next_video = true;
                    firstGallery.getData('gallery').nextSlide();
                }
            }
        }
    }, !1)
});
</script>