Fix listeners for preview thumbs when changing source
This commit is contained in:
parent
6bf6c3f0f4
commit
fa4868a26d
280
demo/dist/demo.js
vendored
280
demo/dist/demo.js
vendored
@ -8875,6 +8875,38 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
||||||
return controls.updateSeekTooltip.call(player, event);
|
return controls.updateSeekTooltip.call(player, event);
|
||||||
|
}); // Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseleave click', function () {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
}); // Show scrubbing preview
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
}); // Polyfill for lower fill in <input type="range"> for webkit
|
}); // Polyfill for lower fill in <input type="range"> for webkit
|
||||||
|
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
@ -10733,17 +10765,15 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
this.elements = {
|
this.elements = {
|
||||||
thumb: {},
|
thumb: {},
|
||||||
scrubbing: {}
|
scrubbing: {}
|
||||||
};
|
};
|
||||||
|
this.load();
|
||||||
if (this.enabled) {
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(PreviewThumbnails, [{
|
_createClass(PreviewThumbnails, [{
|
||||||
@ -10751,17 +10781,23 @@ typeof navigator === "object" && (function () {
|
|||||||
value: function load() {
|
value: function load() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
// Render DOM elements
|
||||||
_this.listeners(); // Render DOM elements
|
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
_this.determineContainerAutoSizing();
|
_this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
_this.loaded = true;
|
||||||
});
|
});
|
||||||
} // Download VTT files and parse them
|
} // Download VTT files and parse them
|
||||||
|
|
||||||
@ -10830,6 +10866,89 @@ typeof navigator === "object" && (function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "startMove",
|
||||||
|
value: function startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
} // Wait until media has a duration
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
var clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX; // Set time text inside image container
|
||||||
|
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
} // Download and show image
|
||||||
|
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "endMove",
|
||||||
|
value: function endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "startScrubbing",
|
||||||
|
value: function startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true; // Wait until media has a duration
|
||||||
|
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true); // Download and show image
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "finishScrubbing",
|
||||||
|
value: function finishScrubbing() {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', function () {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!_this4.mouseDown) {
|
||||||
|
_this4.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
@ -10837,89 +10956,17 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "listeners",
|
key: "listeners",
|
||||||
value: function listeners() {
|
value: function listeners() {
|
||||||
var _this4 = this;
|
var _this5 = this;
|
||||||
|
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', function (event) {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
var clientRect = _this4.player.elements.progress.getBoundingClientRect();
|
|
||||||
|
|
||||||
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (_this4.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
_this4.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this4.seekTime > _this4.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
_this4.seekTime = _this4.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_this4.mousePosX = event.pageX; // Set time text inside image container
|
|
||||||
|
|
||||||
_this4.elements.thumb.time.innerText = formatTime(_this4.seekTime); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Touch device seeking - performs same function as above
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', function () {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (_this4.player.elements.inputs.seek.value / 100); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', function () {
|
|
||||||
_this4.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', function () {
|
||||||
_this4.toggleThumbContainer(false, true);
|
_this5.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
this.player.on('seeked', function () {
|
this.player.on('seeked', function () {
|
||||||
_this4.toggleThumbContainer(false);
|
_this5.toggleThumbContainer(false);
|
||||||
}); // Show scrubbing preview
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', function (event) {
|
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
_this4.mouseDown = true; // Wait until media has a duration
|
|
||||||
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
_this4.toggleScrubbingContainer(true);
|
|
||||||
|
|
||||||
_this4.toggleThumbContainer(false, true); // Download and show image
|
|
||||||
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
on.call(this.player, this.player.media, 'timeupdate', function () {
|
this.player.on('timeupdate', function () {
|
||||||
_this4.timeAtLastTimeupdate = _this4.player.media.currentTime;
|
_this5.lastTime = _this5.player.media.currentTime;
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', function () {
|
|
||||||
_this4.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
|
|
||||||
if (Math.ceil(_this4.timeAtLastTimeupdate) === Math.ceil(_this4.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(_this4.player, _this4.player.media, 'timeupdate', function () {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!_this4.mouseDown) {
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -10956,7 +11003,7 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "showImageAtCurrentTime",
|
key: "showImageAtCurrentTime",
|
||||||
value: function showImageAtCurrentTime() {
|
value: function showImageAtCurrentTime() {
|
||||||
var _this5 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
@ -10968,7 +11015,7 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
|
|
||||||
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
||||||
return _this5.seekTime >= frame.startTime && _this5.seekTime <= frame.endTime;
|
return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime;
|
||||||
});
|
});
|
||||||
var hasThumb = thumbNum >= 0;
|
var hasThumb = thumbNum >= 0;
|
||||||
var qualityIndex = 0;
|
var qualityIndex = 0;
|
||||||
@ -10980,7 +11027,7 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
|
|
||||||
this.thumbnails.forEach(function (thumbnail, index) {
|
this.thumbnails.forEach(function (thumbnail, index) {
|
||||||
if (_this5.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
||||||
qualityIndex = index;
|
qualityIndex = index;
|
||||||
}
|
}
|
||||||
}); // Only proceed if either thumbnum or thumbfilename has changed
|
}); // Only proceed if either thumbnum or thumbfilename has changed
|
||||||
@ -10994,7 +11041,7 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "loadImage",
|
key: "loadImage",
|
||||||
value: function loadImage() {
|
value: function loadImage() {
|
||||||
var _this6 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||||
var thumbNum = this.showingThumb;
|
var thumbNum = this.showingThumb;
|
||||||
@ -11022,7 +11069,7 @@ typeof navigator === "object" && (function () {
|
|||||||
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
return _this6.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadingImage = previewImage;
|
this.loadingImage = previewImage;
|
||||||
@ -11059,7 +11106,7 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "removeOldImages",
|
key: "removeOldImages",
|
||||||
value: function removeOldImages(currentImage) {
|
value: function removeOldImages(currentImage) {
|
||||||
var _this7 = this;
|
var _this8 = this;
|
||||||
|
|
||||||
// Get a list of all images, convert it from a DOM list to an array
|
// Get a list of all images, convert it from a DOM list to an array
|
||||||
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
||||||
@ -11067,18 +11114,18 @@ typeof navigator === "object" && (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeDelay = _this7.usingSprites ? 500 : 1000;
|
var removeDelay = _this8.usingSprites ? 500 : 1000;
|
||||||
|
|
||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this7.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
currentImageContainer.removeChild(image);
|
currentImageContainer.removeChild(image);
|
||||||
|
|
||||||
_this7.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
_this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -11088,21 +11135,21 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "preloadNearby",
|
key: "preloadNearby",
|
||||||
value: function preloadNearby(thumbNum) {
|
value: function preloadNearby(thumbNum) {
|
||||||
var _this8 = this;
|
var _this9 = this;
|
||||||
|
|
||||||
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var oldThumbFilename = _this8.thumbnails[0].frames[thumbNum].text;
|
var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text;
|
||||||
|
|
||||||
if (_this8.showingThumbFilename === oldThumbFilename) {
|
if (_this9.showingThumbFilename === oldThumbFilename) {
|
||||||
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
||||||
var thumbnailsClone;
|
var thumbnailsClone;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(thumbNum);
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum);
|
||||||
} else {
|
} else {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundOne = false;
|
var foundOne = false;
|
||||||
@ -11111,20 +11158,20 @@ typeof navigator === "object" && (function () {
|
|||||||
|
|
||||||
if (newThumbFilename !== oldThumbFilename) {
|
if (newThumbFilename !== oldThumbFilename) {
|
||||||
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) {
|
if (!_this9.loadedImages.includes(newThumbFilename)) {
|
||||||
foundOne = true;
|
foundOne = true;
|
||||||
|
|
||||||
_this8.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
var urlPrefix = _this8.thumbnails[0].urlPrefix;
|
var urlPrefix = _this9.thumbnails[0].urlPrefix;
|
||||||
var thumbURL = urlPrefix + newThumbFilename;
|
var thumbURL = urlPrefix + newThumbFilename;
|
||||||
var previewImage = new Image();
|
var previewImage = new Image();
|
||||||
previewImage.src = thumbURL;
|
previewImage.src = thumbURL;
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
_this8.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) _this8.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -11143,7 +11190,7 @@ typeof navigator === "object" && (function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "getHigherQuality",
|
key: "getHigherQuality",
|
||||||
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
||||||
var _this9 = this;
|
var _this10 = this;
|
||||||
|
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
@ -11157,10 +11204,10 @@ typeof navigator === "object" && (function () {
|
|||||||
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Make sure the mouse hasn't already moved on and started hovering at another image
|
// Make sure the mouse hasn't already moved on and started hovering at another image
|
||||||
if (_this9.showingThumbFilename === thumbFilename) {
|
if (_this10.showingThumbFilename === thumbFilename) {
|
||||||
_this9.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
_this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
||||||
|
|
||||||
_this9.loadImage(currentQualityIndex + 1);
|
_this10.loadImage(currentQualityIndex + 1);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
@ -11434,11 +11481,16 @@ typeof navigator === "object" && (function () {
|
|||||||
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
||||||
// Setup interface
|
// Setup interface
|
||||||
ui.build.call(_this2);
|
ui.build.call(_this2);
|
||||||
}
|
} // Load HTML5 sources
|
||||||
|
|
||||||
|
|
||||||
if (_this2.isHTML5) {
|
if (_this2.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
_this2.media.load();
|
_this2.media.load();
|
||||||
|
} // Reload thumbnails
|
||||||
|
|
||||||
|
|
||||||
|
if (_this2.previewThumbnails) {
|
||||||
|
_this2.previewThumbnails.load();
|
||||||
} // Update the fullscreen support
|
} // Update the fullscreen support
|
||||||
|
|
||||||
|
|
||||||
|
2
demo/dist/demo.min.js
vendored
2
demo/dist/demo.min.js
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js.map
vendored
2
demo/dist/demo.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -281,17 +281,6 @@
|
|||||||
<script src="https://cdn.rangetouch.com/1.0.1/rangetouch.js" async crossorigin="anonymous"></script>
|
<script src="https://cdn.rangetouch.com/1.0.1/rangetouch.js" async crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<!-- Docs script -->
|
<!-- Docs script -->
|
||||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-132699580-1"></script>
|
|
||||||
<script>
|
|
||||||
if (window.location.host === 'plyr.io') {
|
|
||||||
window.dataLayer = window.dataLayer || [];
|
|
||||||
function gtag() {
|
|
||||||
window.dataLayer.push(arguments);
|
|
||||||
}
|
|
||||||
gtag('js', new Date());
|
|
||||||
gtag('config', 'UA-132699580-1');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="dist/demo.js" crossorigin="anonymous"></script>
|
<script src="dist/demo.js" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
280
dist/plyr.js
vendored
280
dist/plyr.js
vendored
@ -4790,6 +4790,38 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
||||||
return controls.updateSeekTooltip.call(player, event);
|
return controls.updateSeekTooltip.call(player, event);
|
||||||
|
}); // Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseleave click', function () {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
}); // Show scrubbing preview
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
}); // Polyfill for lower fill in <input type="range"> for webkit
|
}); // Polyfill for lower fill in <input type="range"> for webkit
|
||||||
|
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
@ -6654,17 +6686,15 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
this.elements = {
|
this.elements = {
|
||||||
thumb: {},
|
thumb: {},
|
||||||
scrubbing: {}
|
scrubbing: {}
|
||||||
};
|
};
|
||||||
|
this.load();
|
||||||
if (this.enabled) {
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(PreviewThumbnails, [{
|
_createClass(PreviewThumbnails, [{
|
||||||
@ -6672,17 +6702,23 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
value: function load() {
|
value: function load() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
// Render DOM elements
|
||||||
_this.listeners(); // Render DOM elements
|
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
_this.determineContainerAutoSizing();
|
_this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
_this.loaded = true;
|
||||||
});
|
});
|
||||||
} // Download VTT files and parse them
|
} // Download VTT files and parse them
|
||||||
|
|
||||||
@ -6751,6 +6787,89 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "startMove",
|
||||||
|
value: function startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
} // Wait until media has a duration
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
var clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX; // Set time text inside image container
|
||||||
|
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
} // Download and show image
|
||||||
|
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "endMove",
|
||||||
|
value: function endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "startScrubbing",
|
||||||
|
value: function startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true; // Wait until media has a duration
|
||||||
|
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true); // Download and show image
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "finishScrubbing",
|
||||||
|
value: function finishScrubbing() {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', function () {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!_this4.mouseDown) {
|
||||||
|
_this4.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
@ -6758,89 +6877,17 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "listeners",
|
key: "listeners",
|
||||||
value: function listeners() {
|
value: function listeners() {
|
||||||
var _this4 = this;
|
var _this5 = this;
|
||||||
|
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', function (event) {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
var clientRect = _this4.player.elements.progress.getBoundingClientRect();
|
|
||||||
|
|
||||||
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (_this4.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
_this4.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this4.seekTime > _this4.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
_this4.seekTime = _this4.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_this4.mousePosX = event.pageX; // Set time text inside image container
|
|
||||||
|
|
||||||
_this4.elements.thumb.time.innerText = formatTime(_this4.seekTime); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Touch device seeking - performs same function as above
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', function () {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (_this4.player.elements.inputs.seek.value / 100); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', function () {
|
|
||||||
_this4.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', function () {
|
||||||
_this4.toggleThumbContainer(false, true);
|
_this5.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
this.player.on('seeked', function () {
|
this.player.on('seeked', function () {
|
||||||
_this4.toggleThumbContainer(false);
|
_this5.toggleThumbContainer(false);
|
||||||
}); // Show scrubbing preview
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', function (event) {
|
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
_this4.mouseDown = true; // Wait until media has a duration
|
|
||||||
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
_this4.toggleScrubbingContainer(true);
|
|
||||||
|
|
||||||
_this4.toggleThumbContainer(false, true); // Download and show image
|
|
||||||
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
on.call(this.player, this.player.media, 'timeupdate', function () {
|
this.player.on('timeupdate', function () {
|
||||||
_this4.timeAtLastTimeupdate = _this4.player.media.currentTime;
|
_this5.lastTime = _this5.player.media.currentTime;
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', function () {
|
|
||||||
_this4.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
|
|
||||||
if (Math.ceil(_this4.timeAtLastTimeupdate) === Math.ceil(_this4.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(_this4.player, _this4.player.media, 'timeupdate', function () {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!_this4.mouseDown) {
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -6877,7 +6924,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "showImageAtCurrentTime",
|
key: "showImageAtCurrentTime",
|
||||||
value: function showImageAtCurrentTime() {
|
value: function showImageAtCurrentTime() {
|
||||||
var _this5 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
@ -6889,7 +6936,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
||||||
return _this5.seekTime >= frame.startTime && _this5.seekTime <= frame.endTime;
|
return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime;
|
||||||
});
|
});
|
||||||
var hasThumb = thumbNum >= 0;
|
var hasThumb = thumbNum >= 0;
|
||||||
var qualityIndex = 0;
|
var qualityIndex = 0;
|
||||||
@ -6901,7 +6948,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
this.thumbnails.forEach(function (thumbnail, index) {
|
this.thumbnails.forEach(function (thumbnail, index) {
|
||||||
if (_this5.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
||||||
qualityIndex = index;
|
qualityIndex = index;
|
||||||
}
|
}
|
||||||
}); // Only proceed if either thumbnum or thumbfilename has changed
|
}); // Only proceed if either thumbnum or thumbfilename has changed
|
||||||
@ -6915,7 +6962,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "loadImage",
|
key: "loadImage",
|
||||||
value: function loadImage() {
|
value: function loadImage() {
|
||||||
var _this6 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||||
var thumbNum = this.showingThumb;
|
var thumbNum = this.showingThumb;
|
||||||
@ -6943,7 +6990,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
return _this6.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadingImage = previewImage;
|
this.loadingImage = previewImage;
|
||||||
@ -6980,7 +7027,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "removeOldImages",
|
key: "removeOldImages",
|
||||||
value: function removeOldImages(currentImage) {
|
value: function removeOldImages(currentImage) {
|
||||||
var _this7 = this;
|
var _this8 = this;
|
||||||
|
|
||||||
// Get a list of all images, convert it from a DOM list to an array
|
// Get a list of all images, convert it from a DOM list to an array
|
||||||
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
||||||
@ -6988,18 +7035,18 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeDelay = _this7.usingSprites ? 500 : 1000;
|
var removeDelay = _this8.usingSprites ? 500 : 1000;
|
||||||
|
|
||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this7.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
currentImageContainer.removeChild(image);
|
currentImageContainer.removeChild(image);
|
||||||
|
|
||||||
_this7.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
_this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -7009,21 +7056,21 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "preloadNearby",
|
key: "preloadNearby",
|
||||||
value: function preloadNearby(thumbNum) {
|
value: function preloadNearby(thumbNum) {
|
||||||
var _this8 = this;
|
var _this9 = this;
|
||||||
|
|
||||||
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var oldThumbFilename = _this8.thumbnails[0].frames[thumbNum].text;
|
var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text;
|
||||||
|
|
||||||
if (_this8.showingThumbFilename === oldThumbFilename) {
|
if (_this9.showingThumbFilename === oldThumbFilename) {
|
||||||
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
||||||
var thumbnailsClone;
|
var thumbnailsClone;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(thumbNum);
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum);
|
||||||
} else {
|
} else {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundOne = false;
|
var foundOne = false;
|
||||||
@ -7032,20 +7079,20 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
if (newThumbFilename !== oldThumbFilename) {
|
if (newThumbFilename !== oldThumbFilename) {
|
||||||
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) {
|
if (!_this9.loadedImages.includes(newThumbFilename)) {
|
||||||
foundOne = true;
|
foundOne = true;
|
||||||
|
|
||||||
_this8.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
var urlPrefix = _this8.thumbnails[0].urlPrefix;
|
var urlPrefix = _this9.thumbnails[0].urlPrefix;
|
||||||
var thumbURL = urlPrefix + newThumbFilename;
|
var thumbURL = urlPrefix + newThumbFilename;
|
||||||
var previewImage = new Image();
|
var previewImage = new Image();
|
||||||
previewImage.src = thumbURL;
|
previewImage.src = thumbURL;
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
_this8.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) _this8.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -7064,7 +7111,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "getHigherQuality",
|
key: "getHigherQuality",
|
||||||
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
||||||
var _this9 = this;
|
var _this10 = this;
|
||||||
|
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
@ -7078,10 +7125,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Make sure the mouse hasn't already moved on and started hovering at another image
|
// Make sure the mouse hasn't already moved on and started hovering at another image
|
||||||
if (_this9.showingThumbFilename === thumbFilename) {
|
if (_this10.showingThumbFilename === thumbFilename) {
|
||||||
_this9.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
_this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
||||||
|
|
||||||
_this9.loadImage(currentQualityIndex + 1);
|
_this10.loadImage(currentQualityIndex + 1);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
@ -7355,11 +7402,16 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
||||||
// Setup interface
|
// Setup interface
|
||||||
ui.build.call(_this2);
|
ui.build.call(_this2);
|
||||||
}
|
} // Load HTML5 sources
|
||||||
|
|
||||||
|
|
||||||
if (_this2.isHTML5) {
|
if (_this2.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
_this2.media.load();
|
_this2.media.load();
|
||||||
|
} // Reload thumbnails
|
||||||
|
|
||||||
|
|
||||||
|
if (_this2.previewThumbnails) {
|
||||||
|
_this2.previewThumbnails.load();
|
||||||
} // Update the fullscreen support
|
} // Update the fullscreen support
|
||||||
|
|
||||||
|
|
||||||
|
2
dist/plyr.min.js
vendored
2
dist/plyr.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js.map
vendored
2
dist/plyr.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.mjs
vendored
2
dist/plyr.min.mjs
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.mjs.map
vendored
2
dist/plyr.min.mjs.map
vendored
File diff suppressed because one or more lines are too long
280
dist/plyr.mjs
vendored
280
dist/plyr.mjs
vendored
@ -4784,6 +4784,38 @@ function () {
|
|||||||
|
|
||||||
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
||||||
return controls.updateSeekTooltip.call(player, event);
|
return controls.updateSeekTooltip.call(player, event);
|
||||||
|
}); // Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseleave click', function () {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
}); // Show scrubbing preview
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
}); // Polyfill for lower fill in <input type="range"> for webkit
|
}); // Polyfill for lower fill in <input type="range"> for webkit
|
||||||
|
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
@ -6648,17 +6680,15 @@ function () {
|
|||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
this.elements = {
|
this.elements = {
|
||||||
thumb: {},
|
thumb: {},
|
||||||
scrubbing: {}
|
scrubbing: {}
|
||||||
};
|
};
|
||||||
|
this.load();
|
||||||
if (this.enabled) {
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(PreviewThumbnails, [{
|
_createClass(PreviewThumbnails, [{
|
||||||
@ -6666,17 +6696,23 @@ function () {
|
|||||||
value: function load() {
|
value: function load() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
// Render DOM elements
|
||||||
_this.listeners(); // Render DOM elements
|
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
_this.determineContainerAutoSizing();
|
_this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
_this.loaded = true;
|
||||||
});
|
});
|
||||||
} // Download VTT files and parse them
|
} // Download VTT files and parse them
|
||||||
|
|
||||||
@ -6745,6 +6781,89 @@ function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "startMove",
|
||||||
|
value: function startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
} // Wait until media has a duration
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
var clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX; // Set time text inside image container
|
||||||
|
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
} // Download and show image
|
||||||
|
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "endMove",
|
||||||
|
value: function endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "startScrubbing",
|
||||||
|
value: function startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true; // Wait until media has a duration
|
||||||
|
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true); // Download and show image
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "finishScrubbing",
|
||||||
|
value: function finishScrubbing() {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', function () {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!_this4.mouseDown) {
|
||||||
|
_this4.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
@ -6752,89 +6871,17 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "listeners",
|
key: "listeners",
|
||||||
value: function listeners() {
|
value: function listeners() {
|
||||||
var _this4 = this;
|
var _this5 = this;
|
||||||
|
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', function (event) {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
var clientRect = _this4.player.elements.progress.getBoundingClientRect();
|
|
||||||
|
|
||||||
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (_this4.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
_this4.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this4.seekTime > _this4.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
_this4.seekTime = _this4.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_this4.mousePosX = event.pageX; // Set time text inside image container
|
|
||||||
|
|
||||||
_this4.elements.thumb.time.innerText = formatTime(_this4.seekTime); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Touch device seeking - performs same function as above
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', function () {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (_this4.player.elements.inputs.seek.value / 100); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', function () {
|
|
||||||
_this4.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', function () {
|
||||||
_this4.toggleThumbContainer(false, true);
|
_this5.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
this.player.on('seeked', function () {
|
this.player.on('seeked', function () {
|
||||||
_this4.toggleThumbContainer(false);
|
_this5.toggleThumbContainer(false);
|
||||||
}); // Show scrubbing preview
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', function (event) {
|
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
_this4.mouseDown = true; // Wait until media has a duration
|
|
||||||
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
_this4.toggleScrubbingContainer(true);
|
|
||||||
|
|
||||||
_this4.toggleThumbContainer(false, true); // Download and show image
|
|
||||||
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
on.call(this.player, this.player.media, 'timeupdate', function () {
|
this.player.on('timeupdate', function () {
|
||||||
_this4.timeAtLastTimeupdate = _this4.player.media.currentTime;
|
_this5.lastTime = _this5.player.media.currentTime;
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', function () {
|
|
||||||
_this4.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
|
|
||||||
if (Math.ceil(_this4.timeAtLastTimeupdate) === Math.ceil(_this4.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(_this4.player, _this4.player.media, 'timeupdate', function () {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!_this4.mouseDown) {
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -6871,7 +6918,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "showImageAtCurrentTime",
|
key: "showImageAtCurrentTime",
|
||||||
value: function showImageAtCurrentTime() {
|
value: function showImageAtCurrentTime() {
|
||||||
var _this5 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
@ -6883,7 +6930,7 @@ function () {
|
|||||||
|
|
||||||
|
|
||||||
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
||||||
return _this5.seekTime >= frame.startTime && _this5.seekTime <= frame.endTime;
|
return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime;
|
||||||
});
|
});
|
||||||
var hasThumb = thumbNum >= 0;
|
var hasThumb = thumbNum >= 0;
|
||||||
var qualityIndex = 0;
|
var qualityIndex = 0;
|
||||||
@ -6895,7 +6942,7 @@ function () {
|
|||||||
|
|
||||||
|
|
||||||
this.thumbnails.forEach(function (thumbnail, index) {
|
this.thumbnails.forEach(function (thumbnail, index) {
|
||||||
if (_this5.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
||||||
qualityIndex = index;
|
qualityIndex = index;
|
||||||
}
|
}
|
||||||
}); // Only proceed if either thumbnum or thumbfilename has changed
|
}); // Only proceed if either thumbnum or thumbfilename has changed
|
||||||
@ -6909,7 +6956,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "loadImage",
|
key: "loadImage",
|
||||||
value: function loadImage() {
|
value: function loadImage() {
|
||||||
var _this6 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||||
var thumbNum = this.showingThumb;
|
var thumbNum = this.showingThumb;
|
||||||
@ -6937,7 +6984,7 @@ function () {
|
|||||||
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
return _this6.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadingImage = previewImage;
|
this.loadingImage = previewImage;
|
||||||
@ -6974,7 +7021,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "removeOldImages",
|
key: "removeOldImages",
|
||||||
value: function removeOldImages(currentImage) {
|
value: function removeOldImages(currentImage) {
|
||||||
var _this7 = this;
|
var _this8 = this;
|
||||||
|
|
||||||
// Get a list of all images, convert it from a DOM list to an array
|
// Get a list of all images, convert it from a DOM list to an array
|
||||||
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
||||||
@ -6982,18 +7029,18 @@ function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeDelay = _this7.usingSprites ? 500 : 1000;
|
var removeDelay = _this8.usingSprites ? 500 : 1000;
|
||||||
|
|
||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this7.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
currentImageContainer.removeChild(image);
|
currentImageContainer.removeChild(image);
|
||||||
|
|
||||||
_this7.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
_this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -7003,21 +7050,21 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "preloadNearby",
|
key: "preloadNearby",
|
||||||
value: function preloadNearby(thumbNum) {
|
value: function preloadNearby(thumbNum) {
|
||||||
var _this8 = this;
|
var _this9 = this;
|
||||||
|
|
||||||
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var oldThumbFilename = _this8.thumbnails[0].frames[thumbNum].text;
|
var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text;
|
||||||
|
|
||||||
if (_this8.showingThumbFilename === oldThumbFilename) {
|
if (_this9.showingThumbFilename === oldThumbFilename) {
|
||||||
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
||||||
var thumbnailsClone;
|
var thumbnailsClone;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(thumbNum);
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum);
|
||||||
} else {
|
} else {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundOne = false;
|
var foundOne = false;
|
||||||
@ -7026,20 +7073,20 @@ function () {
|
|||||||
|
|
||||||
if (newThumbFilename !== oldThumbFilename) {
|
if (newThumbFilename !== oldThumbFilename) {
|
||||||
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) {
|
if (!_this9.loadedImages.includes(newThumbFilename)) {
|
||||||
foundOne = true;
|
foundOne = true;
|
||||||
|
|
||||||
_this8.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
var urlPrefix = _this8.thumbnails[0].urlPrefix;
|
var urlPrefix = _this9.thumbnails[0].urlPrefix;
|
||||||
var thumbURL = urlPrefix + newThumbFilename;
|
var thumbURL = urlPrefix + newThumbFilename;
|
||||||
var previewImage = new Image();
|
var previewImage = new Image();
|
||||||
previewImage.src = thumbURL;
|
previewImage.src = thumbURL;
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
_this8.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) _this8.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -7058,7 +7105,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "getHigherQuality",
|
key: "getHigherQuality",
|
||||||
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
||||||
var _this9 = this;
|
var _this10 = this;
|
||||||
|
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
@ -7072,10 +7119,10 @@ function () {
|
|||||||
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Make sure the mouse hasn't already moved on and started hovering at another image
|
// Make sure the mouse hasn't already moved on and started hovering at another image
|
||||||
if (_this9.showingThumbFilename === thumbFilename) {
|
if (_this10.showingThumbFilename === thumbFilename) {
|
||||||
_this9.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
_this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
||||||
|
|
||||||
_this9.loadImage(currentQualityIndex + 1);
|
_this10.loadImage(currentQualityIndex + 1);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
@ -7349,11 +7396,16 @@ var source = {
|
|||||||
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
||||||
// Setup interface
|
// Setup interface
|
||||||
ui.build.call(_this2);
|
ui.build.call(_this2);
|
||||||
}
|
} // Load HTML5 sources
|
||||||
|
|
||||||
|
|
||||||
if (_this2.isHTML5) {
|
if (_this2.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
_this2.media.load();
|
_this2.media.load();
|
||||||
|
} // Reload thumbnails
|
||||||
|
|
||||||
|
|
||||||
|
if (_this2.previewThumbnails) {
|
||||||
|
_this2.previewThumbnails.load();
|
||||||
} // Update the fullscreen support
|
} // Update the fullscreen support
|
||||||
|
|
||||||
|
|
||||||
|
280
dist/plyr.polyfilled.js
vendored
280
dist/plyr.polyfilled.js
vendored
@ -7863,6 +7863,38 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
||||||
return controls.updateSeekTooltip.call(player, event);
|
return controls.updateSeekTooltip.call(player, event);
|
||||||
|
}); // Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseleave click', function () {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
}); // Show scrubbing preview
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
}); // Polyfill for lower fill in <input type="range"> for webkit
|
}); // Polyfill for lower fill in <input type="range"> for webkit
|
||||||
|
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
@ -9782,17 +9814,15 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
this.elements = {
|
this.elements = {
|
||||||
thumb: {},
|
thumb: {},
|
||||||
scrubbing: {}
|
scrubbing: {}
|
||||||
};
|
};
|
||||||
|
this.load();
|
||||||
if (this.enabled) {
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(PreviewThumbnails, [{
|
_createClass(PreviewThumbnails, [{
|
||||||
@ -9800,17 +9830,23 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
value: function load() {
|
value: function load() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
// Render DOM elements
|
||||||
_this.listeners(); // Render DOM elements
|
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
_this.determineContainerAutoSizing();
|
_this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
_this.loaded = true;
|
||||||
});
|
});
|
||||||
} // Download VTT files and parse them
|
} // Download VTT files and parse them
|
||||||
|
|
||||||
@ -9879,6 +9915,89 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "startMove",
|
||||||
|
value: function startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is$1.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
} // Wait until media has a duration
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
var clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX; // Set time text inside image container
|
||||||
|
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
} // Download and show image
|
||||||
|
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "endMove",
|
||||||
|
value: function endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "startScrubbing",
|
||||||
|
value: function startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true; // Wait until media has a duration
|
||||||
|
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true); // Download and show image
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "finishScrubbing",
|
||||||
|
value: function finishScrubbing() {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', function () {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!_this4.mouseDown) {
|
||||||
|
_this4.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
@ -9886,89 +10005,17 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "listeners",
|
key: "listeners",
|
||||||
value: function listeners() {
|
value: function listeners() {
|
||||||
var _this4 = this;
|
var _this5 = this;
|
||||||
|
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', function (event) {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
var clientRect = _this4.player.elements.progress.getBoundingClientRect();
|
|
||||||
|
|
||||||
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (_this4.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
_this4.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this4.seekTime > _this4.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
_this4.seekTime = _this4.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_this4.mousePosX = event.pageX; // Set time text inside image container
|
|
||||||
|
|
||||||
_this4.elements.thumb.time.innerText = formatTime(_this4.seekTime); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Touch device seeking - performs same function as above
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', function () {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (_this4.player.elements.inputs.seek.value / 100); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', function () {
|
|
||||||
_this4.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', function () {
|
||||||
_this4.toggleThumbContainer(false, true);
|
_this5.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
this.player.on('seeked', function () {
|
this.player.on('seeked', function () {
|
||||||
_this4.toggleThumbContainer(false);
|
_this5.toggleThumbContainer(false);
|
||||||
}); // Show scrubbing preview
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', function (event) {
|
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
_this4.mouseDown = true; // Wait until media has a duration
|
|
||||||
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
_this4.toggleScrubbingContainer(true);
|
|
||||||
|
|
||||||
_this4.toggleThumbContainer(false, true); // Download and show image
|
|
||||||
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
on.call(this.player, this.player.media, 'timeupdate', function () {
|
this.player.on('timeupdate', function () {
|
||||||
_this4.timeAtLastTimeupdate = _this4.player.media.currentTime;
|
_this5.lastTime = _this5.player.media.currentTime;
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', function () {
|
|
||||||
_this4.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
|
|
||||||
if (Math.ceil(_this4.timeAtLastTimeupdate) === Math.ceil(_this4.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(_this4.player, _this4.player.media, 'timeupdate', function () {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!_this4.mouseDown) {
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -10005,7 +10052,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "showImageAtCurrentTime",
|
key: "showImageAtCurrentTime",
|
||||||
value: function showImageAtCurrentTime() {
|
value: function showImageAtCurrentTime() {
|
||||||
var _this5 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
@ -10017,7 +10064,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
||||||
return _this5.seekTime >= frame.startTime && _this5.seekTime <= frame.endTime;
|
return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime;
|
||||||
});
|
});
|
||||||
var hasThumb = thumbNum >= 0;
|
var hasThumb = thumbNum >= 0;
|
||||||
var qualityIndex = 0;
|
var qualityIndex = 0;
|
||||||
@ -10029,7 +10076,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
this.thumbnails.forEach(function (thumbnail, index) {
|
this.thumbnails.forEach(function (thumbnail, index) {
|
||||||
if (_this5.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
||||||
qualityIndex = index;
|
qualityIndex = index;
|
||||||
}
|
}
|
||||||
}); // Only proceed if either thumbnum or thumbfilename has changed
|
}); // Only proceed if either thumbnum or thumbfilename has changed
|
||||||
@ -10043,7 +10090,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "loadImage",
|
key: "loadImage",
|
||||||
value: function loadImage() {
|
value: function loadImage() {
|
||||||
var _this6 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||||
var thumbNum = this.showingThumb;
|
var thumbNum = this.showingThumb;
|
||||||
@ -10071,7 +10118,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
return _this6.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadingImage = previewImage;
|
this.loadingImage = previewImage;
|
||||||
@ -10108,7 +10155,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "removeOldImages",
|
key: "removeOldImages",
|
||||||
value: function removeOldImages(currentImage) {
|
value: function removeOldImages(currentImage) {
|
||||||
var _this7 = this;
|
var _this8 = this;
|
||||||
|
|
||||||
// Get a list of all images, convert it from a DOM list to an array
|
// Get a list of all images, convert it from a DOM list to an array
|
||||||
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
||||||
@ -10116,18 +10163,18 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeDelay = _this7.usingSprites ? 500 : 1000;
|
var removeDelay = _this8.usingSprites ? 500 : 1000;
|
||||||
|
|
||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this7.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
currentImageContainer.removeChild(image);
|
currentImageContainer.removeChild(image);
|
||||||
|
|
||||||
_this7.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
_this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -10137,21 +10184,21 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "preloadNearby",
|
key: "preloadNearby",
|
||||||
value: function preloadNearby(thumbNum) {
|
value: function preloadNearby(thumbNum) {
|
||||||
var _this8 = this;
|
var _this9 = this;
|
||||||
|
|
||||||
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var oldThumbFilename = _this8.thumbnails[0].frames[thumbNum].text;
|
var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text;
|
||||||
|
|
||||||
if (_this8.showingThumbFilename === oldThumbFilename) {
|
if (_this9.showingThumbFilename === oldThumbFilename) {
|
||||||
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
||||||
var thumbnailsClone;
|
var thumbnailsClone;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(thumbNum);
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum);
|
||||||
} else {
|
} else {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundOne = false;
|
var foundOne = false;
|
||||||
@ -10160,20 +10207,20 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
if (newThumbFilename !== oldThumbFilename) {
|
if (newThumbFilename !== oldThumbFilename) {
|
||||||
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) {
|
if (!_this9.loadedImages.includes(newThumbFilename)) {
|
||||||
foundOne = true;
|
foundOne = true;
|
||||||
|
|
||||||
_this8.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
var urlPrefix = _this8.thumbnails[0].urlPrefix;
|
var urlPrefix = _this9.thumbnails[0].urlPrefix;
|
||||||
var thumbURL = urlPrefix + newThumbFilename;
|
var thumbURL = urlPrefix + newThumbFilename;
|
||||||
var previewImage = new Image();
|
var previewImage = new Image();
|
||||||
previewImage.src = thumbURL;
|
previewImage.src = thumbURL;
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
_this8.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) _this8.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -10192,7 +10239,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "getHigherQuality",
|
key: "getHigherQuality",
|
||||||
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
||||||
var _this9 = this;
|
var _this10 = this;
|
||||||
|
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
@ -10206,10 +10253,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Make sure the mouse hasn't already moved on and started hovering at another image
|
// Make sure the mouse hasn't already moved on and started hovering at another image
|
||||||
if (_this9.showingThumbFilename === thumbFilename) {
|
if (_this10.showingThumbFilename === thumbFilename) {
|
||||||
_this9.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
_this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
||||||
|
|
||||||
_this9.loadImage(currentQualityIndex + 1);
|
_this10.loadImage(currentQualityIndex + 1);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
@ -10483,11 +10530,16 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
||||||
// Setup interface
|
// Setup interface
|
||||||
ui.build.call(_this2);
|
ui.build.call(_this2);
|
||||||
}
|
} // Load HTML5 sources
|
||||||
|
|
||||||
|
|
||||||
if (_this2.isHTML5) {
|
if (_this2.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
_this2.media.load();
|
_this2.media.load();
|
||||||
|
} // Reload thumbnails
|
||||||
|
|
||||||
|
|
||||||
|
if (_this2.previewThumbnails) {
|
||||||
|
_this2.previewThumbnails.load();
|
||||||
} // Update the fullscreen support
|
} // Update the fullscreen support
|
||||||
|
|
||||||
|
|
||||||
|
2
dist/plyr.polyfilled.min.js
vendored
2
dist/plyr.polyfilled.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js.map
vendored
2
dist/plyr.polyfilled.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.mjs
vendored
2
dist/plyr.polyfilled.min.mjs
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.mjs.map
vendored
2
dist/plyr.polyfilled.min.mjs.map
vendored
File diff suppressed because one or more lines are too long
280
dist/plyr.polyfilled.mjs
vendored
280
dist/plyr.polyfilled.mjs
vendored
@ -7857,6 +7857,38 @@ function () {
|
|||||||
|
|
||||||
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) {
|
||||||
return controls.updateSeekTooltip.call(player, event);
|
return controls.updateSeekTooltip.call(player, event);
|
||||||
|
}); // Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseleave click', function () {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
}); // Show scrubbing preview
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', function (event) {
|
||||||
|
var previewThumbnails = player.previewThumbnails;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
}); // Polyfill for lower fill in <input type="range"> for webkit
|
}); // Polyfill for lower fill in <input type="range"> for webkit
|
||||||
|
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
@ -9776,17 +9808,15 @@ function () {
|
|||||||
|
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
this.elements = {
|
this.elements = {
|
||||||
thumb: {},
|
thumb: {},
|
||||||
scrubbing: {}
|
scrubbing: {}
|
||||||
};
|
};
|
||||||
|
this.load();
|
||||||
if (this.enabled) {
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(PreviewThumbnails, [{
|
_createClass(PreviewThumbnails, [{
|
||||||
@ -9794,17 +9824,23 @@ function () {
|
|||||||
value: function load() {
|
value: function load() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
// Render DOM elements
|
||||||
_this.listeners(); // Render DOM elements
|
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
_this.determineContainerAutoSizing();
|
_this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
_this.loaded = true;
|
||||||
});
|
});
|
||||||
} // Download VTT files and parse them
|
} // Download VTT files and parse them
|
||||||
|
|
||||||
@ -9873,6 +9909,89 @@ function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "startMove",
|
||||||
|
value: function startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is$1.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
} // Wait until media has a duration
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
var clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX; // Set time text inside image container
|
||||||
|
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
} // Download and show image
|
||||||
|
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "endMove",
|
||||||
|
value: function endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "startScrubbing",
|
||||||
|
value: function startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true; // Wait until media has a duration
|
||||||
|
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true); // Download and show image
|
||||||
|
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "finishScrubbing",
|
||||||
|
value: function finishScrubbing() {
|
||||||
|
var _this4 = this;
|
||||||
|
|
||||||
|
this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', function () {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!_this4.mouseDown) {
|
||||||
|
_this4.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
@ -9880,89 +9999,17 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "listeners",
|
key: "listeners",
|
||||||
value: function listeners() {
|
value: function listeners() {
|
||||||
var _this4 = this;
|
var _this5 = this;
|
||||||
|
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', function (event) {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
var clientRect = _this4.player.elements.progress.getBoundingClientRect();
|
|
||||||
|
|
||||||
var percentage = 100 / clientRect.width * (event.pageX - clientRect.left);
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (_this4.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
_this4.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this4.seekTime > _this4.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
_this4.seekTime = _this4.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_this4.mousePosX = event.pageX; // Set time text inside image container
|
|
||||||
|
|
||||||
_this4.elements.thumb.time.innerText = formatTime(_this4.seekTime); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Touch device seeking - performs same function as above
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', function () {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
_this4.seekTime = _this4.player.media.duration * (_this4.player.elements.inputs.seek.value / 100); // Download and show image
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', function () {
|
|
||||||
_this4.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', function () {
|
||||||
_this4.toggleThumbContainer(false, true);
|
_this5.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
this.player.on('seeked', function () {
|
this.player.on('seeked', function () {
|
||||||
_this4.toggleThumbContainer(false);
|
_this5.toggleThumbContainer(false);
|
||||||
}); // Show scrubbing preview
|
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', function (event) {
|
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
_this4.mouseDown = true; // Wait until media has a duration
|
|
||||||
|
|
||||||
if (_this4.player.media.duration) {
|
|
||||||
_this4.toggleScrubbingContainer(true);
|
|
||||||
|
|
||||||
_this4.toggleThumbContainer(false, true); // Download and show image
|
|
||||||
|
|
||||||
|
|
||||||
_this4.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
on.call(this.player, this.player.media, 'timeupdate', function () {
|
this.player.on('timeupdate', function () {
|
||||||
_this4.timeAtLastTimeupdate = _this4.player.media.currentTime;
|
_this5.lastTime = _this5.player.media.currentTime;
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', function () {
|
|
||||||
_this4.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
|
|
||||||
if (Math.ceil(_this4.timeAtLastTimeupdate) === Math.ceil(_this4.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(_this4.player, _this4.player.media, 'timeupdate', function () {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!_this4.mouseDown) {
|
|
||||||
_this4.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -9999,7 +10046,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "showImageAtCurrentTime",
|
key: "showImageAtCurrentTime",
|
||||||
value: function showImageAtCurrentTime() {
|
value: function showImageAtCurrentTime() {
|
||||||
var _this5 = this;
|
var _this6 = this;
|
||||||
|
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
@ -10011,7 +10058,7 @@ function () {
|
|||||||
|
|
||||||
|
|
||||||
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
var thumbNum = this.thumbnails[0].frames.findIndex(function (frame) {
|
||||||
return _this5.seekTime >= frame.startTime && _this5.seekTime <= frame.endTime;
|
return _this6.seekTime >= frame.startTime && _this6.seekTime <= frame.endTime;
|
||||||
});
|
});
|
||||||
var hasThumb = thumbNum >= 0;
|
var hasThumb = thumbNum >= 0;
|
||||||
var qualityIndex = 0;
|
var qualityIndex = 0;
|
||||||
@ -10023,7 +10070,7 @@ function () {
|
|||||||
|
|
||||||
|
|
||||||
this.thumbnails.forEach(function (thumbnail, index) {
|
this.thumbnails.forEach(function (thumbnail, index) {
|
||||||
if (_this5.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
if (_this6.loadedImages.includes(thumbnail.frames[thumbNum].text)) {
|
||||||
qualityIndex = index;
|
qualityIndex = index;
|
||||||
}
|
}
|
||||||
}); // Only proceed if either thumbnum or thumbfilename has changed
|
}); // Only proceed if either thumbnum or thumbfilename has changed
|
||||||
@ -10037,7 +10084,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "loadImage",
|
key: "loadImage",
|
||||||
value: function loadImage() {
|
value: function loadImage() {
|
||||||
var _this6 = this;
|
var _this7 = this;
|
||||||
|
|
||||||
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
var qualityIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||||||
var thumbNum = this.showingThumb;
|
var thumbNum = this.showingThumb;
|
||||||
@ -10065,7 +10112,7 @@ function () {
|
|||||||
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
this.player.debug.log("Loading image: ".concat(thumbUrl)); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
return _this6.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
return _this7.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loadingImage = previewImage;
|
this.loadingImage = previewImage;
|
||||||
@ -10102,7 +10149,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "removeOldImages",
|
key: "removeOldImages",
|
||||||
value: function removeOldImages(currentImage) {
|
value: function removeOldImages(currentImage) {
|
||||||
var _this7 = this;
|
var _this8 = this;
|
||||||
|
|
||||||
// Get a list of all images, convert it from a DOM list to an array
|
// Get a list of all images, convert it from a DOM list to an array
|
||||||
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
Array.from(this.currentImageContainer.children).forEach(function (image) {
|
||||||
@ -10110,18 +10157,18 @@ function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var removeDelay = _this7.usingSprites ? 500 : 1000;
|
var removeDelay = _this8.usingSprites ? 500 : 1000;
|
||||||
|
|
||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this7.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
currentImageContainer.removeChild(image);
|
currentImageContainer.removeChild(image);
|
||||||
|
|
||||||
_this7.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
_this8.player.debug.log("Removing thumb: ".concat(image.dataset.filename));
|
||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -10131,21 +10178,21 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "preloadNearby",
|
key: "preloadNearby",
|
||||||
value: function preloadNearby(thumbNum) {
|
value: function preloadNearby(thumbNum) {
|
||||||
var _this8 = this;
|
var _this9 = this;
|
||||||
|
|
||||||
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
var forward = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var oldThumbFilename = _this8.thumbnails[0].frames[thumbNum].text;
|
var oldThumbFilename = _this9.thumbnails[0].frames[thumbNum].text;
|
||||||
|
|
||||||
if (_this8.showingThumbFilename === oldThumbFilename) {
|
if (_this9.showingThumbFilename === oldThumbFilename) {
|
||||||
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
// Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away
|
||||||
var thumbnailsClone;
|
var thumbnailsClone;
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(thumbNum);
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(thumbNum);
|
||||||
} else {
|
} else {
|
||||||
thumbnailsClone = _this8.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
thumbnailsClone = _this9.thumbnails[0].frames.slice(0, thumbNum).reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
var foundOne = false;
|
var foundOne = false;
|
||||||
@ -10154,20 +10201,20 @@ function () {
|
|||||||
|
|
||||||
if (newThumbFilename !== oldThumbFilename) {
|
if (newThumbFilename !== oldThumbFilename) {
|
||||||
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
// Found one with a different filename. Make sure it hasn't already been loaded on this page visit
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) {
|
if (!_this9.loadedImages.includes(newThumbFilename)) {
|
||||||
foundOne = true;
|
foundOne = true;
|
||||||
|
|
||||||
_this8.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloading thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
var urlPrefix = _this8.thumbnails[0].urlPrefix;
|
var urlPrefix = _this9.thumbnails[0].urlPrefix;
|
||||||
var thumbURL = urlPrefix + newThumbFilename;
|
var thumbURL = urlPrefix + newThumbFilename;
|
||||||
var previewImage = new Image();
|
var previewImage = new Image();
|
||||||
previewImage.src = thumbURL;
|
previewImage.src = thumbURL;
|
||||||
|
|
||||||
previewImage.onload = function () {
|
previewImage.onload = function () {
|
||||||
_this8.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
_this9.player.debug.log("Preloaded thumb filename: ".concat(newThumbFilename));
|
||||||
|
|
||||||
if (!_this8.loadedImages.includes(newThumbFilename)) _this8.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
if (!_this9.loadedImages.includes(newThumbFilename)) _this9.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -10186,7 +10233,7 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "getHigherQuality",
|
key: "getHigherQuality",
|
||||||
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
value: function getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
||||||
var _this9 = this;
|
var _this10 = this;
|
||||||
|
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
@ -10200,10 +10247,10 @@ function () {
|
|||||||
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
// Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Make sure the mouse hasn't already moved on and started hovering at another image
|
// Make sure the mouse hasn't already moved on and started hovering at another image
|
||||||
if (_this9.showingThumbFilename === thumbFilename) {
|
if (_this10.showingThumbFilename === thumbFilename) {
|
||||||
_this9.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
_this10.player.debug.log("Showing higher quality thumb for: ".concat(thumbFilename));
|
||||||
|
|
||||||
_this9.loadImage(currentQualityIndex + 1);
|
_this10.loadImage(currentQualityIndex + 1);
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
@ -10477,11 +10524,16 @@ var source = {
|
|||||||
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
if (_this2.isHTML5 || _this2.isEmbed && !_this2.supported.ui) {
|
||||||
// Setup interface
|
// Setup interface
|
||||||
ui.build.call(_this2);
|
ui.build.call(_this2);
|
||||||
}
|
} // Load HTML5 sources
|
||||||
|
|
||||||
|
|
||||||
if (_this2.isHTML5) {
|
if (_this2.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
_this2.media.load();
|
_this2.media.load();
|
||||||
|
} // Reload thumbnails
|
||||||
|
|
||||||
|
|
||||||
|
if (_this2.previewThumbnails) {
|
||||||
|
_this2.previewThumbnails.load();
|
||||||
} // Update the fullscreen support
|
} // Update the fullscreen support
|
||||||
|
|
||||||
|
|
||||||
|
@ -740,6 +740,42 @@ class Listeners {
|
|||||||
controls.updateSeekTooltip.call(player, event),
|
controls.updateSeekTooltip.call(player, event),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Preview thumbnails plugin
|
||||||
|
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
|
||||||
|
this.bind(elements.progress, 'mousemove touchmove', event => {
|
||||||
|
const { previewThumbnails } = player;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startMove(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
||||||
|
this.bind(elements.progress, 'mouseleave click', () => {
|
||||||
|
const { previewThumbnails } = player;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endMove(false, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show scrubbing preview
|
||||||
|
this.bind(elements.progress, 'mousedown touchstart', event => {
|
||||||
|
const { previewThumbnails } = player;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.startScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bind(elements.progress, 'mouseup touchend', event => {
|
||||||
|
const { previewThumbnails } = player;
|
||||||
|
|
||||||
|
if (previewThumbnails && previewThumbnails.loaded) {
|
||||||
|
previewThumbnails.endScrubbing(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Polyfill for lower fill in <input type="range"> for webkit
|
// Polyfill for lower fill in <input type="range"> for webkit
|
||||||
if (browser.isWebkit) {
|
if (browser.isWebkit) {
|
||||||
Array.from(getElements.call(player, 'input[type="range"]')).forEach(element => {
|
Array.from(getElements.call(player, 'input[type="range"]')).forEach(element => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createElement } from '../utils/elements';
|
import { createElement } from '../utils/elements';
|
||||||
import { on, once } from '../utils/events';
|
import { once } from '../utils/events';
|
||||||
import fetch from '../utils/fetch';
|
import fetch from '../utils/fetch';
|
||||||
import is from '../utils/is';
|
import is from '../utils/is';
|
||||||
import { formatTime } from '../utils/time';
|
import { formatTime } from '../utils/time';
|
||||||
@ -72,7 +72,8 @@ class PreviewThumbnails {
|
|||||||
constructor(player) {
|
constructor(player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.thumbnails = [];
|
this.thumbnails = [];
|
||||||
this.lastMousemoveEventTime = Date.now();
|
this.loaded = false;
|
||||||
|
this.lastMouseMoveTime = Date.now();
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
this.loadedImages = [];
|
this.loadedImages = [];
|
||||||
|
|
||||||
@ -81,9 +82,7 @@ class PreviewThumbnails {
|
|||||||
scrubbing: {},
|
scrubbing: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.enabled) {
|
this.load();
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get enabled() {
|
get enabled() {
|
||||||
@ -91,18 +90,23 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
// Turn off the regular seek tooltip
|
// Togglethe regular seek tooltip
|
||||||
this.player.config.tooltips.seek = false;
|
if (this.player.elements.display.seekTooltip) {
|
||||||
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(() => {
|
this.getThumbnails().then(() => {
|
||||||
// Initiate DOM listeners so that our preview thumbnails can be used
|
|
||||||
this.listeners();
|
|
||||||
|
|
||||||
// Render DOM elements
|
// Render DOM elements
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
// Check to see if thumb container size was specified manually in CSS
|
// Check to see if thumb container size was specified manually in CSS
|
||||||
this.determineContainerAutoSizing();
|
this.determineContainerAutoSizing();
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,96 +169,101 @@ class PreviewThumbnails {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startMove(event) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until media has a duration
|
||||||
|
if (!this.player.media.duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'touchmove') {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
||||||
|
} else {
|
||||||
|
// Calculate seek hover position as approx video seconds
|
||||||
|
const clientRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
|
const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);
|
||||||
|
this.seekTime = this.player.media.duration * (percentage / 100);
|
||||||
|
|
||||||
|
if (this.seekTime < 0) {
|
||||||
|
// The mousemove fires for 10+px out to the left
|
||||||
|
this.seekTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.seekTime > this.player.media.duration - 1) {
|
||||||
|
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
||||||
|
this.seekTime = this.player.media.duration - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mousePosX = event.pageX;
|
||||||
|
|
||||||
|
// Set time text inside image container
|
||||||
|
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download and show image
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
endMove() {
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
startScrubbing(event) {
|
||||||
|
// Only act on left mouse button (0), or touch device (event.button is false)
|
||||||
|
if (event.button === false || event.button === 0) {
|
||||||
|
this.mouseDown = true;
|
||||||
|
// Wait until media has a duration
|
||||||
|
if (this.player.media.duration) {
|
||||||
|
this.toggleScrubbingContainer(true);
|
||||||
|
this.toggleThumbContainer(false, true);
|
||||||
|
|
||||||
|
// Download and show image
|
||||||
|
this.showImageAtCurrentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finishScrubbing() {
|
||||||
|
this.mouseDown = false;
|
||||||
|
|
||||||
|
// Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
|
if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {
|
||||||
|
// The video was already seeked/loaded at the chosen time - hide immediately
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
} else {
|
||||||
|
// The video hasn't seeked yet. Wait for that
|
||||||
|
once.call(this.player, this.player.media, 'timeupdate', () => {
|
||||||
|
// Re-check mousedown - we might have already started scrubbing again
|
||||||
|
if (!this.mouseDown) {
|
||||||
|
this.toggleScrubbingContainer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
listeners() {
|
listeners() {
|
||||||
// Mouse hover over seek bar
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
on.call(this.player, this.player.elements.progress, 'mousemove', event => {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (this.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
const clientRect = this.player.elements.progress.getBoundingClientRect();
|
|
||||||
const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);
|
|
||||||
this.seekTime = this.player.media.duration * (percentage / 100);
|
|
||||||
|
|
||||||
if (this.seekTime < 0) {
|
|
||||||
// The mousemove fires for 10+px out to the left
|
|
||||||
this.seekTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.seekTime > this.player.media.duration - 1) {
|
|
||||||
// Took 1 second off the duration for safety, because different players can disagree on the real duration of a video
|
|
||||||
this.seekTime = this.player.media.duration - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mousePosX = event.pageX;
|
|
||||||
|
|
||||||
// Set time text inside image container
|
|
||||||
this.elements.thumb.time.innerText = formatTime(this.seekTime);
|
|
||||||
|
|
||||||
// Download and show image
|
|
||||||
this.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Touch device seeking - performs same function as above
|
|
||||||
on.call(this.player, this.player.elements.progress, 'touchmove', () => {
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (this.player.media.duration) {
|
|
||||||
// Calculate seek hover position as approx video seconds
|
|
||||||
this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);
|
|
||||||
|
|
||||||
// Download and show image
|
|
||||||
this.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseleave click', () => {
|
|
||||||
this.toggleThumbContainer(false, true);
|
|
||||||
});
|
|
||||||
this.player.on('play', () => {
|
this.player.on('play', () => {
|
||||||
this.toggleThumbContainer(false, true);
|
this.toggleThumbContainer(false, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.player.on('seeked', () => {
|
this.player.on('seeked', () => {
|
||||||
this.toggleThumbContainer(false);
|
this.toggleThumbContainer(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show scrubbing preview
|
this.player.on('timeupdate', () => {
|
||||||
on.call(this.player, this.player.elements.progress, 'mousedown touchstart', event => {
|
this.lastTime = this.player.media.currentTime;
|
||||||
// Only act on left mouse button (0), or touch device (event.button is false)
|
|
||||||
if (event.button === false || event.button === 0) {
|
|
||||||
this.mouseDown = true;
|
|
||||||
// Wait until media has a duration
|
|
||||||
if (this.player.media.duration) {
|
|
||||||
this.toggleScrubbingContainer(true);
|
|
||||||
this.toggleThumbContainer(false, true);
|
|
||||||
|
|
||||||
// Download and show image
|
|
||||||
this.showImageAtCurrentTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
on.call(this.player, this.player.media, 'timeupdate', () => {
|
|
||||||
this.timeAtLastTimeupdate = this.player.media.currentTime;
|
|
||||||
});
|
|
||||||
on.call(this.player, this.player.elements.progress, 'mouseup touchend', () => {
|
|
||||||
this.mouseDown = false;
|
|
||||||
|
|
||||||
// Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
|
||||||
if (Math.ceil(this.timeAtLastTimeupdate) === Math.ceil(this.player.media.currentTime)) {
|
|
||||||
// The video was already seeked/loaded at the chosen time - hide immediately
|
|
||||||
this.toggleScrubbingContainer(false);
|
|
||||||
} else {
|
|
||||||
// The video hasn't seeked yet. Wait for that
|
|
||||||
once.call(this.player, this.player.media, 'timeupdate', () => {
|
|
||||||
// Re-check mousedown - we might have already started scrubbing again
|
|
||||||
if (!this.mouseDown) {
|
|
||||||
this.toggleScrubbingContainer(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +125,16 @@ const source = {
|
|||||||
ui.build.call(this);
|
ui.build.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load HTML5 sources
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
// Load HTML5 sources
|
|
||||||
this.media.load();
|
this.media.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload thumbnails
|
||||||
|
if (this.previewThumbnails) {
|
||||||
|
this.previewThumbnails.load();
|
||||||
|
}
|
||||||
|
|
||||||
// Update the fullscreen support
|
// Update the fullscreen support
|
||||||
this.fullscreen.update();
|
this.fullscreen.update();
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user