Controls fixes

This commit is contained in:
Sam Potts
2018-03-27 23:43:38 +11:00
parent 0cf75eed3f
commit 7b1e4abda7
17 changed files with 219 additions and 128 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+77 -46
View File
@@ -170,7 +170,6 @@ var defaults = {
end: 'End', end: 'End',
all: 'All', all: 'All',
reset: 'Reset', reset: 'Reset',
none: 'None',
disabled: 'Disabled', disabled: 'Disabled',
advertisement: 'Ad' advertisement: 'Ad'
}, },
@@ -1964,7 +1963,7 @@ var support = {
}(), }(),
// Touch // Touch
// Remember a device can be moust + touch enabled // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event
touch: 'ontouchstart' in document.documentElement, touch: 'ontouchstart' in document.documentElement,
// Detect transitions support // Detect transitions support
@@ -2869,6 +2868,7 @@ var ui = {
// Plyr controls // Plyr controls
// ========================================================================== // ==========================================================================
// Sniff out the browser
var browser$2 = utils.getBrowser(); var browser$2 = utils.getBrowser();
var controls = { var controls = {
@@ -3206,6 +3206,8 @@ var controls = {
// Update hover tooltip for seeking // Update hover tooltip for seeking
updateSeekTooltip: function updateSeekTooltip(event) { updateSeekTooltip: function updateSeekTooltip(event) {
var _this = this;
// Bail if setting not true // Bail if setting not true
if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) { if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) {
return; return;
@@ -3216,6 +3218,16 @@ var controls = {
var clientRect = this.elements.inputs.seek.getBoundingClientRect(); var clientRect = this.elements.inputs.seek.getBoundingClientRect();
var visible = this.config.classNames.tooltip + '--visible'; var visible = this.config.classNames.tooltip + '--visible';
var toggle = function toggle(_toggle) {
utils.toggleClass(_this.elements.display.seekTooltip, visible, _toggle);
};
// Hide on touch
if (this.touch) {
toggle(false);
return;
}
// Determine percentage, if already visible // Determine percentage, if already visible
if (utils.is.event(event)) { if (utils.is.event(event)) {
percent = 100 / clientRect.width * (event.pageX - clientRect.left); percent = 100 / clientRect.width * (event.pageX - clientRect.left);
@@ -3241,7 +3253,7 @@ var controls = {
// Show/hide the tooltip // Show/hide the tooltip
// If the event is a moues in/out and percentage is inside bounds // If the event is a moues in/out and percentage is inside bounds
if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {
utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); toggle(event.type === 'mouseenter');
} }
}, },
@@ -3259,7 +3271,7 @@ var controls = {
// Set the YouTube quality menu // Set the YouTube quality menu
// TODO: Support for HTML5 // TODO: Support for HTML5
setQualityMenu: function setQualityMenu(options) { setQualityMenu: function setQualityMenu(options) {
var _this = this; var _this2 = this;
// Menu required // Menu required
if (!utils.is.element(this.elements.settings.panes.quality)) { if (!utils.is.element(this.elements.settings.panes.quality)) {
@@ -3272,7 +3284,7 @@ var controls = {
// Set options if passed and filter based on config // Set options if passed and filter based on config
if (utils.is.array(options)) { if (utils.is.array(options)) {
this.options.quality = options.filter(function (quality) { this.options.quality = options.filter(function (quality) {
return _this.config.quality.options.includes(quality); return _this2.config.quality.options.includes(quality);
}); });
} else { } else {
this.options.quality = this.config.quality.options; this.options.quality = this.config.quality.options;
@@ -3319,11 +3331,11 @@ var controls = {
return null; return null;
} }
return controls.createBadge.call(_this, label); return controls.createBadge.call(_this2, label);
}; };
this.options.quality.forEach(function (quality) { this.options.quality.forEach(function (quality) {
return controls.createMenuItem.call(_this, quality, list, type, controls.getLabel.call(_this, 'quality', quality), getBadge(quality)); return controls.createMenuItem.call(_this2, quality, list, type, controls.getLabel.call(_this2, 'quality', quality), getBadge(quality));
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -3378,7 +3390,7 @@ var controls = {
switch (setting) { switch (setting) {
case 'captions': case 'captions':
value = this.captions.active ? this.captions.language : ''; value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
break; break;
default: default:
@@ -3468,11 +3480,7 @@ var controls = {
return null; return null;
} }
if (!support.textTracks || !captions.getTracks.call(this).length) { if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
return i18n.get('none', this.config);
}
if (this.captions.active) {
var currentTrack = captions.getCurrentTrack.call(this); var currentTrack = captions.getCurrentTrack.call(this);
if (utils.is.track(currentTrack)) { if (utils.is.track(currentTrack)) {
@@ -3486,7 +3494,7 @@ var controls = {
// Set a list of available captions languages // Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() { setCaptionsMenu: function setCaptionsMenu() {
var _this2 = this; var _this3 = this;
// TODO: Captions or language? Currently it's mixed // TODO: Captions or language? Currently it's mixed
var type = 'captions'; var type = 'captions';
@@ -3512,15 +3520,15 @@ var controls = {
}; };
}); });
// Add the "None" option to turn off captions // Add the "Disabled" option to turn off captions
tracks.unshift({ tracks.unshift({
language: '', language: '',
label: i18n.get('none', this.config) label: i18n.get('disabled', this.config)
}); });
// Generate options // Generate options
tracks.forEach(function (track) { tracks.forEach(function (track) {
controls.createMenuItem.call(_this2, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this2, track.language.toUpperCase()), track.language.toLowerCase() === _this2.captions.language.toLowerCase()); controls.createMenuItem.call(_this3, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this3, track.language.toUpperCase()), track.language.toLowerCase() === _this3.captions.language.toLowerCase());
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -3529,7 +3537,7 @@ var controls = {
// Set a list of available captions languages // Set a list of available captions languages
setSpeedMenu: function setSpeedMenu() { setSpeedMenu: function setSpeedMenu() {
var _this3 = this; var _this4 = this;
// Menu required // Menu required
if (!utils.is.element(this.elements.settings.panes.speed)) { if (!utils.is.element(this.elements.settings.panes.speed)) {
@@ -3545,7 +3553,7 @@ var controls = {
// Set options if passed and filter based on config // Set options if passed and filter based on config
this.options.speed = this.options.speed.filter(function (speed) { this.options.speed = this.options.speed.filter(function (speed) {
return _this3.config.speed.options.includes(speed); return _this4.config.speed.options.includes(speed);
}); });
// Toggle the pane and tab // Toggle the pane and tab
@@ -3569,7 +3577,7 @@ var controls = {
// Create items // Create items
this.options.speed.forEach(function (speed) { this.options.speed.forEach(function (speed) {
return controls.createMenuItem.call(_this3, speed, list, type, controls.getLabel.call(_this3, 'speed', speed)); return controls.createMenuItem.call(_this4, speed, list, type, controls.getLabel.call(_this4, 'speed', speed));
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -3732,7 +3740,7 @@ var controls = {
// Build the default HTML // Build the default HTML
// TODO: Set order based on order in the config.controls array? // TODO: Set order based on order in the config.controls array?
create: function create(data) { create: function create(data) {
var _this4 = this; var _this5 = this;
// Do nothing if we want no controls // Do nothing if we want no controls
if (utils.is.empty(this.config.controls)) { if (utils.is.empty(this.config.controls)) {
@@ -3881,17 +3889,17 @@ var controls = {
hidden: '' hidden: ''
}); });
var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this4.config.selectors.buttons.settings), { var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this5.config.selectors.buttons.settings), {
type: 'button', type: 'button',
class: _this4.config.classNames.control + ' ' + _this4.config.classNames.control + '--forward', class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--forward',
id: 'plyr-settings-' + data.id + '-' + type + '-tab', id: 'plyr-settings-' + data.id + '-' + type + '-tab',
'aria-haspopup': true, 'aria-haspopup': true,
'aria-controls': 'plyr-settings-' + data.id + '-' + type, 'aria-controls': 'plyr-settings-' + data.id + '-' + type,
'aria-expanded': false 'aria-expanded': false
}), i18n.get(type, _this4.config)); }), i18n.get(type, _this5.config));
var value = utils.createElement('span', { var value = utils.createElement('span', {
class: _this4.config.classNames.menu.value class: _this5.config.classNames.menu.value
}); });
// Speed contains HTML entities // Speed contains HTML entities
@@ -3901,7 +3909,7 @@ var controls = {
tab.appendChild(button); tab.appendChild(button);
tabs.appendChild(tab); tabs.appendChild(tab);
_this4.elements.settings.tabs[type] = tab; _this5.elements.settings.tabs[type] = tab;
}); });
home.appendChild(tabs); home.appendChild(tabs);
@@ -3920,11 +3928,11 @@ var controls = {
var back = utils.createElement('button', { var back = utils.createElement('button', {
type: 'button', type: 'button',
class: _this4.config.classNames.control + ' ' + _this4.config.classNames.control + '--back', class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--back',
'aria-haspopup': true, 'aria-haspopup': true,
'aria-controls': 'plyr-settings-' + data.id + '-home', 'aria-controls': 'plyr-settings-' + data.id + '-home',
'aria-expanded': false 'aria-expanded': false
}, i18n.get(type, _this4.config)); }, i18n.get(type, _this5.config));
pane.appendChild(back); pane.appendChild(back);
@@ -3933,7 +3941,7 @@ var controls = {
pane.appendChild(options); pane.appendChild(options);
inner.appendChild(pane); inner.appendChild(pane);
_this4.elements.settings.panes[type] = pane; _this5.elements.settings.panes[type] = pane;
}); });
form.appendChild(inner); form.appendChild(inner);
@@ -3976,7 +3984,7 @@ var controls = {
// Insert controls // Insert controls
inject: function inject() { inject: function inject() {
var _this5 = this; var _this6 = this;
// Sprite // Sprite
if (this.config.loadSprite) { if (this.config.loadSprite) {
@@ -4054,8 +4062,8 @@ var controls = {
var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join('')); var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join(''));
Array.from(labels).forEach(function (label) { Array.from(labels).forEach(function (label) {
utils.toggleClass(label, _this5.config.classNames.hidden, false); utils.toggleClass(label, _this6.config.classNames.hidden, false);
utils.toggleClass(label, _this5.config.classNames.tooltip, true); utils.toggleClass(label, _this6.config.classNames.tooltip, true);
label.setAttribute('role', 'tooltip'); label.setAttribute('role', 'tooltip');
}); });
} }
@@ -4077,6 +4085,7 @@ var Listeners = function () {
this.handleKey = this.handleKey.bind(this); this.handleKey = this.handleKey.bind(this);
this.toggleMenu = this.toggleMenu.bind(this); this.toggleMenu = this.toggleMenu.bind(this);
this.firstTouch = this.firstTouch.bind(this);
} }
// Handle key presses // Handle key presses
@@ -4232,6 +4241,20 @@ var Listeners = function () {
controls.toggleMenu.call(this.player, event); controls.toggleMenu.call(this.player, event);
} }
// Device is touch enabled
}, {
key: 'firstTouch',
value: function firstTouch() {
this.player.touch = true;
// Add touch class
utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
// Clean up
utils.off(document.body, 'touchstart', this.firstTouch);
}
// Global window & document listeners // Global window & document listeners
}, { }, {
@@ -4246,6 +4269,9 @@ var Listeners = function () {
// Click anywhere closes menu // Click anywhere closes menu
utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);
// Detect touch by events
utils.on(document.body, 'touchstart', this.firstTouch);
} }
// Container listeners // Container listeners
@@ -4360,7 +4386,7 @@ var Listeners = function () {
// On click play, pause ore restart // On click play, pause ore restart
utils.on(wrapper, 'click', function () { utils.on(wrapper, 'click', function () {
// Touch devices will just show controls (if we're hiding controls) // Touch devices will just show controls (if we're hiding controls)
if (_this3.player.config.hideControls && support.touch && !_this3.player.paused) { if (_this3.player.config.hideControls && _this3.player.touch && !_this3.player.paused) {
return; return;
} }
@@ -4486,7 +4512,7 @@ var Listeners = function () {
on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind'); on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');
// Rewind // Rewind
on(this.player.elements.buttons.fastForward, 'click', this.player.fastForward, 'fastForward'); on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');
// Mute toggle // Mute toggle
on(this.player.elements.buttons.mute, 'click', function () { on(this.player.elements.buttons.mute, 'click', function () {
@@ -4576,7 +4602,7 @@ var Listeners = function () {
if (this.player.config.hideControls) { if (this.player.config.hideControls) {
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
on(this.player.elements.controls, 'mouseenter mouseleave', function (event) { on(this.player.elements.controls, 'mouseenter mouseleave', function (event) {
_this4.player.elements.controls.hover = event.type === 'mouseenter'; _this4.player.elements.controls.hover = !_this4.player.touch && event.type === 'mouseenter';
}); });
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
@@ -6183,7 +6209,7 @@ var media = {
utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser$3.isIos); utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser$3.isIos);
// Add touch class // Add touch class
utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch); utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);
} }
// Inject the player wrapper // Inject the player wrapper
@@ -6390,12 +6416,6 @@ var source = {
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
// Private properties
// TODO: Use a WeakMap for private globals
// const globals = new WeakMap();
// Plyr instance
var Plyr = function () { var Plyr = function () {
function Plyr(target, options) { function Plyr(target, options) {
var _this = this; var _this = this;
@@ -6409,6 +6429,9 @@ var Plyr = function () {
this.loading = false; this.loading = false;
this.failed = false; this.failed = false;
// Touch device
this.touch = support.touch;
// Set the media element // Set the media element
this.media = target; this.media = target;
@@ -6889,16 +6912,22 @@ var Plyr = function () {
// Is the enter fullscreen event // Is the enter fullscreen event
isEnterFullscreen = toggle.type === 'enterfullscreen'; isEnterFullscreen = toggle.type === 'enterfullscreen';
// Events that show the controls
var showEvents = ['touchstart', 'touchmove', 'mouseenter', 'mousemove', 'focusin'];
// Events that delay hiding
var delayEvents = ['touchmove', 'touchend', 'mousemove'];
// Whether to show controls // Whether to show controls
show = ['mouseenter', 'mousemove', 'touchstart', 'touchmove', 'focusin'].includes(toggle.type); show = showEvents.includes(toggle.type);
// Delay hiding on move events // Delay hiding on move events
if (['mousemove', 'touchmove', 'touchend'].includes(toggle.type)) { if (delayEvents.includes(toggle.type)) {
delay = 2000; delay = 2000;
} }
// Delay a little more for keyboard users // Delay a little more for keyboard users
if (toggle.type === 'focusin') { if (!this.touch && toggle.type === 'focusin') {
delay = 3000; delay = 3000;
utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);
} }
@@ -6926,7 +6955,7 @@ var Plyr = function () {
} }
// Delay for hiding on touch // Delay for hiding on touch
if (support.touch) { if (this.touch) {
delay = 3000; delay = 3000;
} }
} }
@@ -6935,6 +6964,8 @@ var Plyr = function () {
// then set the timer to hide the controls // then set the timer to hide the controls
if (!show || this.playing) { if (!show || this.playing) {
this.timers.controls = setTimeout(function () { this.timers.controls = setTimeout(function () {
console.warn(_this3.elements.controls.pressed, _this3.elements.controls.hover, delay);
// If the mouse is over the controls (and not entering fullscreen), bail // If the mouse is over the controls (and not entering fullscreen), bail
if ((_this3.elements.controls.pressed || _this3.elements.controls.hover) && !isEnterFullscreen) { if ((_this3.elements.controls.pressed || _this3.elements.controls.hover) && !isEnterFullscreen) {
return; return;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+77 -46
View File
@@ -6078,7 +6078,6 @@ var defaults = {
end: 'End', end: 'End',
all: 'All', all: 'All',
reset: 'Reset', reset: 'Reset',
none: 'None',
disabled: 'Disabled', disabled: 'Disabled',
advertisement: 'Ad' advertisement: 'Ad'
}, },
@@ -7862,7 +7861,7 @@ var support = {
}(), }(),
// Touch // Touch
// Remember a device can be moust + touch enabled // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event
touch: 'ontouchstart' in document.documentElement, touch: 'ontouchstart' in document.documentElement,
// Detect transitions support // Detect transitions support
@@ -8767,6 +8766,7 @@ var ui = {
// Plyr controls // Plyr controls
// ========================================================================== // ==========================================================================
// Sniff out the browser
var browser$2 = utils.getBrowser(); var browser$2 = utils.getBrowser();
var controls = { var controls = {
@@ -9104,6 +9104,8 @@ var controls = {
// Update hover tooltip for seeking // Update hover tooltip for seeking
updateSeekTooltip: function updateSeekTooltip(event) { updateSeekTooltip: function updateSeekTooltip(event) {
var _this = this;
// Bail if setting not true // Bail if setting not true
if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) { if (!this.config.tooltips.seek || !utils.is.element(this.elements.inputs.seek) || !utils.is.element(this.elements.display.seekTooltip) || this.duration === 0) {
return; return;
@@ -9114,6 +9116,16 @@ var controls = {
var clientRect = this.elements.inputs.seek.getBoundingClientRect(); var clientRect = this.elements.inputs.seek.getBoundingClientRect();
var visible = this.config.classNames.tooltip + '--visible'; var visible = this.config.classNames.tooltip + '--visible';
var toggle = function toggle(_toggle) {
utils.toggleClass(_this.elements.display.seekTooltip, visible, _toggle);
};
// Hide on touch
if (this.touch) {
toggle(false);
return;
}
// Determine percentage, if already visible // Determine percentage, if already visible
if (utils.is.event(event)) { if (utils.is.event(event)) {
percent = 100 / clientRect.width * (event.pageX - clientRect.left); percent = 100 / clientRect.width * (event.pageX - clientRect.left);
@@ -9139,7 +9151,7 @@ var controls = {
// Show/hide the tooltip // Show/hide the tooltip
// If the event is a moues in/out and percentage is inside bounds // If the event is a moues in/out and percentage is inside bounds
if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) { if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {
utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); toggle(event.type === 'mouseenter');
} }
}, },
@@ -9157,7 +9169,7 @@ var controls = {
// Set the YouTube quality menu // Set the YouTube quality menu
// TODO: Support for HTML5 // TODO: Support for HTML5
setQualityMenu: function setQualityMenu(options) { setQualityMenu: function setQualityMenu(options) {
var _this = this; var _this2 = this;
// Menu required // Menu required
if (!utils.is.element(this.elements.settings.panes.quality)) { if (!utils.is.element(this.elements.settings.panes.quality)) {
@@ -9170,7 +9182,7 @@ var controls = {
// Set options if passed and filter based on config // Set options if passed and filter based on config
if (utils.is.array(options)) { if (utils.is.array(options)) {
this.options.quality = options.filter(function (quality) { this.options.quality = options.filter(function (quality) {
return _this.config.quality.options.includes(quality); return _this2.config.quality.options.includes(quality);
}); });
} else { } else {
this.options.quality = this.config.quality.options; this.options.quality = this.config.quality.options;
@@ -9217,11 +9229,11 @@ var controls = {
return null; return null;
} }
return controls.createBadge.call(_this, label); return controls.createBadge.call(_this2, label);
}; };
this.options.quality.forEach(function (quality) { this.options.quality.forEach(function (quality) {
return controls.createMenuItem.call(_this, quality, list, type, controls.getLabel.call(_this, 'quality', quality), getBadge(quality)); return controls.createMenuItem.call(_this2, quality, list, type, controls.getLabel.call(_this2, 'quality', quality), getBadge(quality));
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -9276,7 +9288,7 @@ var controls = {
switch (setting) { switch (setting) {
case 'captions': case 'captions':
value = this.captions.active ? this.captions.language : ''; value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
break; break;
default: default:
@@ -9366,11 +9378,7 @@ var controls = {
return null; return null;
} }
if (!support.textTracks || !captions.getTracks.call(this).length) { if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
return i18n.get('none', this.config);
}
if (this.captions.active) {
var currentTrack = captions.getCurrentTrack.call(this); var currentTrack = captions.getCurrentTrack.call(this);
if (utils.is.track(currentTrack)) { if (utils.is.track(currentTrack)) {
@@ -9384,7 +9392,7 @@ var controls = {
// Set a list of available captions languages // Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() { setCaptionsMenu: function setCaptionsMenu() {
var _this2 = this; var _this3 = this;
// TODO: Captions or language? Currently it's mixed // TODO: Captions or language? Currently it's mixed
var type = 'captions'; var type = 'captions';
@@ -9410,15 +9418,15 @@ var controls = {
}; };
}); });
// Add the "None" option to turn off captions // Add the "Disabled" option to turn off captions
tracks.unshift({ tracks.unshift({
language: '', language: '',
label: i18n.get('none', this.config) label: i18n.get('disabled', this.config)
}); });
// Generate options // Generate options
tracks.forEach(function (track) { tracks.forEach(function (track) {
controls.createMenuItem.call(_this2, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this2, track.language.toUpperCase()), track.language.toLowerCase() === _this2.captions.language.toLowerCase()); controls.createMenuItem.call(_this3, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this3, track.language.toUpperCase()), track.language.toLowerCase() === _this3.captions.language.toLowerCase());
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -9427,7 +9435,7 @@ var controls = {
// Set a list of available captions languages // Set a list of available captions languages
setSpeedMenu: function setSpeedMenu() { setSpeedMenu: function setSpeedMenu() {
var _this3 = this; var _this4 = this;
// Menu required // Menu required
if (!utils.is.element(this.elements.settings.panes.speed)) { if (!utils.is.element(this.elements.settings.panes.speed)) {
@@ -9443,7 +9451,7 @@ var controls = {
// Set options if passed and filter based on config // Set options if passed and filter based on config
this.options.speed = this.options.speed.filter(function (speed) { this.options.speed = this.options.speed.filter(function (speed) {
return _this3.config.speed.options.includes(speed); return _this4.config.speed.options.includes(speed);
}); });
// Toggle the pane and tab // Toggle the pane and tab
@@ -9467,7 +9475,7 @@ var controls = {
// Create items // Create items
this.options.speed.forEach(function (speed) { this.options.speed.forEach(function (speed) {
return controls.createMenuItem.call(_this3, speed, list, type, controls.getLabel.call(_this3, 'speed', speed)); return controls.createMenuItem.call(_this4, speed, list, type, controls.getLabel.call(_this4, 'speed', speed));
}); });
controls.updateSetting.call(this, type, list); controls.updateSetting.call(this, type, list);
@@ -9630,7 +9638,7 @@ var controls = {
// Build the default HTML // Build the default HTML
// TODO: Set order based on order in the config.controls array? // TODO: Set order based on order in the config.controls array?
create: function create(data) { create: function create(data) {
var _this4 = this; var _this5 = this;
// Do nothing if we want no controls // Do nothing if we want no controls
if (utils.is.empty(this.config.controls)) { if (utils.is.empty(this.config.controls)) {
@@ -9779,17 +9787,17 @@ var controls = {
hidden: '' hidden: ''
}); });
var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this4.config.selectors.buttons.settings), { var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(_this5.config.selectors.buttons.settings), {
type: 'button', type: 'button',
class: _this4.config.classNames.control + ' ' + _this4.config.classNames.control + '--forward', class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--forward',
id: 'plyr-settings-' + data.id + '-' + type + '-tab', id: 'plyr-settings-' + data.id + '-' + type + '-tab',
'aria-haspopup': true, 'aria-haspopup': true,
'aria-controls': 'plyr-settings-' + data.id + '-' + type, 'aria-controls': 'plyr-settings-' + data.id + '-' + type,
'aria-expanded': false 'aria-expanded': false
}), i18n.get(type, _this4.config)); }), i18n.get(type, _this5.config));
var value = utils.createElement('span', { var value = utils.createElement('span', {
class: _this4.config.classNames.menu.value class: _this5.config.classNames.menu.value
}); });
// Speed contains HTML entities // Speed contains HTML entities
@@ -9799,7 +9807,7 @@ var controls = {
tab.appendChild(button); tab.appendChild(button);
tabs.appendChild(tab); tabs.appendChild(tab);
_this4.elements.settings.tabs[type] = tab; _this5.elements.settings.tabs[type] = tab;
}); });
home.appendChild(tabs); home.appendChild(tabs);
@@ -9818,11 +9826,11 @@ var controls = {
var back = utils.createElement('button', { var back = utils.createElement('button', {
type: 'button', type: 'button',
class: _this4.config.classNames.control + ' ' + _this4.config.classNames.control + '--back', class: _this5.config.classNames.control + ' ' + _this5.config.classNames.control + '--back',
'aria-haspopup': true, 'aria-haspopup': true,
'aria-controls': 'plyr-settings-' + data.id + '-home', 'aria-controls': 'plyr-settings-' + data.id + '-home',
'aria-expanded': false 'aria-expanded': false
}, i18n.get(type, _this4.config)); }, i18n.get(type, _this5.config));
pane.appendChild(back); pane.appendChild(back);
@@ -9831,7 +9839,7 @@ var controls = {
pane.appendChild(options); pane.appendChild(options);
inner.appendChild(pane); inner.appendChild(pane);
_this4.elements.settings.panes[type] = pane; _this5.elements.settings.panes[type] = pane;
}); });
form.appendChild(inner); form.appendChild(inner);
@@ -9874,7 +9882,7 @@ var controls = {
// Insert controls // Insert controls
inject: function inject() { inject: function inject() {
var _this5 = this; var _this6 = this;
// Sprite // Sprite
if (this.config.loadSprite) { if (this.config.loadSprite) {
@@ -9952,8 +9960,8 @@ var controls = {
var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join('')); var labels = utils.getElements.call(this, [this.config.selectors.controls.wrapper, ' ', this.config.selectors.labels, ' .', this.config.classNames.hidden].join(''));
Array.from(labels).forEach(function (label) { Array.from(labels).forEach(function (label) {
utils.toggleClass(label, _this5.config.classNames.hidden, false); utils.toggleClass(label, _this6.config.classNames.hidden, false);
utils.toggleClass(label, _this5.config.classNames.tooltip, true); utils.toggleClass(label, _this6.config.classNames.tooltip, true);
label.setAttribute('role', 'tooltip'); label.setAttribute('role', 'tooltip');
}); });
} }
@@ -9975,6 +9983,7 @@ var Listeners = function () {
this.handleKey = this.handleKey.bind(this); this.handleKey = this.handleKey.bind(this);
this.toggleMenu = this.toggleMenu.bind(this); this.toggleMenu = this.toggleMenu.bind(this);
this.firstTouch = this.firstTouch.bind(this);
} }
// Handle key presses // Handle key presses
@@ -10130,6 +10139,20 @@ var Listeners = function () {
controls.toggleMenu.call(this.player, event); controls.toggleMenu.call(this.player, event);
} }
// Device is touch enabled
}, {
key: 'firstTouch',
value: function firstTouch() {
this.player.touch = true;
// Add touch class
utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
// Clean up
utils.off(document.body, 'touchstart', this.firstTouch);
}
// Global window & document listeners // Global window & document listeners
}, { }, {
@@ -10144,6 +10167,9 @@ var Listeners = function () {
// Click anywhere closes menu // Click anywhere closes menu
utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);
// Detect touch by events
utils.on(document.body, 'touchstart', this.firstTouch);
} }
// Container listeners // Container listeners
@@ -10258,7 +10284,7 @@ var Listeners = function () {
// On click play, pause ore restart // On click play, pause ore restart
utils.on(wrapper, 'click', function () { utils.on(wrapper, 'click', function () {
// Touch devices will just show controls (if we're hiding controls) // Touch devices will just show controls (if we're hiding controls)
if (_this3.player.config.hideControls && support.touch && !_this3.player.paused) { if (_this3.player.config.hideControls && _this3.player.touch && !_this3.player.paused) {
return; return;
} }
@@ -10384,7 +10410,7 @@ var Listeners = function () {
on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind'); on(this.player.elements.buttons.rewind, 'click', this.player.rewind, 'rewind');
// Rewind // Rewind
on(this.player.elements.buttons.fastForward, 'click', this.player.fastForward, 'fastForward'); on(this.player.elements.buttons.fastForward, 'click', this.player.forward, 'fastForward');
// Mute toggle // Mute toggle
on(this.player.elements.buttons.mute, 'click', function () { on(this.player.elements.buttons.mute, 'click', function () {
@@ -10474,7 +10500,7 @@ var Listeners = function () {
if (this.player.config.hideControls) { if (this.player.config.hideControls) {
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
on(this.player.elements.controls, 'mouseenter mouseleave', function (event) { on(this.player.elements.controls, 'mouseenter mouseleave', function (event) {
_this4.player.elements.controls.hover = event.type === 'mouseenter'; _this4.player.elements.controls.hover = !_this4.player.touch && event.type === 'mouseenter';
}); });
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
@@ -12081,7 +12107,7 @@ var media = {
utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser$3.isIos); utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser$3.isIos);
// Add touch class // Add touch class
utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch); utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);
} }
// Inject the player wrapper // Inject the player wrapper
@@ -12288,12 +12314,6 @@ var source = {
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
// Private properties
// TODO: Use a WeakMap for private globals
// const globals = new WeakMap();
// Plyr instance
var Plyr$1 = function () { var Plyr$1 = function () {
function Plyr(target, options) { function Plyr(target, options) {
var _this = this; var _this = this;
@@ -12307,6 +12327,9 @@ var Plyr$1 = function () {
this.loading = false; this.loading = false;
this.failed = false; this.failed = false;
// Touch device
this.touch = support.touch;
// Set the media element // Set the media element
this.media = target; this.media = target;
@@ -12787,16 +12810,22 @@ var Plyr$1 = function () {
// Is the enter fullscreen event // Is the enter fullscreen event
isEnterFullscreen = toggle.type === 'enterfullscreen'; isEnterFullscreen = toggle.type === 'enterfullscreen';
// Events that show the controls
var showEvents = ['touchstart', 'touchmove', 'mouseenter', 'mousemove', 'focusin'];
// Events that delay hiding
var delayEvents = ['touchmove', 'touchend', 'mousemove'];
// Whether to show controls // Whether to show controls
show = ['mouseenter', 'mousemove', 'touchstart', 'touchmove', 'focusin'].includes(toggle.type); show = showEvents.includes(toggle.type);
// Delay hiding on move events // Delay hiding on move events
if (['mousemove', 'touchmove', 'touchend'].includes(toggle.type)) { if (delayEvents.includes(toggle.type)) {
delay = 2000; delay = 2000;
} }
// Delay a little more for keyboard users // Delay a little more for keyboard users
if (toggle.type === 'focusin') { if (!this.touch && toggle.type === 'focusin') {
delay = 3000; delay = 3000;
utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);
} }
@@ -12824,7 +12853,7 @@ var Plyr$1 = function () {
} }
// Delay for hiding on touch // Delay for hiding on touch
if (support.touch) { if (this.touch) {
delay = 3000; delay = 3000;
} }
} }
@@ -12833,6 +12862,8 @@ var Plyr$1 = function () {
// then set the timer to hide the controls // then set the timer to hide the controls
if (!show || this.playing) { if (!show || this.playing) {
this.timers.controls = setTimeout(function () { this.timers.controls = setTimeout(function () {
console.warn(_this3.elements.controls.pressed, _this3.elements.controls.hover, delay);
// If the mouse is over the controls (and not entering fullscreen), bail // If the mouse is over the controls (and not entering fullscreen), bail
if ((_this3.elements.controls.pressed || _this3.elements.controls.hover) && !isEnterFullscreen) { if ((_this3.elements.controls.pressed || _this3.elements.controls.hover) && !isEnterFullscreen) {
return; return;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+15 -9
View File
@@ -384,6 +384,16 @@ const controls = {
const clientRect = this.elements.inputs.seek.getBoundingClientRect(); const clientRect = this.elements.inputs.seek.getBoundingClientRect();
const visible = `${this.config.classNames.tooltip}--visible`; const visible = `${this.config.classNames.tooltip}--visible`;
const toggle = toggle => {
utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);
};
// Hide on touch
if (this.touch) {
toggle(false);
return;
}
// Determine percentage, if already visible // Determine percentage, if already visible
if (utils.is.event(event)) { if (utils.is.event(event)) {
percent = 100 / clientRect.width * (event.pageX - clientRect.left); percent = 100 / clientRect.width * (event.pageX - clientRect.left);
@@ -412,7 +422,7 @@ const controls = {
'mouseenter', 'mouseenter',
'mouseleave', 'mouseleave',
].includes(event.type)) { ].includes(event.type)) {
utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter'); toggle(event.type === 'mouseenter');
} }
}, },
@@ -541,7 +551,7 @@ const controls = {
switch (setting) { switch (setting) {
case 'captions': case 'captions':
value = this.captions.active ? this.captions.language : ''; value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
break; break;
default: default:
@@ -638,11 +648,7 @@ const controls = {
return null; return null;
} }
if (!support.textTracks || !captions.getTracks.call(this).length) { if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
return i18n.get('none', this.config);
}
if (this.captions.active) {
const currentTrack = captions.getCurrentTrack.call(this); const currentTrack = captions.getCurrentTrack.call(this);
if (utils.is.track(currentTrack)) { if (utils.is.track(currentTrack)) {
@@ -677,10 +683,10 @@ const controls = {
label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase(), label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase(),
})); }));
// Add the "None" option to turn off captions // Add the "Disabled" option to turn off captions
tracks.unshift({ tracks.unshift({
language: '', language: '',
label: i18n.get('none', this.config), label: i18n.get('disabled', this.config),
}); });
// Generate options // Generate options
-1
View File
@@ -181,7 +181,6 @@ const defaults = {
end: 'End', end: 'End',
all: 'All', all: 'All',
reset: 'Reset', reset: 'Reset',
none: 'None',
disabled: 'Disabled', disabled: 'Disabled',
advertisement: 'Ad', advertisement: 'Ad',
}, },
+17 -2
View File
@@ -17,6 +17,7 @@ class Listeners {
this.handleKey = this.handleKey.bind(this); this.handleKey = this.handleKey.bind(this);
this.toggleMenu = this.toggleMenu.bind(this); this.toggleMenu = this.toggleMenu.bind(this);
this.firstTouch = this.firstTouch.bind(this);
} }
// Handle key presses // Handle key presses
@@ -187,6 +188,17 @@ class Listeners {
controls.toggleMenu.call(this.player, event); controls.toggleMenu.call(this.player, event);
} }
// Device is touch enabled
firstTouch() {
this.player.touch = true;
// Add touch class
utils.toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
// Clean up
utils.off(document.body, 'touchstart', this.firstTouch);
}
// Global window & document listeners // Global window & document listeners
global(toggle = true) { global(toggle = true) {
// Keyboard shortcuts // Keyboard shortcuts
@@ -196,6 +208,9 @@ class Listeners {
// Click anywhere closes menu // Click anywhere closes menu
utils.toggleListener(document.body, 'click', this.toggleMenu, toggle); utils.toggleListener(document.body, 'click', this.toggleMenu, toggle);
// Detect touch by events
utils.on(document.body, 'touchstart', this.firstTouch);
} }
// Container listeners // Container listeners
@@ -288,7 +303,7 @@ class Listeners {
// On click play, pause ore restart // On click play, pause ore restart
utils.on(wrapper, 'click', () => { utils.on(wrapper, 'click', () => {
// Touch devices will just show controls (if we're hiding controls) // Touch devices will just show controls (if we're hiding controls)
if (this.player.config.hideControls && support.touch && !this.player.paused) { if (this.player.config.hideControls && this.player.touch && !this.player.paused) {
return; return;
} }
@@ -538,7 +553,7 @@ class Listeners {
if (this.player.config.hideControls) { if (this.player.config.hideControls) {
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
on(this.player.elements.controls, 'mouseenter mouseleave', event => { on(this.player.elements.controls, 'mouseenter mouseleave', event => {
this.player.elements.controls.hover = event.type === 'mouseenter'; this.player.elements.controls.hover = !this.player.touch && event.type === 'mouseenter';
}); });
// Watch for cursor over controls so they don't hide when trying to interact // Watch for cursor over controls so they don't hide when trying to interact
+1 -1
View File
@@ -46,7 +46,7 @@ const media = {
utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);
// Add touch class // Add touch class
utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch); utils.toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);
} }
// Inject the player wrapper // Inject the player wrapper
+23 -12
View File
@@ -36,6 +36,9 @@ class Plyr {
this.loading = false; this.loading = false;
this.failed = false; this.failed = false;
// Touch device
this.touch = support.touch;
// Set the media element // Set the media element
this.media = target; this.media = target;
@@ -954,26 +957,32 @@ class Plyr {
// Is the enter fullscreen event // Is the enter fullscreen event
isEnterFullscreen = toggle.type === 'enterfullscreen'; isEnterFullscreen = toggle.type === 'enterfullscreen';
// Whether to show controls // Events that show the controls
show = [ const showEvents = [
'mouseenter',
'mousemove',
'touchstart', 'touchstart',
'touchmove', 'touchmove',
'focusin', 'mouseenter',
].includes(toggle.type);
// Delay hiding on move events
if ([
'mousemove', 'mousemove',
'focusin',
];
// Events that delay hiding
const delayEvents = [
'touchmove', 'touchmove',
'touchend', 'touchend',
].includes(toggle.type)) { 'mousemove',
];
// Whether to show controls
show = showEvents.includes(toggle.type);
// Delay hiding on move events
if (delayEvents.includes(toggle.type)) {
delay = 2000; delay = 2000;
} }
// Delay a little more for keyboard users // Delay a little more for keyboard users
if (toggle.type === 'focusin') { if (!this.touch && toggle.type === 'focusin') {
delay = 3000; delay = 3000;
utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true); utils.toggleClass(this.elements.controls, this.config.classNames.noTransition, true);
} }
@@ -1001,7 +1010,7 @@ class Plyr {
} }
// Delay for hiding on touch // Delay for hiding on touch
if (support.touch) { if (this.touch) {
delay = 3000; delay = 3000;
} }
} }
@@ -1010,6 +1019,8 @@ class Plyr {
// then set the timer to hide the controls // then set the timer to hide the controls
if (!show || this.playing) { if (!show || this.playing) {
this.timers.controls = setTimeout(() => { this.timers.controls = setTimeout(() => {
console.warn(this.elements.controls.pressed, this.elements.controls.hover, delay);
// If the mouse is over the controls (and not entering fullscreen), bail // If the mouse is over the controls (and not entering fullscreen), bail
if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) { if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {
return; return;
+1 -1
View File
@@ -143,7 +143,7 @@ const support = {
})(), })(),
// Touch // Touch
// Remember a device can be moust + touch enabled // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event
touch: 'ontouchstart' in document.documentElement, touch: 'ontouchstart' in document.documentElement,
// Detect transitions support // Detect transitions support
-2
View File
@@ -84,7 +84,6 @@
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
transition: border-color 0.2s ease;
} }
&--forward { &--forward {
@@ -108,7 +107,6 @@
margin-bottom: floor($plyr-control-padding / 2); margin-bottom: floor($plyr-control-padding / 2);
padding-left: ceil($plyr-control-padding * 4); padding-left: ceil($plyr-control-padding * 4);
position: relative; position: relative;
width: calc(100% - #{$horizontal-padding}); width: calc(100% - #{$horizontal-padding});
&::after { &::after {