@hola.org/videojs-thumbnails
Advanced tools
Comparing version 0.1.1-6 to 0.1.1-7
{ | ||
"name": "@hola.org/videojs-thumbnails", | ||
"version": "0.1.1-6", | ||
"version": "0.1.1-7", | ||
"description": "progress bar thumbnails plugin for video.js", | ||
@@ -5,0 +5,0 @@ "main": "videojs.thumbnails.js", |
(function() { | ||
'use strict'; | ||
var defaults = { | ||
0: { | ||
src: 'example-thumbnail.png' | ||
} | ||
}, | ||
extend = function() { | ||
var extend = function() { | ||
var args, target, i, object, property; | ||
@@ -78,4 +73,2 @@ args = Array.prototype.slice.call(arguments); | ||
top: '-'+s.height*y+'px', | ||
width: s.width*cols+'px', | ||
height: s.height*rows+'px', | ||
} | ||
@@ -88,6 +81,6 @@ }); | ||
}, | ||
androidHack = function() { | ||
androidHack = function(player) { | ||
// Android doesn't support :active and :hover on non-anchor and non-button elements | ||
// so, we need to fake the :active selector for thumbnails to show up. | ||
if (navigator.userAgent.toLowerCase().indexOf("android") !== -1) { | ||
if (navigator.userAgent.toLowerCase().indexOf('android') !== -1) { | ||
var progressControl = player.controlBar.progressControl; | ||
@@ -104,135 +97,179 @@ var addFakeActive = function() { | ||
} | ||
}; | ||
}, | ||
resolveUrl = function(baseUrl, url) { | ||
var base = document.createElement('base'); | ||
base.href = baseUrl; | ||
var head = document.getElementsByTagName('head')[0]; | ||
head.insertBefore(base, head.firstChild); | ||
var a = document.createElement('a'); | ||
a.href = url; | ||
var result = a.href; | ||
head.removeChild(base); | ||
return result; | ||
}, | ||
getConfByVtt = function(track, baseUrl) { | ||
var res = {}, cues = track.cues; | ||
for (var i = 0; i < cues.length; i++) { | ||
var cue = cues[i]; | ||
var thumb = res[cue.startTime] = { | ||
src: resolveUrl(baseUrl, cue.text.split('#')[0]), | ||
}; | ||
var opt = cue.text.split('#')[1]; | ||
if (opt && opt.substring(0, 5) === 'xywh=') { | ||
var params = opt.substring(5).split(','); | ||
thumb.width = params[2]; | ||
thumb.height = params[3]; | ||
thumb.style = { | ||
left: '-'+params[0]+'px', | ||
top: '-'+params[1]+'px', | ||
}; | ||
} | ||
} | ||
return res; | ||
}, | ||
init = function(player, options) { | ||
if (player._thumbs) { | ||
player._thumbs.settings = options; | ||
return; | ||
} | ||
player._thumbs = {settings: options}; | ||
androidHack(player); | ||
/** | ||
* register the thubmnails plugin | ||
*/ | ||
videojs.plugin('thumbnails', function(options) { | ||
var player = this; | ||
options = options && unfoldSpritesConf(options); | ||
if (player._thumbs) { | ||
player._thumbs.settings = extend({}, defaults, options); | ||
return; | ||
} | ||
player._thumbs = {}; | ||
player._thumbs.settings = extend({}, defaults, options); | ||
androidHack(); | ||
// create the thumbnail | ||
var div = document.createElement('div'); | ||
div.className = 'vjs-thumbnail-holder'; | ||
var img = document.createElement('img'); | ||
div.appendChild(img); | ||
img.className = 'vjs-thumbnail'; | ||
// create the thumbnail | ||
var div = document.createElement('div'); | ||
div.className = 'vjs-thumbnail-holder'; | ||
var img = document.createElement('img'); | ||
div.appendChild(img); | ||
img.src = player._thumbs.settings['0'].src; | ||
img.className = 'vjs-thumbnail'; | ||
extend(img.style, player._thumbs.settings['0'].style); | ||
// keep track of the duration to calculate correct thumbnail to display | ||
var duration = player.duration(); | ||
// center the thumbnail over the cursor if an offset wasn't provided | ||
if (!img.style.left && !img.style.right) { | ||
img.onload = function() { | ||
img.style.left = -(img.naturalWidth / 2) + 'px'; | ||
}; | ||
} | ||
// when the container is MP4 | ||
player.on('durationchange', function(event) { | ||
duration = player.duration(); | ||
}); | ||
// keep track of the duration to calculate correct thumbnail to display | ||
var duration = player.duration(); | ||
// when the container is HLS | ||
player.on('loadedmetadata', function(event) { | ||
duration = player.duration(); | ||
}); | ||
// when the container is MP4 | ||
player.on('durationchange', function(event) { | ||
duration = player.duration(); | ||
}); | ||
// add the thumbnail to the player | ||
var progressControl = player.controlBar.progressControl; | ||
var seekBar = progressControl.seekBar; | ||
var el = progressControl.el(); | ||
if (el.firstChild) | ||
el.insertBefore(div, el.firstChild); | ||
else | ||
el.appendChild(div); | ||
// when the container is HLS | ||
player.on('loadedmetadata', function(event) { | ||
duration = player.duration(); | ||
}); | ||
var moveListener = function(event) { | ||
if (event.target === div || event.target === img) { | ||
return; | ||
} | ||
var pageXOffset = getScrollOffset().x; | ||
var clientRect = offsetParent(progressControl.el()).getBoundingClientRect(); | ||
var right = (clientRect.width || clientRect.right) + pageXOffset; | ||
// add the thumbnail to the player | ||
var progressControl = player.controlBar.progressControl; | ||
var el = progressControl.el(); | ||
if (el.firstChild) | ||
el.insertBefore(div, el.firstChild); | ||
else | ||
el.appendChild(div); | ||
var pageX = event.pageX; | ||
if (event.changedTouches) { | ||
pageX = event.changedTouches[0].pageX; | ||
} | ||
var moveListener = function(event) { | ||
var pageXOffset = getScrollOffset().x; | ||
var clientRect = offsetParent(progressControl.el()).getBoundingClientRect(); | ||
var right = (clientRect.width || clientRect.right) + pageXOffset; | ||
// find the page offset of the mouse | ||
var left = pageX || (event.clientX + document.body.scrollLeft + | ||
document.documentElement.scrollLeft); | ||
// subtract the page offset of the positioned offset parent | ||
left -= offsetParent(progressControl.el()).getBoundingClientRect().left + | ||
pageXOffset; | ||
var pageX = event.pageX; | ||
if (event.changedTouches) { | ||
pageX = event.changedTouches[0].pageX; | ||
} | ||
// apply updated styles to the thumbnail if necessary | ||
// mouseTime is the position of the mouse along the progress control bar | ||
// `left` applies to the mouse position relative to the player so we need | ||
// to remove the progress control's left offset to know the mouse position | ||
// relative to the progress control | ||
var mouseTime = Math.floor(seekBar.calculateDistance(event)*duration); | ||
var active = 0, settings = player._thumbs.settings; | ||
for (var time in settings) { | ||
if (mouseTime > time) { | ||
active = Math.max(active, time); | ||
} | ||
} | ||
var setting = settings[active]; | ||
if (!setting) { | ||
return; | ||
} | ||
if (setting.src && img.src != setting.src) { | ||
img.src = setting.src; | ||
} | ||
var scale = player.hasClass('vjs-fullscreen') ? 1.5 : 1; | ||
if (setting.style) { | ||
img.style.left = parseFloat(setting.style.left)*scale+'px'; | ||
img.style.top = parseFloat(setting.style.top)*scale+'px'; | ||
} | ||
if (img.naturalWidth) { | ||
img.style.width = img.naturalWidth*scale+'px'; | ||
img.style.height = img.naturalHeight*scale+'px'; | ||
} | ||
// find the page offset of the mouse | ||
var left = pageX || (event.clientX + document.body.scrollLeft + | ||
document.documentElement.scrollLeft); | ||
// subtract the page offset of the positioned offset parent | ||
left -= offsetParent(progressControl.el()).getBoundingClientRect().left + | ||
pageXOffset; | ||
var width = parseFloat(setting.width || settings[0].width)*scale; | ||
var height = parseFloat(setting.height || settings[0].height)*scale; | ||
var halfWidth = width / 2; | ||
// apply updated styles to the thumbnail if necessary | ||
// mouseTime is the position of the mouse along the progress control bar | ||
// `left` applies to the mouse position relative to the player so we need | ||
// to remove the progress control's left offset to know the mouse position | ||
// relative to the progress control | ||
var mouseTime = Math.floor((left - progressControl.el().offsetLeft) / | ||
progressControl.width() * duration); | ||
var active = 0, settings = player._thumbs.settings; | ||
for (var time in settings) { | ||
if (mouseTime > time) { | ||
active = Math.max(active, time); | ||
// make sure that the thumbnail doesn't fall off the right side of the | ||
// left side of the player | ||
if ((left + halfWidth) > right) { | ||
left = right - width; | ||
} else if (left < halfWidth) { | ||
left = 0; | ||
} else { | ||
left -= halfWidth; | ||
} | ||
} | ||
var setting = settings[active]; | ||
if (setting.src && img.src != setting.src) { | ||
img.src = setting.src; | ||
} | ||
var scale = player.hasClass('vjs-fullscreen') ? 1.5 : 1; | ||
if (setting.style) { | ||
img.style.left = parseFloat(setting.style.left)*scale+'px'; | ||
img.style.top = parseFloat(setting.style.top)*scale+'px'; | ||
img.style.width = parseFloat(setting.style.width)*scale+'px'; | ||
img.style.height = parseFloat(setting.style.height)*scale+'px'; | ||
} else { | ||
img.style.width = 100*scale+'%'; | ||
img.style.height = 100*scale+'%'; | ||
} | ||
var width = parseFloat(setting.width || settings[0].width)*scale; | ||
var height = parseFloat(setting.height || settings[0].height)*scale; | ||
var halfWidth = width / 2; | ||
div.style.width = width + 'px'; | ||
div.style.height = height + 'px'; | ||
div.style.left = left + 'px'; | ||
div.style.top = '-' + height + 'px'; | ||
div.style.display = 'block'; | ||
}; | ||
// make sure that the thumbnail doesn't fall off the right side of the | ||
// left side of the player | ||
if ((left + halfWidth) > right) { | ||
left = right - width; | ||
} else if (left < halfWidth) { | ||
left = 0; | ||
} else { | ||
left -= halfWidth; | ||
} | ||
// update the thumbnail while hovering | ||
progressControl.on('mousemove', moveListener); | ||
progressControl.on('touchmove', moveListener); | ||
div.style.width = width + 'px'; | ||
div.style.height = height + 'px'; | ||
div.style.left = left + 'px'; | ||
div.style.top = '-' + height + 'px'; | ||
div.style.display = 'block'; | ||
}; | ||
var moveCancel = function(event) { | ||
div.style.display = 'none'; | ||
}; | ||
// update the thumbnail while hovering | ||
progressControl.on('mousemove', moveListener); | ||
progressControl.on('touchmove', moveListener); | ||
var moveCancel = function(event) { | ||
div.style.display = 'none'; | ||
// move the placeholder out of the way when not hovering | ||
progressControl.on('mouseout', moveCancel); | ||
progressControl.on('touchcancel', moveCancel); | ||
progressControl.on('touchend', moveCancel); | ||
player.on('userinactive', moveCancel); | ||
}; | ||
// move the placeholder out of the way when not hovering | ||
progressControl.on('mouseout', moveCancel); | ||
progressControl.on('touchcancel', moveCancel); | ||
progressControl.on('touchend', moveCancel); | ||
player.on('userinactive', moveCancel); | ||
/** | ||
* register the thubmnails plugin | ||
*/ | ||
videojs.plugin('thumbnails', function(options) { | ||
if (!options) { | ||
return; | ||
} | ||
var player = this; | ||
if (!options.vtt) { | ||
init(player, unfoldSpritesConf(options)); | ||
return; | ||
} | ||
var trackEl = player.addRemoteTextTrack({ | ||
id: 'thumbnails', | ||
kind: 'metadata', | ||
src: options.vtt, | ||
}); | ||
trackEl.addEventListener('load', function onLoad() { | ||
trackEl.removeEventListener('load', onLoad); | ||
var track = player.textTracks().getTrackById('thumbnails'); | ||
init(player, getConfByVtt(track, options.vtt)); | ||
}); | ||
}); | ||
})(); |
85876
311