423 lines
12 KiB
JavaScript
Executable File
423 lines
12 KiB
JavaScript
Executable File
/*
|
|
BigVideo - The jQuery Plugin for Big Background Video (and Images)
|
|
by John Polacek (@johnpolacek)
|
|
|
|
Dual licensed under MIT and GPL.
|
|
|
|
Dependencies: jQuery, jQuery UI (Slider), Video.js, ImagesLoaded
|
|
*/
|
|
|
|
(function (factory) {
|
|
'use strict';
|
|
if (typeof define === 'function' && define.amd) {
|
|
// Register as an anonymous AMD module:
|
|
define([
|
|
'jquery',
|
|
'videojs',
|
|
'imagesloaded',
|
|
'jquery-ui'
|
|
], factory);
|
|
} else {
|
|
factory(jQuery, videojs);
|
|
}
|
|
})(function($, videojs) {
|
|
|
|
$.BigVideo = function(options) {
|
|
|
|
var defaults = {
|
|
// If you want to use a single mp4 source, set as true
|
|
useFlashForFirefox:true,
|
|
// If you are doing a playlist, the video won't play the first time
|
|
// on a touchscreen unless the play event is attached to a user click
|
|
forceAutoplay:false,
|
|
controls:false,
|
|
doLoop:false,
|
|
container:$('body'),
|
|
shrinkable:false
|
|
};
|
|
|
|
var BigVideo = {},
|
|
player,
|
|
vidEl = '#big-video-vid',
|
|
wrap = $('<div id="big-video-wrap"></div>'),
|
|
video = $(''),
|
|
mediaAspect = 16/9,
|
|
vidDur = 0,
|
|
defaultVolume = 0.8,
|
|
isInitialized = false,
|
|
isSeeking = false,
|
|
isPlaying = false,
|
|
isQueued = false,
|
|
isAmbient = false,
|
|
playlist = [],
|
|
currMediaIndex,
|
|
currMediaType;
|
|
|
|
var settings = $.extend({}, defaults, options);
|
|
|
|
function updateSize() {
|
|
var containerW = settings.container.outerWidth() < $(window).width() ? settings.container.outerWidth() : $(window).width(),
|
|
containerH = settings.container.outerHeight() < $(window).height() ? settings.container.outerHeight() : $(window).height(),
|
|
containerAspect = containerW/containerH;
|
|
|
|
if (settings.container.is($('body'))) {
|
|
$('html,body').css('height',$(window).height() > $('body').css('height','auto').height() ? '100%' : 'auto');
|
|
}
|
|
|
|
if (containerAspect < mediaAspect) {
|
|
// taller
|
|
if (currMediaType == 'video') {
|
|
player
|
|
.width(containerH*mediaAspect)
|
|
.height(containerH);
|
|
if (!settings.shrinkable) {
|
|
$(vidEl)
|
|
.css('top',0)
|
|
.css('left',-(containerH*mediaAspect-containerW)/2)
|
|
.css('height',containerH);
|
|
} else {
|
|
$(vidEl)
|
|
.css('top',-(containerW/mediaAspect-containerH)/2)
|
|
.css('left',0)
|
|
.css('height',containerW/mediaAspect);
|
|
}
|
|
$(vidEl+'_html5_api')
|
|
.css('width',containerH*mediaAspect)
|
|
.css('height',containerH);
|
|
$(vidEl+'_flash_api')
|
|
.css('width',containerH*mediaAspect)
|
|
.css('height',containerH);
|
|
} else {
|
|
// is image
|
|
$('#big-video-image')
|
|
.css({
|
|
width: 'auto',
|
|
height: containerH,
|
|
top:0,
|
|
left:-(containerH*mediaAspect-containerW)/2
|
|
});
|
|
}
|
|
} else {
|
|
// wider
|
|
if (currMediaType == 'video') {
|
|
player
|
|
.width(containerW)
|
|
.height(containerW/mediaAspect);
|
|
$(vidEl)
|
|
.css('top',-(containerW/mediaAspect-containerH)/2)
|
|
.css('left',0)
|
|
.css('height',containerW/mediaAspect);
|
|
$(vidEl+'_html5_api')
|
|
.css('width',$(vidEl+'_html5_api').parent().width()+"px")
|
|
.css('height','auto');
|
|
$(vidEl+'_flash_api')
|
|
.css('width',containerW)
|
|
.css('height',containerW/mediaAspect);
|
|
} else {
|
|
// is image
|
|
$('#big-video-image')
|
|
.css({
|
|
width: containerW,
|
|
height: 'auto',
|
|
top:-(containerW/mediaAspect-containerH)/2,
|
|
left:0
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function initPlayControl() {
|
|
// create video controls
|
|
var markup = ''+
|
|
'<div id="big-video-control-container">'+
|
|
'<div id="big-video-control">'+
|
|
'<a href="#" id="big-video-control-play"></a>'+
|
|
'<div id="big-video-control-middle">'+
|
|
'<div id="big-video-control-bar">'+
|
|
'<div id="big-video-control-bound-left"></div>'+
|
|
'<div id="big-video-control-progress"></div>'+
|
|
'<div id="big-video-control-track"></div>'+
|
|
'<div id="big-video-control-bound-right"></div>'+
|
|
'</div>'+
|
|
'</div>'+
|
|
' <div id="big-video-control-timer"></div>'+
|
|
'</div>'+
|
|
'</div>';
|
|
settings.container.append(markup);
|
|
|
|
// hide until playVideo
|
|
$('#big-video-control-container').css('display','none');
|
|
$('#big-video-control-timer').css('display','none');
|
|
|
|
// add events
|
|
$('#big-video-control-track').slider({
|
|
animate: true,
|
|
step: 0.01,
|
|
slide: function(e,ui) {
|
|
isSeeking = true;
|
|
$('#big-video-control-progress').css('width',(ui.value-0.16)+'%');
|
|
player.currentTime((ui.value/100)*player.duration());
|
|
},
|
|
stop:function(e,ui) {
|
|
isSeeking = false;
|
|
player.currentTime((ui.value/100)*player.duration());
|
|
}
|
|
});
|
|
$('#big-video-control-bar').click(function(e) {
|
|
player.currentTime((e.offsetX/$(this).width())*player.duration());
|
|
});
|
|
$('#big-video-control-play').click(function(e) {
|
|
e.preventDefault();
|
|
playControl('toggle');
|
|
});
|
|
player.on('timeupdate', function() {
|
|
if (!isSeeking && (player.currentTime()/player.duration())) {
|
|
var currTime = player.currentTime();
|
|
var minutes = Math.floor(currTime/60);
|
|
var seconds = Math.floor(currTime) - (60*minutes);
|
|
if (seconds < 10) seconds='0'+seconds;
|
|
var progress = player.currentTime()/player.duration()*100;
|
|
$('#big-video-control-track').slider('value',progress);
|
|
$('#big-video-control-progress').css('width',(progress-0.16)+'%');
|
|
$('#big-video-control-timer').text(minutes+':'+seconds+'/'+vidDur);
|
|
}
|
|
});
|
|
}
|
|
|
|
function playControl(a) {
|
|
var action = a || 'toggle';
|
|
if (action == 'toggle') action = isPlaying ? 'pause' : 'play';
|
|
if (action == 'pause') {
|
|
player.pause();
|
|
$('#big-video-control-play').css('background-position','-16px');
|
|
isPlaying = false;
|
|
|
|
} else if (action == 'play') {
|
|
player.play();
|
|
$('#big-video-control-play').css('background-position','0');
|
|
isPlaying = true;
|
|
} else if (action == 'skip') {
|
|
nextMedia();
|
|
}
|
|
}
|
|
|
|
function setUpAutoPlay() {
|
|
player.play();
|
|
settings.container.off('click',setUpAutoPlay);
|
|
}
|
|
|
|
function nextMedia() {
|
|
currMediaIndex++;
|
|
if (currMediaIndex === playlist.length) currMediaIndex=0;
|
|
playVideo(playlist[currMediaIndex]);
|
|
}
|
|
|
|
function playVideo(source) {
|
|
|
|
// clear image
|
|
$(vidEl).css('display','block');
|
|
currMediaType = 'video';
|
|
player.src(source);
|
|
isPlaying = true;
|
|
if (isAmbient) {
|
|
$('#big-video-control-container').css('display','none');
|
|
player.ready(function(){
|
|
player.volume(0);
|
|
});
|
|
doLoop = true;
|
|
} else {
|
|
$('#big-video-control-container').css('display','block');
|
|
player.ready(function(){
|
|
player.volume(defaultVolume);
|
|
});
|
|
doLoop = false;
|
|
}
|
|
$('#big-video-image').css('display','none');
|
|
$(vidEl).css('display','block');
|
|
}
|
|
|
|
function showPoster(source) {
|
|
// remove old image
|
|
$('#big-video-image').remove();
|
|
|
|
// hide video
|
|
player.pause();
|
|
$(vidEl).css('display','none');
|
|
$('#big-video-control-container').css('display','none');
|
|
|
|
// show image
|
|
currMediaType = 'image';
|
|
var bgImage = $('<img id="big-video-image" src='+source+' />');
|
|
wrap.append(bgImage);
|
|
|
|
$('#big-video-image').imagesLoaded(function() {
|
|
mediaAspect = $('#big-video-image').width() / $('#big-video-image').height();
|
|
updateSize();
|
|
});
|
|
}
|
|
|
|
BigVideo.init = function() {
|
|
if (!isInitialized) {
|
|
// create player
|
|
settings.container.prepend(wrap);
|
|
var autoPlayString = settings.forceAutoplay ? 'autoplay' : '';
|
|
player = $('<video id="'+vidEl.substr(1)+'" class="video-js vjs-default-skin" height="1" width="1" preload="auto" data-setup="{}" '+autoPlayString+' webkit-playsinline></video>');
|
|
player.css('position','absolute');
|
|
wrap.append(player);
|
|
|
|
var videoTechOrder = ['html5','flash'];
|
|
// If only using mp4s and on firefox, use flash fallback
|
|
var ua = navigator.userAgent.toLowerCase();
|
|
var isFirefox = ua.indexOf('firefox') != -1;
|
|
if (settings.useFlashForFirefox && (isFirefox)) {
|
|
videoTechOrder = ['flash', 'html5'];
|
|
}
|
|
player = videojs(vidEl.substr(1), {
|
|
controls:false,
|
|
autoplay:true,
|
|
preload:'auto',
|
|
techOrder:videoTechOrder
|
|
});
|
|
|
|
// add controls
|
|
if (settings.controls) initPlayControl();
|
|
|
|
// set initial state
|
|
updateSize();
|
|
isInitialized = true;
|
|
isPlaying = false;
|
|
|
|
if (settings.forceAutoplay) {
|
|
$('body').on('click', setUpAutoPlay);
|
|
}
|
|
|
|
$('#big-video-vid_flash_api')
|
|
.attr('scale','noborder')
|
|
.attr('width','100%')
|
|
.attr('height','100%');
|
|
|
|
// set events
|
|
$(window).on('resize.bigvideo', function() {
|
|
updateSize();
|
|
});
|
|
|
|
player.on('loadedmetadata', function(data) {
|
|
if (document.getElementById('big-video-vid_flash_api')) {
|
|
// use flash callback to get mediaAspect ratio
|
|
mediaAspect = document.getElementById('big-video-vid_flash_api').vjs_getProperty('videoWidth')/document.getElementById('big-video-vid_flash_api').vjs_getProperty('videoHeight');
|
|
} else {
|
|
// use html5 player to get mediaAspect
|
|
mediaAspect = $('#big-video-vid_html5_api').prop('videoWidth')/$('#big-video-vid_html5_api').prop('videoHeight');
|
|
}
|
|
updateSize();
|
|
var dur = Math.round(player.duration());
|
|
var durMinutes = Math.floor(dur/60);
|
|
var durSeconds = dur - durMinutes*60;
|
|
if (durSeconds < 10) durSeconds='0'+durSeconds;
|
|
vidDur = durMinutes+':'+durSeconds;
|
|
});
|
|
|
|
player.on('ended', function() {
|
|
if (settings.doLoop) {
|
|
player.currentTime(0);
|
|
player.play();
|
|
}
|
|
if (isQueued) {
|
|
nextMedia();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show video or image file
|
|
*
|
|
* @param source: The file to show, can be:
|
|
* - an array with objects for video files types
|
|
* - a string to a single video file
|
|
* - a string to a image file
|
|
* @param options: An object with those possible attributes:
|
|
* - boolean "ambient" to set video to loop
|
|
* - function onShown
|
|
*/
|
|
BigVideo.show = function(source,options) {
|
|
if (options === undefined) options = {};
|
|
isAmbient = options.ambient === true;
|
|
if (isAmbient || options.doLoop) settings.doLoop = true;
|
|
|
|
if (typeof(source) === 'string') {
|
|
// if input was a string, try show that image or video
|
|
var ext = ( source.lastIndexOf('?') > 0 ) ? source.substring(source.lastIndexOf('.')+1, source.lastIndexOf('?')) : source.substring( source.lastIndexOf('.')+1);
|
|
if (ext == 'jpg' || ext == 'gif' || ext == 'png') {
|
|
showPoster(source);
|
|
} else if (ext == 'mp4' || ext == 'ogg' || ext == 'ogv'|| ext == 'webm') {
|
|
playVideo(source);
|
|
if (options.onShown) options.onShown();
|
|
isQueued = false;
|
|
}
|
|
} else if ($.isArray(source)) {
|
|
// if the input was an array, pass it to videojs
|
|
playVideo(source);
|
|
} else if (typeof(source) === "object" && source.src && source.type) {
|
|
// if the input was an object with valid attributes, wrap it in an
|
|
// array and pass it to videojs
|
|
playVideo([source]);
|
|
} else {
|
|
// fail without valid input
|
|
throw("BigVideo.show received invalid input for parameter source");
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Show a playlist of video files
|
|
*
|
|
* @param files: array of elements to pass to BigVideo.show in sequence
|
|
* @param options: An object with those possible attributes:
|
|
* - boolean "ambient" to set video to loop
|
|
* - function onShown
|
|
*/
|
|
BigVideo.showPlaylist = function (files, options) {
|
|
if (!$.isArray(files)) {
|
|
throw("BigVideo.showPlaylist parameter files accepts only arrays");
|
|
}
|
|
|
|
if (options === undefined) options = {};
|
|
isAmbient = options.ambient === true;
|
|
if (isAmbient || options.doLoop) settings.doLoop = true;
|
|
|
|
playlist = files;
|
|
currMediaIndex = 0;
|
|
this.show(playlist[currMediaIndex]);
|
|
if (options.onShown) options.onShown();
|
|
isQueued = true;
|
|
};
|
|
|
|
// Expose Video.js player
|
|
BigVideo.getPlayer = function() {
|
|
return player;
|
|
};
|
|
|
|
// Remove/dispose the player
|
|
BigVideo.remove = BigVideo.dispose = function() {
|
|
isInitialized = false;
|
|
|
|
wrap.remove();
|
|
$(window).off('resize.bigvideo');
|
|
|
|
if(player) {
|
|
player.off('loadedmetadata');
|
|
player.off('ended');
|
|
player.dispose();
|
|
}
|
|
};
|
|
|
|
// Expose BigVideoJS player actions play, pause, skip (if a playlist is available)
|
|
// Example: BigVideo.triggerPlayer('skip')
|
|
BigVideo.triggerPlayer = function(action){
|
|
playControl(action);
|
|
};
|
|
|
|
return BigVideo;
|
|
|
|
};
|
|
}); |