/**
* Complex TV Youtube Recommended
*
* @author Jonathan Crockett
* @version 1.0.0
* @data 2/11/14
* @param {object} userOptions
* {
selector: '#youtube-player', (required)
auotplayTimeout: 40000, (optional)
channelSlug: 'music' (optional)
};
@desecription Finds all the youtube iframe players specified in the selector and displays a
Complex TV ooyala player widget over the video when it completes. Supports modern browsers desktop & mobile. IE9+
@usage:
ytRecWidget({
selector: '#youtube-player',
autoplayTimeout: 40000,
channelSlug: 'music'
});
@link git@gitlab.complexmedianetwork.com:jonathanc/youtube-overlay-widget.git
*/
var ytRecWidget = function (userOptions) {
// No IE8
if (!window.addEventListener) {
return false;
}
if (!userOptions.hasOwnProperty('selector')) {
console.log('ytRecWidget error: No selector specified');
return false;
}
var ytIframeEmbeds, ooRecWidgets = [], options = {}, autoIdPrefix = 'yt-player-id-', videoAutoPlayed = false;
var defaultOptions = {
selector: '',
autoplayTimeout: 8000,
channelSlug: ''
};
for (var x in defaultOptions) {
options[x] = userOptions[x] ? userOptions[x] : defaultOptions[x];
}
/**
* Gets all the youtube iframe embeds on the page based on the selector.
* Also adds wmode transparent which is need for the widget to display properly in IE.
* @return {[type]}
*/
function getYTiFrameEmbeds() {
var youtubeIframeEmbeds = document.querySelectorAll(options.selector), appendUrlParams;
for (var x = 0; x < youtubeIframeEmbeds.length; x++) {
appendUrlParams = '';
// Assigns ID to iframe if one does not exists. This is needed to hook in the youtube API.
if (!youtubeIframeEmbeds[x].id) {
youtubeIframeEmbeds[x].id = autoIdPrefix + x;
}
// Need to add this param for overlay on IE.
if (!/mode=transparent/.test(youtubeIframeEmbeds[x].src)) {
if (/\?/.test(youtubeIframeEmbeds[x].src)) {
appendUrlParams += '&wmode=transparent';
} else {
appendUrlParams += '?wmode=transparent';
}
}
// Need to add this param for overlay on IE.
if (!/enablejsapi=1/.test(youtubeIframeEmbeds[x].src)) {
if (/\?/.test(youtubeIframeEmbeds[x].src) || appendUrlParams) {
appendUrlParams += '&enablejsapi=1';
} else {
appendUrlParams += '?enablejsapi=1';
}
}
if (appendUrlParams) {
youtubeIframeEmbeds[x].src += appendUrlParams;
}
}
return youtubeIframeEmbeds;
}
/**
* creates and returns the Oyalla recommended widget object exposing "show" method.
* @param {HTML Iframe Element} youtubePlayer
* @param {int} widgetIndex
* @return {Object}
*/
function ooRecWidget(youtubePlayer, widgetIndex) {
var overlayDiv, throttleTimeout,
videoApiUrl,
videoAutoPlayTimeout,
videoAutoPlay = options.autoplayTimeout,
widgetId = "ooyala-rec-widget-" + widgetIndex;
/**
* Resizes the overlay player div to fit the youtube embed.
* @return {[type]}
*/
function resizeOverlayPlayerDiv() {
if (!overlayDiv) {
return;
}
overlayDiv.style.left = youtubePlayer.offsetLeft + 'px';
overlayDiv.style.top = youtubePlayer.offsetTop + 'px';
overlayDiv.style.width = youtubePlayer.offsetWidth + 'px';
overlayDiv.style.height = youtubePlayer.offsetHeight + 'px';
}
/**
* Creates the widget dif to overlay over the youtube player.
* @return {[type]} [description]
*/
function createWidgetElement() {
overlayDiv = document.createElement('div');
overlayDiv.id = widgetId;
overlayDiv.className = "ooyala-rec-widget";
overlayDiv.style.position = 'absolute';
overlayDiv.style.zIndex = '1000000';
resizeOverlayPlayerDiv();
overlayDiv.style.backgroundColor = "#000";
overlayDiv.innerHTML = '';
youtubePlayer.parentNode.appendChild(overlayDiv);
}
/**
* Retrieves and displays the ComplexTV vids from the API.
*/
function getOOVids() {
var relatedVidsHTML = '';
if (options.channelSlug) {
videoApiUrl = 'http://www.complex.com/tv/api/labels/original/latest_videos/' + options.channelSlug;
} else {
videoApiUrl = 'http://www.complex.com/tv/api/videos/original/latest';
}
var oReq = createCORSRequest('GET', videoApiUrl);
oReq.open("GET", videoApiUrl, true);
oReq.responseType = "text";
oReq.onload = function (evt) {
var response = JSON.parse(oReq.responseText), marker;
// The latest_videos api link returns an object with a data prop.
if (response.data) {
response = response.data;
}
for (var x = 0; x < 2 && x < response.length; x++) {
_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', 'Thumbnail Load', response[x].name]);
relatedVidsHTML += '
';
}
overlayDiv.innerHTML = '' + relatedVidsHTML;
videoAutoPlayTimeout = setTimeout(function () {
//user didn't click on thumbnail, video autoplays fired
//_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', 'AutoPlay', response[0].display_title]);
loadAndPlayOyallaPlayer(response[0].embed_code, response[0].display_title, 'AutoPlay');
}, videoAutoPlay);
marker = document.querySelectorAll('#' + widgetId + ' .cplx-related-vid-progress-mark')[0];
marker.parentNode.style.display = 'block';
// Need to wrap in timeout so that the dom has time to initialize for the css property.
setTimeout(function() {
var seconds = videoAutoPlay / 1000;
marker.style.webkitTransition = "width " + seconds + "s linear";
marker.style.oTransition = "width " + seconds + "s linear";
marker.style.msTransition = "width " + seconds + "s linear";
marker.style.mozTransition = "width " + seconds + "s linear";
marker.style.transition = "width " + seconds + "s linear";
marker.style.width = "100%";
}, 100);
document.getElementById(widgetId).addEventListener('click', videoClickCallback, false);
};
oReq.send();
}
/**
* Creates the dom elements and displays the widget
* @return {void}
*/
function show() {
if (!overlayDiv) {
createWidgetElement();
_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', 'Load Complete', 'Overlay loaded']);
getOOVids();
} else {
overlayDiv.style.display = 'block';
}
}
/**
* Creates the dom elements and displays the widget
* @return {void}
*/
function hide() {
if (overlayDiv) {
overlayDiv.style.display = 'none';
}
}
/**
* Plays the video
* @param {clickEvent} evt
* @return {void}
*/
function videoClickCallback(evt) {
var parentElement = evt.target.parentNode.parentNode;
var titleEl = parentElement.querySelector('h3');
var title = titleEl.innerHTML;
//_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', 'Click', title]);
clearTimeout(videoAutoPlayTimeout);
if (evt.target.className === 'cplx-related-vid') {
loadAndPlayOyallaPlayer(evt.target.getAttribute('data-embedcode'), title, 'Click');
} else if (evt.target.parentNode.className === 'cplx-related-vid') {
loadAndPlayOyallaPlayer(evt.target.parentNode.getAttribute('data-embedcode'), title, 'Click');
} else if (evt.target.parentNode.parentNode.className === 'cplx-related-vid') {
loadAndPlayOyallaPlayer(evt.target.parentNode.parentNode.getAttribute('data-embedcode'), title, 'Click');
}
}
function loadAndPlayOyallaPlayer(oyallaId, title, eventType) {
var player = OO.Player.create(widgetId, oyallaId);
if(player.mb != undefined){
mesb = player.mb;
mesb.subscribe(OO.EVENTS.PLAYING, 'ComplexYouTubeOverlay',
function(eventName) {
if(!videoAutoPlayed){
_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', eventType, title]);
videoAutoPlayed = true;
}
});
mesb.subscribe(OO.EVENTS.WILL_PLAY_ADS, 'ComplexYouTubeOverlay',
function(eventName) {
if(!videoAutoPlayed){
_gaq.push(['ComplexYouTubeOverlay._trackEvent', 'ComplexYouTubeOverlay', eventType, title]);
videoAutoPlayed = true;
}
});
}
player.play();
}
/**
* Cross browser AJAX request object
* @param {[type]} method
* @param {[type]} url
* @return {[type]}
*/
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest !== "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
window.addEventListener('resize', function () {
clearTimeout(throttleTimeout);
throttleTimeout = setTimeout(resizeOverlayPlayerDiv, 200);
}, false);
window.addEventListener('orientationchange', resizeOverlayPlayerDiv);
return {
show: show,
hide: hide,
};
}
/**
* Loads the dependancy scripts
* @return {void}
*/
function loadScripts() {
var oyallaScript, youtubeScript;
if (typeof YT === 'undefined') {
youtubeScript = document.createElement('script');
youtubeScript.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(youtubeScript, firstScriptTag);
}
if (typeof OO === 'undefined') {
oyallaScript = document.createElement('script');
oyallaScript.setAttribute("type", "text/javascript");
oyallaScript.setAttribute("src", 'http://player.ooyala.com/v3/556f8260656c47a4ab49bf6f2dde85f3?platform=html5-fallback');
if (typeof oyallaScript !== "undefined") {
document.getElementsByTagName("head")[0].appendChild(oyallaScript);
}
}
}
function youtubeVideoComplete(evt) {
if (evt.data === YT.PlayerState.ENDED) {
if (document.getElementById(evt.target.a.id).hasOwnProperty('ooRecWigetIndex')) {
ooRecWidgets[document.getElementById(evt.target.a.id).ooRecWigetIndex].show();
}
}
}
// Load script dependancies
loadScripts();
ytIframeEmbeds = getYTiFrameEmbeds();
if (ytIframeEmbeds.length === 0) {
return false;
}
// Creates Oyalla recommended widget objects and assigns widget index to iframe embeds.
for (var y = 0; y < ytIframeEmbeds.length; y++) {
ooRecWidgets.push(ooRecWidget(ytIframeEmbeds[y], y));
// Create pointer to rec windget index so it can be accessed within the yt event playback complete callback.
ytIframeEmbeds[y].ooRecWigetIndex = y;
}
// Callback from youtube api
window.onYouTubeIframeAPIReady = function (evt) {
var players = [];
// Iterates through the iframe yt players and assigns callbacks to load the OO rec widget.
for (var x = 0; x < ytIframeEmbeds.length; x++) {
players.push(new YT.Player(ytIframeEmbeds[x].id, {
events: {
'onStateChange': youtubeVideoComplete
}
}));
}
};
};