aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/utils')
-rw-r--r--src/js/utils/elements.js22
-rw-r--r--src/js/utils/events.js1
-rw-r--r--src/js/utils/i18n.js4
-rw-r--r--src/js/utils/loadSprite.js3
-rw-r--r--src/js/utils/numbers.js17
-rw-r--r--src/js/utils/style.js70
-rw-r--r--src/js/utils/time.js1
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);