1

I'd like to launch a second tubular instance an x ammount of seconds after the first one is playing.

I'm using 2 div's to attach the player to

<div id="player1"></div>
<div id="player2"></div>

I have 2 scripts that launch tubular.

var options = { 
            videoId: ytid, 
            start: diffInSeconds, 
            mute: false, 
            width: $(window).width(), 
            height:$(window).height(),
            playercount: 1
            };

$('#player' + options.playercount).tubular(options);

It succesfully launches the first tubular instance. When the second instance playercount: 2 should launch it only appends the tubular containers and shield, not the iframe.

Only player1 is loaded.

I've added console logs to monitor whether the instances are getting loaded.

Console log

Here's a link to the jquery.rhtv.init.js (this calls the tubular function).

http://nopaste.linux-dev.org/?833094

And here's a link to the modified tubular JS:

http://nopaste.linux-dev.org/?833101

This is all running live on:

http://www.realhardstyle.tv

How can I manage to get the youtube iframe loaded in the second instance (and further on), The end result should be a non-stop playing stream of youtube video's. Where for every video that has been started a 'now playing' div should appear (like in the jquery.rhtv.init.js)

Thank you in Advance!

John Slegers
  • 45,213
  • 22
  • 199
  • 169
GRX
  • 479
  • 1
  • 5
  • 22

2 Answers2

2

The problem you are experiencing is due to how you are initializing tubular. If you wish for both players to use the same options, you'll want to add a class to the players and initialize tubular using that class name. For this example, let's add the class name tubular-player to our containers and initialize tubular for each class that is present.

HTML

<div id="player1" class="tubular-player"></div>
<div id="player2" class="tubular-player"></div>

JavaScript

$('.tubular-player').tubular(options);
anthonysmothers
  • 307
  • 1
  • 6
1

Tubular library does not support the reloading of a different video by default. I have made some tweaks so that it can be done.

Following is the working jsfiddle link:

*Edits

Following library now supports videoFinshed callback and multiple calls to tubular

http://jsfiddle.net/j1t9zwx6/3/

There are movie trailers playing back to back.

Also attaching the code here for backup

Modified tubular library:

/* jQuery tubular plugin
|* by Sean McCambridge
|* http://www.seanmccambridge.com/tubular
|* version: 1.0
|* updated: October 1, 2012
|* since 2010
|* licensed under the MIT License
|* Enjoy.
|* 
|* Thanks,
|* Sean */

//modified tubular library, to support multiple calls to tubular and videoFinished callback //
(function ($, window) {

    // test for feature support and return if failure

    // defaults
    var defaults = {
        ratio: 16/9, // usually either 4/3 or 16/9 -- tweak as needed
        videoId: 'ZCAnLxRvNNc', // toy robot in space is a good default, no?
        mute: true,
        repeat: true,
        width: $(window).width(),
        wrapperZIndex: 99,
        playButtonClass: 'tubular-play',
        pauseButtonClass: 'tubular-pause',
        muteButtonClass: 'tubular-mute',
        volumeUpClass: 'tubular-volume-up',
        volumeDownClass: 'tubular-volume-down',
        increaseVolumeBy: 10,
        start: 0,
        playercount: 1,
        videoFinished: function () {}
    };
    // methods

    var options = null; // options
    var tubularOnceCalled = false;
    window.player = null;

    var tubular = function(node, paramOptions) {     // should be called on the wrapper div
        options = $.extend({}, defaults, paramOptions),
            $body = $(node) // cache body node
            $node = $(node); // cache wrapper node

        // set up iframe player, use global scope so YT api can talk
        var loadAVideo = function() {
            player && player.destroy();
            player = new YT.Player('tubular-player' + options.playercount , {
                width: options.width,
                height: Math.ceil(options.width / options.ratio),
                videoId: options.videoId,
                playerVars: {
                    iv_load_policy: 3,
                    controls: 0,
                    showinfo: 0,
                    modestbranding: 1,
                    wmode: 'transparent'
                },
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
        }

        if(tubularOnceCalled) {
            loadAVideo();
            return;
        }

        tubularOnceCalled = true;
        // build container
        var tubularContainer = '<div id="tubular-container' + options.playercount + '" style="overflow: hidden; position: fixed; z-index: 1; width: 100%; height: 100%"><div id="tubular-player' + options.playercount + '" style="position: absolute"></div></div><div id="tubular-shield' + options.playercount + '" style="width: 100%; height: 100%; z-index: 2; position: absolute; left: 0; top: 0;"></div>';

        // set up css prereq's, inject tubular container and set up wrapper defaults
        $('html,body').css({'width': '100%', 'height': '100%'});
        $body.prepend(tubularContainer);
        $node.css({position: 'relative', 'z-index': options.wrapperZIndex});

        window.onYouTubeIframeAPIReady = loadAVideo;
        console.log('Player ' + options.playercount + ' is initiating')
        window.onPlayerReady = function(e) {
            resize();
            if (options.mute) e.target.mute();
            e.target.seekTo(options.start);
            e.target.playVideo();
            $('#loadcontainer').delay(1000).fadeOut('slow');
            $('html').delay(3000).rhtvinit();
            console.log('Player ' + options.playercount + ' has started')    
        }

        window.onPlayerStateChange = function(state) {
            if (state.data === 0 && options.repeat) { // video ended and repeat option is set true
                player.seekTo(options.start); // restart
            }
            if(state.data === 0) {
                options.videoFinished(state, player);
            }
        }

        var playdetect = 0;

        // resize handler updates width, height and offset of player after resize/init
        var resize = function() {
            var width = $(window).width(),
                pWidth, // player width, to be defined
                height = $(window).height(),
                pHeight, // player height, tbd
                $tubularPlayer = $('#tubular-player' + options.playercount);

            // when screen aspect ratio differs from video, video must center and underlay one dimension

            if (width / options.ratio < height) { // if new video height < window height (gap underneath)
                pWidth = Math.ceil(height * options.ratio); // get new player width
                $tubularPlayer.width(pWidth).height(height).css({left: (width - pWidth) / 2, top: 0}); // player width is greater, offset left; reset top
            } else { // new video width < window width (gap to right)
                pHeight = Math.ceil(width / options.ratio); // get new player height
                $tubularPlayer.width(width).height(pHeight).css({left: 0, top: (height - pHeight) / 2}); // player height is greater, offset top; reset left
            }

        }

        // events
        $(window).on('resize.tubular', function() {
            resize();
        })

        $('body').on('click','.' + options.playButtonClass, function(e) { // play button
            e.preventDefault();
            player.playVideo();
        }).on('click', '.' + options.pauseButtonClass, function(e) { // pause button
            e.preventDefault();
            player.pauseVideo();
        }).on('click', '.' + options.muteButtonClass, function(e) { // mute button
            e.preventDefault();
            (player.isMuted()) ? player.unMute() : player.mute();
        }).on('click', '.' + options.volumeDownClass, function(e) { // volume down button
            e.preventDefault();
            var currentVolume = player.getVolume();
            if (currentVolume < options.increaseVolumeBy) currentVolume = options.increaseVolumeBy;
            player.setVolume(currentVolume - options.increaseVolumeBy);
        }).on('click', '.' + options.volumeUpClass, function(e) { // volume up button
            e.preventDefault();
            if (player.isMuted()) player.unMute(); // if mute is on, unmute
            var currentVolume = player.getVolume();
            if (currentVolume > 100 - options.increaseVolumeBy) currentVolume = 100 - options.increaseVolumeBy;
            player.setVolume(currentVolume + options.increaseVolumeBy);
        })
    }

    // load yt iframe js api

    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    // create plugin

    $.fn.tubular = function (options) {
        return this.each(function () {
                $.data(this, tubular(this, options));
                console.log('Player: ' + options.playercount + ' is initiated!')
        });
    }

})(jQuery, window);

Sample usage to load videos back to back

$(function () {
    var videoArr = ["InqU8CLwbPg", "owgrkAQ-Log", "UgBWSPD6MUU"];
    var vidI = 0;

    try {
        $('#wrapper').tubular({
            videoId: videoArr[vidI], 
            mute: false,
            videoFinished: function (state, player) {
                vidI++;
                vidI %= videoArr.length;
                var nextVideo = videoArr[vidI];/* it can directly be loaded from server */
                player.loadVideoById(nextVideo);
            }
        });
    } catch(e) {
    }
});
11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • But is it possible to dynamic load a new video ID? So that if the 1st video ends -> second video starts -> first video container gets a new youtube ID -> second video ends -> first video starts and so on and on. – GRX Nov 23 '15 at 08:14
  • You don't already have the ID's of videos that you want to show as background of your site ? If you already have them and you don't want to print entire list in the HTML or js, then you can always load the nextId from server using Ajax. – 11thdimension Nov 23 '15 at 08:20
  • There is a script running on the server that mimics a "player" so everytime someone gets on my website it should load the video ID of the current playing video and how many seconds from start it should be playing. (The livestream effect) So whenever a track is finished, it should receive a new video ID from the "player" script in order to continue playing. Is it possible to realize this? – GRX Nov 23 '15 at 09:32
  • Yes it is, I have made some more modifications to make it possible through tubular itself. See the changes and the new jsfiddle link. I hope this is what you need. – 11thdimension Nov 24 '15 at 00:42
  • Well it is initialising, and it's also playing a dynamicly loaded que! Can we edit the script minor, So the nextvideo will start on interval instead of videostate and on the moment it start. it should also execute another function? – GRX Nov 24 '15 at 16:25