Files
namaste/html/js/modules (optional)/jarallax-video.js
gramps 373ebc8c93 Archive: Namaste PHP AMQP framework v1.0 (2017-2020)
952 days continuous production uptime, 40k+ tp/s single node.
Original corpo Bitbucket history not included — clean archive commit.
2026-04-05 09:49:30 -07:00

800 lines
27 KiB
JavaScript
Executable File

/*!
* Name : Video Worker (wrapper for Youtube, Vimeo and Local videos)
* Version : 1.2.1
* Author : _nK https://nkdev.info
* GitHub : https://github.com/nk-o/jarallax
*/
(function (window) {
'use strict';
// Extend like jQuery.extend
function extend (out) {
out = out || {};
for (var i = 1; i < arguments.length; i++) {
if (!arguments[i]) {
continue;
}
for (var key in arguments[i]) {
if (arguments[i].hasOwnProperty(key)) {
out[key] = arguments[i][key];
}
}
}
return out;
}
// Deferred
// thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery
function Deferred () {
this._done = [];
this._fail = [];
}
Deferred.prototype = {
execute: function (list, args) {
var i = list.length;
args = Array.prototype.slice.call(args);
while(i--) {
list[i].apply(null, args);
}
},
resolve: function () {
this.execute(this._done, arguments);
},
reject: function () {
this.execute(this._fail, arguments);
},
done: function (callback) {
this._done.push(callback);
},
fail: function (callback) {
this._fail.push(callback);
}
};
// init events
function addEventListener (el, eventName, handler) {
if (el.addEventListener) {
el.addEventListener(eventName, handler);
} else {
el.attachEvent('on' + eventName, function (){
handler.call(el);
});
}
}
var VideoWorker = (function () {
var ID = 0;
function VideoWorker_inner (url, options) {
var _this = this;
_this.url = url;
_this.options_default = {
autoplay: 1,
loop: 1,
mute: 1,
controls: 0,
// start / end video time in ms
startTime: 0,
endTime: 0
};
_this.options = extend({}, _this.options_default, options);
// check URL
_this.videoID = _this.parseURL(url);
// init
if(_this.videoID) {
_this.ID = ID++;
_this.loadAPI();
_this.init();
}
}
return VideoWorker_inner;
}());
VideoWorker.prototype.parseURL = function (url) {
// parse youtube ID
function getYoutubeID (ytUrl) {
var regExp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
var match = ytUrl.match(regExp);
return match && match[1].length === 11 ? match[1] : false;
}
// parse vimeo ID
function getVimeoID (vmUrl) {
var regExp = /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
var match = vmUrl.match(regExp);
return match && match[3] ? match[3] : false;
}
// parse local string
function getLocalVideos (locUrl) {
var videoFormats = locUrl.split(/,(?=mp4\:|webm\:|ogv\:|ogg\:)/);
var result = {};
var ready = 0;
for(var k = 0; k < videoFormats.length; k++) {
var match = videoFormats[k].match(/^(mp4|webm|ogv|ogg)\:(.*)/);
if(match && match[1] && match[2]) {
result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];
ready = 1;
}
}
return ready ? result : false;
}
var Youtube = getYoutubeID(url);
var Vimeo = getVimeoID(url);
var Local = getLocalVideos(url);
if(Youtube) {
this.type = 'youtube';
return Youtube;
} else if (Vimeo) {
this.type = 'vimeo';
return Vimeo;
} else if (Local) {
this.type = 'local';
return Local;
}
return false;
};
VideoWorker.prototype.isValid = function () {
return !!this.videoID;
};
// events
VideoWorker.prototype.on = function (name, callback) {
this.userEventsList = this.userEventsList || [];
// add new callback in events list
(this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);
};
VideoWorker.prototype.off = function (name, callback) {
if(!this.userEventsList || !this.userEventsList[name]) {
return;
}
if(!callback) {
delete this.userEventsList[name];
} else {
for(var k = 0; k < this.userEventsList[name].length; k++) {
if(this.userEventsList[name][k] === callback) {
this.userEventsList[name][k] = false;
}
}
}
};
VideoWorker.prototype.fire = function (name) {
var args = [].slice.call(arguments, 1);
if(this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {
for(var k in this.userEventsList[name]) {
// call with all arguments
if(this.userEventsList[name][k]) {
this.userEventsList[name][k].apply(this, args);
}
}
}
};
VideoWorker.prototype.play = function (start) {
var _this = this;
if(!_this.player) {
return;
}
if(_this.type === 'youtube' && _this.player.playVideo) {
if(typeof start !== 'undefined') {
_this.player.seekTo(start || 0);
}
_this.player.playVideo();
}
if(_this.type === 'vimeo') {
if (typeof start !== 'undefined') {
_this.player.setCurrentTime(start);
}
_this.player.getPaused().then(function(paused) {
if (paused) {
_this.player.play();
}
});
}
if(_this.type === 'local') {
if(typeof start !== 'undefined') {
_this.player.currentTime = start;
}
_this.player.play();
}
};
VideoWorker.prototype.pause = function () {
if(!this.player) {
return;
}
if(this.type === 'youtube' && this.player.pauseVideo) {
this.player.pauseVideo();
}
if(this.type === 'vimeo') {
this.player.pause();
}
if(this.type === 'local') {
this.player.pause();
}
};
VideoWorker.prototype.getImageURL = function (callback) {
var _this = this;
if(_this.videoImage) {
callback(_this.videoImage);
return;
}
if(_this.type === 'youtube') {
var availableSizes = [
'maxresdefault',
'sddefault',
'hqdefault',
'0'
];
var step = 0;
var tempImg = new Image();
tempImg.onload = function () {
// if no thumbnail, youtube add their own image with width = 120px
if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {
// ok
_this.videoImage = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
callback(_this.videoImage);
} else {
// try another size
step++;
this.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
}
};
tempImg.src = 'https://img.youtube.com/vi/' + _this.videoID + '/' + availableSizes[step] + '.jpg';
}
if(_this.type === 'vimeo') {
var request = new XMLHttpRequest();
request.open('GET', 'https://vimeo.com/api/v2/video/' + _this.videoID + '.json', true);
request.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 400) {
// Success!
var response = JSON.parse(this.responseText);
_this.videoImage = response[0].thumbnail_large;
callback(_this.videoImage);
} else {
// Error :(
}
}
};
request.send();
request = null;
}
};
VideoWorker.prototype.getIframe = function (callback) {
var _this = this;
// return generated iframe
if(_this.$iframe) {
callback(_this.$iframe);
return;
}
// generate new iframe
_this.onAPIready(function () {
var hiddenDiv;
if(!_this.$iframe) {
hiddenDiv = document.createElement('div');
hiddenDiv.style.display = 'none';
}
// Youtube
if(_this.type === 'youtube') {
_this.playerOptions = {};
_this.playerOptions.videoId = _this.videoID;
_this.playerOptions.playerVars = {
autohide: 1,
rel: 0,
autoplay: 0
};
// hide controls
if(!_this.options.controls) {
_this.playerOptions.playerVars.iv_load_policy = 3;
_this.playerOptions.playerVars.modestbranding = 1;
_this.playerOptions.playerVars.controls = 0;
_this.playerOptions.playerVars.showinfo = 0;
_this.playerOptions.playerVars.disablekb = 1;
}
// events
var ytStarted;
var ytProgressInterval;
_this.playerOptions.events = {
onReady: function (e) {
// mute
if(_this.options.mute) {
e.target.mute();
}
// autoplay
if(_this.options.autoplay) {
_this.play(_this.options.startTime);
}
_this.fire('ready', e);
},
onStateChange: function (e) {
// loop
if(_this.options.loop && e.data === YT.PlayerState.ENDED) {
_this.play(_this.options.startTime);
}
if(!ytStarted && e.data === YT.PlayerState.PLAYING) {
ytStarted = 1;
_this.fire('started', e);
}
if(e.data === YT.PlayerState.PLAYING) {
_this.fire('play', e);
}
if(e.data === YT.PlayerState.PAUSED) {
_this.fire('pause', e);
}
if(e.data === YT.PlayerState.ENDED) {
_this.fire('end', e);
}
// check for end of video and play again or stop
if(_this.options.endTime) {
if(e.data === YT.PlayerState.PLAYING) {
ytProgressInterval = setInterval(function () {
if(_this.options.endTime && _this.player.getCurrentTime() >= _this.options.endTime) {
if(_this.options.loop) {
_this.play(_this.options.startTime);
} else {
_this.pause();
}
}
}, 150);
} else {
clearInterval(ytProgressInterval);
}
}
}
};
var firstInit = !_this.$iframe;
if(firstInit) {
var div = document.createElement('div');
div.setAttribute('id', _this.playerID);
hiddenDiv.appendChild(div);
document.body.appendChild(hiddenDiv);
}
_this.player = _this.player || new window.YT.Player(_this.playerID, _this.playerOptions);
if(firstInit) {
_this.$iframe = document.getElementById(_this.playerID);
// get video width and height
_this.videoWidth = parseInt(_this.$iframe.getAttribute('width'), 10) || 1280;
_this.videoHeight = parseInt(_this.$iframe.getAttribute('height'), 10) || 720;
}
}
// Vimeo
if(_this.type === 'vimeo') {
_this.playerOptions = '';
_this.playerOptions += 'player_id=' + _this.playerID;
_this.playerOptions += '&autopause=0';
// hide controls
if(!_this.options.controls) {
_this.playerOptions += '&badge=0&byline=0&portrait=0&title=0';
}
// autoplay
_this.playerOptions += '&autoplay=' + (_this.options.autoplay ? '1' : '0');
// loop
_this.playerOptions += '&loop=' + (_this.options.loop ? 1 : 0);
if(!_this.$iframe) {
_this.$iframe = document.createElement('iframe');
_this.$iframe.setAttribute('id', _this.playerID);
_this.$iframe.setAttribute('src', 'https://player.vimeo.com/video/' + _this.videoID + '?' + _this.playerOptions);
_this.$iframe.setAttribute('frameborder', '0');
hiddenDiv.appendChild(_this.$iframe);
document.body.appendChild(hiddenDiv);
}
_this.player = _this.player || new Vimeo.Player(_this.$iframe);
// get video width and height
_this.player.getVideoWidth().then(function (width) {
_this.videoWidth = width || 1280;
});
_this.player.getVideoHeight().then(function (height) {
_this.videoHeight = height || 720;
});
// mute
_this.player.setVolume(_this.options.mute ? 0 : 100);
var vmStarted;
_this.player.on('timeupdate', function (e) {
if(!vmStarted) {
_this.fire('started', e);
}
vmStarted = 1;
// check for end of video and play again or stop
if(_this.options.endTime) {
if(_this.options.endTime && e.seconds >= _this.options.endTime) {
if(_this.options.loop) {
_this.play(_this.options.startTime);
} else {
_this.pause();
}
}
}
});
_this.player.on('play', function (e) {
_this.fire('play', e);
// check for the start time and start with it
if(_this.options.startTime && e.seconds === 0) {
_this.play(_this.options.startTime);
}
});
_this.player.on('pause', function (e) {
_this.fire('pause', e);
});
_this.player.on('ended', function (e) {
_this.fire('end', e);
});
_this.player.on('loaded', function (e) {
_this.fire('ready', e);
});
}
// Local
function addSourceToLocal (element, src, type) {
var source = document.createElement('source');
source.src = src;
source.type = type;
element.appendChild(source);
}
if(_this.type === 'local') {
if(!_this.$iframe) {
_this.$iframe = document.createElement('video');
// mute
if(_this.options.mute) {
_this.$iframe.muted = true;
}
// loop
if(_this.options.loop) {
_this.$iframe.loop = true;
}
_this.$iframe.setAttribute('id', _this.playerID);
hiddenDiv.appendChild(_this.$iframe);
document.body.appendChild(hiddenDiv);
for(var k in _this.videoID) {
addSourceToLocal(_this.$iframe, _this.videoID[k], 'video/' + k);
}
}
_this.player = _this.player || _this.$iframe;
var locStarted;
addEventListener(_this.player, 'playing', function (e) {
if(!locStarted) {
_this.fire('started', e);
}
locStarted = 1;
});
addEventListener(_this.player, 'timeupdate', function () {
// check for end of video and play again or stop
if(_this.options.endTime) {
if(_this.options.endTime && this.currentTime >= _this.options.endTime) {
if(_this.options.loop) {
_this.play(_this.options.startTime);
} else {
_this.pause();
}
}
}
});
addEventListener(_this.player, 'play', function (e) {
_this.fire('play', e);
});
addEventListener(_this.player, 'pause', function (e) {
_this.fire('pause', e);
});
addEventListener(_this.player, 'ended', function (e) {
_this.fire('end', e);
});
addEventListener(_this.player, 'loadedmetadata', function () {
// get video width and height
_this.videoWidth = this.videoWidth || 1280;
_this.videoHeight = this.videoHeight || 720;
_this.fire('ready');
// autoplay
if(_this.options.autoplay) {
_this.play(_this.options.startTime);
}
});
}
callback(_this.$iframe);
});
};
VideoWorker.prototype.init = function () {
var _this = this;
_this.playerID = 'VideoWorker-' + _this.ID;
};
var YoutubeAPIadded = 0;
var VimeoAPIadded = 0;
VideoWorker.prototype.loadAPI = function () {
var _this = this;
if(YoutubeAPIadded && VimeoAPIadded) {
return;
}
var src = '';
// load Youtube API
if(_this.type === 'youtube' && !YoutubeAPIadded) {
YoutubeAPIadded = 1;
src = '//www.youtube.com/iframe_api';
}
// load Vimeo API
if(_this.type === 'vimeo' && !VimeoAPIadded) {
VimeoAPIadded = 1;
src = '//player.vimeo.com/api/player.js';
}
if(!src) {
return;
}
if (window.location.origin === 'file://') {
src = 'http:' + src;
}
// add script in head section
var tag = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
tag.src = src;
head.appendChild(tag);
head = null;
tag = null;
};
var loadingYoutubePlayer = 0;
var loadingVimeoPlayer = 0;
var loadingYoutubeDeffer = new Deferred();
var loadingVimeoDeffer = new Deferred();
VideoWorker.prototype.onAPIready = function (callback) {
var _this = this;
// Youtube
if(_this.type === 'youtube') {
// Listen for global YT player callback
if ((typeof YT === 'undefined' || YT.loaded === 0) && !loadingYoutubePlayer) {
// Prevents Ready event from being called twice
loadingYoutubePlayer = 1;
// Creates deferred so, other players know when to wait.
window.onYouTubeIframeAPIReady = function () {
window.onYouTubeIframeAPIReady = null;
loadingYoutubeDeffer.resolve('done');
callback();
};
} else if (typeof YT === 'object' && YT.loaded === 1) {
callback();
} else {
loadingYoutubeDeffer.done(function () {
callback();
});
}
}
// Vimeo
if(_this.type === 'vimeo') {
if(typeof Vimeo === 'undefined' && !loadingVimeoPlayer) {
loadingVimeoPlayer = 1;
var vimeo_interval = setInterval(function () {
if(typeof Vimeo !== 'undefined') {
clearInterval(vimeo_interval);
loadingVimeoDeffer.resolve('done');
callback();
}
}, 20);
} else if (typeof Vimeo !== 'undefined') {
callback();
} else {
loadingVimeoDeffer.done(function () {
callback();
});
}
}
// Local
if(_this.type === 'local') {
callback();
}
};
window.VideoWorker = VideoWorker;
}(window));
/*!
* Name : Video Background Extension for Jarallax
* Version : 1.0.0
* Author : _nK http://nkdev.info
* GitHub : https://github.com/nk-o/jarallax
*/
(function () {
'use strict';
if(typeof jarallax === 'undefined') {
return;
}
var Jarallax = jarallax.constructor;
// append video after init Jarallax
var def_init = Jarallax.prototype.init;
Jarallax.prototype.init = function () {
var _this = this;
def_init.apply(_this);
if(_this.video) {
_this.video.getIframe(function (iframe) {
var $parent = iframe.parentNode;
_this.css(iframe, {
position: _this.image.position,
top: '0px', left: '0px', right: '0px', bottom: '0px',
width: '100%',
height: '100%',
maxWidth: 'none',
maxHeight: 'none',
visibility: 'hidden',
margin: 0,
zIndex: -1
});
_this.$video = iframe;
_this.image.$container.appendChild(iframe);
// remove parent iframe element (created by VideoWorker)
$parent.parentNode.removeChild($parent);
});
}
};
// cover video
var def_coverImage = Jarallax.prototype.coverImage;
Jarallax.prototype.coverImage = function () {
var _this = this;
def_coverImage.apply(_this);
// add video height over than need to hide controls
if(_this.video && _this.image.$item.nodeName === 'IFRAME') {
_this.css(_this.image.$item, {
height: _this.image.$item.getBoundingClientRect().height + 400 + 'px',
marginTop: (-200 + parseFloat(_this.css(_this.image.$item, 'margin-top'))) + 'px'
});
}
};
// init video
var def_initImg = Jarallax.prototype.initImg;
Jarallax.prototype.initImg = function () {
var _this = this;
var defaultResult = def_initImg.apply(_this);
if(!_this.options.videoSrc) {
_this.options.videoSrc = _this.$item.getAttribute('data-jarallax-video') || false;
}
if(_this.options.videoSrc) {
var video = new VideoWorker(_this.options.videoSrc, {
startTime: _this.options.videoStartTime || 0,
endTime: _this.options.videoEndTime || 0
});
if(video.isValid()) {
_this.image.useImgTag = true;
video.on('ready', function () {
var oldOnScroll = _this.onScroll;
_this.onScroll = function () {
oldOnScroll.apply(_this);
if(_this.isVisible()) {
video.play();
} else {
video.pause();
}
};
});
video.on('started', function () {
_this.image.$default_item = _this.image.$item;
_this.image.$item = _this.$video;
// set video width and height
_this.image.width = _this.options.imgWidth = _this.video.videoWidth || 1280;
_this.image.height = _this.options.imgHeight = _this.video.videoHeight || 720;
_this.coverImage();
_this.clipContainer();
_this.onScroll();
// hide image
if(_this.image.$default_item) {
_this.image.$default_item.style.display = 'none';
}
});
_this.video = video;
if(video.type !== 'local') {
video.getImageURL(function (url) {
_this.image.src = url;
_this.init();
});
}
}
// prevent default image loading when not local video
if(video.type !== 'local') {
return false;
}
// set empty image on local video if not defined
else if (!defaultResult) {
_this.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
return true;
}
}
return defaultResult;
};
// Destroy video parallax
var def_destroy = Jarallax.prototype.destroy;
Jarallax.prototype.destroy = function () {
var _this = this;
def_destroy.apply(_this);
};
}());