From c94ab2a39fde5ce41a2473f7e9ac29f51886fe18 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Mon, 3 Jun 2019 20:12:21 +1000 Subject: Repaint clean up --- src/js/utils/animation.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/animation.js b/src/js/utils/animation.js index 6b950b61..3f721b5a 100644 --- a/src/js/utils/animation.js +++ b/src/js/utils/animation.js @@ -2,7 +2,6 @@ // Animation utils // ========================================================================== -import { toggleHidden } from './elements'; import is from './is'; export const transitionEndEvent = (() => { @@ -21,14 +20,19 @@ export const transitionEndEvent = (() => { })(); // Force repaint of element -export function repaint(element) { +export function repaint(element, delay) { setTimeout(() => { try { - toggleHidden(element, true); - element.offsetHeight; // eslint-disable-line - toggleHidden(element, false); + // eslint-disable-next-line no-param-reassign + element.hidden = true; + + // eslint-disable-next-line no-unused-expressions + element.offsetHeight; + + // eslint-disable-next-line no-param-reassign + element.hidden = false; } catch (e) { // Do nothing } - }, 0); + }, delay); } -- cgit v1.2.3 From 97d9228bed639f0c20b1f21468dd3f181af6b262 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Mon, 3 Jun 2019 20:13:16 +1000 Subject: Aspect ratio tweaks --- src/js/utils/elements.js | 7 ++----- src/js/utils/style.js | 11 ++--------- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index 98b44f13..4f10938e 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -192,11 +192,8 @@ export function toggleHidden(element, hidden) { hide = !element.hidden; } - if (hide) { - element.setAttribute('hidden', ''); - } else { - element.removeAttribute('hidden'); - } + // eslint-disable-next-line no-param-reassign + element.hidden = hide; } // Mirror Element.classList.toggle, with IE compatibility for "force" argument diff --git a/src/js/utils/style.js b/src/js/utils/style.js index 6f3069c9..941db8f2 100644 --- a/src/js/utils/style.js +++ b/src/js/utils/style.js @@ -27,15 +27,8 @@ export function reduceAspectRatio(ratio) { } export function getAspectRatio(input) { - const parse = ratio => { - if (!validateRatio(ratio)) { - return null; - } - - return ratio.split(':').map(Number); - }; - - // Provided ratio + const parse = ratio => (validateRatio(ratio) ? ratio.split(':').map(Number) : null); + // Try provided ratio let ratio = parse(input); // Get from config -- cgit v1.2.3 From 8fc6c2ba526bf1ef8cdb9476f1644089281ce60d Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Fri, 21 Jun 2019 00:19:37 +1000 Subject: File rename and clean up --- src/js/utils/load-image.js | 19 ++++++++++++ src/js/utils/load-script.js | 14 +++++++++ src/js/utils/load-sprite.js | 75 +++++++++++++++++++++++++++++++++++++++++++++ src/js/utils/loadImage.js | 19 ------------ src/js/utils/loadScript.js | 14 --------- src/js/utils/loadSprite.js | 75 --------------------------------------------- 6 files changed, 108 insertions(+), 108 deletions(-) create mode 100644 src/js/utils/load-image.js create mode 100644 src/js/utils/load-script.js create mode 100644 src/js/utils/load-sprite.js delete mode 100644 src/js/utils/loadImage.js delete mode 100644 src/js/utils/loadScript.js delete mode 100644 src/js/utils/loadSprite.js (limited to 'src/js/utils') diff --git a/src/js/utils/load-image.js b/src/js/utils/load-image.js new file mode 100644 index 00000000..8acd2496 --- /dev/null +++ b/src/js/utils/load-image.js @@ -0,0 +1,19 @@ +// ========================================================================== +// Load image avoiding xhr/fetch CORS issues +// Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded +// By default it checks if it is at least 1px, but you can add a second argument to change this +// ========================================================================== + +export default function loadImage(src, minWidth = 1) { + return new Promise((resolve, reject) => { + const image = new Image(); + + const handler = () => { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; + + Object.assign(image, { onload: handler, onerror: handler, src }); + }); +} diff --git a/src/js/utils/load-script.js b/src/js/utils/load-script.js new file mode 100644 index 00000000..81ae36f4 --- /dev/null +++ b/src/js/utils/load-script.js @@ -0,0 +1,14 @@ +// ========================================================================== +// Load an external script +// ========================================================================== + +import loadjs from 'loadjs'; + +export default function loadScript(url) { + return new Promise((resolve, reject) => { + loadjs(url, { + success: resolve, + error: reject, + }); + }); +} diff --git a/src/js/utils/load-sprite.js b/src/js/utils/load-sprite.js new file mode 100644 index 00000000..fe4add00 --- /dev/null +++ b/src/js/utils/load-sprite.js @@ -0,0 +1,75 @@ +// ========================================================================== +// Sprite loader +// ========================================================================== + +import Storage from '../storage'; +import fetch from './fetch'; +import is from './is'; + +// Load an external SVG sprite +export default function loadSprite(url, id) { + if (!is.string(url)) { + return; + } + + const prefix = 'cache'; + const hasId = is.string(id); + let isCached = false; + const exists = () => document.getElementById(id) !== null; + + const update = (container, data) => { + // eslint-disable-next-line no-param-reassign + container.innerHTML = data; + + // Check again incase of race condition + if (hasId && exists()) { + return; + } + + // Inject the SVG to the body + document.body.insertAdjacentElement('afterbegin', container); + }; + + // Only load once if ID set + if (!hasId || !exists()) { + const useStorage = Storage.supported; + // Create container + const container = document.createElement('div'); + container.setAttribute('hidden', ''); + + if (hasId) { + container.setAttribute('id', id); + } + + // Check in cache + if (useStorage) { + const cached = window.localStorage.getItem(`${prefix}-${id}`); + isCached = cached !== null; + + if (isCached) { + const data = JSON.parse(cached); + update(container, data.content); + } + } + + // Get the sprite + fetch(url) + .then(result => { + if (is.empty(result)) { + return; + } + + if (useStorage) { + window.localStorage.setItem( + `${prefix}-${id}`, + JSON.stringify({ + content: result, + }), + ); + } + + update(container, result); + }) + .catch(() => {}); + } +} diff --git a/src/js/utils/loadImage.js b/src/js/utils/loadImage.js deleted file mode 100644 index 8acd2496..00000000 --- a/src/js/utils/loadImage.js +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// Load image avoiding xhr/fetch CORS issues -// Server status can't be obtained this way unfortunately, so this uses "naturalWidth" to determine if the image has loaded -// By default it checks if it is at least 1px, but you can add a second argument to change this -// ========================================================================== - -export default function loadImage(src, minWidth = 1) { - return new Promise((resolve, reject) => { - const image = new Image(); - - const handler = () => { - delete image.onload; - delete image.onerror; - (image.naturalWidth >= minWidth ? resolve : reject)(image); - }; - - Object.assign(image, { onload: handler, onerror: handler, src }); - }); -} diff --git a/src/js/utils/loadScript.js b/src/js/utils/loadScript.js deleted file mode 100644 index 81ae36f4..00000000 --- a/src/js/utils/loadScript.js +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// Load an external script -// ========================================================================== - -import loadjs from 'loadjs'; - -export default function loadScript(url) { - return new Promise((resolve, reject) => { - loadjs(url, { - success: resolve, - error: reject, - }); - }); -} diff --git a/src/js/utils/loadSprite.js b/src/js/utils/loadSprite.js deleted file mode 100644 index fe4add00..00000000 --- a/src/js/utils/loadSprite.js +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================================== -// Sprite loader -// ========================================================================== - -import Storage from '../storage'; -import fetch from './fetch'; -import is from './is'; - -// Load an external SVG sprite -export default function loadSprite(url, id) { - if (!is.string(url)) { - return; - } - - const prefix = 'cache'; - const hasId = is.string(id); - let isCached = false; - const exists = () => document.getElementById(id) !== null; - - const update = (container, data) => { - // eslint-disable-next-line no-param-reassign - container.innerHTML = data; - - // Check again incase of race condition - if (hasId && exists()) { - return; - } - - // Inject the SVG to the body - document.body.insertAdjacentElement('afterbegin', container); - }; - - // Only load once if ID set - if (!hasId || !exists()) { - const useStorage = Storage.supported; - // Create container - const container = document.createElement('div'); - container.setAttribute('hidden', ''); - - if (hasId) { - container.setAttribute('id', id); - } - - // Check in cache - if (useStorage) { - const cached = window.localStorage.getItem(`${prefix}-${id}`); - isCached = cached !== null; - - if (isCached) { - const data = JSON.parse(cached); - update(container, data.content); - } - } - - // Get the sprite - fetch(url) - .then(result => { - if (is.empty(result)) { - return; - } - - if (useStorage) { - window.localStorage.setItem( - `${prefix}-${id}`, - JSON.stringify({ - content: result, - }), - ); - } - - update(container, result); - }) - .catch(() => {}); - } -} -- cgit v1.2.3 From 0b240ae7d1a0bece3609e3dc6d0eddf8d70ddc16 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Mon, 13 Jan 2020 16:20:02 +0000 Subject: Fix linting issues --- src/js/utils/events.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/events.js b/src/js/utils/events.js index 87c35d26..31571b2d 100644 --- a/src/js/utils/events.js +++ b/src/js/utils/events.js @@ -90,9 +90,7 @@ export function triggerEvent(element, type = '', bubbles = false, detail = {}) { // Create and dispatch the event const event = new CustomEvent(type, { bubbles, - detail: Object.assign({}, detail, { - plyr: this, - }), + detail: { ...detail, plyr: this,}, }); // Dispatch the event -- cgit v1.2.3 From c3f10e7df3e77c3cf8ad3165ad881bcd11a9b7e3 Mon Sep 17 00:00:00 2001 From: Binyamin Laukstein <7raivis@inbox.lv> Date: Wed, 22 Jan 2020 08:53:08 +0200 Subject: Uncaught RangeError: Maximum call stack size exceeded Fix formatTime infinite loop #1621 --- src/js/utils/time.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js/utils') diff --git a/src/js/utils/time.js b/src/js/utils/time.js index ffca88b2..17228de5 100644 --- a/src/js/utils/time.js +++ b/src/js/utils/time.js @@ -13,7 +13,7 @@ export const getSeconds = value => Math.trunc(value % 60, 10); export function formatTime(time = 0, displayHours = false, inverted = false) { // Bail if the value isn't a number if (!is.number(time)) { - return formatTime(null, displayHours, inverted); + return formatTime(undefined, displayHours, inverted); } // Format time component to add leading zero -- cgit v1.2.3 From f8a28b632cf12a2c557a766010252b9edd4cdb8e Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sun, 26 Jan 2020 22:05:21 +0000 Subject: Audio style fix --- src/js/utils/style.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/style.js b/src/js/utils/style.js index 941db8f2..17a033fe 100644 --- a/src/js/utils/style.js +++ b/src/js/utils/style.js @@ -56,11 +56,12 @@ export function setAspectRatio(input) { return {}; } + const { wrapper } = this.elements; const ratio = getAspectRatio.call(this, input); const [w, h] = is.array(ratio) ? ratio : [0, 0]; const padding = (100 / w) * h; - this.elements.wrapper.style.paddingBottom = `${padding}%`; + wrapper.style.paddingBottom = `${padding}%`; // For Vimeo we have an extra
to hide the standard controls and UI if (this.isVimeo && this.supported.ui) { @@ -68,7 +69,7 @@ export function setAspectRatio(input) { const offset = (height - padding) / (height / 50); this.media.style.transform = `translateY(-${offset}%)`; } else if (this.isHTML5) { - this.elements.wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); + wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); } return { padding, ratio }; -- cgit v1.2.3 From e17da7dfd467e5d970400a32860f6653bcc0f556 Mon Sep 17 00:00:00 2001 From: Kimberley Jensen Date: Fri, 7 Feb 2020 15:00:04 +0100 Subject: Bail out of focus trap if fullscreen is not active - detailed in https://github.com/sampotts/plyr/issues/1665 --- src/js/utils/elements.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/js/utils') diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index 4f10938e..921d533a 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -257,10 +257,11 @@ export function trapFocus(element = null, toggle = false) { const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); const first = focusable[0]; const last = focusable[focusable.length - 1]; + const player = this; const trap = event => { // Bail if not tab key or not fullscreen - if (event.key !== 'Tab' || event.keyCode !== 9) { + if (event.key !== 'Tab' || event.keyCode !== 9 || !player.fullscreen.active) { return; } -- cgit v1.2.3 From 90dc985657190f08e91686cdcf404a106c498511 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sat, 8 Feb 2020 23:09:41 +0000 Subject: Clean up speed options logic --- src/js/utils/arrays.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/js/utils') diff --git a/src/js/utils/arrays.js b/src/js/utils/arrays.js index 69ef242c..c0d69626 100644 --- a/src/js/utils/arrays.js +++ b/src/js/utils/arrays.js @@ -21,3 +21,11 @@ export function closest(array, value) { return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); } + +export function fillRange(start, end, step = 1) { + const len = Math.floor((end - start) / step) + 1; + + return Array(len) + .fill() + .map((_, idx) => start + idx * step); +} -- cgit v1.2.3 From 2d13ad3d397423e527caa6f3eba9df242505dfff Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sun, 9 Feb 2020 21:42:12 +0000 Subject: Focus trap improvements --- src/js/utils/elements.js | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index 921d533a..b88aad0c 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -2,7 +2,6 @@ // Element utils // ========================================================================== -import { toggleListener } from './events'; import is from './is'; import { extend } from './objects'; @@ -248,40 +247,6 @@ export function getElement(selector) { return this.elements.container.querySelector(selector); } -// Trap focus inside container -export function trapFocus(element = null, toggle = false) { - if (!is.element(element)) { - return; - } - - const focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]'); - const first = focusable[0]; - const last = focusable[focusable.length - 1]; - const player = this; - - const trap = event => { - // Bail if not tab key or not fullscreen - if (event.key !== 'Tab' || event.keyCode !== 9 || !player.fullscreen.active) { - return; - } - - // Get the current focused element - const focused = document.activeElement; - - if (focused === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - first.focus(); - event.preventDefault(); - } else if (focused === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - last.focus(); - event.preventDefault(); - } - }; - - toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false); -} - // Set focus and tab focus class export function setFocus(element = null, tabFocus = false) { if (!is.element(element)) { -- cgit v1.2.3 From 1619510dcf9e3ccc1693caa20a173aaf2789e346 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Mon, 10 Feb 2020 18:34:05 +0000 Subject: Speed settings logic improvements --- src/js/utils/arrays.js | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src/js/utils') diff --git a/src/js/utils/arrays.js b/src/js/utils/arrays.js index c0d69626..69ef242c 100644 --- a/src/js/utils/arrays.js +++ b/src/js/utils/arrays.js @@ -21,11 +21,3 @@ export function closest(array, value) { return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); } - -export function fillRange(start, end, step = 1) { - const len = Math.floor((end - start) / step) + 1; - - return Array(len) - .fill() - .map((_, idx) => start + idx * step); -} -- cgit v1.2.3 From c7bf0c5c03a5c7716a39a0f2f5a11681eedbac7f Mon Sep 17 00:00:00 2001 From: Jesper Date: Tue, 10 Mar 2020 09:19:34 +0100 Subject: Fix prototype used for selector matcher function --- src/js/utils/elements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/js/utils') diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index b88aad0c..43f46416 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -221,7 +221,7 @@ export function hasClass(element, className) { // Element matches selector export function matches(element, selector) { - const prototype = { Element }; + const prototype = Element.prototype; function match() { return Array.from(document.querySelectorAll(selector)).includes(this); -- cgit v1.2.3 From 71928443f317e624ab94ff18e207447f06f745ad Mon Sep 17 00:00:00 2001 From: ydylla Date: Mon, 23 Mar 2020 22:50:19 +0100 Subject: silence all internal play promises --- src/js/utils/promise.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/js/utils/promise.js (limited to 'src/js/utils') diff --git a/src/js/utils/promise.js b/src/js/utils/promise.js new file mode 100644 index 00000000..42fcc2c3 --- /dev/null +++ b/src/js/utils/promise.js @@ -0,0 +1,27 @@ +/** + * Returns whether an object is `Promise`-like (i.e. has a `then` method). + * + * @param {Object} value + * An object that may or may not be `Promise`-like. + * + * @return {boolean} + * Whether or not the object is `Promise`-like. + */ +export function isPromise(value) { + return value !== undefined && value !== null && typeof value.then === 'function'; +} + +/** + * Silence a Promise-like object. + * + * This is useful for avoiding non-harmful, but potentially confusing "uncaught + * play promise" rejection error messages. + * + * @param {Object} value + * An object that may or may not be `Promise`-like. + */ +export function silencePromise(value) { + if (isPromise(value)) { + value.then(null, () => {}); + } +} -- cgit v1.2.3