diff options
Diffstat (limited to 'src/js/utils')
-rw-r--r-- | src/js/utils/animation.js | 46 | ||||
-rw-r--r-- | src/js/utils/arrays.js | 16 | ||||
-rw-r--r-- | src/js/utils/browser.js | 10 | ||||
-rw-r--r-- | src/js/utils/elements.js | 336 | ||||
-rw-r--r-- | src/js/utils/events.js | 144 | ||||
-rw-r--r-- | src/js/utils/fetch.js | 58 | ||||
-rw-r--r-- | src/js/utils/i18n.js | 50 | ||||
-rw-r--r-- | src/js/utils/is.js | 78 | ||||
-rw-r--r-- | src/js/utils/load-image.js | 18 | ||||
-rw-r--r-- | src/js/utils/load-script.js | 10 | ||||
-rw-r--r-- | src/js/utils/load-sprite.js | 104 | ||||
-rw-r--r-- | src/js/utils/numbers.js | 2 | ||||
-rw-r--r-- | src/js/utils/objects.js | 40 | ||||
-rw-r--r-- | src/js/utils/promise.js | 6 | ||||
-rw-r--r-- | src/js/utils/strings.js | 75 | ||||
-rw-r--r-- | src/js/utils/style.js | 108 | ||||
-rw-r--r-- | src/js/utils/time.js | 36 | ||||
-rw-r--r-- | src/js/utils/urls.js | 36 |
18 files changed, 584 insertions, 589 deletions
diff --git a/src/js/utils/animation.js b/src/js/utils/animation.js index 3f721b5a..d9e7615e 100644 --- a/src/js/utils/animation.js +++ b/src/js/utils/animation.js @@ -5,34 +5,34 @@ import is from './is'; export const transitionEndEvent = (() => { - const element = document.createElement('span'); + const element = document.createElement('span'); - const events = { - WebkitTransition: 'webkitTransitionEnd', - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd otransitionend', - transition: 'transitionend', - }; + const events = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend', + }; - const type = Object.keys(events).find(event => element.style[event] !== undefined); + const type = Object.keys(events).find(event => element.style[event] !== undefined); - return is.string(type) ? events[type] : false; + return is.string(type) ? events[type] : false; })(); // Force repaint of element export function repaint(element, delay) { - setTimeout(() => { - try { - // 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 - } - }, delay); + setTimeout(() => { + try { + // 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 + } + }, delay); } diff --git a/src/js/utils/arrays.js b/src/js/utils/arrays.js index 69ef242c..aed951cd 100644 --- a/src/js/utils/arrays.js +++ b/src/js/utils/arrays.js @@ -6,18 +6,18 @@ import is from './is'; // Remove duplicates in an array export function dedupe(array) { - if (!is.array(array)) { - return array; - } + if (!is.array(array)) { + return array; + } - return array.filter((item, index) => array.indexOf(item) === index); + return array.filter((item, index) => array.indexOf(item) === index); } // Get the closest value in an array export function closest(array, value) { - if (!is.array(array) || !array.length) { - return null; - } + if (!is.array(array) || !array.length) { + return null; + } - return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); + return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev)); } diff --git a/src/js/utils/browser.js b/src/js/utils/browser.js index 11705074..7b8fa5e2 100644 --- a/src/js/utils/browser.js +++ b/src/js/utils/browser.js @@ -4,11 +4,11 @@ // ========================================================================== const browser = { - isIE: /* @cc_on!@ */ false || !!document.documentMode, - isEdge: window.navigator.userAgent.includes('Edge'), - isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), - isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), - isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), + isIE: /* @cc_on!@ */ false || !!document.documentMode, + isEdge: window.navigator.userAgent.includes('Edge'), + isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent), + isIPhone: /(iPhone|iPod)/gi.test(navigator.platform), + isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform), }; export default browser; diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index acff0dd9..b48fa7e1 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -7,257 +7,257 @@ import { extend } from './objects'; // Wrap an element export function wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - const targets = elements.length ? elements : [elements]; - - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - Array.from(targets) - .reverse() - .forEach((element, index) => { - const child = index > 0 ? wrapper.cloneNode(true) : wrapper; - // Cache the current parent and sibling. - const parent = element.parentNode; - const sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - }); + // Convert `elements` to an array, if necessary. + const targets = elements.length ? elements : [elements]; + + // Loops backwards to prevent having to clone the wrapper on the + // first element (see `child` below). + Array.from(targets) + .reverse() + .forEach((element, index) => { + const child = index > 0 ? wrapper.cloneNode(true) : wrapper; + // Cache the current parent and sibling. + const parent = element.parentNode; + const sibling = element.nextSibling; + + // Wrap the element (is automatically removed from its current + // parent). + child.appendChild(element); + + // If the element had a sibling, insert the wrapper before + // the sibling to maintain the HTML structure; otherwise, just + // append it to the parent. + if (sibling) { + parent.insertBefore(child, sibling); + } else { + parent.appendChild(child); + } + }); } // Set attributes export function setAttributes(element, attributes) { - if (!is.element(element) || is.empty(attributes)) { - return; - } - - // Assume null and undefined attributes should be left out, - // Setting them would otherwise convert them to "null" and "undefined" - Object.entries(attributes) - .filter(([, value]) => !is.nullOrUndefined(value)) - .forEach(([key, value]) => element.setAttribute(key, value)); + if (!is.element(element) || is.empty(attributes)) { + return; + } + + // Assume null and undefined attributes should be left out, + // Setting them would otherwise convert them to "null" and "undefined" + Object.entries(attributes) + .filter(([, value]) => !is.nullOrUndefined(value)) + .forEach(([key, value]) => element.setAttribute(key, value)); } // Create a DocumentFragment export function createElement(type, attributes, text) { - // Create a new <element> - const element = document.createElement(type); + // Create a new <element> + const element = document.createElement(type); - // Set all passed attributes - if (is.object(attributes)) { - setAttributes(element, attributes); - } + // Set all passed attributes + if (is.object(attributes)) { + setAttributes(element, attributes); + } - // Add text node - if (is.string(text)) { - element.innerText = text; - } + // Add text node + if (is.string(text)) { + element.innerText = text; + } - // Return built element - return element; + // Return built element + return element; } // Inaert an element after another export function insertAfter(element, target) { - if (!is.element(element) || !is.element(target)) { - return; - } + if (!is.element(element) || !is.element(target)) { + return; + } - target.parentNode.insertBefore(element, target.nextSibling); + target.parentNode.insertBefore(element, target.nextSibling); } // Insert a DocumentFragment export function insertElement(type, parent, attributes, text) { - if (!is.element(parent)) { - return; - } + if (!is.element(parent)) { + return; + } - parent.appendChild(createElement(type, attributes, text)); + parent.appendChild(createElement(type, attributes, text)); } // Remove element(s) export function removeElement(element) { - if (is.nodeList(element) || is.array(element)) { - Array.from(element).forEach(removeElement); - return; - } + if (is.nodeList(element) || is.array(element)) { + Array.from(element).forEach(removeElement); + return; + } - if (!is.element(element) || !is.element(element.parentNode)) { - return; - } + if (!is.element(element) || !is.element(element.parentNode)) { + return; + } - element.parentNode.removeChild(element); + element.parentNode.removeChild(element); } // Remove all child elements export function emptyElement(element) { - if (!is.element(element)) { - return; - } + if (!is.element(element)) { + return; + } - let { length } = element.childNodes; + let { length } = element.childNodes; - while (length > 0) { - element.removeChild(element.lastChild); - length -= 1; - } + while (length > 0) { + element.removeChild(element.lastChild); + length -= 1; + } } // Replace element export function replaceElement(newChild, oldChild) { - if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { - return null; - } + if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) { + return null; + } - oldChild.parentNode.replaceChild(newChild, oldChild); + oldChild.parentNode.replaceChild(newChild, oldChild); - return newChild; + return newChild; } // Get an attribute object from a string selector export function getAttributesFromSelector(sel, existingAttributes) { - // For example: - // '.test' to { class: 'test' } - // '#test' to { id: 'test' } - // '[data-test="test"]' to { 'data-test': 'test' } + // For example: + // '.test' to { class: 'test' } + // '#test' to { id: 'test' } + // '[data-test="test"]' to { 'data-test': 'test' } + + if (!is.string(sel) || is.empty(sel)) { + return {}; + } + + const attributes = {}; + const existing = extend({}, existingAttributes); + + sel.split(',').forEach(s => { + // Remove whitespace + const selector = s.trim(); + const className = selector.replace('.', ''); + const stripped = selector.replace(/[[\]]/g, ''); + // Get the parts and value + const parts = stripped.split('='); + const [key] = parts; + const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; + // Get the first character + const start = selector.charAt(0); + + switch (start) { + case '.': + // Add to existing classname + if (is.string(existing.class)) { + attributes.class = `${existing.class} ${className}`; + } else { + attributes.class = className; + } + break; - if (!is.string(sel) || is.empty(sel)) { - return {}; - } + case '#': + // ID selector + attributes.id = selector.replace('#', ''); + break; - const attributes = {}; - const existing = extend({}, existingAttributes); - - sel.split(',').forEach(s => { - // Remove whitespace - const selector = s.trim(); - const className = selector.replace('.', ''); - const stripped = selector.replace(/[[\]]/g, ''); - // Get the parts and value - const parts = stripped.split('='); - const [key] = parts; - const value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; - // Get the first character - const start = selector.charAt(0); - - switch (start) { - case '.': - // Add to existing classname - if (is.string(existing.class)) { - attributes.class = `${existing.class} ${className}`; - } else { - attributes.class = className; - } - break; - - case '#': - // ID selector - attributes.id = selector.replace('#', ''); - break; - - case '[': - // Attribute selector - attributes[key] = value; - - break; - - default: - break; - } - }); + case '[': + // Attribute selector + attributes[key] = value; - return extend(existing, attributes); + break; + + default: + break; + } + }); + + return extend(existing, attributes); } // Toggle hidden export function toggleHidden(element, hidden) { - if (!is.element(element)) { - return; - } + if (!is.element(element)) { + return; + } - let hide = hidden; + let hide = hidden; - if (!is.boolean(hide)) { - hide = !element.hidden; - } + if (!is.boolean(hide)) { + hide = !element.hidden; + } - // eslint-disable-next-line no-param-reassign - element.hidden = hide; + // eslint-disable-next-line no-param-reassign + element.hidden = hide; } // Mirror Element.classList.toggle, with IE compatibility for "force" argument export function toggleClass(element, className, force) { - if (is.nodeList(element)) { - return Array.from(element).map(e => toggleClass(e, className, force)); + if (is.nodeList(element)) { + return Array.from(element).map(e => toggleClass(e, className, force)); + } + + if (is.element(element)) { + let method = 'toggle'; + if (typeof force !== 'undefined') { + method = force ? 'add' : 'remove'; } - if (is.element(element)) { - let method = 'toggle'; - if (typeof force !== 'undefined') { - method = force ? 'add' : 'remove'; - } - - element.classList[method](className); - return element.classList.contains(className); - } + element.classList[method](className); + return element.classList.contains(className); + } - return false; + return false; } // Has class name export function hasClass(element, className) { - return is.element(element) && element.classList.contains(className); + return is.element(element) && element.classList.contains(className); } // Element matches selector export function matches(element, selector) { - const { prototype } = Element; + const { prototype } = Element; - function match() { - return Array.from(document.querySelectorAll(selector)).includes(this); - } + function match() { + return Array.from(document.querySelectorAll(selector)).includes(this); + } - const method = - prototype.matches || - prototype.webkitMatchesSelector || - prototype.mozMatchesSelector || - prototype.msMatchesSelector || - match; + const method = + prototype.matches || + prototype.webkitMatchesSelector || + prototype.mozMatchesSelector || + prototype.msMatchesSelector || + match; - return method.call(element, selector); + return method.call(element, selector); } // Find all elements export function getElements(selector) { - return this.elements.container.querySelectorAll(selector); + return this.elements.container.querySelectorAll(selector); } // Find a single element export function getElement(selector) { - return this.elements.container.querySelector(selector); + return this.elements.container.querySelector(selector); } // Set focus and tab focus class export function setFocus(element = null, tabFocus = false) { - if (!is.element(element)) { - return; - } + if (!is.element(element)) { + return; + } - // Set regular focus - element.focus({ preventScroll: true }); + // Set regular focus + element.focus({ preventScroll: true }); - // If we want to mimic keyboard focus via tab - if (tabFocus) { - toggleClass(element, this.config.classNames.tabFocus); - } + // If we want to mimic keyboard focus via tab + if (tabFocus) { + toggleClass(element, this.config.classNames.tabFocus); + } } diff --git a/src/js/utils/events.js b/src/js/utils/events.js index 48300b6b..235eb629 100644 --- a/src/js/utils/events.js +++ b/src/js/utils/events.js @@ -8,110 +8,110 @@ import is from './is'; // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md // https://www.youtube.com/watch?v=NPM6172J22g const supportsPassiveListeners = (() => { - // Test via a getter in the options object to see if the passive property is accessed - let supported = false; - try { - const options = Object.defineProperty({}, 'passive', { - get() { - supported = true; - return null; - }, - }); - window.addEventListener('test', null, options); - window.removeEventListener('test', null, options); - } catch (e) { - // Do nothing - } + // Test via a getter in the options object to see if the passive property is accessed + let supported = false; + try { + const options = Object.defineProperty({}, 'passive', { + get() { + supported = true; + return null; + }, + }); + window.addEventListener('test', null, options); + window.removeEventListener('test', null, options); + } catch (e) { + // Do nothing + } - return supported; + return supported; })(); // Toggle event listener export function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) { - // Bail if no element, event, or callback - if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { - return; - } + // Bail if no element, event, or callback + if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) { + return; + } + + // Allow multiple events + const events = event.split(' '); + // Build options + // Default to just the capture boolean for browsers with no passive listener support + let options = capture; + + // If passive events listeners are supported + if (supportsPassiveListeners) { + options = { + // Whether the listener can be passive (i.e. default never prevented) + passive, + // Whether the listener is a capturing listener or not + capture, + }; + } - // Allow multiple events - const events = event.split(' '); - // Build options - // Default to just the capture boolean for browsers with no passive listener support - let options = capture; - - // If passive events listeners are supported - if (supportsPassiveListeners) { - options = { - // Whether the listener can be passive (i.e. default never prevented) - passive, - // Whether the listener is a capturing listener or not - capture, - }; + // If a single node is passed, bind the event listener + events.forEach(type => { + if (this && this.eventListeners && toggle) { + // Cache event listener + this.eventListeners.push({ element, type, callback, options }); } - // If a single node is passed, bind the event listener - events.forEach(type => { - if (this && this.eventListeners && toggle) { - // Cache event listener - this.eventListeners.push({ element, type, callback, options }); - } - - element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); - }); + element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options); + }); } // Bind event handler export function on(element, events = '', callback, passive = true, capture = false) { - toggleListener.call(this, element, events, callback, true, passive, capture); + toggleListener.call(this, element, events, callback, true, passive, capture); } // Unbind event handler export function off(element, events = '', callback, passive = true, capture = false) { - toggleListener.call(this, element, events, callback, false, passive, capture); + toggleListener.call(this, element, events, callback, false, passive, capture); } // Bind once-only event handler export function once(element, events = '', callback, passive = true, capture = false) { - const onceCallback = (...args) => { - off(element, events, onceCallback, passive, capture); - callback.apply(this, args); - }; + const onceCallback = (...args) => { + off(element, events, onceCallback, passive, capture); + callback.apply(this, args); + }; - toggleListener.call(this, element, events, onceCallback, true, passive, capture); + toggleListener.call(this, element, events, onceCallback, true, passive, capture); } // Trigger event export function triggerEvent(element, type = '', bubbles = false, detail = {}) { - // Bail if no element - if (!is.element(element) || is.empty(type)) { - return; - } - - // Create and dispatch the event - const event = new CustomEvent(type, { - bubbles, - detail: { ...detail, plyr: this }, - }); - - // Dispatch the event - element.dispatchEvent(event); + // Bail if no element + if (!is.element(element) || is.empty(type)) { + return; + } + + // Create and dispatch the event + const event = new CustomEvent(type, { + bubbles, + detail: { ...detail, plyr: this }, + }); + + // Dispatch the event + element.dispatchEvent(event); } // Unbind all cached event listeners export function unbindListeners() { - if (this && this.eventListeners) { - this.eventListeners.forEach(item => { - const { element, type, callback, options } = item; - element.removeEventListener(type, callback, options); - }); + if (this && this.eventListeners) { + this.eventListeners.forEach(item => { + const { element, type, callback, options } = item; + element.removeEventListener(type, callback, options); + }); - this.eventListeners = []; - } + this.eventListeners = []; + } } // Run method when / if player is ready export function ready() { - return new Promise(resolve => - this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve), - ).then(() => {}); + return new Promise(resolve => + this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve), + ).then(() => {}); } diff --git a/src/js/utils/fetch.js b/src/js/utils/fetch.js index ee33ea7c..ef695193 100644 --- a/src/js/utils/fetch.js +++ b/src/js/utils/fetch.js @@ -4,39 +4,39 @@ // ========================================================================== export default function fetch(url, responseType = 'text') { - return new Promise((resolve, reject) => { - try { - const request = new XMLHttpRequest(); + return new Promise((resolve, reject) => { + try { + const request = new XMLHttpRequest(); - // Check for CORS support - if (!('withCredentials' in request)) { - return; - } + // Check for CORS support + if (!('withCredentials' in request)) { + return; + } - request.addEventListener('load', () => { - if (responseType === 'text') { - try { - resolve(JSON.parse(request.responseText)); - } catch (e) { - resolve(request.responseText); - } - } else { - resolve(request.response); - } - }); + request.addEventListener('load', () => { + if (responseType === 'text') { + try { + resolve(JSON.parse(request.responseText)); + } catch (e) { + resolve(request.responseText); + } + } else { + resolve(request.response); + } + }); - request.addEventListener('error', () => { - throw new Error(request.status); - }); + request.addEventListener('error', () => { + throw new Error(request.status); + }); - request.open('GET', url, true); + request.open('GET', url, true); - // Set the required response type - request.responseType = responseType; + // Set the required response type + request.responseType = responseType; - request.send(); - } catch (e) { - reject(e); - } - }); + request.send(); + } catch (e) { + reject(e); + } + }); } diff --git a/src/js/utils/i18n.js b/src/js/utils/i18n.js index 5eee5829..70868527 100644 --- a/src/js/utils/i18n.js +++ b/src/js/utils/i18n.js @@ -8,40 +8,40 @@ import { replaceAll } from './strings'; // Skip i18n for abbreviations and brand names const resources = { - pip: 'PIP', - airplay: 'AirPlay', - html5: 'HTML5', - vimeo: 'Vimeo', - youtube: 'YouTube', + pip: 'PIP', + airplay: 'AirPlay', + html5: 'HTML5', + vimeo: 'Vimeo', + youtube: 'YouTube', }; const i18n = { - get(key = '', config = {}) { - if (is.empty(key) || is.empty(config)) { - return ''; - } + get(key = '', config = {}) { + if (is.empty(key) || is.empty(config)) { + return ''; + } - let string = getDeep(config.i18n, key); + let string = getDeep(config.i18n, key); - if (is.empty(string)) { - if (Object.keys(resources).includes(key)) { - return resources[key]; - } + if (is.empty(string)) { + if (Object.keys(resources).includes(key)) { + return resources[key]; + } - return ''; - } + return ''; + } - const replace = { - '{seektime}': config.seekTime, - '{title}': config.title, - }; + const replace = { + '{seektime}': config.seekTime, + '{title}': config.title, + }; - Object.entries(replace).forEach(([k, v]) => { - string = replaceAll(string, k, v); - }); + Object.entries(replace).forEach(([k, v]) => { + string = replaceAll(string, k, v); + }); - return string; - }, + return string; + }, }; export default i18n; diff --git a/src/js/utils/is.js b/src/js/utils/is.js index 24f176cc..1cc33848 100644 --- a/src/js/utils/is.js +++ b/src/js/utils/is.js @@ -22,51 +22,51 @@ const isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(inp const isPromise = input => instanceOf(input, Promise) && isFunction(input.then); const isEmpty = input => - isNullOrUndefined(input) || - ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) || - (isObject(input) && !Object.keys(input).length); + isNullOrUndefined(input) || + ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) || + (isObject(input) && !Object.keys(input).length); const isUrl = input => { - // Accept a URL object - if (instanceOf(input, window.URL)) { - return true; - } + // Accept a URL object + if (instanceOf(input, window.URL)) { + return true; + } - // Must be string from here - if (!isString(input)) { - return false; - } + // Must be string from here + if (!isString(input)) { + return false; + } - // Add the protocol if required - let string = input; - if (!input.startsWith('http://') || !input.startsWith('https://')) { - string = `http://${input}`; - } + // Add the protocol if required + let string = input; + if (!input.startsWith('http://') || !input.startsWith('https://')) { + string = `http://${input}`; + } - try { - return !isEmpty(new URL(string).hostname); - } catch (e) { - return false; - } + try { + return !isEmpty(new URL(string).hostname); + } catch (e) { + return false; + } }; export default { - nullOrUndefined: isNullOrUndefined, - object: isObject, - number: isNumber, - string: isString, - boolean: isBoolean, - function: isFunction, - array: isArray, - weakMap: isWeakMap, - nodeList: isNodeList, - element: isElement, - textNode: isTextNode, - event: isEvent, - keyboardEvent: isKeyboardEvent, - cue: isCue, - track: isTrack, - promise: isPromise, - url: isUrl, - empty: isEmpty, + nullOrUndefined: isNullOrUndefined, + object: isObject, + number: isNumber, + string: isString, + boolean: isBoolean, + function: isFunction, + array: isArray, + weakMap: isWeakMap, + nodeList: isNodeList, + element: isElement, + textNode: isTextNode, + event: isEvent, + keyboardEvent: isKeyboardEvent, + cue: isCue, + track: isTrack, + promise: isPromise, + url: isUrl, + empty: isEmpty, }; diff --git a/src/js/utils/load-image.js b/src/js/utils/load-image.js index 8acd2496..36d6ab81 100644 --- a/src/js/utils/load-image.js +++ b/src/js/utils/load-image.js @@ -5,15 +5,15 @@ // ========================================================================== export default function loadImage(src, minWidth = 1) { - return new Promise((resolve, reject) => { - const image = new Image(); + return new Promise((resolve, reject) => { + const image = new Image(); - const handler = () => { - delete image.onload; - delete image.onerror; - (image.naturalWidth >= minWidth ? resolve : reject)(image); - }; + const handler = () => { + delete image.onload; + delete image.onerror; + (image.naturalWidth >= minWidth ? resolve : reject)(image); + }; - Object.assign(image, { onload: handler, onerror: handler, src }); - }); + Object.assign(image, { onload: handler, onerror: handler, src }); + }); } diff --git a/src/js/utils/load-script.js b/src/js/utils/load-script.js index 81ae36f4..53b660c8 100644 --- a/src/js/utils/load-script.js +++ b/src/js/utils/load-script.js @@ -5,10 +5,10 @@ import loadjs from 'loadjs'; export default function loadScript(url) { - return new Promise((resolve, reject) => { - loadjs(url, { - success: resolve, - error: reject, - }); + 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 index fe4add00..0a4eff99 100644 --- a/src/js/utils/load-sprite.js +++ b/src/js/utils/load-sprite.js @@ -8,68 +8,68 @@ import is from './is'; // Load an external SVG sprite export default function loadSprite(url, id) { - if (!is.string(url)) { - return; + 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; } - const prefix = 'cache'; - const hasId = is.string(id); - let isCached = false; - const exists = () => document.getElementById(id) !== null; + // Inject the SVG to the body + document.body.insertAdjacentElement('afterbegin', container); + }; - const update = (container, data) => { - // eslint-disable-next-line no-param-reassign - container.innerHTML = data; + // Only load once if ID set + if (!hasId || !exists()) { + const useStorage = Storage.supported; + // Create container + const container = document.createElement('div'); + container.setAttribute('hidden', ''); - // Check again incase of race condition - if (hasId && exists()) { - return; - } + if (hasId) { + container.setAttribute('id', id); + } - // Inject the SVG to the body - document.body.insertAdjacentElement('afterbegin', container); - }; + // Check in cache + if (useStorage) { + const cached = window.localStorage.getItem(`${prefix}-${id}`); + isCached = cached !== null; - // Only load once if ID set - if (!hasId || !exists()) { - const useStorage = Storage.supported; - // Create container - const container = document.createElement('div'); - container.setAttribute('hidden', ''); + if (isCached) { + const data = JSON.parse(cached); + update(container, data.content); + } + } - if (hasId) { - container.setAttribute('id', id); + // Get the sprite + fetch(url) + .then(result => { + if (is.empty(result)) { + return; } - // 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); - } + window.localStorage.setItem( + `${prefix}-${id}`, + JSON.stringify({ + content: result, + }), + ); } - // 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(() => {}); - } + update(container, result); + }) + .catch(() => {}); + } } diff --git a/src/js/utils/numbers.js b/src/js/utils/numbers.js index f6eb65c8..87bbe7e2 100644 --- a/src/js/utils/numbers.js +++ b/src/js/utils/numbers.js @@ -11,7 +11,7 @@ * @type Number */ export function clamp(input = 0, min = 0, max = 255) { - return Math.min(Math.max(input, min), max); + return Math.min(Math.max(input, min), max); } export default { clamp }; diff --git a/src/js/utils/objects.js b/src/js/utils/objects.js index 225bb459..a327e488 100644 --- a/src/js/utils/objects.js +++ b/src/js/utils/objects.js @@ -6,37 +6,37 @@ import is from './is'; // Clone nested objects export function cloneDeep(object) { - return JSON.parse(JSON.stringify(object)); + return JSON.parse(JSON.stringify(object)); } // Get a nested value in an object export function getDeep(object, path) { - return path.split('.').reduce((obj, key) => obj && obj[key], object); + return path.split('.').reduce((obj, key) => obj && obj[key], object); } // Deep extend destination object with N more objects export function extend(target = {}, ...sources) { - if (!sources.length) { - return target; - } + if (!sources.length) { + return target; + } - const source = sources.shift(); + const source = sources.shift(); - if (!is.object(source)) { - return target; - } + if (!is.object(source)) { + return target; + } - Object.keys(source).forEach(key => { - if (is.object(source[key])) { - if (!Object.keys(target).includes(key)) { - Object.assign(target, { [key]: {} }); - } + Object.keys(source).forEach(key => { + if (is.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, { [key]: {} }); + } - extend(target[key], source[key]); - } else { - Object.assign(target, { [key]: source[key] }); - } - }); + extend(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); + } + }); - return extend(target, ...sources); + return extend(target, ...sources); } diff --git a/src/js/utils/promise.js b/src/js/utils/promise.js index f45b46ab..4b59bba3 100644 --- a/src/js/utils/promise.js +++ b/src/js/utils/promise.js @@ -6,9 +6,9 @@ import is from './is'; * @param {Object} value An object that may or may not be `Promise`-like. */ export function silencePromise(value) { - if (is.promise(value)) { - value.then(null, () => {}); - } + if (is.promise(value)) { + value.then(null, () => {}); + } } export default { silencePromise }; diff --git a/src/js/utils/strings.js b/src/js/utils/strings.js index 6b9a65a2..b7de04c1 100644 --- a/src/js/utils/strings.js +++ b/src/js/utils/strings.js @@ -6,80 +6,75 @@ import is from './is'; // Generate a random ID export function generateId(prefix) { - return `${prefix}-${Math.floor(Math.random() * 10000)}`; + return `${prefix}-${Math.floor(Math.random() * 10000)}`; } // Format string export function format(input, ...args) { - if (is.empty(input)) { - return input; - } + if (is.empty(input)) { + return input; + } - return input.toString().replace(/{(\d+)}/g, (match, i) => args[i].toString()); + return input.toString().replace(/{(\d+)}/g, (match, i) => args[i].toString()); } // Get percentage export function getPercentage(current, max) { - if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { - return 0; - } + if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) { + return 0; + } - return ((current / max) * 100).toFixed(2); + return ((current / max) * 100).toFixed(2); } // Replace all occurances of a string in a string -export function replaceAll(input = '', find = '', replace = '') { - return input.replace( - new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), - replace.toString(), - ); -} +export const replaceAll = (input = '', find = '', replace = '') => + input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); // Convert to title case -export function toTitleCase(input = '') { - return input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); -} +export const toTitleCase = (input = '') => + input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); // Convert string to pascalCase export function toPascalCase(input = '') { - let string = input.toString(); + let string = input.toString(); - // Convert kebab case - string = replaceAll(string, '-', ' '); + // Convert kebab case + string = replaceAll(string, '-', ' '); - // Convert snake case - string = replaceAll(string, '_', ' '); + // Convert snake case + string = replaceAll(string, '_', ' '); - // Convert to title case - string = toTitleCase(string); + // Convert to title case + string = toTitleCase(string); - // Convert to pascal case - return replaceAll(string, ' ', ''); + // Convert to pascal case + return replaceAll(string, ' ', ''); } // Convert string to pascalCase export function toCamelCase(input = '') { - let string = input.toString(); + let string = input.toString(); - // Convert to pascal case - string = toPascalCase(string); + // Convert to pascal case + string = toPascalCase(string); - // Convert first character to lowercase - return string.charAt(0).toLowerCase() + string.slice(1); + // Convert first character to lowercase + return string.charAt(0).toLowerCase() + string.slice(1); } // Remove HTML from a string export function stripHTML(source) { - const fragment = document.createDocumentFragment(); - const element = document.createElement('div'); - fragment.appendChild(element); - element.innerHTML = source; - return fragment.firstChild.innerText; + const fragment = document.createDocumentFragment(); + const element = document.createElement('div'); + fragment.appendChild(element); + element.innerHTML = source; + return fragment.firstChild.innerText; } // Like outerHTML, but also works for DocumentFragment export function getHTML(element) { - const wrapper = document.createElement('div'); - wrapper.appendChild(element); - return wrapper.innerHTML; + const wrapper = document.createElement('div'); + wrapper.appendChild(element); + return wrapper.innerHTML; } diff --git a/src/js/utils/style.js b/src/js/utils/style.js index 17a033fe..0a37e595 100644 --- a/src/js/utils/style.js +++ b/src/js/utils/style.js @@ -5,74 +5,74 @@ import is from './is'; export function validateRatio(input) { - if (!is.array(input) && (!is.string(input) || !input.includes(':'))) { - return false; - } + if (!is.array(input) && (!is.string(input) || !input.includes(':'))) { + return false; + } - const ratio = is.array(input) ? input : input.split(':'); + const ratio = is.array(input) ? input : input.split(':'); - return ratio.map(Number).every(is.number); + return ratio.map(Number).every(is.number); } export function reduceAspectRatio(ratio) { - if (!is.array(ratio) || !ratio.every(is.number)) { - return null; - } + if (!is.array(ratio) || !ratio.every(is.number)) { + return null; + } - const [width, height] = ratio; - const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h)); - const divider = getDivider(width, height); + const [width, height] = ratio; + const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h)); + const divider = getDivider(width, height); - return [width / divider, height / divider]; + return [width / divider, height / divider]; } export function getAspectRatio(input) { - const parse = ratio => (validateRatio(ratio) ? ratio.split(':').map(Number) : null); - // Try provided ratio - let ratio = parse(input); - - // Get from config - if (ratio === null) { - ratio = parse(this.config.ratio); - } - - // Get from embed - if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) { - ({ ratio } = this.embed); - } - - // Get from HTML5 video - if (ratio === null && this.isHTML5) { - const { videoWidth, videoHeight } = this.media; - ratio = reduceAspectRatio([videoWidth, videoHeight]); - } - - return ratio; + const parse = ratio => (validateRatio(ratio) ? ratio.split(':').map(Number) : null); + // Try provided ratio + let ratio = parse(input); + + // Get from config + if (ratio === null) { + ratio = parse(this.config.ratio); + } + + // Get from embed + if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) { + ({ ratio } = this.embed); + } + + // Get from HTML5 video + if (ratio === null && this.isHTML5) { + const { videoWidth, videoHeight } = this.media; + ratio = reduceAspectRatio([videoWidth, videoHeight]); + } + + return ratio; } // Set aspect ratio for responsive container export function setAspectRatio(input) { - if (!this.isVideo) { - 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; - - wrapper.style.paddingBottom = `${padding}%`; - - // For Vimeo we have an extra <div> to hide the standard controls and UI - if (this.isVimeo && this.supported.ui) { - const height = 240; - const offset = (height - padding) / (height / 50); - this.media.style.transform = `translateY(-${offset}%)`; - } else if (this.isHTML5) { - wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); - } - - return { padding, ratio }; + if (!this.isVideo) { + 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; + + wrapper.style.paddingBottom = `${padding}%`; + + // For Vimeo we have an extra <div> to hide the standard controls and UI + if (this.isVimeo && this.supported.ui) { + const height = 240; + const offset = (height - padding) / (height / 50); + this.media.style.transform = `translateY(-${offset}%)`; + } else if (this.isHTML5) { + wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); + } + + return { padding, ratio }; } export default { setAspectRatio }; diff --git a/src/js/utils/time.js b/src/js/utils/time.js index 17228de5..31660c4a 100644 --- a/src/js/utils/time.js +++ b/src/js/utils/time.js @@ -11,25 +11,25 @@ export const getSeconds = value => Math.trunc(value % 60, 10); // Format time to UI friendly string export function formatTime(time = 0, displayHours = false, inverted = false) { - // Bail if the value isn't a number - if (!is.number(time)) { - return formatTime(undefined, displayHours, inverted); - } + // Bail if the value isn't a number + if (!is.number(time)) { + return formatTime(undefined, displayHours, inverted); + } - // Format time component to add leading zero - const format = value => `0${value}`.slice(-2); - // Breakdown to hours, mins, secs - let hours = getHours(time); - const mins = getMinutes(time); - const secs = getSeconds(time); + // Format time component to add leading zero + const format = value => `0${value}`.slice(-2); + // Breakdown to hours, mins, secs + let hours = getHours(time); + const mins = getMinutes(time); + const secs = getSeconds(time); - // Do we need to display hours? - if (displayHours || hours > 0) { - hours = `${hours}:`; - } else { - hours = ''; - } + // Do we need to display hours? + if (displayHours || hours > 0) { + hours = `${hours}:`; + } else { + hours = ''; + } - // Render - return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`; + // Render + return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`; } diff --git a/src/js/utils/urls.js b/src/js/utils/urls.js index 843c6aa6..ba264511 100644 --- a/src/js/utils/urls.js +++ b/src/js/utils/urls.js @@ -10,30 +10,30 @@ import is from './is'; * @param {Boolean} safe - failsafe parsing */ export function parseUrl(input, safe = true) { - let url = input; + let url = input; - if (safe) { - const parser = document.createElement('a'); - parser.href = url; - url = parser.href; - } + if (safe) { + const parser = document.createElement('a'); + parser.href = url; + url = parser.href; + } - try { - return new URL(url); - } catch (e) { - return null; - } + try { + return new URL(url); + } catch (e) { + return null; + } } // Convert object to URLSearchParams export function buildUrlParams(input) { - const params = new URLSearchParams(); + const params = new URLSearchParams(); - if (is.object(input)) { - Object.entries(input).forEach(([key, value]) => { - params.set(key, value); - }); - } + if (is.object(input)) { + Object.entries(input).forEach(([key, value]) => { + params.set(key, value); + }); + } - return params; + return params; } |