aboutsummaryrefslogtreecommitdiffstats
path: root/dist/plyr.js
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2018-07-15 19:23:28 +1000
committerSam Potts <sam@potts.es>2018-07-15 19:23:28 +1000
commite63ad7c74bd763043344fd2bd568a64e7ea18622 (patch)
tree2367ed9ff7d5d14fd6a5d207550a4a3bdc5d7502 /dist/plyr.js
parentead660139489d3b0cf082d97117f735929adaf49 (diff)
downloadplyr-e63ad7c74bd763043344fd2bd568a64e7ea18622.tar.lz
plyr-e63ad7c74bd763043344fd2bd568a64e7ea18622.tar.xz
plyr-e63ad7c74bd763043344fd2bd568a64e7ea18622.zip
Keyboard and focus improvements
Diffstat (limited to 'dist/plyr.js')
-rw-r--r--dist/plyr.js474
1 files changed, 279 insertions, 195 deletions
diff --git a/dist/plyr.js b/dist/plyr.js
index 35daacd5..697dd12f 100644
--- a/dist/plyr.js
+++ b/dist/plyr.js
@@ -548,6 +548,12 @@ typeof navigator === "object" && (function (global, factory) {
// Mirror Element.classList.toggle, with IE compatibility for "force" argument
function toggleClass(element, className, force) {
+ if (is.nodeList(element)) {
+ return Array.from(element).map(function (e) {
+ return toggleClass(e, className, force);
+ });
+ }
+
if (is.element(element)) {
var method = 'toggle';
if (typeof force !== 'undefined') {
@@ -558,7 +564,7 @@ typeof navigator === "object" && (function (global, factory) {
return element.classList.contains(className);
}
- return null;
+ return false;
}
// Has class name
@@ -589,19 +595,6 @@ typeof navigator === "object" && (function (global, factory) {
return this.elements.container.querySelector(selector);
}
- // Get the focused element
- function getFocusElement() {
- var focused = document.activeElement;
-
- if (!focused || focused === document.body) {
- focused = null;
- } else {
- focused = document.querySelector(':focus');
- }
-
- return focused;
- }
-
// Trap focus inside container
function trapFocus() {
var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
@@ -622,7 +615,7 @@ typeof navigator === "object" && (function (global, factory) {
}
// Get the current focused element
- var focused = getFocusElement();
+ var focused = document.activeElement;
if (focused === last && !event.shiftKey) {
// Move focus to first element that can be tabbed if Shift isn't used
@@ -1685,9 +1678,54 @@ typeof navigator === "object" && (function (global, factory) {
},
+ // Bind keyboard shortcuts for a menu item
+ bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) {
+ var _this = this;
+
+ // Handle space or -> to open menu
+ on(menuItem, 'keydown', function (event) {
+ // We only care about space and ⬆️ ⬇️️ ➡️
+ if (![32, 38, 39, 40].includes(event.which)) {
+ return;
+ }
+
+ // Prevent play / seek
+ event.preventDefault();
+ event.stopPropagation();
+
+ var isRadioButton = matches(menuItem, '[role="menuitemradio"]');
+
+ // Show the respective menu
+ if (!isRadioButton && [32, 39].includes(event.which)) {
+ controls.showMenuPanel.call(_this, type);
+ } else {
+ var target = void 0;
+
+ if (event.which !== 32) {
+ if (event.which === 40 || isRadioButton && event.which === 39) {
+ target = menuItem.nextElementSibling;
+
+ if (!is.element(target)) {
+ target = menuItem.parentNode.firstElementChild;
+ }
+ } else {
+ target = menuItem.previousElementSibling;
+
+ if (!is.element(target)) {
+ target = menuItem.parentNode.lastElementChild;
+ }
+ }
+
+ setFocus.call(_this, target, true);
+ }
+ }
+ }, false);
+ },
+
+
// Create a settings menu item
createMenuItem: function createMenuItem(_ref) {
- var _this = this;
+ var _this2 = this;
var value = _ref.value,
list = _ref.list,
@@ -1700,7 +1738,7 @@ typeof navigator === "object" && (function (global, factory) {
var attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);
- var item = createElement('button', extend(attributes, {
+ var menuItem = createElement('button', extend(attributes, {
type: 'button',
role: 'menuitemradio',
class: (this.config.classNames.control + ' ' + (attributes.class ? attributes.class : '')).trim(),
@@ -1717,51 +1755,61 @@ typeof navigator === "object" && (function (global, factory) {
flex.appendChild(badge);
}
- item.appendChild(flex);
+ menuItem.appendChild(flex);
- Object.defineProperty(item, 'checked', {
+ // Replicate radio button behaviour
+ Object.defineProperty(menuItem, 'checked', {
enumerable: true,
get: function get$$1() {
- return item.getAttribute('aria-checked') === 'true';
+ return menuItem.getAttribute('aria-checked') === 'true';
},
set: function set$$1(checked) {
// Ensure exclusivity
if (checked) {
- Array.from(item.parentNode.children).filter(function (node) {
+ Array.from(menuItem.parentNode.children).filter(function (node) {
return matches(node, '[role="menuitemradio"]');
}).forEach(function (node) {
return node.setAttribute('aria-checked', 'false');
});
}
- item.setAttribute('aria-checked', checked ? 'true' : 'false');
+ menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');
}
});
- this.listeners.bind(item, 'click', function () {
- item.checked = true;
+ this.listeners.bind(menuItem, 'click keydown', function (event) {
+ if (event.type === 'keydown' && event.which !== 32) {
+ return;
+ }
+
+ event.preventDefault();
+ event.stopPropagation();
+
+ menuItem.checked = true;
switch (type) {
case 'language':
- _this.currentTrack = Number(value);
+ _this2.currentTrack = Number(value);
break;
case 'quality':
- _this.quality = value;
+ _this2.quality = value;
break;
case 'speed':
- _this.speed = parseFloat(value);
+ _this2.speed = parseFloat(value);
break;
default:
break;
}
- controls.showMenuPanel.call(_this, 'home');
- }, type);
+ controls.showMenuPanel.call(_this2, 'home');
+ }, type, false);
- list.appendChild(item);
+ controls.bindMenuItemShortcuts.call(this, menuItem, type);
+
+ list.appendChild(menuItem);
},
@@ -1834,7 +1882,7 @@ typeof navigator === "object" && (function (global, factory) {
// Update <progress> elements
updateProgress: function updateProgress(event) {
- var _this2 = this;
+ var _this3 = this;
if (!this.supported.ui || !is.event(event)) {
return;
@@ -1844,7 +1892,7 @@ typeof navigator === "object" && (function (global, factory) {
var setProgress = function setProgress(target, input) {
var value = is.number(input) ? input : 0;
- var progress = is.element(target) ? target : _this2.elements.display.buffer;
+ var progress = is.element(target) ? target : _this3.elements.display.buffer;
// Update value and label
if (is.element(progress)) {
@@ -1924,7 +1972,7 @@ typeof navigator === "object" && (function (global, factory) {
// Update hover tooltip for seeking
updateSeekTooltip: function updateSeekTooltip(event) {
- var _this3 = this;
+ var _this4 = this;
// Bail if setting not true
if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) {
@@ -1937,7 +1985,7 @@ typeof navigator === "object" && (function (global, factory) {
var visible = this.config.classNames.tooltip + '--visible';
var toggle = function toggle(_toggle) {
- toggleClass(_this3.elements.display.seekTooltip, visible, _toggle);
+ toggleClass(_this4.elements.display.seekTooltip, visible, _toggle);
};
// Hide on touch
@@ -2122,7 +2170,7 @@ typeof navigator === "object" && (function (global, factory) {
// Set the quality menu
setQualityMenu: function setQualityMenu(options) {
- var _this4 = this;
+ var _this5 = this;
// Menu required
if (!is.element(this.elements.settings.panels.quality)) {
@@ -2135,7 +2183,7 @@ typeof navigator === "object" && (function (global, factory) {
// Set options if passed and filter based on uniqueness and config
if (is.array(options)) {
this.options.quality = dedupe(options).filter(function (quality) {
- return _this4.config.quality.options.includes(quality);
+ return _this5.config.quality.options.includes(quality);
});
}
@@ -2156,25 +2204,25 @@ typeof navigator === "object" && (function (global, factory) {
// Get the badge HTML for HD, 4K etc
var getBadge = function getBadge(quality) {
- var label = i18n.get('qualityBadge.' + quality, _this4.config);
+ var label = i18n.get('qualityBadge.' + quality, _this5.config);
if (!label.length) {
return null;
}
- return controls.createBadge.call(_this4, label);
+ return controls.createBadge.call(_this5, label);
};
// Sort options by the config and then render options
this.options.quality.sort(function (a, b) {
- var sorting = _this4.config.quality.options;
+ var sorting = _this5.config.quality.options;
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
}).forEach(function (quality) {
- controls.createMenuItem.call(_this4, {
+ controls.createMenuItem.call(_this5, {
value: quality,
list: list,
type: type,
- title: controls.getLabel.call(_this4, 'quality', quality),
+ title: controls.getLabel.call(_this5, 'quality', quality),
badge: getBadge(quality)
});
});
@@ -2224,7 +2272,7 @@ typeof navigator === "object" && (function (global, factory) {
// Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() {
- var _this5 = this;
+ var _this6 = this;
// Menu required
if (!is.element(this.elements.settings.panels.captions)) {
@@ -2255,9 +2303,9 @@ typeof navigator === "object" && (function (global, factory) {
var options = tracks.map(function (track, value) {
return {
value: value,
- checked: _this5.captions.toggled && _this5.currentTrack === value,
- title: captions.getLabel.call(_this5, track),
- badge: track.language && controls.createBadge.call(_this5, track.language.toUpperCase()),
+ checked: _this6.captions.toggled && _this6.currentTrack === value,
+ title: captions.getLabel.call(_this6, track),
+ badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()),
list: list,
type: 'language'
};
@@ -2281,7 +2329,7 @@ typeof navigator === "object" && (function (global, factory) {
// Set a list of available captions languages
setSpeedMenu: function setSpeedMenu(options) {
- var _this6 = this;
+ var _this7 = this;
// Menu required
if (!is.element(this.elements.settings.panels.speed)) {
@@ -2300,7 +2348,7 @@ typeof navigator === "object" && (function (global, factory) {
// Set options if passed and filter based on config
this.options.speed = this.options.speed.filter(function (speed) {
- return _this6.config.speed.options.includes(speed);
+ return _this7.config.speed.options.includes(speed);
});
// Toggle the pane and tab
@@ -2320,11 +2368,11 @@ typeof navigator === "object" && (function (global, factory) {
// Create items
this.options.speed.forEach(function (speed) {
- controls.createMenuItem.call(_this6, {
+ controls.createMenuItem.call(_this7, {
value: speed,
list: list,
type: type,
- title: controls.getLabel.call(_this6, 'speed', speed)
+ title: controls.getLabel.call(_this7, 'speed', speed)
});
});
@@ -2345,7 +2393,7 @@ typeof navigator === "object" && (function (global, factory) {
// Show/hide menu
- toggleMenu: function toggleMenu(event) {
+ toggleMenu: function toggleMenu(input) {
var popup = this.elements.settings.popup;
var button = this.elements.buttons.settings;
@@ -2355,11 +2403,11 @@ typeof navigator === "object" && (function (global, factory) {
return;
}
- var show = is.boolean(event) ? event : is.element(popup) && popup.hasAttribute('hidden');
+ var show = is.boolean(input) ? input : is.element(popup) && popup.hasAttribute('hidden');
- if (is.event(event)) {
- var isMenuItem = is.element(popup) && popup.contains(event.target);
- var isButton = event.target === this.elements.buttons.settings;
+ if (is.event(input)) {
+ var isMenuItem = is.element(popup) && popup.contains(input.target);
+ var isButton = input.target === this.elements.buttons.settings;
// If the click was inside the form or if the click
// wasn't the button or menu item and we're trying to
@@ -2370,7 +2418,7 @@ typeof navigator === "object" && (function (global, factory) {
// Prevent the toggle being caught by the doc listener
if (isButton) {
- event.stopPropagation();
+ input.stopPropagation();
}
}
@@ -2384,19 +2432,13 @@ typeof navigator === "object" && (function (global, factory) {
toggleHidden(popup, !show);
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
- if (show) {
- popup.removeAttribute('tabindex');
-
- // Focus the first item if key interaction
- if (event.type === 'keydown') {
- var pane = Object.values(this.elements.settings.panels).find(function (pane) {
- return !pane.hidden;
- });
- var firstItem = pane.querySelector('[role^="menuitem"]');
- setFocus.call(this, firstItem, true);
- }
- } else {
- popup.setAttribute('tabindex', -1);
+ // Focus the first item if key interaction
+ if (show && is.event(input) && input.type === 'keydown') {
+ var pane = Object.values(this.elements.settings.panels).find(function (pane) {
+ return !pane.hidden;
+ });
+ var firstItem = pane.querySelector('[role^="menuitem"]');
+ setFocus.call(this, firstItem, true);
}
}
},
@@ -2428,7 +2470,7 @@ typeof navigator === "object" && (function (global, factory) {
// Show a panel in the menu
showMenuPanel: function showMenuPanel() {
- var _this7 = this;
+ var _this8 = this;
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@@ -2466,7 +2508,7 @@ typeof navigator === "object" && (function (global, factory) {
container.style.height = '';
// Only listen once
- off.call(_this7, container, transitionEndEvent, restore);
+ off.call(_this8, container, transitionEndEvent, restore);
};
// Listen for the transition finishing and restore auto height/width
@@ -2492,7 +2534,7 @@ typeof navigator === "object" && (function (global, factory) {
// Build the default HTML
// TODO: Set order based on order in the config.controls array?
create: function create(data) {
- var _this8 = this;
+ var _this9 = this;
// Do nothing if we want no controls
if (is.empty(this.config.controls)) {
@@ -2627,41 +2669,31 @@ typeof navigator === "object" && (function (global, factory) {
home.appendChild(menu);
inner.appendChild(home);
+ this.elements.settings.panels.home = home;
// Build the menu items
this.config.settings.forEach(function (type) {
- var menuItem = createElement('button', extend(getAttributesFromSelector(_this8.config.selectors.buttons.settings), {
+ // TODO: bundle this with the createMenuItem helper and bindings
+ var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), {
type: 'button',
- class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--forward',
+ class: _this9.config.classNames.control + ' ' + _this9.config.classNames.control + '--forward',
role: 'menuitem',
'aria-haspopup': true,
hidden: ''
}));
- // Handle space or -> to open menu
- on(menuItem, 'keydown', function (event) {
- // We only care about space and ->
- if (![32, 39].includes(event.which)) {
- return;
- }
-
- // Prevent play / seek
- event.preventDefault();
- event.stopPropagation();
-
- // Show the respective menu
- controls.showMenuPanel.call(_this8, type);
- }, false);
+ // Bind menu shortcuts for keyboard users
+ controls.bindMenuItemShortcuts.call(_this9, menuItem, type);
// Show menu on click
on(menuItem, 'click', function () {
- controls.showMenuPanel.call(_this8, type);
+ controls.showMenuPanel.call(_this9, type);
});
- var flex = createElement('span', null, i18n.get(type, _this8.config));
+ var flex = createElement('span', null, i18n.get(type, _this9.config));
var value = createElement('span', {
- class: _this8.config.classNames.menu.value
+ class: _this9.config.classNames.menu.value
});
// Speed contains HTML entities
@@ -2680,21 +2712,21 @@ typeof navigator === "object" && (function (global, factory) {
// Back button
var backButton = createElement('button', {
type: 'button',
- class: _this8.config.classNames.control + ' ' + _this8.config.classNames.control + '--back'
+ class: _this9.config.classNames.control + ' ' + _this9.config.classNames.control + '--back'
});
// Visible label
backButton.appendChild(createElement('span', {
'aria-hidden': true
- }, i18n.get(type, _this8.config)));
+ }, i18n.get(type, _this9.config)));
// Screen reader label
backButton.appendChild(createElement('span', {
- class: _this8.config.classNames.hidden
- }, i18n.get('menuBack', _this8.config)));
+ class: _this9.config.classNames.hidden
+ }, i18n.get('menuBack', _this9.config)));
- // Handle space or -> to open menu
- on(backButton, 'keydown', function (event) {
+ // Go back via keyboard
+ on(pane, 'keydown', function (event) {
// We only care about <-
if (event.which !== 37) {
return;
@@ -2705,12 +2737,12 @@ typeof navigator === "object" && (function (global, factory) {
event.stopPropagation();
// Show the respective menu
- controls.showMenuPanel.call(_this8, 'home');
+ controls.showMenuPanel.call(_this9, 'home');
}, false);
- // Go back
+ // Go back via button click
on(backButton, 'click', function () {
- controls.showMenuPanel.call(_this8, 'home');
+ controls.showMenuPanel.call(_this9, 'home');
});
// Add to pane
@@ -2723,8 +2755,8 @@ typeof navigator === "object" && (function (global, factory) {
inner.appendChild(pane);
- _this8.elements.settings.buttons[type] = menuItem;
- _this8.elements.settings.panels[type] = pane;
+ _this9.elements.settings.buttons[type] = menuItem;
+ _this9.elements.settings.panels[type] = pane;
});
popup.appendChild(inner);
@@ -2769,7 +2801,7 @@ typeof navigator === "object" && (function (global, factory) {
// Insert controls
inject: function inject() {
- var _this9 = this;
+ var _this10 = this;
// Sprite
if (this.config.loadSprite) {
@@ -2881,8 +2913,8 @@ typeof navigator === "object" && (function (global, factory) {
var labels = getElements.call(this, selector);
Array.from(labels).forEach(function (label) {
- toggleClass(label, _this9.config.classNames.hidden, false);
- toggleClass(label, _this9.config.classNames.tooltip, true);
+ toggleClass(label, _this10.config.classNames.hidden, false);
+ toggleClass(label, _this10.config.classNames.tooltip, true);
});
}
}
@@ -4272,9 +4304,12 @@ typeof navigator === "object" && (function (global, factory) {
this.player = player;
this.lastKey = null;
+ this.focusTimer = null;
+ this.lastKeyDown = null;
this.handleKey = this.handleKey.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
+ this.setTabFocus = this.setTabFocus.bind(this);
this.firstTouch = this.firstTouch.bind(this);
}
@@ -4310,17 +4345,27 @@ typeof navigator === "object" && (function (global, factory) {
// Handle the key on keydown
// Reset on keyup
if (pressed) {
- // Which keycodes should we prevent default
- var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];
-
// Check focused element
// and if the focused element is not editable (e.g. text input)
// and any that accept key input http://webaim.org/techniques/keyboard/
- var focused = getFocusElement();
- if (is.element(focused) && focused !== this.player.elements.inputs.seek && matches(focused, this.player.config.selectors.editable)) {
- return;
+ var focused = document.activeElement;
+ if (is.element(focused)) {
+ var editable = this.player.config.selectors.editable;
+ var seek = this.player.elements.inputs.seek;
+
+
+ if (focused !== seek && matches(focused, editable)) {
+ return;
+ }
+
+ if (event.which === 32 && matches(focused, 'button, [role^="menuitem"]')) {
+ return;
+ }
}
+ // Which keycodes should we prevent default
+ var preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];
+
// If the code is found prevent default (e.g. prevent scrolling for arrows)
if (preventDefault.includes(code)) {
event.preventDefault();
@@ -4441,6 +4486,55 @@ typeof navigator === "object" && (function (global, factory) {
// Add touch class
toggleClass(this.player.elements.container, this.player.config.classNames.isTouch, true);
}
+ }, {
+ key: 'setTabFocus',
+ value: function setTabFocus(event) {
+ var _this2 = this;
+
+ clearTimeout(this.focusTimer);
+
+ // Ignore any key other than tab
+ if (event.type === 'keydown' && event.code !== 'Tab') {
+ return;
+ }
+
+ // Store reference to event timeStamp
+ if (event.type === 'keydown') {
+ this.lastKeyDown = event.timeStamp;
+ }
+
+ // Remove current classes
+ var removeCurrent = function removeCurrent() {
+ var className = _this2.player.config.classNames.tabFocus;
+ var current = getElements.call(_this2.player, '.' + className);
+ toggleClass(current, className, false);
+ };
+
+ // Determine if a key was pressed to trigger this event
+ var wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;
+
+ // Ignore focus events if a key was pressed prior
+ if (event.type === 'focus' && !wasKeyDown) {
+ return;
+ }
+
+ // Remove all current
+ removeCurrent();
+
+ // Delay the adding of classname until the focus has changed
+ // This event fires before the focusin event
+
+ this.focusTimer = setTimeout(function () {
+ var focused = document.activeElement;
+
+ // Ignore if current focus element isn't inside the player
+ if (!_this2.player.elements.container.contains(focused)) {
+ return;
+ }
+
+ toggleClass(document.activeElement, _this2.player.config.classNames.tabFocus, true);
+ }, 10);
+ }
// Global window & document listeners
@@ -4459,6 +4553,9 @@ typeof navigator === "object" && (function (global, factory) {
// Detect touch by events
once.call(this.player, document.body, 'touchstart', this.firstTouch);
+
+ // Tab focus detection
+ toggleListener.call(this.player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true);
}
// Container listeners
@@ -4466,34 +4563,16 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'container',
value: function container() {
- var _this2 = this;
+ var _this3 = this;
// Keyboard shortcuts
if (!this.player.config.keyboard.global && this.player.config.keyboard.focused) {
on.call(this.player, this.player.elements.container, 'keydown keyup', this.handleKey, false);
}
- // Detect tab focus
- // Remove class on blur/focusout
- on.call(this.player, this.player.elements.container, 'focusout', function (event) {
- toggleClass(event.target, _this2.player.config.classNames.tabFocus, false);
- });
- // Add classname to tabbed elements
- on.call(this.player, this.player.elements.container, 'keydown', function (event) {
- if (event.keyCode !== 9) {
- return;
- }
-
- // Delay the adding of classname until the focus has changed
- // This event fires before the focusin event
- setTimeout(function () {
- toggleClass(getFocusElement(), _this2.player.config.classNames.tabFocus, true);
- }, 0);
- });
-
// Toggle controls on mouse events and entering fullscreen
on.call(this.player, this.player.elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) {
- var controls$$1 = _this2.player.elements.controls;
+ var controls$$1 = _this3.player.elements.controls;
// Remove button states for fullscreen
@@ -4508,17 +4587,17 @@ typeof navigator === "object" && (function (global, factory) {
var delay = 0;
if (show) {
- ui.toggleControls.call(_this2.player, true);
+ ui.toggleControls.call(_this3.player, true);
// Use longer timeout for touch devices
- delay = _this2.player.touch ? 3000 : 2000;
+ delay = _this3.player.touch ? 3000 : 2000;
}
// Clear timer
- clearTimeout(_this2.player.timers.controls);
+ clearTimeout(_this3.player.timers.controls);
// Set new timer to prevent flicker when seeking
- _this2.player.timers.controls = setTimeout(function () {
- return ui.toggleControls.call(_this2.player, false);
+ _this3.player.timers.controls = setTimeout(function () {
+ return ui.toggleControls.call(_this3.player, false);
}, delay);
});
}
@@ -4528,68 +4607,68 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'media',
value: function media() {
- var _this3 = this;
+ var _this4 = this;
// Time change on media
on.call(this.player, this.player.media, 'timeupdate seeking seeked', function (event) {
- return controls.timeUpdate.call(_this3.player, event);
+ return controls.timeUpdate.call(_this4.player, event);
});
// Display duration
on.call(this.player, this.player.media, 'durationchange loadeddata loadedmetadata', function (event) {
- return controls.durationUpdate.call(_this3.player, event);
+ return controls.durationUpdate.call(_this4.player, event);
});
// Check for audio tracks on load
// We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
on.call(this.player, this.player.media, 'canplay', function () {
- toggleHidden(_this3.player.elements.volume, !_this3.player.hasAudio);
- toggleHidden(_this3.player.elements.buttons.mute, !_this3.player.hasAudio);
+ toggleHidden(_this4.player.elements.volume, !_this4.player.hasAudio);
+ toggleHidden(_this4.player.elements.buttons.mute, !_this4.player.hasAudio);
});
// Handle the media finishing
on.call(this.player, this.player.media, 'ended', function () {
// Show poster on end
- if (_this3.player.isHTML5 && _this3.player.isVideo && _this3.player.config.resetOnEnd) {
+ if (_this4.player.isHTML5 && _this4.player.isVideo && _this4.player.config.resetOnEnd) {
// Restart
- _this3.player.restart();
+ _this4.player.restart();
}
});
// Check for buffer progress
on.call(this.player, this.player.media, 'progress playing seeking seeked', function (event) {
- return controls.updateProgress.call(_this3.player, event);
+ return controls.updateProgress.call(_this4.player, event);
});
// Handle volume changes
on.call(this.player, this.player.media, 'volumechange', function (event) {
- return controls.updateVolume.call(_this3.player, event);
+ return controls.updateVolume.call(_this4.player, event);
});
// Handle play/pause
on.call(this.player, this.player.media, 'playing play pause ended emptied timeupdate', function (event) {
- return ui.checkPlaying.call(_this3.player, event);
+ return ui.checkPlaying.call(_this4.player, event);
});
// Loading state
on.call(this.player, this.player.media, 'waiting canplay seeked playing', function (event) {
- return ui.checkLoading.call(_this3.player, event);
+ return ui.checkLoading.call(_this4.player, event);
});
// If autoplay, then load advertisement if required
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
on.call(this.player, this.player.media, 'playing', function () {
- if (!_this3.player.ads) {
+ if (!_this4.player.ads) {
return;
}
// If ads are enabled, wait for them first
- if (_this3.player.ads.enabled && !_this3.player.ads.initialized) {
+ if (_this4.player.ads.enabled && !_this4.player.ads.initialized) {
// Wait for manager response
- _this3.player.ads.managerPromise.then(function () {
- return _this3.player.ads.play();
+ _this4.player.ads.managerPromise.then(function () {
+ return _this4.player.ads.play();
}).catch(function () {
- return _this3.player.play();
+ return _this4.player.play();
});
}
});
@@ -4607,17 +4686,17 @@ typeof navigator === "object" && (function (global, factory) {
// On click play, pause ore restart
on.call(this.player, wrapper, 'click', function () {
// Touch devices will just show controls (if we're hiding controls)
- if (_this3.player.config.hideControls && _this3.player.touch && !_this3.player.paused) {
+ if (_this4.player.config.hideControls && _this4.player.touch && !_this4.player.paused) {
return;
}
- if (_this3.player.paused) {
- _this3.player.play();
- } else if (_this3.player.ended) {
- _this3.player.restart();
- _this3.player.play();
+ if (_this4.player.paused) {
+ _this4.player.play();
+ } else if (_this4.player.ended) {
+ _this4.player.restart();
+ _this4.player.play();
} else {
- _this3.player.pause();
+ _this4.player.pause();
}
});
}
@@ -4632,33 +4711,37 @@ typeof navigator === "object" && (function (global, factory) {
// Volume change
on.call(this.player, this.player.media, 'volumechange', function () {
// Save to storage
- _this3.player.storage.set({ volume: _this3.player.volume, muted: _this3.player.muted });
+ _this4.player.storage.set({
+ volume: _this4.player.volume,
+ muted: _this4.player.muted
+ });
});
// Speed change
on.call(this.player, this.player.media, 'ratechange', function () {
// Update UI
- controls.updateSetting.call(_this3.player, 'speed');
+ controls.updateSetting.call(_this4.player, 'speed');
// Save to storage
- _this3.player.storage.set({ speed: _this3.player.speed });
+ _this4.player.storage.set({ speed: _this4.player.speed });
});
// Quality request
on.call(this.player, this.player.media, 'qualityrequested', function (event) {
// Save to storage
- _this3.player.storage.set({ quality: event.detail.quality });
+ _this4.player.storage.set({ quality: event.detail.quality });
});
// Quality change
on.call(this.player, this.player.media, 'qualitychange', function (event) {
// Update UI
- controls.updateSetting.call(_this3.player, 'quality', null, event.detail.quality);
+ controls.updateSetting.call(_this4.player, 'quality', null, event.detail.quality);
});
// Proxy events to container
// Bubble up key events for Edge
var proxyEvents = this.player.config.events.concat(['keyup', 'keydown']).join(' ');
+
on.call(this.player, this.player.media, proxyEvents, function (event) {
var _event$detail = event.detail,
detail = _event$detail === undefined ? {} : _event$detail;
@@ -4666,10 +4749,10 @@ typeof navigator === "object" && (function (global, factory) {
// Get error details from media
if (event.type === 'error') {
- detail = _this3.player.media.error;
+ detail = _this4.player.media.error;
}
- triggerEvent.call(_this3.player, _this3.player.elements.container, event.type, true, detail);
+ triggerEvent.call(_this4.player, _this4.player.elements.container, event.type, true, detail);
});
}
@@ -4698,7 +4781,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'bind',
value: function bind(element, type, defaultHandler, customHandlerKey) {
- var _this4 = this;
+ var _this5 = this;
var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
@@ -4706,7 +4789,7 @@ typeof navigator === "object" && (function (global, factory) {
var hasCustomHandler = is.function(customHandler);
on.call(this.player, element, type, function (event) {
- return _this4.proxy(event, defaultHandler, customHandlerKey);
+ return _this5.proxy(event, defaultHandler, customHandlerKey);
}, passive && !hasCustomHandler);
}
@@ -4715,7 +4798,7 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: 'controls',
value: function controls$$1() {
- var _this5 = this;
+ var _this6 = this;
// IE doesn't support input event, so we fallback to change
var inputEvent = browser.isIE ? 'change' : 'input';
@@ -4723,7 +4806,7 @@ typeof navigator === "object" && (function (global, factory) {
// Play/pause toggle
if (this.player.elements.buttons.play) {
Array.from(this.player.elements.buttons.play).forEach(function (button) {
- _this5.bind(button, 'click', _this5.player.togglePlay, 'play');
+ _this6.bind(button, 'click', _this6.player.togglePlay, 'play');
});
}
@@ -4738,22 +4821,22 @@ typeof navigator === "object" && (function (global, factory) {
// Mute toggle
this.bind(this.player.elements.buttons.mute, 'click', function () {
- _this5.player.muted = !_this5.player.muted;
+ _this6.player.muted = !_this6.player.muted;
}, 'mute');
// Captions toggle
this.bind(this.player.elements.buttons.captions, 'click', function () {
- return _this5.player.toggleCaptions();
+ return _this6.player.toggleCaptions();
});
// Fullscreen toggle
this.bind(this.player.elements.buttons.fullscreen, 'click', function () {
- _this5.player.fullscreen.toggle();
+ _this6.player.fullscreen.toggle();
}, 'fullscreen');
// Picture-in-Picture
this.bind(this.player.elements.buttons.pip, 'click', function () {
- _this5.player.pip = 'toggle';
+ _this6.player.pip = 'toggle';
}, 'pip');
// Airplay
@@ -4761,7 +4844,7 @@ typeof navigator === "object" && (function (global, factory) {
// Settings menu - click toggle
this.bind(this.player.elements.buttons.settings, 'click', function (event) {
- controls.toggleMenu.call(_this5.player, event);
+ controls.toggleMenu.call(_this6.player, event);
});
// Settings menu - keyboard toggle
@@ -4778,12 +4861,12 @@ typeof navigator === "object" && (function (global, factory) {
event.stopPropagation();
// Toggle menu
- controls.toggleMenu.call(_this5.player, event);
+ controls.toggleMenu.call(_this6.player, event);
}, null, false);
// Set range input alternative "value", which matches the tooltip time (#954)
this.bind(this.player.elements.inputs.seek, 'mousedown mousemove', function (event) {
- var clientRect = _this5.player.elements.progress.getBoundingClientRect();
+ var clientRect = _this6.player.elements.progress.getBoundingClientRect();
var percent = 100 / clientRect.width * (event.pageX - clientRect.left);
event.currentTarget.setAttribute('seek-value', percent);
});
@@ -4807,10 +4890,10 @@ typeof navigator === "object" && (function (global, factory) {
// If we're done seeking and it was playing, resume playback
if (play && done) {
seek.removeAttribute('play-on-seeked');
- _this5.player.play();
- } else if (!done && _this5.player.playing) {
+ _this6.player.play();
+ } else if (!done && _this6.player.playing) {
seek.setAttribute('play-on-seeked', '');
- _this5.player.pause();
+ _this6.player.pause();
}
});
@@ -4827,7 +4910,7 @@ typeof navigator === "object" && (function (global, factory) {
seek.removeAttribute('seek-value');
- _this5.player.currentTime = seekTo / seek.max * _this5.player.duration;
+ _this6.player.currentTime = seekTo / seek.max * _this6.player.duration;
}, 'seek');
// Current time invert
@@ -4835,48 +4918,48 @@ typeof navigator === "object" && (function (global, factory) {
if (this.player.config.toggleInvert && !is.element(this.player.elements.display.duration)) {
this.bind(this.player.elements.display.currentTime, 'click', function () {
// Do nothing if we're at the start
- if (_this5.player.currentTime === 0) {
+ if (_this6.player.currentTime === 0) {
return;
}
- _this5.player.config.invertTime = !_this5.player.config.invertTime;
+ _this6.player.config.invertTime = !_this6.player.config.invertTime;
- controls.timeUpdate.call(_this5.player);
+ controls.timeUpdate.call(_this6.player);
});
}
// Volume
this.bind(this.player.elements.inputs.volume, inputEvent, function (event) {
- _this5.player.volume = event.target.value;
+ _this6.player.volume = event.target.value;
}, 'volume');
// Polyfill for lower fill in <input type="range"> for webkit
if (browser.isWebkit) {
Array.from(getElements.call(this.player, 'input[type="range"]')).forEach(function (element) {
- _this5.bind(element, 'input', function (event) {
- return controls.updateRangeFill.call(_this5.player, event.target);
+ _this6.bind(element, 'input', function (event) {
+ return controls.updateRangeFill.call(_this6.player, event.target);
});
});
}
// Seek tooltip
this.bind(this.player.elements.progress, 'mouseenter mouseleave mousemove', function (event) {
- return controls.updateSeekTooltip.call(_this5.player, event);
+ return controls.updateSeekTooltip.call(_this6.player, event);
});
// Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(this.player.elements.controls, 'mouseenter mouseleave', function (event) {
- _this5.player.elements.controls.hover = !_this5.player.touch && event.type === 'mouseenter';
+ _this6.player.elements.controls.hover = !_this6.player.touch && event.type === 'mouseenter';
});
// Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(this.player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) {
- _this5.player.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
+ _this6.player.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
});
// Focus in/out on controls
this.bind(this.player.elements.controls, 'focusin focusout', function (event) {
- var _player = _this5.player,
+ var _player = _this6.player,
config = _player.config,
elements = _player.elements,
timers = _player.timers;
@@ -4886,7 +4969,7 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(elements.controls, config.classNames.noTransition, event.type === 'focusin');
// Toggle
- ui.toggleControls.call(_this5.player, event.type === 'focusin');
+ ui.toggleControls.call(_this6.player, event.type === 'focusin');
// If focusin, hide again after delay
if (event.type === 'focusin') {
@@ -4896,13 +4979,14 @@ typeof navigator === "object" && (function (global, factory) {
}, 0);
// Delay a little more for keyboard users
- var delay = _this5.touch ? 3000 : 4000;
+ var delay = _this6.touch ? 3000 : 4000;
// Clear timer
clearTimeout(timers.controls);
+
// Hide
timers.controls = setTimeout(function () {
- return ui.toggleControls.call(_this5.player, false);
+ return ui.toggleControls.call(_this6.player, false);
}, delay);
}
});
@@ -4928,10 +5012,10 @@ typeof navigator === "object" && (function (global, factory) {
var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
// Change the volume by 2%
- _this5.player.increaseVolume(direction / 50);
+ _this6.player.increaseVolume(direction / 50);
// Don't break page scrolling at max and min
- var volume = _this5.player.media.volume;
+ var volume = _this6.player.media.volume;
if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
event.preventDefault();