Skip to content

Instantly share code, notes, and snippets.

@FranciscoG
Last active August 10, 2016 15:33
Show Gist options
  • Save FranciscoG/d61eb9342a5728e0a646e6ce0b0ec8d7 to your computer and use it in GitHub Desktop.
Save FranciscoG/d61eb9342a5728e0a646e6ce0b0ec8d7 to your computer and use it in GitHub Desktop.
(function( $ ) {
"use strict";
/**
* jQuery.videoSwap.js
* by: https://gist.github.com/FranciscoG
*
* Switches between a silent teaser video and a full video
* Uses html5 <video>
* Very very basic "mobile" support solely based on window width
*
* Options:
* teaser: a looping silent short teaser video.
* video: a full audio video, when it ends it reverts back to the loop
* playBtn: external play button that triggers the swap from teaser to full video
*
* When using more than one <source>, name your files EXACTLY THE SAME (including paths)
* and remove the file extensions.
*
* Examples:
* teaser : "/public/video/my-video"
* OR
* teaser : "https://cdn.videohost.com/my-video"
*
* TODO: allow different file names and accept arrays in teaser/video options
* TODO: Codepen demo
*/
function requestFullScreen(element) {
// Supports most browsers and their versions.
var requestMethod = element.requestFullScreen ||
element.webkitRequestFullScreen ||
element.mozRequestFullScreen;
if (requestMethod) {
requestMethod.call(element);
}
}
// Exit fullscreen
function exitFullScreen(){
var requestMethod = document.exitFullscreen ||
document.mozCancelFullScreen ||
document.webkitExitFullscreen;
if (requestMethod) {
requestMethod.call(document);
}
}
$.fn.videoSwap = function( options ) {
if (!options) {
options = {};
}
var player = this.get(0); // the actual DOM and not jQuery obj
var $player = this; // it's more declarative for me than using "this"
var whichVideo = 'teaser';
var $sources = null;
var defaults = {
teaser: null, // required - src location
video: null, // required - src location
playBtn: null // required - play button selector
};
var settings = $.extend({}, defaults, options);
var $playBtn = $(settings.playBtn);
var isMobile = $(window).width() <= 414; // iPhone 6plus
var checkRequired = function(){
var result = true;
if (!$playBtn.length || !settings.playBtn){
result = false;
console.warn("VideoSwapper: playBtn element missing");
}
if (!settings.teaser){
result = false;
console.warn("VideoSwapper: ID for the looping video is missing");
}
if (!settings.video){
result = false;
console.warn("VideoSwapper: ID for the main video is missing");
}
return result;
};
function progressEvents() {
var prog25reached = false;
var prog50reached = false;
var prog75reached = false;
$player.on('timeupdate, seeked', function () {
var percent = (100 / player.duration) * player.currentTime;
if (percent >= 25 && !prog25reached) {
$player.trigger('videoSwap:progress', [whichVideo, '25%'] );
prog25reached = true;
}
if (percent >= 50 && !prog50reached) {
$player.trigger('videoSwap:progress', [whichVideo, '50%']);
prog50reached = true;
}
if (percent >= 75 && !prog75reached) {
$player.trigger('videoSwap:progress', [whichVideo, '75%']);
prog75reached = true;
}
});
$player.on('ended', function () {
prog25reached = false;
prog50reached = false;
prog75reached = false;
});
}
var switchSources = function(which) {
for (var type in $sources) {
$sources[type].attr('src', which + '.' + type);
}
};
var resetPlayer = function(){
whichVideo = 'teaser';
$player.trigger('videoSwap:switch', [whichVideo]);
switchSources(settings.teaser);
player.controls = false;
setTimeout(function () {
exitFullScreen();
player.muted = true;
player.volume = 0;
player.play();
}, 150);
};
var playMainVideo = function(){
whichVideo = 'video';
$player.trigger('videoSwap:switch', [whichVideo]);
switchSources(settings.video);
player.controls = true;
player.load();
setTimeout(function () {
if (isMobile) {
requestFullScreen(player);
}
player.play();
player.muted = false;
player.volume = 1.0;
// add the end listener to switch back
$player.one('ended', function () {
resetPlayer();
});
}, 150);
};
var setupBtn = function(){
$playBtn.on('click', function(){
if (typeof settings.onPlay === 'function') {
settings.onPlay();
}
player.pause();
playMainVideo();
});
};
var getSrc = function($el){
var _tmp = $el.attr('src').split(".");
// just in case the video has more periods in it
return _tmp[_tmp.length - 1] ;
};
var setupSources = function($ctx){
var $sources = {};
var sources = $ctx.find('source');
if (sources.length > 0) {
sources.each(function(i,el){
var src = getSrc($(el));
$sources[src] = $(el);
});
} else {
// get the source from the <video> element itself
var src = getSrc($player);
$sources[src] = $player;
}
return $sources;
};
/**********************************************
* Init stuff
*/
if (!checkRequired()) { return this; }
$sources = setupSources($player);
setupBtn();
if (!isMobile) {
// loop the video because for some reason the loop attribute doesn't work on localhost
$player.on('ended', function () {
this.load();
setTimeout(function () {
player.play();
}, 150);
});
}
progressEvents();
return this; // for chainability
};
/* global $, jQuery */
}( jQuery ));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment