diff options
Diffstat (limited to 'dist/plyr.js')
-rw-r--r-- | dist/plyr.js | 177 |
1 files changed, 99 insertions, 78 deletions
diff --git a/dist/plyr.js b/dist/plyr.js index 20d94a02..1f3e49f4 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -50,6 +50,9 @@ typeof navigator === "object" && (function (global, factory) { var isEvent = function isEvent(input) { return instanceOf(input, Event); }; + var isKeyboardEvent = function isKeyboardEvent(input) { + return instanceOf(input, KeyboardEvent); + }; var isCue = function isCue(input) { return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); }; @@ -93,6 +96,7 @@ typeof navigator === "object" && (function (global, factory) { element: isElement, textNode: isTextNode, event: isEvent, + keyboardEvent: isKeyboardEvent, cue: isCue, track: isTrack, url: isUrl, @@ -1797,7 +1801,7 @@ typeof navigator === "object" && (function (global, factory) { }); this.listeners.bind(menuItem, 'click keyup', function (event) { - if (event.type === 'keyup' && event.which !== 32) { + if (is.keyboardEvent(event) && event.which !== 32) { return; } @@ -1823,7 +1827,7 @@ typeof navigator === "object" && (function (global, factory) { break; } - controls.showMenuPanel.call(_this2, 'home', event.type === 'keyup'); + controls.showMenuPanel.call(_this2, 'home', is.keyboardEvent(event)); }, type, false); controls.bindMenuItemShortcuts.call(this, menuItem, type); @@ -2422,13 +2426,18 @@ typeof navigator === "object" && (function (global, factory) { return; } - var show = is.boolean(input) ? input : is.element(popup) && popup.hasAttribute('hidden'); + // True toggle by default + var show = is.element(popup) && popup.hasAttribute('hidden'); - if (is.event(input)) { - var isMenuItem = is.element(popup) && popup.contains(input.target); - var isButton = input.target === this.elements.buttons.settings; + if (is.boolean(input)) { + show = input; + } else if (is.keyboardEvent(input) && input.which === 27) { + show = false; + } else if (is.event(input)) { + var isMenuItem = popup.contains(input.target); + var isButton = input.target === button; - // If the click was inside the form or if the click + // If the click was inside the menu or if the click // wasn't the button or menu item and we're trying to // show the menu (a doc click shouldn't show the menu) if (isMenuItem || !isMenuItem && !isButton && show) { @@ -2441,27 +2450,27 @@ typeof navigator === "object" && (function (global, factory) { } } - // Set form and button attributes - if (is.element(button)) { - button.setAttribute('aria-expanded', show); - } + // Set button attributes + button.setAttribute('aria-expanded', show); // Show the actual popup - if (is.element(popup)) { - toggleHidden(popup, !show); + toggleHidden(popup, !show); - toggleClass(this.elements.container, this.config.classNames.menu.open, show); + // Add class hook + toggleClass(this.elements.container, this.config.classNames.menu.open, show); - // Focus the first item if key interaction - if (show && is.event(input) && input.type === 'keyup') { - 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); - } + // Focus the first item if key interaction + if (show && is.keyboardEvent(input)) { + 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); } + // If closing, re-focus the button + else if (!show) { + setFocus.call(this, button, is.keyboardEvent(input)); + } }, @@ -4340,6 +4349,7 @@ typeof navigator === "object" && (function (global, factory) { key: 'handleKey', value: function handleKey(event) { var player = this.player; + var elements = player.elements; var code = event.keyCode ? event.keyCode : event.which; var pressed = event.type === 'keydown'; @@ -4371,7 +4381,7 @@ typeof navigator === "object" && (function (global, factory) { var focused = document.activeElement; if (is.element(focused)) { var editable = player.config.selectors.editable; - var seek = player.elements.inputs.seek; + var seek = elements.inputs.seek; if (focused !== seek && matches(focused, editable)) { @@ -4502,17 +4512,19 @@ typeof navigator === "object" && (function (global, factory) { key: 'firstTouch', value: function firstTouch() { var player = this.player; + var elements = player.elements; player.touch = true; // Add touch class - toggleClass(player.elements.container, player.config.classNames.isTouch, true); + toggleClass(elements.container, player.config.classNames.isTouch, true); } }, { key: 'setTabFocus', value: function setTabFocus(event) { var player = this.player; + var elements = player.elements; clearTimeout(this.focusTimer); @@ -4551,7 +4563,7 @@ typeof navigator === "object" && (function (global, factory) { var focused = document.activeElement; // Ignore if current focus element isn't inside the player - if (!player.elements.container.contains(focused)) { + if (!elements.container.contains(focused)) { return; } @@ -4589,16 +4601,17 @@ typeof navigator === "object" && (function (global, factory) { key: 'container', value: function container() { var player = this.player; + var elements = player.elements; // Keyboard shortcuts if (!player.config.keyboard.global && player.config.keyboard.focused) { - on.call(player, player.elements.container, 'keydown keyup', this.handleKey, false); + on.call(player, elements.container, 'keydown keyup', this.handleKey, false); } // Toggle controls on mouse events and entering fullscreen - on.call(player, player.elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { - var controls$$1 = player.elements.controls; + on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { + var controls$$1 = elements.controls; // Remove button states for fullscreen @@ -4634,6 +4647,7 @@ typeof navigator === "object" && (function (global, factory) { key: 'media', value: function media() { var player = this.player; + var elements = player.elements; // Time change on media @@ -4649,8 +4663,8 @@ typeof navigator === "object" && (function (global, factory) { // 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(player, player.media, 'canplay', function () { - toggleHidden(player.elements.volume, !player.hasAudio); - toggleHidden(player.elements.buttons.mute, !player.hasAudio); + toggleHidden(elements.volume, !player.hasAudio); + toggleHidden(elements.buttons.mute, !player.hasAudio); }); // Handle the media finishing @@ -4711,8 +4725,8 @@ typeof navigator === "object" && (function (global, factory) { } // On click play, pause ore restart - on.call(player, player.elements.container, 'click touchstart', function (event) { - var targets = [player.elements.container, wrapper]; + on.call(player, elements.container, 'click touchstart', function (event) { + var targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper if (!targets.includes(event.target) && !wrapper.contains(event.target)) { @@ -4721,7 +4735,7 @@ typeof navigator === "object" && (function (global, factory) { // First touch on touch devices will just show controls (if we're hiding controls) // If controls are shown then it'll toggle like a pointer device - if (player.config.hideControls && player.touch && hasClass(player.elements.container, player.config.classNames.hideControls)) { + if (player.config.hideControls && player.touch && hasClass(elements.container, player.config.classNames.hideControls)) { return; } @@ -4736,7 +4750,7 @@ typeof navigator === "object" && (function (global, factory) { // Disable right click if (player.supported.ui && player.config.disableContextMenu) { - on.call(player, player.elements.wrapper, 'contextmenu', function (event) { + on.call(player, elements.wrapper, 'contextmenu', function (event) { event.preventDefault(); }, false); } @@ -4785,7 +4799,7 @@ typeof navigator === "object" && (function (global, factory) { detail = player.media.error; } - triggerEvent.call(player, player.elements.container, event.type, true, detail); + triggerEvent.call(player, elements.container, event.type, true, detail); }); } @@ -4837,59 +4851,60 @@ typeof navigator === "object" && (function (global, factory) { var _this2 = this; var player = this.player; + var elements = player.elements; // IE doesn't support input event, so we fallback to change var inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle - if (player.elements.buttons.play) { - Array.from(player.elements.buttons.play).forEach(function (button) { + if (elements.buttons.play) { + Array.from(elements.buttons.play).forEach(function (button) { _this2.bind(button, 'click', player.togglePlay, 'play'); }); } // Pause - this.bind(player.elements.buttons.restart, 'click', player.restart, 'restart'); + this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind - this.bind(player.elements.buttons.rewind, 'click', player.rewind, 'rewind'); + this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind - this.bind(player.elements.buttons.fastForward, 'click', player.forward, 'fastForward'); + this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle - this.bind(player.elements.buttons.mute, 'click', function () { + this.bind(elements.buttons.mute, 'click', function () { player.muted = !player.muted; }, 'mute'); // Captions toggle - this.bind(player.elements.buttons.captions, 'click', function () { + this.bind(elements.buttons.captions, 'click', function () { return player.toggleCaptions(); }); // Fullscreen toggle - this.bind(player.elements.buttons.fullscreen, 'click', function () { + this.bind(elements.buttons.fullscreen, 'click', function () { player.fullscreen.toggle(); }, 'fullscreen'); // Picture-in-Picture - this.bind(player.elements.buttons.pip, 'click', function () { + this.bind(elements.buttons.pip, 'click', function () { player.pip = 'toggle'; }, 'pip'); // Airplay - this.bind(player.elements.buttons.airplay, 'click', player.airplay, 'airplay'); + this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle - this.bind(player.elements.buttons.settings, 'click', function (event) { + this.bind(elements.buttons.settings, 'click', function (event) { controls.toggleMenu.call(player, event); }); // Settings menu - keyboard toggle // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 - this.bind(player.elements.buttons.settings, 'keyup', function (event) { + this.bind(elements.buttons.settings, 'keyup', function (event) { // We only care about space and return if (event.which !== 32 && event.which !== 13) { return; @@ -4907,23 +4922,30 @@ typeof navigator === "object" && (function (global, factory) { controls.toggleMenu.call(player, event); }, null, false); + // Escape closes menu + this.bind(elements.settings.menu, 'keydown', function (event) { + if (event.which === 27) { + controls.toggleMenu.call(player, event); + } + }); + // Set range input alternative "value", which matches the tooltip time (#954) - this.bind(player.elements.inputs.seek, 'mousedown mousemove', function (event) { - var rect = player.elements.progress.getBoundingClientRect(); + this.bind(elements.inputs.seek, 'mousedown mousemove', function (event) { + var rect = elements.progress.getBoundingClientRect(); var percent = 100 / rect.width * (event.pageX - rect.left); event.currentTarget.setAttribute('seek-value', percent); }); // Pause while seeking - this.bind(player.elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { + this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { var seek = event.currentTarget; var code = event.keyCode ? event.keyCode : event.which; - var eventType = event.type; var attribute = 'play-on-seeked'; - if ((eventType === 'keydown' || eventType === 'keyup') && code !== 39 && code !== 37) { + if (is.keyboardEvent(event) && code !== 39 && code !== 37) { return; } + // Was playing before? var play = seek.hasAttribute(attribute); @@ -4945,7 +4967,6 @@ typeof navigator === "object" && (function (global, factory) { // it takes over further interactions on the page. This is a hack if (browser.isIos) { var inputs = getElements.call(player, 'input[type="range"]'); - Array.from(inputs).forEach(function (input) { return _this2.bind(input, inputEvent, function (event) { return repaint(event.target); @@ -4954,7 +4975,7 @@ typeof navigator === "object" && (function (global, factory) { } // Seek - this.bind(player.elements.inputs.seek, inputEvent, function (event) { + this.bind(elements.inputs.seek, inputEvent, function (event) { var seek = event.currentTarget; // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) @@ -4969,10 +4990,24 @@ typeof navigator === "object" && (function (global, factory) { player.currentTime = seekTo / seek.max * player.duration; }, 'seek'); + // Seek tooltip + this.bind(elements.progress, 'mouseenter mouseleave mousemove', function (event) { + return controls.updateSeekTooltip.call(player, event); + }); + + // Polyfill for lower fill in <input type="range"> for webkit + if (browser.isWebkit) { + Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { + _this2.bind(element, 'input', function (event) { + return controls.updateRangeFill.call(player, event.target); + }); + }); + } + // Current time invert // Only if one time element is used for both currentTime and duration - if (player.config.toggleInvert && !is.element(player.elements.display.duration)) { - this.bind(player.elements.display.currentTime, 'click', function () { + if (player.config.toggleInvert && !is.element(elements.display.duration)) { + this.bind(elements.display.currentTime, 'click', function () { // Do nothing if we're at the start if (player.currentTime === 0) { return; @@ -4985,36 +5020,22 @@ typeof navigator === "object" && (function (global, factory) { } // Volume - this.bind(player.elements.inputs.volume, inputEvent, function (event) { + this.bind(elements.inputs.volume, inputEvent, function (event) { player.volume = event.target.value; }, 'volume'); - // Polyfill for lower fill in <input type="range"> for webkit - if (browser.isWebkit) { - Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { - _this2.bind(element, 'input', function (event) { - return controls.updateRangeFill.call(player, event.target); - }); - }); - } - - // Seek tooltip - this.bind(player.elements.progress, 'mouseenter mouseleave mousemove', function (event) { - return controls.updateSeekTooltip.call(player, event); - }); - // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) - this.bind(player.elements.controls, 'mouseenter mouseleave', function (event) { - player.elements.controls.hover = !player.touch && event.type === 'mouseenter'; + this.bind(elements.controls, 'mouseenter mouseleave', function (event) { + elements.controls.hover = !player.touch && event.type === 'mouseenter'; }); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) - this.bind(player.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { - player.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); + this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { + elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); }); // Focus in/out on controls - this.bind(player.elements.controls, 'focusin focusout', function (event) { + this.bind(elements.controls, 'focusin focusout', function (event) { var config = player.config, elements = player.elements, timers = player.timers; @@ -5048,7 +5069,7 @@ typeof navigator === "object" && (function (global, factory) { }); // Mouse wheel for volume - this.bind(player.elements.inputs.volume, 'wheel', function (event) { + this.bind(elements.inputs.volume, 'wheel', function (event) { // Detect "natural" scroll - suppored on OS X Safari only // Other browsers on OS X will be inverted until support improves var inverted = event.webkitDirectionInvertedFromDevice; |