Last active
August 10, 2016 15:33
-
-
Save FranciscoG/d61eb9342a5728e0a646e6ce0b0ec8d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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