Skip to content

Instantly share code, notes, and snippets.

@wehrhaus
Last active August 29, 2015 14:07
Show Gist options
  • Save wehrhaus/44df4f22719ec170378f to your computer and use it in GitHub Desktop.
Save wehrhaus/44df4f22719ec170378f to your computer and use it in GitHub Desktop.
YouTube iFrame Video Loader - Over simplifies working with the YouTube iFrame API
// # YTVideoLoader.js
// Doc: []
// ## Namespacing
// * Namespace YTVideoLoader Object
// ### Public Methods Available:
// * YTVideoLoader.confirmAPIReady()
// * YTVideoLoader.destroyPlayer()
// * YTVideoLoader.playerControl()
// * YTVideoLoader.buildPlayer()
// * Additionally YTVideoLoader.PlayerSettings Object
var YTVideoLoader = (function () {
// Private Vars
var YTVL = {},
// YouTube iFrame API Path that gets loaded to the dom
youTubeAPIPath = 'https://www.youtube.com/iframe_api',
apiReady = false,
confirmAPIRecursor = null,
playerLocationCache = '',
// All Private Functions are declared here
Initialize = function () {},
resetPlayerSettings = function () {},
confirmAPIReady = function () {},
loadAPI = function () {},
loadNewPlayer = function () {},
setPlayerAttributes = function () {};
/**
* Player settings object
* - Temporary storage for current video settings
*/
YTVL.PlayerSettings = {
yt_currentPlayer: false,
yt_width: 200,
yt_height: 200,
yt_id: '',
yt_playerVars: {},
yt_location: 'youtube_player',
yt_autoplay: false
};
/**
* loadAPI()
* - Loads the YouTube iFrame API
* - Makes a required callback to onYouTubeIframeAPIReady() on load
* - onYouTubeIframeAPIReady() sits in the Global scope
* - onYouTubeIframeAPIReady() makes a callback to YTVL.confirmAPIReady()
* - this confirms that everything is loaded correctly in the event that it
* - gets called prematurely from another script
*/
loadAPI = function () {
var scriptTag = document.createElement('script'),
scriptPosition = document.getElementsByTagName('script')[0];
scriptTag.src = youTubeAPIPath;
scriptPosition.parentNode.insertBefore(scriptTag, scriptPosition);
};
/**
* loadNewPlayer()
* - creates new YT.Player object using YTVideoLoader.PlayerSettings
*/
loadNewPlayer = function (player) {
var playerVarObject = JSON.parse(player.yt_playerVars),
setAutoplay = function () {
if (player.yt_autoplay) {
return 1;
}
return 0;
};
player.yt_currentPlayer = new YT.Player(player.yt_location, {
playerVars: playerVarObject,
width: player.yt_width,
height: player.yt_height,
videoId: player.yt_id,
autoplay: setAutoplay(),
events: {
'onReady': function () {
// NOTE: fixes position:fixed issue with Samsung Galaxy S4
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('samsung-sgh') > -1) {
window.scrollTo(0, 0);
}
}
}
});
};
/**
* setPlayerAttributes()
* - Set YTVideoLoader.PlayerSettings based off
* - @item data attributes
*/
setPlayerAttributes = function (item) {
if (apiReady) {
var itemData = function (dataAttr) {
if (typeof item[0] !== 'undefined') {
item = item[0]; // used when jQuery object passed as item
}
return item.getAttribute(dataAttr);
};
if (YTVL.PlayerSettings.yt_currentPlayer === false) {
playerLocationCache = document.getElementById(itemData('data-yt-location')).outerHTML;
} else {
YTVL.destroyPlayer();
}
// set attributes of new player
YTVL.PlayerSettings.yt_location = itemData('data-yt-location');
YTVL.PlayerSettings.yt_id = itemData('data-yt-id');
YTVL.PlayerSettings.yt_width = itemData('data-yt-width');
YTVL.PlayerSettings.yt_height = itemData('data-yt-height');
YTVL.PlayerSettings.yt_playerVars = itemData('data-yt-playerVars');
YTVL.PlayerSettings.yt_autoplay = itemData('data-yt-autoplay');
return loadNewPlayer(YTVL.PlayerSettings);
}
};
/**
* YTVideoLoader.confirmAPIReady()
* - Confirm that YT obect is loaded
* - Once load is complete set @apiReady to true
* - Thow an error if API is not loaded after @recurseCount attempts
*/
YTVL.confirmAPIReady = function () {
var recurseCount = 10,
ytVerify = function () {};
ytVerify = function () {
if (typeof YT === 'undefined' && recurseCount > 0 && apiReady === false) {
confirmAPIRecursor = setTimeout(function () {
recurseCount = recurseCount - 1;
clearTimeout(confirmAPIRecursor);
loadAPI();
ytVerify();
}, 1000);
} else if (typeof YT !== 'undefined') {
apiReady = true;
clearTimeout(confirmAPIRecursor);
return apiReady;
} else {
apiReady = false;
clearTimeout(confirmAPIRecursor);
throw new Error('<!>YTVideoLoader --> Unable to load API');
}
};
ytVerify();
};
/**
* YTVideoLoader.destroyPlayer()
* - Hides iFrame to avoid ie8 hiccups
* - Resets player to original html or
* - replaces with passed in @html string
*/
YTVL.destroyPlayer = function (htmlString) {
try {
htmlString = htmlString || playerLocationCache;
var currIFrame = YTVL.PlayerSettings.yt_currentPlayer.getIframe();
currIFrame.style.display = 'none';
document.getElementById(YTVL.PlayerSettings.yt_location).outerHTML = htmlString;
} catch (err) {
// NOTE: If modal cleared out prior to this call nothing to destroy
return true;
}
};
/**
* YTVideoLoader.playerControl(@instruction)
* - Accepts 'pause', 'play', 'stop'
*/
YTVL.playerControl = function (instruction) {
var control = {
'pause': function () {
YTVL.PlayerSettings.yt_currentPlayer.pauseVideo();
},
'play': function () {
YTVL.PlayerSettings.yt_currentPlayer.playVideo();
},
'stop': function () {
YTVL.PlayerSettings.yt_currentPlayer.stopVideo();
}
};
if (control[instruction]) {
return control[instruction]();
} else {
throw new Error('<!>YTVideoLoader --> Instruction not recognized');
}
};
/**
* YTVideoLoader.buildPlayer(@item)
*/
YTVL.buildPlayer = function (item) {
setPlayerAttributes(item);
};
Initialize = (function () {
YTVL.confirmAPIReady('YTVL.confirmAPIReady');
}());
return YTVL;
}());
var onYouTubeIframeAPIReady = function () {
YTVideoLoader.confirmAPIReady();
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example | YouTube iFrame Video Loader</title>
</head>
<body>
<h2>YouTube API Tests using YTVideoLoader.js Module:</h2>
<h3>Requirements:</h3>
<strong>YTVideoLoader.js</strong>
<strong><em>jQuery is NOT required</em></strong>
<h4>Examples:</h4>
<em>Click below to view video</em>
<!-- Simplest Version only passes data-yt-location and data-yt-id -->
<div class="action youtube_init" data-yt-location="youtube_player" data-yt-id="PN8Eg1K9xjE">Only Required Params</div>
<!-- Passing additional data-yt-width and data-yt-height parameters -->
<div class="action youtube_init" data-yt-location="youtube_player" data-yt-id="AcT0gvSjlsE" data-yt-width="640" data-yt-height="390" data-yt-autoplay="true">All Params Plus Autoplay</div>
<!-- Passing Player Vars:
Note: data-yt-playerVars attribute must be wrapped in single quotes and json data wrapped in double quotes -->
<div id="test" class="action youtube_init" data-yt-location="youtube_player" data-yt-id="c-kav7Tf834" data-yt-width="920" data-yt-height="480" data-yt-playerVars='{"controls":0,"rel":0}'>All Params Except Autoplay<br>No Controls, No Related Videos</div>
<p>Player Controls:</p>
<div class="action control play">Play Current Video</div>
<div class="action control stop">Stop Current</div>
<div class="action control pause">Pause Current</div>
<div class="action destroy">Destroy Current</div>
<p>Destroy can also accept replacement html</p>
<div class="action destroy">Destroy with <span class="replacementHTML">&lt;h2&gt;HEY&lt;/h2&gt;</span></div>
<div id="playerContainer">
<p>Player Container:</p>
<div id="youtube_player"></div>
</div>
<script src="YTVideoLoader.js"></script>
<script>
$(document).ready(function () {
var loadVideoModule = function () {};
var initVideoMod = function (item) {
alert(item);
YTVideoLoader.buildPlayer($(this));
};
// This example binds click events to all '.youtube_init' elements
// and, when clicked, passes the element over to YTVideoLoader.buildPlayer(@element)
// which will handle everything from there.
loadVideoModule = function () {
if (typeof YTVideoLoader === 'object') {
$('.youtube_init').on('click', initVideoMod);
/*
$('.youtube_init').on('click', function (evt) {
YTVideoLoader.buildPlayer($(this));
});
*/
} else {
setTimeout(function () {
loadVideoModule();
}, 500);
}
};
loadVideoModule();
// This example binds click events to all '.control' elements and
// passes the corresponding 'instruction' via control class to YTVideoLoader.playerControl(@instruction)
$('.control').on('click', function (evt) {
var instruction = $(this).attr('class').replace('action control ', '');
YTVideoLoader.playerControl(instruction);
});
// This example binds click events to all '.destroy' elements and
// destroys the current video, if '.replacementHTML' exists it is passed to the
// YTVideoLoader.destroyPlayer(@htmlString) method
$('.destroy').on('click', function () {
YTVideoLoader.destroyPlayer($(this).find('.replacementHTML').text());
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment