diff options
Diffstat (limited to 'src/js/utils')
-rw-r--r-- | src/js/utils/elements.js | 22 | ||||
-rw-r--r-- | src/js/utils/events.js | 1 | ||||
-rw-r--r-- | src/js/utils/i18n.js | 4 | ||||
-rw-r--r-- | src/js/utils/loadSprite.js | 3 | ||||
-rw-r--r-- | src/js/utils/numbers.js | 17 | ||||
-rw-r--r-- | src/js/utils/style.js | 70 | ||||
-rw-r--r-- | src/js/utils/time.js | 1 |
7 files changed, 87 insertions, 31 deletions
diff --git a/src/js/utils/elements.js b/src/js/utils/elements.js index 6be634e5..98b44f13 100644 --- a/src/js/utils/elements.js +++ b/src/js/utils/elements.js @@ -4,6 +4,7 @@ import { toggleListener } from './events'; import is from './is'; +import { extend } from './objects'; // Wrap an element export function wrap(elements, wrapper) { @@ -16,7 +17,6 @@ export function wrap(elements, wrapper) { .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; @@ -137,30 +137,28 @@ export function getAttributesFromSelector(sel, existingAttributes) { } const attributes = {}; - const existing = existingAttributes; + 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[0]; + 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.object(existing) && is.string(existing.class)) { - existing.class += ` ${className}`; + if (is.string(existing.class)) { + attributes.class = `${existing.class} ${className}`; + } else { + attributes.class = className; } - - attributes.class = className; break; case '#': @@ -179,7 +177,7 @@ export function getAttributesFromSelector(sel, existingAttributes) { } }); - return attributes; + return extend(existing, attributes); } // Toggle hidden @@ -233,14 +231,14 @@ export function matches(element, selector) { return Array.from(document.querySelectorAll(selector)).includes(this); } - const matches = + const method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match; - return matches.call(element, selector); + return method.call(element, selector); } // Find all elements diff --git a/src/js/utils/events.js b/src/js/utils/events.js index d304c312..87c35d26 100644 --- a/src/js/utils/events.js +++ b/src/js/utils/events.js @@ -35,7 +35,6 @@ export function toggleListener(element, event, callback, toggle = false, passive // 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; diff --git a/src/js/utils/i18n.js b/src/js/utils/i18n.js index 758ed695..5eee5829 100644 --- a/src/js/utils/i18n.js +++ b/src/js/utils/i18n.js @@ -36,8 +36,8 @@ const i18n = { '{title}': config.title, }; - Object.entries(replace).forEach(([key, value]) => { - string = replaceAll(string, key, value); + Object.entries(replace).forEach(([k, v]) => { + string = replaceAll(string, k, v); }); return string; diff --git a/src/js/utils/loadSprite.js b/src/js/utils/loadSprite.js index 917bd6ac..fe4add00 100644 --- a/src/js/utils/loadSprite.js +++ b/src/js/utils/loadSprite.js @@ -15,10 +15,10 @@ export default function loadSprite(url, id) { 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 @@ -33,7 +33,6 @@ export default function loadSprite(url, id) { // Only load once if ID set if (!hasId || !exists()) { const useStorage = Storage.supported; - // Create container const container = document.createElement('div'); container.setAttribute('hidden', ''); diff --git a/src/js/utils/numbers.js b/src/js/utils/numbers.js new file mode 100644 index 00000000..f6eb65c8 --- /dev/null +++ b/src/js/utils/numbers.js @@ -0,0 +1,17 @@ +/** + * Returns a number whose value is limited to the given range. + * + * Example: limit the output of this computation to between 0 and 255 + * (x * 255).clamp(0, 255) + * + * @param {Number} input + * @param {Number} min The lower boundary of the output range + * @param {Number} max The upper boundary of the output range + * @returns A number in the range [min, max] + * @type Number + */ +export function clamp(input = 0, min = 0, max = 255) { + return Math.min(Math.max(input, min), max); +} + +export default { clamp }; diff --git a/src/js/utils/style.js b/src/js/utils/style.js index a8eb393b..6f3069c9 100644 --- a/src/js/utils/style.js +++ b/src/js/utils/style.js @@ -4,26 +4,68 @@ import is from './is'; -/* function reduceAspectRatio(width, height) { - const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h)); - const ratio = getRatio(width, height); - return `${width / ratio}:${height / ratio}`; -} */ +export function validateRatio(input) { + if (!is.array(input) && (!is.string(input) || !input.includes(':'))) { + return false; + } -// Set aspect ratio for responsive container -export function setAspectRatio(input) { - let ratio = input; + const ratio = is.array(input) ? input : input.split(':'); + + return ratio.map(Number).every(is.number); +} + +export function reduceAspectRatio(ratio) { + 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); + + return [width / divider, height / divider]; +} + +export function getAspectRatio(input) { + const parse = ratio => { + if (!validateRatio(ratio)) { + return null; + } - if (!is.string(ratio) && !is.nullOrUndefined(this.embed)) { + return ratio.split(':').map(Number); + }; + + // 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); } - if (!is.string(ratio)) { - ({ ratio } = this.config); + // 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 [x, y] = ratio.split(':').map(Number); - const padding = (100 / x) * y; + 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}%`; @@ -32,6 +74,8 @@ export function setAspectRatio(input) { const height = 240; 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); } return { padding, ratio }; diff --git a/src/js/utils/time.js b/src/js/utils/time.js index 2deccf65..ffca88b2 100644 --- a/src/js/utils/time.js +++ b/src/js/utils/time.js @@ -18,7 +18,6 @@ export function formatTime(time = 0, displayHours = false, inverted = false) { // 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); |