diff --git a/jquery.youtube-background.js b/jquery.youtube-background.js
index 0aaaf94..abfa42b 100644
--- a/jquery.youtube-background.js
+++ b/jquery.youtube-background.js
@@ -240,7 +240,8 @@
"volume": 1,
"no-cookie": true,
"force-on-low-battery": false,
- "lazyloading": false
+ "lazyloading": false,
+ "title": "Video background"
};
this.params = this.parseProperties(params, DEFAULTS, this.element, ["data-ytbg-", "data-vbg-"]);
if (this.params.pause) {
@@ -546,6 +547,8 @@
}
generatePlayerElement() {
const playerElement = document.createElement("iframe");
+ if (this.params.title)
+ playerElement.setAttribute("title", this.params.title);
playerElement.setAttribute("frameborder", 0);
playerElement.setAttribute("allow", "autoplay; mute");
if (this.params["lazyloading"])
@@ -728,9 +731,10 @@
// src/lib/vimeo-background.js
var VimeoBackground = class extends SuperVideoBackground {
constructor(elem, params, id, uid, factoryInstance) {
- super(elem, params, id, uid, "vimeo", factoryInstance);
+ super(elem, params, id.id, uid, "vimeo", factoryInstance);
if (!id)
return;
+ this.unlisted = id.unlisted;
if (this.is_mobile && !this.params.mobile)
return;
this.injectScript();
@@ -768,14 +772,17 @@
}
generatePlayerElement() {
const playerElement = document.createElement("iframe");
+ if (this.params.title)
+ playerElement.setAttribute("title", this.params.title);
playerElement.setAttribute("frameborder", 0);
playerElement.setAttribute("allow", "autoplay; mute");
if (this.params["lazyloading"])
playerElement.setAttribute("loading", "lazy");
return playerElement;
}
- generateSrcURL(id) {
- let src = "https://player.vimeo.com/video/" + id + "?background=1&controls=0";
+ generateSrcURL(id, unlisted) {
+ unlisted = unlisted ? `h=${unlisted}&` : "";
+ let src = `https://player.vimeo.com/video/${id}?${unlisted}background=1&controls=0`;
if (this.params.muted) {
src += "&muted=1";
}
@@ -795,7 +802,7 @@
}
injectPlayer() {
this.playerElement = this.generatePlayerElement();
- this.src = this.generateSrcURL(this.id);
+ this.src = this.generateSrcURL(this.id, this.unlisted);
this.playerElement.src = this.src;
this.playerElement.id = this.uid;
this.stylePlayerElement(this.playerElement);
@@ -969,6 +976,8 @@
}
generatePlayerElement() {
const playerElement = document.createElement("video");
+ if (this.params.title)
+ playerElement.setAttribute("title", this.params.title);
playerElement.setAttribute("playsinline", "");
if (this.params.loop)
playerElement.setAttribute("loop", "");
@@ -1232,7 +1241,7 @@
this.index[uid] = yb;
break;
case "VIMEO":
- const vm = new VimeoBackground(element, params, vid_data.id, uid, this);
+ const vm = new VimeoBackground(element, params, vid_data, uid, this);
this.index[uid] = vm;
break;
case "VIDEO":
@@ -1274,12 +1283,20 @@
const pts = link.match(this.re[k]);
if (pts && pts.length) {
this.re[k].lastIndex = 0;
- return {
+ const data = {
id: pts[1],
type: k,
regex_pts: pts,
link
};
+ if (k === "VIMEO") {
+ const unlistedQueryRegex = /(\?|&)h=([^=?]+)/;
+ const unlistedPathRegex = /\/[^\/\:\.]+(\:|\/)([^:?\/]+)\s?$/;
+ const unlistedQuery = link.match(unlistedPathRegex) || link.match(unlistedQueryRegex);
+ if (unlistedQuery)
+ data.unlisted = unlistedQuery[2];
+ }
+ return data;
}
}
return;
diff --git a/jquery.youtube-background.js.map b/jquery.youtube-background.js.map
index 03facc6..5781e9c 100644
--- a/jquery.youtube-background.js.map
+++ b/jquery.youtube-background.js.map
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["src/lib/buttons.js", "node_modules/book-of-spells/src/helpers.mjs", "node_modules/book-of-spells/src/regex.mjs", "node_modules/book-of-spells/src/parsers.mjs", "node_modules/book-of-spells/src/dom.mjs", "node_modules/book-of-spells/src/browser.mjs", "src/lib/super-video-background.js", "src/lib/youtube-background.js", "src/lib/vimeo-background.js", "src/lib/video-background.js", "src/video-backgrounds.js", "src/main.js"],
- "sourcesContent": ["\nfunction buttonOn(buttonObj) {\n if (!buttonObj) return;\n buttonObj.element.classList.add(buttonObj.stateClassName);\n buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[0]);\n buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[1]);\n buttonObj.element.setAttribute('aria-checked', false);\n}\n\nfunction buttonOff(buttonObj) {\n if (!buttonObj) return;\n buttonObj.element.classList.remove(buttonObj.stateClassName);\n buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[0]);\n buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[1]);\n buttonObj.element.setAttribute('aria-checked', true);\n}\n\nexport function generateActionButton(obj, props) {\n const btn = document.createElement('button');\n btn.className = props.className;\n btn.innerHTML = props.innerHtml;\n btn.setAttribute('role', 'switch');\n btn.firstChild.classList.add(props.stateChildClassNames[0]);\n btn.setAttribute('aria-checked', !props.initialState);\n props.element = btn;\n\n if (obj.params[props.condition_parameter] === props.initialState) {\n buttonOn(props);\n }\n\n btn.addEventListener('click', function(e) {\n if (this.classList.contains(props.stateClassName)) {\n buttonOff(props);\n obj[props.actions[0]]();\n } else {\n buttonOn(props);\n obj[props.actions[1]]();\n }\n });\n\n obj.buttons[props.name] = {\n element: btn,\n button_properties: props\n };\n\n obj.controls_element.appendChild(btn);\n};\n", "/**\n * Shallow merges two objects together. Used to pass simple options to functions.\n * \n * @param {object} target The target object to merge into\n * @param {object} source The source object to merge from\n * @returns object The merged object, in this case the target object with the source object's properties merged into it\n * @example\n * const target = { foo: 'bar' }\n * const source = { bar: 'baz' }\n * shallowMerge(target, source) // { foo: 'bar', bar: 'baz' }\n */\nexport function shallowMerge(target, source) {\n for (const key in source) {\n target[key] = source[key]\n }\n\n return target\n}\n\n/**\n * Deep merge function that's mindful of arrays and objects\n * \n * @param {object} target The target object to merge into\n * @param {object} source The source object to merge from\n * @returns object The merged object, in this case the target object with the source object's properties merged into it\n * @example\n * const target = { foo: 'bar' }\n * const source = { bar: 'baz' }\n * deepMerge(target, source) // { foo: 'bar', bar: 'baz' }\n */\nexport function deepMerge(target, source) {\n if (isObject(source) && isObject(target)) {\n for (const key in source) {\n target[key] = deepMerge(target[key], source[key])\n }\n } else if (isArray(source) && isArray(target)) {\n for (let i = 0; i < source.length; i++) {\n target[i] = deepMerge(target[i], source[i])\n }\n } else {\n target = source\n }\n return target\n}\n\n/**\n * Deep clone function that's mindful of nested arrays and objects\n * \n * @param {object} o The object to clone\n * @returns object The cloned object\n * @example\n * const obj = { foo: 'bar' }\n * const clone = clone(obj)\n * clone.foo = 'baz'\n * console.log(obj.foo) // 'bar'\n * console.log(clone.foo) // 'baz'\n * console.log(obj === clone) // false\n * console.log(JSON.stringify(obj) === JSON.stringify(clone)) // true\n * @todo Check if faster than assign. This function is pretty old...\n */ \nexport function clone(o) {\n let res = null\n if (isArray(o)) {\n res = []\n for (const i in o) {\n res[i] = clone(o[i])\n }\n } else if (isObject(o)) {\n res = {}\n for (const i in o) {\n res[i] = clone(o[i])\n }\n } else {\n res = o\n }\n return res\n}\n\n/**\n * Check if an object is empty\n * \n * @param {object} o The object to check\n * @returns boolean True if the object is empty, false otherwise\n * @example\n * isEmptyObject({}) // => true\n * isEmptyObject({ foo: 'bar' }) // => false\n */\nexport function isEmptyObject(o) {\n for (const i in o) {\n return false\n }\n return true\n}\n\n/**\n * Check if an array is empty, substitute for Array.length === 0\n * \n * @param {array} o The array to check\n * @returns boolean True if the array is empty, false otherwise\n * @example\n * isEmptyArray([]) // => true\n * isEmptyArray([1, 2, 3]) // => false\n */\nexport function isEmptyArray(o) {\n return o.length === 0\n}\n\n/**\n * Check if a variable is empty\n * \n * @param {any} o The variable to check\n * @returns boolean True if the variable is empty, false otherwise\n * @example\n * isEmpty({}) // => true\n * isEmpty([]) // => true\n * isEmpty('') // => true\n * isEmpty(null) // => false\n * isEmpty(undefined) // => false\n * isEmpty(0) // => false\n */\nexport function isEmpty(o) {\n if (isObject(o)) {\n return isEmptyObject(o)\n } else if (isArray(o)) {\n return isEmptyArray(o)\n } else if (isString(o)) {\n return o === ''\n }\n return false\n}\n\n/**\n * Try to convert a string to a boolean\n * \n * @param {string} str The string to convert\n * @returns boolean The converted boolean or undefined if conversion failed\n * @example\n * stringToBoolean('true') // => true\n * stringToBoolean('false') // => false\n * stringToBoolean('foo') // => null\n */\nexport function stringToBoolean(str) {\n if (/^\\s*(true|false)\\s*$/i.test(str)) return str === 'true'\n}\n\n/**\n * Try to convert a string to a number\n * \n * @param {string} str The string to convert\n * @returns number The converted number or undefined if conversion failed\n * @example\n * stringToNumber('1') // => 1\n * stringToNumber('1.5') // => 1.5\n * stringToNumber('foo') // => null\n * stringToNumber('1foo') // => null\n */\nexport function stringToNumber(str) {\n if (/^\\s*\\d+\\s*$/.test(str)) return parseInt(str)\n if (/^\\s*[\\d.]+\\s*$/.test(str)) return parseFloat(str)\n}\n\n/**\n * Try to convert a string to an array\n * \n * @param {string} str The string to convert\n * @returns array The converted array or undefined if conversion failed\n * @example\n * stringToArray('[1, 2, 3]') // => [1, 2, 3]\n * stringToArray('foo') // => null\n * stringToArray('1') // => null\n * stringToArray('{\"foo\": \"bar\"}') // => null\n */\nexport function stringToArray(str) {\n if (!/^\\s*\\[.*\\]\\s*$/.test(str)) return\n try {\n return JSON.parse(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to an object\n * \n * @param {string} str The string to convert\n * @returns object The converted object or undefined if conversion failed\n * @example\n * stringToObject('{ \"foo\": \"bar\" }') // => { foo: 'bar' }\n * stringToObject('foo') // => null\n * stringToObject('1') // => null\n * stringToObject('[1, 2, 3]') // => null\n */\nexport function stringToObject(str) {\n if (!/^\\s*\\{.*\\}\\s*$/.test(str)) return\n try {\n return JSON.parse(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to a regex\n * \n * @param {string} str The string to convert\n * @returns regex The converted regex or undefined if conversion failed\n * @example\n * stringToRegex('/foo/i') // => /foo/i\n * stringToRegex('foo') // => null\n * stringToRegex('1') // => null\n */\nexport function stringToRegex(str) {\n if (!/^\\s*\\/.*\\/g?i?\\s*$/.test(str)) return\n try {\n return new RegExp(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to a primitive\n * \n * @param {string} str The string to convert\n * @returns {null|boolean|int|float|string} The converted primitive or input string if conversion failed\n * @example\n * stringToPrimitive('null') // => null\n * stringToPrimitive('true') // => true\n * stringToPrimitive('false') // => false\n * stringToPrimitive('1') // => 1\n * stringToPrimitive('1.5') // => 1.5\n * stringToPrimitive('foo') // => 'foo'\n * stringToPrimitive('1foo') // => '1foo'\n */\nexport function stringToPrimitive(str) {\n if (/^\\s*null\\s*$/.test(str)) return null\n const bool = stringToBoolean(str)\n if (bool !== undefined) return bool\n return stringToNumber(str) || str\n}\n\n/**\n * Try to convert a string to a data type\n * \n * @param {string} str The string to convert\n * @returns any The converted data type or input string if conversion failed\n * @example\n * stringToData('null') // => null\n * stringToData('true') // => true\n * stringToData('false') // => false\n * stringToData('1') // => 1\n * stringToData('1.5') // => 1.5\n * stringToData('foo') // => 'foo'\n * stringToData('1foo') // => '1foo'\n * stringToData('[1, 2, 3]') // => [1, 2, 3]\n * stringToData('{ \"foo\": \"bar\" }') // => { foo: 'bar' }\n * stringToData('/foo/i') // => /foo/i\n */\nexport function stringToType(str) {\n if (/^\\s*null\\s*$/.test(str)) return null\n const bool = stringToBoolean(str)\n if (bool !== undefined) return bool\n return stringToNumber(str) || stringToArray(str) || stringToObject(str) || stringToRegex(str) || str\n}\n\n/**\n * If provided variable is an object\n * \n * @param {any} o \n * @returns boolean\n * @example\n * isObject({}) // => true\n * isObject([]) // => false\n * isObject(null) // => false\n */\nexport function isObject(o) {\n return typeof o === 'object' && !Array.isArray(o) && o !== null\n}\n\n/**\n * If provided variable is an array. Just a wrapper for Array.isArray\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isArray([]) // => true\n * isArray({}) // => false\n */\nexport function isArray(o) {\n return Array.isArray(o)\n}\n\n/**\n * If provided variable is a string. Just a wrapper for typeof === 'string'\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isString('foo') // => true\n * isString({}) // => false\n */\nexport function isString(o) {\n return typeof o === 'string'\n}\n\n/**\n * If provided variable is a function, substitute for typeof === 'function'\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isFunction(function() {}) // => true\n * isFunction({}) // => false\n */\nexport function isFunction(o) {\n return typeof o === 'function'\n}\n\n/**\n * If object property is a function\n * \n * @param {object} obj\n * @param {string} propertyName\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: function() {} }\n * propertyIsFunction(obj, 'foo') // => false\n * propertyIsFunction(obj, 'baz') // => true\n */\nexport function propertyIsFunction(obj, propertyName) {\n return obj.hasOwnProperty(propertyName) && isFunction(obj[propertyName])\n}\n\n/**\n * If object property is a string\n * \n * @param {object} obj\n * @param {string} propertyName\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: function() {} }\n * propertyIsString(obj, 'foo') // => true\n * propertyIsString(obj, 'baz') // => false\n */\nexport function propertyIsString(obj, propertyName) {\n return obj.hasOwnProperty(propertyName) && isString(obj[propertyName])\n}\n\n/**\n * Transforms a dash separated string to camelCase\n *\n * @param {string} str\n * @returns boolean\n * @example\n * transformDashToCamelCase('foo-bar') // => 'fooBar'\n * transformDashToCamelCase('foo-bar-baz') // => 'fooBarBaz'\n * transformDashToCamelCase('foo') // => 'foo'\n * transformDashToCamelCase('fooBarBaz-qux') // => 'fooBarBazQux'\n */\nexport function transformDashToCamelCase(str) {\n return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase() });\n}\n\n/**\n * Transforms a camelCase string to dash separated string\n * \n * @param {string} str\n * @returns boolean\n * @example\n * transformCamelCaseToDash('fooBar') // => 'foo-bar'\n * transformCamelCaseToDash('fooBarBaz') // => 'foo-bar-baz'\n * transformCamelCaseToDash('foo') // => 'foo'\n * transformDashToCamelCase('fooBarBaz-qux') // => 'foo-bar-baz-qux'\n */\nexport function transformCamelCaseToDash(str) {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n}\n\n/**\n * Maps an array of objects by a property name\n * \n * @param {array} arr\n * @param {string} propertyName\n * @returns object\n * @example\n * const arr = [{ foo: 'bar' }, { foo: 'baz' }]\n * mapByProperty(arr, 'foo') // => { bar: { foo: 'bar' }, baz: { foo: 'baz' } }\n */\nexport function mapByProperty(arr, propertyName) {\n const res = {}\n for (let i = 0; i < arr.length; i++) {\n res[arr[i][propertyName]] = arr[i]\n }\n return res\n}\n\n/**\n * Maps an array of objects by a property name to another property name\n * \n * @param {array} arr\n * @param {string} keyPropertyName\n * @param {string} valuePropertyName\n * @returns object\n * @example\n * const arr = [{ foo: 'bar', baz: 'qux' }, { foo: 'quux', baz: 'corge' }]\n * mapPropertyToProperty(arr, 'foo', 'baz') // => { bar: 'qux', quux: 'corge' }\n */\nexport function mapPropertyToProperty(arr, keyPropertyName, valuePropertyName) {\n const res = {}\n for (let i = 0; i < arr.length; i++) {\n res[arr[i][keyPropertyName]] = arr[i][valuePropertyName]\n }\n return res\n}\n\n/**\n * Remove accents from a string\n * \n * @param {string} inputString\n * @returns string\n * @example\n * removeAccents('\u00E1\u00E9\u00ED\u00F3\u00FA') // => 'aeiou'\n * removeAccents('\u00C1\u00C9\u00CD\u00D3\u00DA') // => 'AEIOU'\n * removeAccents('se\u00F1or') // => 'senor'\n * removeAccents('\u0152') // => 'OE'\n */\nexport function removeAccents(inputString) {\n return inputString.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').replace(/\\\u0153/g, \"oe\").replace(/\\\u00E6/g, \"ae\").normalize('NFC')\n}\n\n/**\n * Strip HTML tags from a string\n * \n * @param {string} inputString\n * @returns string\n * @example\n * stripHTMLTags('
foo ') // => 'foo'\n * stripHTMLTags('
foo bar ') // => 'foo bar'\n */\nexport function stripHTMLTags(inputString) {\n return inputString.replace(/<[^>]*>/g, '')\n}\n\n/**\n * Slugify a string, e.g. 'Foo Bar' => 'foo-bar'. Similar to WordPress' sanitize_title(). Will remove accents and HTML tags.\n * \n * @param {string} str \n * @returns string\n * @example\n * slugify('Foo Bar') // => 'foo-bar'\n * slugify('Foo Bar
baz ') // => 'foo-bar-baz'\n */\nexport function slugify(str) {\n str = str.trim().toLowerCase()\n str = removeAccents(str)\n str = stripHTMLTags(str)\n return str.replace(/\\s+|\\.+|\\/+|\\\\+|\u2014+|\u2013+/g, '-').replace(/[^\\w0-9\\-]+/g, '').replace(/-{2,}/g, '-').replace(/^-|-$/g, '')\n}\n\n/**\n * Check if object has multiple properties\n * \n * @param {object} obj\n * @param {string|array} properties\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: 'qux' }\n * hasOwnProperties(obj, ['foo', 'baz']) // => true\n * hasOwnProperties(obj, ['foo', 'baz', 'qux']) // => false\n */\nexport function hasOwnProperties(obj, properties) {\n if(!isArray(properties)) properties = [properties]\n for (let i = 0; i < properties.length; i++) {\n if (!obj.hasOwnProperty(properties[i])) return false\n }\n return true\n}\n\n/**\n * Finds the closest number to the set goal in an array to a given number\n * \n * @param {number} goal Number to search for\n * @param {array} arr Array of numbers to search in\n * @returns number\n * @example\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9]) // => 9\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]) // => 9\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 9.5]) // => 9.5\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) // => 10\n */\nexport function closestNumber(goal, arr) {\n return arr.reduce(function(prev, curr) {\n return Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev\n })\n}\n\n/**\n * Truncate a string to a given number of words\n * \n * @param {string} str String to truncate\n * @param {number} numWords Number of words to truncate to\n * @param {string} ellipsis Ellipsis to append to the end of the string\n * @returns string\n * @example\n * truncateString('foo bar baz', 2) // => 'foo bar\u2026'\n * truncateString('foo bar baz', 2, '...') // => 'foo bar...'\n * truncateString('foo bar. baz', 2, '...') // => 'foo bar. ...'\n */\nexport function truncateString(str, numWords, ellipsis = '\u2026') {\n const words = str.trim().split(' ')\n if (words.length <= numWords) return str\n if (numWords <= 0) return ''\n if (/[.?!]$/.test(words[numWords - 1]) && ellipsis.trim() !== '') ellipsis = ` ${ellipsis}`\n return words.slice(0, numWords).join(' ') + ellipsis\n}\n\n/**\n * Generates a random integer between two values, inclusive of both\n * \n * @param {number} min Minimum value\n * @param {number} max Maximum value\n * @param {boolean} safe Defaults to false, if true will use a cryptographically secure random number generator\n * @returns number\n * @example\n * randomIntInclusive(1, 10) // => 1\n * randomIntInclusive(1, 10) // => 10\n * randomIntInclusive(1, 10) // => 5\n */\nexport function randomIntInclusive(min, max, safe = false) {\n min = Number(min)\n max = Number(max)\n if (isNaN(min) || isNaN(max)) throw new TypeError('Both min and max must be numbers')\n if (min > max) [min, max] = [max, min]\n if (min === max) return min\n min = Math.round(min)\n max = Math.round(max)\n const rand = safe ? random() : Math.random()\n return Math.floor(rand * (max - min + 1)) + min\n}\n\n/**\n * Gets fixed number of digits after the decimal point\n * \n * @param {number} number Number to fix\n * @param {number} digits Number of digits to fix to\n * @returns number\n * @example\n * fixed(1.234, 2) // => 1.23\n * fixed(1.235, 2) // => 1.24\n * fixed(1.234) // => 1\n * fixed(1.234, 0) // => 1\n * fixed(1.234, 5) // => 1.234\n * @note Gotta ask myself why I wrote this function in the first place... \uD83E\uDD14 It's just not useful in a lot of cases lol...\n */\nexport function fixed(number, digits) {\n if (!digits) return parseInt(number)\n return parseFloat(number.toFixed(digits))\n}\n\n/**\n * Calculates the percentage of a number in relation to another number\n * \n * @param {number} num Number to calculate percentage of\n * @param {number} total Total number\n * @returns number\n * @example\n * percentage(1, 10) // => 10\n * percentage(5, 10) // => 50\n * percentage(10, 10) // => 100\n * percentage(0, 10) // => 0\n * percentage(10, 2) // => 500\n */\nexport function percentage(num, total) {\n if (!num || !total || Number.isNaN(num) || Number.isNaN(total)) return 0\n return num / total * 100\n}\n\nexport function pickProperties(obj, props) {\n const res = {}\n if (!props) return res\n if (!isArray(props)) props = [props]\n for (let i = 0; i < props.length; i++) {\n if (obj.hasOwnProperty(props[i])) res[props[i]] = obj[props[i]]\n }\n return res\n}\n\nexport function rejectProperties(obj, props, clone = true) {\n if (clone) obj = { ...obj }\n if (!props) return obj\n if (!isArray(props)) props = [props]\n for (let i = 0; i < props.length; i++) {\n if (obj.hasOwnProperty(props[i])) delete obj[props[i]]\n }\n return obj\n}\n\nexport function pickArrayElements(arr, indexes) {\n if (!isArray(arr)) return\n if (!isArray(indexes)) indexes = [indexes]\n const res = []\n for (let i = 0; i < indexes.length; i++) {\n if (arr.hasOwnProperty(indexes[i])) res.push(arr[indexes[i]])\n }\n return res\n}\n\nexport function rejectArrayElements(arr, indexes, clone = true) {\n if (clone) arr = [...arr]\n if (!isArray(arr)) return\n if (!isArray(indexes)) indexes = [indexes]\n for (let i = indexes.length - 1; i >= 0; i--) {\n if (arr.hasOwnProperty(indexes[i])) arr.splice(indexes[i], 1)\n }\n return arr\n}\n\n/**\n * Pick properties from an object or elements from an array\n * \n * @param {array} obj Object or array to pick properties or elements from\n * @param {array | string | number} props Properties to remove, can be an array of strings or a single string or number\n * @returns object | array | undefined\n * @example\n * \n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }) // => {}\n * pick({}, []) // => {}\n * pick(null, 'foo') // => undefined\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, undefined) // => {}\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, 'foo') // => { foo: 'bar'}\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, ['foo', 'baz']) // => { foo: 'bar', baz: 'qux' }\n * \n * pick(['foo', 'bar', 'baz'], []) // => []\n * pick([], []) // => []\n * pick(null, 0) // => undefined\n * pick(['foo', 'bar', 'baz'], undefined) // => []\n * pick(['foo', 'bar', 'baz'], 0) // => ['foo']\n * pick(['foo', 'bar', 'baz'], [0, 2]) // => ['foo', 'baz']\n * pick(['foo', 'bar', 'baz'], [0, 2, 3]) // => ['foo', 'baz']\n */\nexport function pick(obj, props) {\n return isObject(obj) ? pickProperties(obj, props) : pickArrayElements(obj, props)\n}\n\n/**\n * Remove properties from an object or elements from an array\n * \n * @param {array} obj Object or array to remove properties or elements from\n * @param {array | string | number} props Properties to remove, can be an array of strings or a single string or number\n * @param {boolean} clone Defaults to true, will clone the object or array before removing properties or elements.\n * @returns object | array | undefined\n * @example\n * \n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }) // => {}\n * reject({}, []) // => {}\n * reject(null, 'foo') // => undefined\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, undefined) // => {}\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, 'foo') // => { bar: 'baz', baz: 'qux' }\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, ['foo', 'baz']) // => { bar: 'baz' }\n * \n * reject(['foo', 'bar', 'baz'], []) // => []\n * reject([], []) // => []\n * reject(null, 0) // => undefined\n * reject(['foo', 'bar', 'baz'], undefined) // => []\n * reject(['foo', 'bar', 'baz'], 0) // => ['bar', 'baz']\n * reject(['foo', 'bar', 'baz'], [0, 2]) // => ['bar']\n * reject(['foo', 'bar', 'baz'], [0, 2, 3]) // => ['bar']\n */\nexport function reject(obj, props, clone = true) {\n return isObject(obj) ? rejectProperties(obj, props, clone) : rejectArrayElements(obj, props, clone)\n}\n\n/**\n * Basic timestamp first UID generator that's good enough for most use cases but not for security purposes.\n * There's an extremely small chance of collision, so create a map object to check for collisions if you're worried about that.\n * \n * - `Date.now().toString(16)` is used for the timestamp, which is a base16 representation of the current timestamp in milliseconds.\n * - `random().toString(16).substring(2)` is used for the random number, which is a base16 representation of a random number between 0 and 1, with the first two characters removed.\n * \n * @param {boolean} safe Defaults to false, if true will use a cryptographically secure random number generator for the random number improving security but reducing performance. If crypto is not available, will use Math.random() instead.\n * @returns string\n * @example\n * basicUID() // => '18d4613e4d2-750bf066ac6158'\n */\nexport function basicUID(safe = false) {\n const rand = safe ? random() : Math.random()\n return Date.now().toString(16)+'-'+rand.toString(16).substring(2)\n}\n\nfunction cryptoUUIDFallback() {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n (c ^ Math.random() * 16 >> c / 4).toString(16)\n )\n}\n\n// Taken from https://stackoverflow.com/a/2117523/5437943\nfunction cryptoRandomUUIDFallback() {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)\n )\n}\n\n/**\n * Generates a UUID v4\n * - Uses crypto.randomUUID if available\n * - Uses crypto.getRandomValues if available\n * - Uses a fallback if neither is available, which is not safe because it uses Math.random() instead of a cryptographically secure random number generator\n * \n * I'm bad at crypto and bitwise operations, not my cup of tea, so I had to rely on StackOverflow for the fallback: https://stackoverflow.com/a/2117523/5437943\n * \n * @param {boolean} safe Defaults to true, if false will use a fallback that's not cryptographically secure but significantly faster\n * @returns string\n * @example\n * generateUUID() // UUID v4, example 09ed0fe4-8eb6-4c2a-a8d3-a862b7513294\n */\nexport function generateUUID(safe = true) {\n if (!crypto || !safe) return cryptoUUIDFallback()\n if (crypto.randomUUID) return crypto.randomUUID()\n if (crypto.getRandomValues) return cryptoRandomUUIDFallback();\n}\n\n/**\n * Generates a random number between 0 and 1, inclusive of 0 but not inclusive of 1.\n * \n * - Uses crypto.getRandomValues if available\n * - Uses Math.random() if crypto.getRandomValues is not available\n * \n * @returns number\n * @example\n * random() // => 0.123456789\n */\nexport function random() {\n if (!crypto) return Math.random()\n if (crypto.getRandomValues) return crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295 // 2^32 - 1 = 4294967295\n}\n", "/**\n * @module regex\n */\n\n/**\n * Regular expression for matching a YouTube video links and extracting their ID, works with both embed and watch URLs\n */\nexport const RE_YOUTUBE = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/ ]{11})/i\n\n/**\n * Regular expression for matching a Vimeo video links and extracting their ID, works with both embed and watch URLs, channels and groups\n */\nexport const RE_VIMEO = /(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^\\/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|video\\/|)(\\d+)(?:[a-zA-Z0-9_\\-]+)?/i\n\n/**\n * Regular expression for matching a video URLs\n */\nexport const RE_VIDEO = /\\/([^\\/]+\\.(?:mp4|ogg|ogv|ogm|webm|avi))\\s*$/i\n\n/**\n * Regular expression for matching a image URLs\n */\nexport const RE_IMAGE = /\\/([^\\/]+\\.(?:jpg|jpeg|png|gif|svg|webp))\\s*$/i\n\n/**\n * Regular expression for matching a URL parameters\n */\nexport const RE_URL_PARAMETER = /([^\\s=&]+)=?([^&\\s]+)?/\n\n/**\n * Regular expression for matching a HTML attribute and tag names, also for matching shortcode attributes and names\n */\nexport const RE_ATTRIBUTES = /\\s*(?:([a-z_]{1}[a-z0-9\\-_]*)=?(?:\"([^\"]+)\"|'([^']+)')*)\\s*/gi\n\n/**\n * Regular expression for matching a single attribute without value\n */\nexport const RE_ATTRIBUTE_WITHOUT_VALUE = /^\\s*([a-z_]{1}[a-z0-9\\-_]*)\\s*$/i\n\n/**\n * Regular expression for matching a single attribute with value\n */\nexport const RE_ATTRIBUTE_WITH_VALUE = /^\\s*([a-z_]{1}[a-z0-9\\-_]*)=(\"[^\"]+\"|'[^']+')\\s*$/i\n\n/**\n * Regular expression for matching the first or last quote of a string used for removing them\n */\nexport const RE_FIRST_OR_LAST_QUOTE = /^[\"']|[\"']$/g\n", "/** @module parsers */\n\nimport { isArray, isObject, isString, stringToType } from './helpers.mjs'\nimport { RE_ATTRIBUTES, RE_ATTRIBUTE_WITHOUT_VALUE, RE_ATTRIBUTE_WITH_VALUE, RE_URL_PARAMETER, RE_FIRST_OR_LAST_QUOTE } from './regex.mjs'\nimport { decodeHTML, encodeHTML } from './dom.mjs'\n\n/**\n * Parse a string of attributes and return an object\n * \n * @param {string} str\n * @returns object\n * @example\n * parseAttributes('button text=\"Click me\" data='{\"key\": \\\"value\"}' class=\"btn btn-primary\"')\n * // => { button: null, text: 'Click me', data: '{\"key\": \"value\"}', class: 'btn btn-primary' }\n */\nexport function parseAttributes(str) {\n\tconst re = RE_ATTRIBUTES\n\tconst reWithoutValue = RE_ATTRIBUTE_WITHOUT_VALUE\n\tconst reHasValue = RE_ATTRIBUTE_WITH_VALUE\n\tconst reReplaceFirstAndLastQuote = RE_FIRST_OR_LAST_QUOTE\n\t\n\tconst res = {}\n\tconst match = str.match(re)\n\n\tfor (let i = 0; i < match.length; i++) {\n\t\tconst m = match[i]\n\t\tif (m === '') continue\n\n\t\tif (reWithoutValue.test(m)) {\n\t\t\tconst [, key] = m.match(reWithoutValue)\n\t\t\tres[key] = null\n\t\t\treWithoutValue.lastIndex = 0\n\t\t} else if (reHasValue.test(m)) {\n\t\t\tconst [, key, value] = m.match(reHasValue)\n\t\t\tres[key] = stringToType(decodeHTML(value.replace(reReplaceFirstAndLastQuote, '')))\n\t\t\treReplaceFirstAndLastQuote.lastIndex = 0\n\t\t\treHasValue.lastIndex = 0\n\t\t}\n\t}\n\n\treturn res\n}\n\n/**\n * Serialize an object of key value pairs into a string of attributes\n * \n * @param {object} obj - The object to serialize\n * @returns {string} of attributes\n * @example\n * serializeAttributes({ button: null, text: 'Click me', data: '{\"key\": \"value\"}', class: 'btn btn-primary' }) // button text=\"Click me\" data=\"{\\\"key\\\": \\\"value\\\"}\" class=\"btn btn-primary\"\n */\nexport function serializeAttributes(obj) {\n\tconst res = []\n\n\tObject.keys(obj).forEach((key) => {\n\t\tlet value = obj[key]\n\t\tif (isObject(value) || isArray(value)) value = JSON.stringify(value)\n\t\tif (isString(value)) value = encodeHTML(value)\n\t\tconst valueString = value === null || value === undefined ? '' : `=\"${value}\"`\n\t\tres.push(`${key}${valueString}`)\n\t})\n\n\treturn res.join(' ')\n}\n\n/**\n * Encodes HTML entities in a string using the following rules:\n * \n * - & (ampersand) becomes &\n * - \" (double quote) becomes "\n * - ' (single quote) becomes '\n * - < (less than) becomes <\n * - > (greater than) becomes >\n * \n * It is different than dom.encodeHTML, which encodes all characters using the browser's DOMParser. This function only encodes the characters listed above and should be used when DOMParser is not available.\n * @see {@link module:dom.encodeHTML}\n * \n * @param {string} str - The string to encode\n * @returns {string} The encoded string\n * @example\n * htmlEncode('
Link ') // <a href="#">Link</a>\n */\nexport function encodeHtmlEntities(str) {\n\treturn str.replace(/[<>\"'\\&]/g, (m) => {\n\t\tswitch (m) {\n\t\t\tcase '<': return '<'\n\t\t\tcase '>': return '>'\n\t\t\tcase '\"': return '"'\n\t\t\tcase \"'\": return '''\n\t\t\tcase '&': return '&'\n\t\t}\n\t})\n}\n\n/**\n * Decodes HTML entities in a string using the following rules:\n * \n * - & becomes &\n * - " becomes \"\n * - ' becomes '\n * - < becomes <\n * - > becomes >\n * \n * It is different than dom.decodeHTML, which decodes all characters using the browser's DOMParser. This function only decodes the characters listed above and should be used when DOMParser is not available.\n * @see {@link module:dom.decodeHTML}\n * \n * @param {string} str - The string to decode\n * @returns {string} The decoded string\n * @example\n * htmlDecode('<a href="#">Link</a>') //
Link \n */\nexport function decodeHtmlEntities(str) {\n\treturn str.replace(/<|>|"|'|&/g, (m) => {\n\t\tswitch (m) {\n\t\t\tcase '<': return '<'\n\t\t\tcase '>': return '>'\n\t\t\tcase '"': return '\"'\n\t\t\tcase ''': return \"'\"\n\t\t\tcase '&': return '&'\n\t\t}\n\t})\n}\n\n\n/**\n * Parses a string of url parameters into an object of key value pairs\n * \n * @param {string} paramString - The string to parse without ? or # and with & as separator\n * @param {boolean} [decode=true] - Whether to decode the values or not\n * @returns {object} of key value pairs\n * @example\n * parseUrlParams('foo=true&baz=555') // { foo: true, baz: 555 }\n * parseUrlParams('foo=bar&baz=qux', false) // { foo: 'true', baz: '555' }\n * parseUrlParams('foo&bar&baz=qux') // { foo: undefined, bar: undefined, baz: 'qux' }\n */\nexport function parseUrlParameters(paramString, decode = true) {\n const res = {}\n\n const paramParts = paramString.split('&')\n paramParts.forEach((part) => {\n const m = part.match(RE_URL_PARAMETER)\n\t\tif (!m) return\n const key = m[1]\n const value = m[2]\n res[key] = value !== undefined && decode ? stringToType(decodeURIComponent(value)) : stringToType(value)\n\t\tRE_URL_PARAMETER.lastIndex = 0\n })\n\n return res\n}\n\n/**\n * Serialize an object of key value pairs into a string of url parameters\n * \n * @param {object} obj - The object to serialize\n * @param {boolean} [encode=true] - Whether to encode the values or not\n * @returns {string} of url parameters\n * @example\n * serializeUrlParams({ foo: true, baz: 555 }) // foo=true&baz=555\n * serializeUrlParams({ bar: undefined, baz: 'qux' }, false) // bar=&baz=qux\n */\nexport function serializeUrlParameters(obj, encode = true) {\n\tconst res = []\n\n\tObject.keys(obj).forEach((key) => {\n\t\tconst value = obj[key]\n\t\tif (value === undefined) return res.push(key)\n\t\tconst encodedValue = encode ? encodeURIComponent(value) : value\n\t\tres.push(`${key}=${encodedValue}`)\n\t})\n\n\treturn res.join('&')\n}\n\n/**\n * Parses a resolution string into a number. Resolution string is in the format of 'width:height', e.g. '16:9' \n * \n * @param {string} res Resolution string. Format is 'width:height', e.g. '16:9', or 'widthxheight', e.g. '16x9', or 'width-height', e.g. '16-9', or 'width/height', e.g. '16/9'\n * @returns number\n * @example\n * parseResolutionString('16:9') // => 1.7777777778\n * parseResolutionString('4:3') // => 1.3333333333\n * parseResolutionString('4x3') // => 1.3333333333\n * parseResolutionString('4-3') // => 1.3333333333\n */\nexport function parseResolutionString(res) {\n const DEFAULT_RESOLUTION = 1.7777777778 // 16:9\n if (!res || !res.length || /16[\\:x\\-\\/]{1}9/i.test(res)) return DEFAULT_RESOLUTION\n const pts = res.split(/\\s?[\\:x\\-\\/]{1}\\s?/i)\n if (pts.length < 2) return DEFAULT_RESOLUTION\n\n const w = parseInt(pts[0])\n const h = parseInt(pts[1])\n\n if (w === 0 || h === 0) return DEFAULT_RESOLUTION\n if (isNaN(w) || isNaN(h)) return DEFAULT_RESOLUTION\n\n return w/h;\n}\n", "/** @module dom */\n\nimport { transformDashToCamelCase, isArray, isString } from './helpers.mjs'\nimport { encodeHtmlEntities, decodeHtmlEntities } from './parsers.mjs'\n\n/**\n * Checks if an element is empty\n * \n * @param {HTMLElement} element \n * @returns boolean\n * @example\n * document.body.innerHTML = `\n *
\n *
foo
\n *
`\n * \n * isEmptyElement(document.getElementById('empty-element')) // => true\n * isEmptyElement(document.getElementById('non-empty-element1')) // => false\n * isEmptyElement(document.getElementById('non-empty-element2')) // => false\n */\nexport function isEmptyElement(element) {\n return element.innerHTML.trim() === ''\n}\n\n/**\n * Removes all elements matching a selector from the DOM\n * \n * @param {string|HTMLElement|Element} selector The selector to select elements to remove\n * @param {HTMLElement|Element} [from=document] The element to remove elements from\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * `\n * remove('#foo, #bar') // => removes #foo and #bar\n */\nexport function remove(selector, from = document) {\n const elements = query(selector, from)\n for (const element of elements) {\n element.remove()\n }\n}\n\n/**\n * Queries the DOM for a single element and returns it. Substitutes for `document.querySelector(selector)` and JQuery's `$(selector).first()`\n * \n * @param {string|HTMLElement|Element|Array
|NodeList} selector The selector to select an element\n * @param {HTMLElement|Element} [from=document] The element to query from\n * @returns {HTMLElement|Element}\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * querySingle('#foo') // =>
\n * querySingle(document.getElementById('foo')) // =>
\n * querySingle(document.querySelector('#foo')) // =>
\n */\nexport function querySingle(selector, from = document) {\n if (selector instanceof Element) return selector\n return from.querySelector(selector)\n}\n\n/**\n * Queries the DOM for elements and returns them. Substitutes for `document.querySelectorAll(selector)` and JQuery's `$(selector)`\n * \n * @param {string|HTMLElement|Element|Array|NodeList} selector The selector to select elements\n * @param {HTMLElement|Element} [from=document] The element to query from\n * @returns {Array|NodeList}\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * query('#foo') // => [
]\n * query(document.getElementById('foo')) // => [
]\n * query('div') // => [
,
,
]\n */\nexport function query(selector, from = document) {\n if (selector instanceof Array || selector instanceof NodeList) return selector\n if (selector instanceof Element) return [selector]\n if (from instanceof Element || from instanceof Document) return from.querySelectorAll(selector)\n if (isString(from)) from = query(from)\n if (!from instanceof Array && !from instanceof NodeList) return []\n const res = []\n for (const element of from) {\n res.push(...element.querySelectorAll(selector))\n }\n return res\n}\n\n/**\n * Sets element styles from passed object of styles. Can also transform dash-case to camelCase for CSS properties\n * \n * @param {HTMLElement} element The element to set styles on\n * @param {object} styles The object of styles to set\n * @param {boolean} transform Whether to transform dash-case to camelCase for CSS properties\n * @example\n * css(document.getElementById('foo'), { 'background-color': 'red', 'font-size': '16px' }, true) // => sets background-color and font-size\n * css(document.getElementById('foo'), { backgroundColor: 'red', fontSize: '16px' }) // => sets background-color and font-size\n */\nexport function css(element, styles, transform = false) {\n if (!element || !styles) return\n for (let property in styles) {\n if (transform) property = transformDashToCamelCase(property)\n element.style[property] = styles[property]\n }\n}\n\n/**\n * Decodes HTML entities in a string using the browser's DOMParser. If the DOMParser is not available, it uses a regular expression to decode the basic entities.\n * \n * @see {@link module:parsers.decodeHtmlEntities}\n * \n * @param {string} html The HTML string to decode\n * @returns {string} The decoded HTML string\n * @example\n * decodeHTML('<div>foo</div>') // => 'foo
'\n * decodeHTML('<div>foo</div><div>bar</div>') // => 'foo
bar
'\n */\nexport function decodeHTML(html) {\n if (typeof document === 'undefined') return decodeHtmlEntities(html)\n const txt = document.createElement('textarea')\n txt.innerHTML = html\n const res = txt.value\n txt.remove()\n return res\n}\n\n/**\n * Encodes HTML entities in a string using the browser's DOMParser. If the DOMParser is not available, it uses a regular expression to encode the basic entities.\n * \n * @see {@link module:parsers.encodeHtmlEntities}\n * \n * @param {string} html The HTML string to encode\n * @returns {string} The encoded HTML string\n * @example\n * encodeHTML('foo
') // => '<div>foo</div>'\n * encodeHTML('foo
bar
') // => '<div>foo</div><div>bar</div>'\n */\nexport function encodeHTML(html) {\n if (typeof document === 'undefined') return encodeHtmlEntities(html)\n const txt = document.createElement('textarea')\n txt.textContent = html\n const res = txt.innerHTML\n txt.remove()\n return res\n}\n\n/**\n * Inserts an element before another element\n * \n * @param {HTMLElement} targetElement The element to insert before\n * @param {HTMLElement} newElement The element to insert\n * @example\n * const target = document.getElementById('target')\n * const newElement = document.createElement('div')\n * newElement.id = 'newElement'\n * insertBeforeElement(target, newElement)\n * //
\n * //
\n */\nexport function insertBeforeElement(targetElement, newElement) {\n if (!targetElement || !newElement) return\n targetElement.parentNode.insertBefore(newElement, targetElement);\n}\n\n/**\n * Toggles an attribute value on an element\n * \n * @param {HTMLElement} element The element to toggle the attribute on\n * @param {string} attribute The attribute to toggle\n * @param {string} on Default: 'true'\n * @param {string} off Default: 'false'\n * @example\n * toggleAttributeValue(element, 'aria-expanded', 'true', 'false')\n * toggleAttributeValue(element, 'aria-expanded')\n */\nexport function toggleAttributeValue(element, attribute, on = 'true', off = 'false') {\n if (!element.hasAttribute(attribute)) return\n\n if (element.getAttribute(attribute) === on) {\n element.setAttribute(attribute, off)\n } else {\n element.setAttribute(attribute, on)\n }\n}\n\n/**\n * Converts a duration string to milliseconds integer\n * \n * @param {string} duration The duration string to convert, e.g. '1s', '100ms', '0.5s'\n * @returns {number} The duration in milliseconds\n * @example\n * convertToMilliseconds('1s') // 1000\n * convertToMilliseconds('100ms') // 100\n * convertToMilliseconds('0.5s') // 500\n * convertToMilliseconds('0.5') // 0\n * convertToMilliseconds('foo') // 0\n */\nexport function cssTimeToMilliseconds(duration) {\n const regExp = new RegExp('([0-9.]+)([a-z]+)', 'i')\n const matches = regExp.exec(duration)\n if (!matches) return 0\n \n const unit = matches[2]\n switch (unit) {\n case 'ms':\n return parseFloat(matches[1])\n case 's':\n return parseFloat(matches[1]) * 1000\n default:\n return 0\n }\n}\n\n/**\n * Returns a map of transition properties and durations\n * \n * @param {HTMLElement} element The element to get the transition properties and durations from\n * @returns {object} A map of transition properties and durations\n * @example\n * getTransitionDurations(element) // { height: 1000 } if transition in CSS is set to 'height 1s'\n * getTransitionDurations(element) // { height: 500, opacity: 1000 } if transition in CSS is set to 'height 0.5s, opacity 1s'\n */\nexport function getTransitionDurations(element) {\n if (!element) {}\n const styles = getComputedStyle(element)\n const transitionProperties = styles.getPropertyValue('transition-property').split(',')\n const transitionDurations = styles.getPropertyValue('transition-duration').split(',')\n \n const map = {}\n \n for (let i = 0; i < transitionProperties.length; i++) {\n const property = transitionProperties[i].trim()\n map[property] = transitionDurations.hasOwnProperty(i) ? cssTimeToMilliseconds(transitionDurations[i].trim()) : null\n }\n \n return map\n}\n\n/**\n * Check a list of elements if any of them matches a selector\n * \n * @param {Array|NodeList|HTMLElement} elements The elements to check\n * @param {string} selector The selector to check\n * @returns {boolean} True if any of the elements matches the selector, false otherwise\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * matchesAny(document.querySelectorAll('div'), '#foo') // => true\n * matchesAny(document.querySelectorAll('div'), '#qux') // => false\n */\nexport function matchesAny(elements, selector) {\n if (!elements || !selector || !elements.length) return false\n if (elements instanceof Element) elements = [elements]\n if (isString(elements)) elements = query(elements)\n for (const element of elements) {\n if (element.matches(selector)) return true\n }\n return false\n}\n\n/**\n * Check a list of elements if all of them matches a selector\n * \n * @param {Array|NodeList|HTMLElement} elements The elements to check\n * @param {string} selector The selector to check\n * @returns {boolean} True if all of the elements matches the selector, false otherwise\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * matchesAll(document.querySelectorAll('div'), 'div') // => true\n * matchesAll(document.querySelectorAll('div'), '#foo') // => false\n */\nexport function matchesAll(elements, selector) {\n if (!elements || !selector || !elements.length) return false\n if (elements instanceof Element) elements = [elements]\n if (isString(elements)) elements = query(elements)\n for (const element of elements) {\n if (!element.matches(selector)) return false\n }\n return true\n}\n\n\n/**\n * Detaches an element from the DOM and returns it\n * \n * @param {HTMLElement} element The element to detach\n * @example\n * detachElement(element)\n * // => element\n * console.log(element.parentNode) // => null\n */\nexport function detachElement(element) {\n if (element && element.parentNode) {\n element.parentNode.removeChild(element);\n }\n return element\n}\n\n/**\n * Gets table data from a table element, a simple regular table element, or a table like structure.\n * Useful for scraping data.\n * \n * @param {string} selector The selector to select the table element\n * @param {Array|string|null} headers The headers to use for the data. If 'auto' is passed, the row containing th or the first row will be used as headers\n * @param {string} [rowSelector='tr'] The selector to select the rows\n * @param {string} [cellSelector='td'] The selector to select the cells\n * @returns {Array} An array of objects with the properties as keys and the cell values as values\n * @example\n * document.body.innerHTML = `\n * \n * \n * \n * Foo \n * Bar \n * \n * \n * \n * \n * Foo 1 \n * Bar 1 \n * \n * \n * Foo 2 \n * Bar 2 \n * \n * \n *
`\n * \n * getTableData('#table', ['foo', 'bar'])\n * // => [\n * // { foo: 'Foo 1', bar: 'Bar 1' },\n * // { foo: 'Foo 2', bar: 'Bar 2' }\n * // ]\n */\nexport function getTableData(selector, headers, rowSelector = 'tr', cellSelector = 'td', headerCellSelector = 'th') {\n const table = typeof selector === 'string' ? document.querySelector(selector) : selector\n const res = []\n const rows = table.querySelectorAll(rowSelector)\n let start = 0\n\n function iterateHeaders(arr) {\n if (!arr || !arr.length) return\n const res = []\n for (let i = 0; i < arr.length; i++) {\n res.push(arr[i].textContent.trim())\n }\n return res\n }\n\n if (headers && isString(headers) && headers === 'auto') {\n let headerCells = table.querySelectorAll(headerCellSelector)\n \n if (headerCells && headerCells.length) {\n headers = iterateHeaders(headerCells)\n } else {\n headers = iterateHeaders(rows[0].querySelectorAll(cellSelector))\n start = 1\n }\n }\n\n for (let i = start; i < rows.length; i++) {\n const row = rows[i]\n const cells = row.querySelectorAll(cellSelector)\n if (!cells || !cells.length) continue\n\n let rowData = []\n if (headers && isArray(headers) && headers.length) {\n rowData = {}\n for (let j = 0; j < headers.length; j++) {\n rowData[headers[j]] = cells[j] ? cells[j].textContent.trim() : null\n }\n } else {\n for (let j = 0; j < cells.length; j++) {\n rowData.push(cells[j].textContent.trim())\n }\n }\n res.push(rowData)\n }\n return res\n}\n\n/**\n * Parses HTML string to a DOM Node\n * \n * @param {string} html The HTML string to parse\n * @param {boolean} [allChildren=false] If true, all children of the body will be returned, otherwise only the first child\n * @returns {Node} The parsed DOM Node\n * @example\n * parseDOM('foo
') // => foo
\n * parseDOM('foo
bar
', true) // => NodeList(2)\u00A0[div, div]\n * parseDOM(document.getElementById('foo')) // =>
\n * parseDOM(document.querySelectorAll('div')) // => NodeList(2)\u00A0[div, div]\n */\nexport function parseDOM(html, allChildren) {\n if (html instanceof Element || html instanceof NodeList) return html\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n return !allChildren ? doc.body.firstChild : doc.body.childNodes\n}\n\n/**\n * Loads an image form a provided source url and calls a callback when it's loaded\n * \n * @param {string} src The source url of the image\n * @param {Function} [callback] The callback to call when the image is loaded\n * @example\n * loadImage('https://example.com/image.png', () => {\n * console.log('Image loaded')\n * })\n */\nexport function loadImage(src, callback) {\n const img = new Image()\n if (callback)\n img.addEventListener('load', callback, false);\n img.src = src\n}\n\n/**\n * Delegate DOM events using MutationObserver with a fallback to document.addEventListener\n * \n * @param {string} selector The selector to select the elements to delegate the event to\n * @param {string} eventType The event type to delegate, like `click`\n * @param {Function} handler The handler to call when the event is triggered.\n * @returns {MutationObserver | null} The MutationObserver instance\n * @example\n * delegateEvent('.foo', 'click', (e, target) => {\n * console.log('Clicked on', target)\n * })\n */\nexport function delegateEvent(selector, eventType, handler) {\n if (typeof MutationObserver === 'undefined') {\n document.addEventListener(eventType, (e) => {\n const target = e.target.closest(selector)\n if (target) handler(e, target)\n })\n\n return null\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (!node.matches(selector)) continue\n node.addEventListener(eventType, (e) => {\n handler(e, e.currentTarget)\n })\n }\n }\n })\n\n for (const node of document.querySelectorAll(selector)) {\n node.addEventListener(eventType, (e) => {\n handler(e, e.currentTarget)\n })\n }\n\n observer.observe(document.body, { childList: true, subtree: true })\n return observer\n}\n\n/**\n * Run a handler on selected elements and on elements added to the DOM with the same selector, \n * or can be delegateEvent alias.\n * \n * @param {string} selector The selector to select the elements to run the handler on\n * @param {string | Function} eventTypeOrHandler The event type to delegate, like `click`, or the handler to call on every element\n * @param {Function} [handler] The handler to call when the event is triggered.\n * @returns {MutationObserver | null} The MutationObserver instance\n * @see delegateEvent\n * @example\n * on('.foo', (el) => {\n * console.log('Element', el, 'added to the DOM')\n * })\n * \n * on('.foo', 'click', (e, target) => {\n * console.log('Clicked on', target)\n * })\n */\nexport function on(selector, eventTypeOrHandler, handler) {\n if (isString(eventTypeOrHandler)) {\n return delegateEvent(selector, eventTypeOrHandler, handler)\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (!node.matches(selector)) continue\n eventTypeOrHandler(node)\n }\n }\n })\n\n for (const node of document.querySelectorAll(selector)) {\n eventTypeOrHandler(node)\n }\n\n observer.observe(document.body, { childList: true, subtree: true })\n\n return observer\n}\n\n/**\n * Adds one listener to multiple events\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to add the event listeners to\n * @param {string|Array} events The event types to add the event listeners for, like `click mouseenter`\n * @param {Function} handler The handler to call when the event is triggered.\n * @param {object} [options] The options to pass to the event listeners\n * @example\n * addListenerForEvents('.foo', 'click mouseenter', (e) => { console.log(e.type) })\n */\nexport function addListenerForEvents(elements, events, handler, options) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n const eventTypes = isArray(events) ? events : events.split(' ')\n for (const element of elements) {\n for (const eventType of eventTypes) {\n element.addEventListener(eventType, handler, options)\n }\n }\n}\n\n/**\n * Removes one listener from multiple registered events\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to remove the event listeners from\n * @param {string|Array} events The event types to remove the event listeners for, like `click mouseenter`\n * @param {Function} handler The handler to remove\n * @param {object} [options] The options to pass to the event listeners\n * @example\n * removeListenerForEvents('.foo', 'click mouseenter', (e) => { console.log(e.type) })\n */\nexport function removeListenerForEvents(elements, events, handler, options) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n const eventTypes = isArray(events) ? events : events.split(' ')\n for (const element of elements) {\n for (const eventType of eventTypes) {\n element.removeEventListener(eventType, handler, options)\n }\n }\n}\n\n/**\n * Resizes an element to cover its parent element while maintaining the aspect ratio\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to resize\n * @param {number} [ratio=1] The ratio to maintain\n * @param {number} [offset=0] An offset to add to the parent element's width and height\n * @example\n * proportionalParentCoverResize('.foo', 16/9, 10)\n */\nexport function proportionalParentCoverResize(elements, ratio = 1, offset = 0) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n for (const element of elements) {\n const h = element.parentNode.offsetHeight + offset\n const w = element.parentNode.offsetWidth + offset\n\n if (ratio > w/h) {\n element.style.width = h*ratio + 'px'\n element.style.height = h + 'px'\n } else {\n element.style.width = w + 'px'\n element.style.height = w/ratio + 'px'\n }\n }\n}\n\n/**\n * If provided element is visible. Checks if the element is not visibility hidden or display none, has no opacity, and has a width and height.\n * \n * @param {HTMLElement} element The element to check\n * @returns {boolean} True if the element is visible, false otherwise\n * \n * @example\n * isVisible(document.getElementById('foo'))\n */\nexport function isVisible(element) {\n if (!element) return false;\n const computedStyle = getComputedStyle(element);\n if (computedStyle.getPropertyValue('display') === 'none') return false;\n if (element.getAttribute('hidden') !== null || computedStyle.getPropertyValue('visibility') === 'hidden' || computedStyle.getPropertyValue('opacity') == \"0\") return false;\n return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)\n}\n\n/**\n * Swipe event handler\n * \n * @param {HTMLElement} element The element to listen for swipe gestures on\n * @param {Function} callback The callback to call when a swipe gesture is detected\n * @param {number} [threshold=150] The threshold in pixels to trigger the callback.\n * @param {number} [timeThreshold=0] The threshold in milliseconds to trigger the callback. Defaults to 0, which means the callback will be called regardless of the time it took to swipe.\n * @event swipestart Fires when a swipe gesture starts\n * @event swipeend Fires when a swipe gesture ends\n * @event swipe Fires when a swipe gesture is detected based on the thresholds\n * @example\n * onSwipe(document.getElementById('foo'), (e) => {\n * console.log(e.direction)\n * console.log(e.deltaX)\n * console.log(e.deltaY)\n * console.log(e.startX)\n * console.log(e.startY)\n * console.log(e.endX)\n * console.log(e.endY)\n * console.log(e.threshold)\n * console.log(e.type)\n * console.log(e.target)\n * console.log(e.horizontal)\n * console.log(e.vertical)\n * console.log(e.horizontalDirection)\n * console.log(e.verticalDirection)\n * console.log(e.timeElapsed)\n * console.log(e.timeThreshold)\n * })\n */\nexport function onSwipe(element, callback, threshold = 150, timeThreshold = 0) {\n let startX = 0\n let startY = 0\n let endX = 0\n let endY = 0\n let startTime = 0\n let endTime = 0\n\n if (!element) return\n if (element.getAttribute('swipe-enabled') === 'true') return\n element.setAttribute('swipe-enabled', 'true')\n\n const handleStart = function(e) {\n const carrier = e.touches ? e.touches[0] : e\n startX = carrier.clientX\n startY = carrier.clientY\n startTime = Date.now();\n element.dispatchEvent(new CustomEvent('swipestart', { detail: { startX, startY, startTime } }))\n }\n\n const handleEnd = function(e) {\n const carrier = e.changedTouches ? e.changedTouches[0] : e\n endX = carrier.clientX\n endY = carrier.clientY\n endTime = Date.now();\n handleSwipeGesture()\n element.dispatchEvent(new CustomEvent('swipeend', { detail: { startX, startY, startTime, endX, endY, endTime } }))\n }\n\n const handleSwipeGesture = function() {\n const deltaX = Math.abs(endX - startX)\n const deltaY = Math.abs(endY - startY)\n const horizontal = deltaX > threshold\n const vertical = deltaY > threshold\n const left = endX < startX\n const up = endY < startY\n const direction = []\n const timeElapsed = endTime - startTime;\n \n if (horizontal) direction.push(left ? 'left' : 'right')\n if (vertical) direction.push(up ? 'up' : 'down')\n\n let condition = direction.length && callback\n if (timeThreshold) condition = condition && timeElapsed <= timeThreshold\n \n if (condition) {\n const res = {\n target: element,\n deltaX: deltaX,\n deltaY: deltaY,\n startX: startX,\n startY: startY,\n endX: endX,\n endY: endY,\n threshold: threshold,\n horizontal: horizontal,\n vertical: vertical,\n horizontalDirection: left ? 'left' : 'right',\n verticalDirection: up ? 'up' : 'down',\n direction: direction.length === 1 ? direction[0] : direction,\n timeElapsed: timeElapsed,\n timeThreshold: timeThreshold\n }\n\n callback(res)\n delete res.target\n element.dispatchEvent(new CustomEvent('swipe', { detail: res })) \n }\n }\n\n element.addEventListener('touchstart', handleStart)\n element.addEventListener('touchend', handleEnd)\n element.addEventListener('mousedown', handleStart)\n element.addEventListener('mouseup', handleEnd)\n\n return {\n destroy: function() {\n element.removeEventListener('touchstart', handleStart)\n element.removeEventListener('touchend', handleEnd)\n element.removeEventListener('mousedown', handleStart)\n element.removeEventListener('mouseup', handleEnd)\n }\n }\n}\n", "/** @module browser */\n\nimport { isEmpty, isFunction } from './helpers.mjs'\nimport { css } from './dom.mjs'\nimport { parseUrlParameters } from './parsers.mjs'\n\nexport function isUserAgentIOS(str) {\n return /iPad|iPhone|iPod/i.test(str)\n}\n\nexport function isUserAgentMobile(str) {\n return /\\b(BlackBerry|webOS|iPhone|IEMobile)\\b/i.test(str) ||\n /\\b(Android|Windows Phone|iPad|iPod)\\b/i.test(str)\n}\n\nexport function isUserAgentSafari(str) {\n return /^((?!chrome|android|crios|fxios).)*safari/i.test(str)\n}\n\n/**\n * Check if the device is an iOS device\n * \n * @returns boolean True if the device is an iOS device, false otherwise\n */\nexport function isIOS() {\n return isUserAgentIOS(navigator.userAgent) && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 1\n}\n\n/**\n * Check if the device is a mobile device\n * \n * @returns boolean True if the device is a mobile device, false otherwise\n */\nexport function isMobile() {\n if ('maxTouchPoints' in navigator) return navigator.maxTouchPoints > 0\n\n if ('matchMedia' in window) return !!matchMedia('(pointer:coarse)').matches\n\n if ('orientation' in window) return true\n\n return isUserAgentMobile(navigator.userAgent)\n}\n\n/**\n * Check if the browser is Safari\n *\n * @returns boolean True if the browser is Safari, false otherwise\n */\nexport function isSafari() {\n if (navigator.hasOwnProperty('vendor')) /apple/i.test(navigator.vendor)\n return isUserAgentSafari(navigator.userAgent)\n}\n\n/**\n * Check if the browser is Safari on iOS\n * \n * @returns boolean True if the browser is Safari on iOS, false otherwise\n */\nexport function isIOSSafari() {\n return isIOS() && isSafari()\n}\n\n/**\n * A wrapper for the matchMedia function, cause with `matchMedia` you can only either add a listener or check the media query\n * this function does both.\n * \n * @param {string} query The media query to check\n * @param {function} [callback] The callback function to call when the media query changes\n * @returns {boolean} The result of the media query\n * \n * @example\n * mediaMatcher('(min-width: 768px)', (matches) => {\n * if (matches) {\n * // Do something\n * } else {\n * // Do something else\n * }\n * })\n * \n * // Or\n * \n * const isDesktop = mediaMatcher('(min-width: 768px)')\n */\nexport function mediaMatcher(query, callback) {\n if (isFunction(callback)) {\n matchMedia(query).addEventListener('change', (e) => {\n callback(e.matches)\n })\n\n const mql = matchMedia(query)\n callback(mql.matches)\n\n return mql.matches\n }\n\n return matchMedia(query).matches\n}\n\n/**\n * Get the scrollbar width\n * \n * When preventing scroll with html overflow hidden the scroll bar will disappear and the whole page will shift (if the scroll bar is visible that is).\n * To substitute for the scrollbar width we can add a padding to the body element.\n * \n * @returns {number} The scrollbar width\n * \n * @example\n * const scrollbarWidth = getScrollbarWidth() // 15 (on MacOS X Safari)\n */\nexport function getScrollbarWidth() {\n const scrollDiv = document.createElement('div')\n \n css(scrollDiv, {\n width: '100px',\n height: '100px',\n position: 'absolute',\n left: '-9999px',\n zIndex: '0',\n overflowX: 'hidden',\n overflowY: 'scroll'\n })\n\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n}\n\n/**\n * Check if the vertical scrollbar is visible\n * \n * @param {number} [scrollbarWidth] The width of the scrollbar, defaults to getScrollbarWidth()\n * @returns {boolean} True if the vertical scrollbar is visible, false otherwise\n */\nexport function hasVerticalScrollbarVisible(scrollbarWidth) {\n if (scrollbarWidth === undefined) scrollbarWidth = getScrollbarWidth()\n return window.innerHeight < document.body.scrollHeight && scrollbarWidth > 0\n}\n\n/**\n * Check if the horizontal scrollbar is visible\n * \n * @param {number} [scrollbarWidth] The width of the scrollbar, defaults to getScrollbarWidth()\n * @returns {boolean} True if the horizontal scrollbar is visible, false otherwise\n */\nexport function hasHorizontalScrollbarVisible(scrollbarWidth) {\n if (scrollbarWidth === undefined) scrollbarWidth = getScrollbarWidth()\n return window.innerWidth < document.body.scrollWidth && scrollbarWidth > 0\n}\n\n/**\n * Disable the scroll on the page.\n * \n * @param {number} [shift=0] If greater than 0 the body will be shifted to the left by the width of the scrollbar, getScrollbarWidth() is used to provide this value \n */\nexport function disableScroll(shift) {\n const body = document.body\n if (shift && hasVerticalScrollbarVisible(shift)) body.style.paddingRight = `${shift}px`\n body.style.overflow = 'hidden'\n}\n\n/**\n * Enable the scroll on the page.\n * \n * @param {boolean} [shift=0] If greater than 0 the body will be shifted back to the left by the width of the scrollbar, getScrollbarWidth() is used to provide this value\n */\nexport function enableScroll(shift) {\n const body = document.body\n body.style.overflow = ''\n if (shift) body.style.paddingRight = ''\n}\n\n/**\n * Parses a string of url query parameters into an object of key value pairs. Converts the values to the correct type.\n * \n * @param {string} [entryQuery] - Optional query string to parse, without the starting ?, defaults to window.location.search without the starting ?\n * @returns {object} of key value pairs\n * @example\n * // url: https://example.com/?test&foo=bar&baz=qux\n * getQueryProperties() // { test: undefined, foo: 'bar', baz: 'qux' }\n */\nexport function getQueryProperties(entryQuery) {\n const query = entryQuery ? entryQuery : window.location.search.replace('?', '')\n if (isEmpty(query)) return {}\n\n return parseUrlParameters(query)\n}\n\n/**\n * Parses a string of url hash parameters into an object of key value pairs. Converts the values to the correct type.\n * \n * @param {string} [entryHash] - Optional hash string to parse, without the starting #, defaults to window.location.hash without the starting #\n * @returns {object} of key value pairs\n * @example\n * // url: https://example.com/#test&foo=bar&baz=qux\n * getHashProperties() // { test: undefined, foo: 'bar', baz: 'qux' }\n */\nexport function getHashProperties(entryHash) {\n const hash = entryHash ? entryHash : window.location.hash.replace('#', '')\n if (isEmpty(hash)) return {}\n\n return parseUrlParameters(hash)\n}\n\nfunction onHashChange(callback) {\n const hash = window.location.hash.replace('#', '')\n if (!isEmpty(hash)) callback(hash)\n}\n\n/**\n * Add a callback function to the hash change event\n * \n * @param {function} callback - The callback function to call when the hash changes\n * @param {string} [single] - Optional string to make sure the listener is initialized only once, defaults to window[single] which is set to true after the first call\n * @example\n * hashChange((hash) => {\n * // Do something with the hash\n * })\n */\nexport function hashChange(callback, single) {\n onHashChange(callback)\n \n if (single && window[single]) return\n if (single) window[single] = true\n \n window.addEventListener('hashchange', () => {\n onHashChange(callback)\n })\n}\n", "import { generateActionButton } from './buttons.js';\nimport { isArray, stringToType, isMobile, parseResolutionString, proportionalParentCoverResize, percentage, fixed } from 'book-of-spells';\n\nexport class SuperVideoBackground {\n constructor(elem, params, id, uid, type, factoryInstance) {\n if (!id) return;\n this.is_mobile = isMobile();\n this.type = type;\n this.id = id;\n this.factoryInstance = factoryInstance;\n\n this.element = elem;\n this.playerElement = null;\n this.uid = uid;\n this.element.setAttribute('data-vbg-uid', uid);\n\n this.buttons = {};\n this.isIntersecting = false;\n\n this.paused = false; // user requested pause. used for blocking intersection softPlay\n this.muted = false;\n this.currentState = 'notstarted';\n\n this.initialPlay = false;\n this.initialVolume = false;\n\n this.volume = 1;\n\n this.params = {};\n\n const DEFAULTS = {\n 'pause': false, //deprecated\n 'play-button': false,\n 'mute-button': false,\n 'autoplay': true,\n 'muted': true,\n 'loop': true,\n 'mobile': true,\n 'load-background': false,\n 'resolution': '16:9',\n 'inline-styles': true,\n 'fit-box': false,\n 'offset': 100, // since showinfo is deprecated and ignored after September 25, 2018. we add +100 to hide it in the overflow\n 'start-at': 0,\n 'end-at': 0,\n 'poster': null,\n 'always-play': false,\n 'volume': 1,\n 'no-cookie': true,\n 'force-on-low-battery': false,\n 'lazyloading': false\n };\n\n this.params = this.parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']);\n\n //pause deprecated\n if (this.params.pause) {\n this.params['play-button'] = this.params.pause;\n }\n\n this.params.resolution_mod = parseResolutionString(this.params.resolution);\n\n this.muted = this.params.muted;\n\n this.volume = this.params.volume;\n\n this.currentTime = this.params['start-at'] || 0;\n this.duration = this.params['end-at'] || 0;\n this.percentComplete = 0;\n if (this.params['start-at']) this.percentComplete = this.timeToPercentage(this.params['start-at']);\n\n this.buildWrapperHTML();\n\n if (this.is_mobile && !this.params.mobile) return;\n\n if (this.params['play-button']) {\n generateActionButton(this, {\n name: 'playing',\n className: 'play-toggle',\n innerHtml: ' ',\n initialState: !this.paused,\n stateClassName: 'paused',\n condition_parameter: 'paused',\n stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'],\n actions: ['play', 'pause']\n });\n }\n\n if (this.params['mute-button']) {\n generateActionButton(this, {\n name: 'muted',\n className: 'mute-toggle',\n innerHtml: ' ',\n initialState: this.muted,\n stateClassName: 'muted',\n condition_parameter: 'muted',\n stateChildClassNames: ['fa-volume-up', 'fa-volume-mute'],\n actions: ['unmute', 'mute']\n });\n }\n }\n\n timeToPercentage(time) {\n if (time <= this.params['start-at']) return 0;\n if (time >= this.duration) return 100;\n if (time <= 0) return 0;\n time -= this.params['start-at']; // normalize\n const duration = this.duration - this.params['start-at']; // normalize\n return percentage(time, duration);\n }\n\n percentageToTime(percentage) {\n if (!this.duration) return this.params['start-at'] || 0;\n if (percentage > 100) return this.duration;\n if (percentage <= 0) return this.params['start-at'] || 0;\n const duration = this.duration - this.params['start-at']; // normalize\n let time = percentage * duration / 100;\n time = fixed(time, 3)\n if (time > duration) time = duration;\n if (this.params['start-at']) time += this.params['start-at']; // normalize\n return time;\n }\n\n resize(element) {\n if (!this.params['fit-box']) proportionalParentCoverResize(element || this.playerElement, this.params.resolution_mod, this.params.offset);\n this.dispatchEvent('video-background-resize');\n }\n\n stylePlayerElement(element) {\n if (!element) return;\n\n if (this.params['inline-styles']) {\n element.style.top = '50%';\n element.style.left = '50%';\n element.style.transform = 'translateX(-50%) translateY(-50%)';\n element.style.position = 'absolute';\n element.style.opacity = 0;\n }\n\n if (this.params['fit-box']) {\n element.style.width = '100%';\n element.style.height = '100%';\n }\n }\n\n buildWrapperHTML() {\n const parent = this.element.parentNode;\n // wrap\n this.element.classList.add('youtube-background', 'video-background');\n \n //set css rules\n const wrapper_styles = {\n \"height\" : \"100%\",\n \"width\" : \"100%\",\n \"z-index\": \"0\",\n \"position\": \"absolute\",\n \"overflow\": \"hidden\",\n \"top\": 0, // added by @insad\n \"left\": 0,\n \"bottom\": 0,\n \"right\": 0\n };\n \n if (!this.params['mute-button']) {\n wrapper_styles[\"pointer-events\"] = \"none\" // avoid right mouse click popup menu\n }\n \n if (this.params['load-background'] || this.params['poster']) {\n this.loadBackground(this.id);\n if (this.params['poster']) wrapper_styles['background-image'] = `url(${ this.params['poster'] })`;\n wrapper_styles['background-size'] = 'cover';\n wrapper_styles['background-repeat'] = 'no-repeat';\n wrapper_styles['background-position'] = 'center';\n }\n \n if (this.params['inline-styles']) {\n for (let property in wrapper_styles) {\n this.element.style[property] = wrapper_styles[property];\n }\n \n if (!['absolute', 'fixed', 'relative', 'sticky'].indexOf(parent.style.position)) {\n parent.style.position = 'relative';\n }\n }\n \n // set play/mute controls wrap\n if (this.params['play-button'] || this.params['mute-button']) {\n const controls = document.createElement('div');\n controls.className = 'video-background-controls';\n \n controls.style.position = 'absolute';\n controls.style.top = '10px';\n controls.style.right = '10px';\n controls.style['z-index'] = 2;\n \n this.controls_element = controls;\n parent.appendChild(controls);\n }\n \n return this.element;\n }\n\n loadBackground(id) {\n if (!this.params['load-background']) return;\n if (!id) return;\n if (this.type === 'youtube') this.element.style['background-image'] = `url(https://img.youtube.com/vi/${id}/hqdefault.jpg)`;\n if (this.type === 'vimeo') this.element.style['background-image'] = `url(https://vumbnail.com/${id}.jpg)`;\n }\n\n destroy() {\n this.playerElement.remove();\n this.element.classList.remove('youtube-background', 'video-background');\n this.element.removeAttribute('data-vbg-uid');\n this.element.style = '';\n\n if (this.params['play-button'] || this.params['mute-button']) {\n this.controls_element.remove();\n }\n\n if (this.timeUpdateTimer) clearInterval(this.timeUpdateTimer);\n this.dispatchEvent('video-background-destroyed');\n }\n\n setDuration(duration) {\n if (this.duration === duration) return;\n\n if (this.params['end-at']) {\n if (duration > this.params['end-at']) {\n this.duration = this.params['end-at'];\n return;\n }\n if (duration < this.params['end-at']) {\n this.duration = duration;\n return;\n }\n } else {\n this.duration = duration;\n return;\n }\n\n if (duration <= 0) this.duration = this.params['end-at'];\n }\n\n setStartAt(startAt) {\n this.params['start-at'] = startAt;\n }\n\n setEndAt(endAt) {\n this.params['end-at'] = endAt;\n if (this.duration > endAt) this.duration = endAt;\n if (this.currentTime > endAt) this.onVideoEnded();\n }\n\n dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n shouldPlay() {\n if (this.currentState === 'ended' && !this.params.loop) return false;\n if (this.params['always-play'] && this.currentState !== 'playing') return true;\n if (this.isIntersecting && this.params.autoplay && this.currentState !== 'playing') return true;\n return false;\n }\n\n mobileLowBatteryAutoplayHack() {\n if (!this.params['force-on-low-battery']) return;\n if (!this.is_mobile && this.params.mobile) return;\n\n const forceAutoplay = function() {\n if (!this.initialPlay && this.params.autoplay && this.params.muted) {\n this.softPlay();\n\n if (!this.isIntersecting && !this.params['always-play']) {\n this.softPause();\n }\n }\n }\n \n document.addEventListener('touchstart', forceAutoplay.bind(this), { once: true });\n }\n\n parseProperties(params, defaults, element, attr_prefix) {\n let res_params = {};\n \n if (!params) {\n res_params = defaults;\n } else {\n for (let k in defaults) {\n //load in defaults if the param hasn't been set\n res_params[k] = !params.hasOwnProperty(k) ? defaults[k] : params[k];\n }\n }\n \n if (!element) return res_params;\n // load params from data attributes\n for (let k in res_params) {\n let data;\n \n if (isArray(attr_prefix)) {\n for (let i = 0; i < attr_prefix.length; i++) {\n const temp_data = element.getAttribute(attr_prefix[i]+k);\n if (temp_data) {\n data = temp_data;\n break;\n }\n }\n } else {\n data = element.getAttribute(attr_prefix+k);\n }\n \n if (data !== undefined && data !== null) {\n res_params[k] = stringToType(data);\n }\n }\n \n return res_params;\n }\n}\n", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_YOUTUBE } from 'book-of-spells';\n\nexport class YoutubeBackground extends SuperVideoBackground {\n constructor(elem, params, id, uid, factoryInstance) {\n super(elem, params, id, uid, 'youtube', factoryInstance);\n\n if (!id) return;\n if (this.is_mobile && !this.params.mobile) return;\n this.injectScript();\n\n this.player = null;\n\n this.injectPlayer();\n\n this.STATES = {\n '-1': 'notstarted',\n '0': 'ended',\n '1': 'playing',\n '2': 'paused',\n '3': 'buffering',\n '5': 'cued'\n };\n\n this.timeUpdateTimer = null;\n this.timeUpdateInterval = 250;\n\n this.initYTPlayer();\n }\n\n startTimeUpdateTimer() {\n if (this.timeUpdateTimer) return;\n this.timeUpdateTimer = setInterval(this.onVideoTimeUpdate.bind(this), this.timeUpdateInterval);\n };\n\n stopTimeUpdateTimer() {\n clearInterval(this.timeUpdateTimer);\n this.timeUpdateTimer = null;\n };\n\n convertState(state) {\n return this.STATES[state];\n }\n\n initYTPlayer() {\n if (!window.hasOwnProperty('YT') || this.player !== null) return;\n\n this.player = new YT.Player(this.uid, {\n events: {\n 'onReady': this.onVideoPlayerReady.bind(this),\n 'onStateChange': this.onVideoStateChange.bind(this),\n // 'onError': this.onVideoError.bind(this)\n }\n });\n\n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n }\n\n onVideoError(event) {\n console.error(event);\n }\n\n injectScript() {\n if (window.hasOwnProperty('YT') || document.querySelector('script[src=\"https://www.youtube.com/player_api\"]')) return\n const tag = document.createElement('script');\n tag.src = \"https://www.youtube.com/player_api\";\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('iframe');\n playerElement.setAttribute('frameborder', 0);\n playerElement.setAttribute('allow', 'autoplay; mute');\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n generateSrcURL(id) {\n let site = 'https://www.youtube.com/embed/';\n if (this.params['no-cookie']) {\n site = 'https://www.youtube-nocookie.com/embed/';\n }\n let src = `${site}${id}?&enablejsapi=1&disablekb=1&controls=0&rel=0&iv_load_policy=3&cc_load_policy=0&playsinline=1&showinfo=0&modestbranding=1&fs=0`;\n\n if (this.params.muted) {\n src += '&mute=1';\n }\n \n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n src += '&autoplay=1';\n }\n \n if (this.params.loop) {\n src += '&loop=1';\n }\n\n return src;\n }\n\n injectPlayer() {\n this.playerElement = this.generatePlayerElement();\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n this.playerElement.id = this.uid;\n\n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(this.playerElement);\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_YOUTUBE);\n if (!pts || !pts.length) return;\n\n this.id = pts[1];\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n this.loadBackground(this.id);\n }\n\n onVideoTimeUpdate() {\n const ctime = this.player.getCurrentTime();\n if (ctime === this.currentTime) return;\n this.currentTime = ctime;\n this.percentComplete = this.timeToPercentage(this.currentTime);\n if (this.params['end-at'] && this.duration && this.currentTime >= this.duration) {\n this.currentState = 'ended';\n this.dispatchEvent('video-background-state-change');\n this.onVideoEnded();\n this.stopTimeUpdateTimer();\n return;\n }\n this.dispatchEvent('video-background-time-update');\n }\n\n onVideoPlayerReady() {\n this.mobileLowBatteryAutoplayHack();\n\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n if (this.params['start-at']) this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n this.setDuration(this.player.getDuration());\n\n this.dispatchEvent('video-background-ready');\n }\n\n onVideoStateChange(event) {\n this.currentState = this.convertState(event.data);\n\n if (this.currentState === 'ended') this.onVideoEnded();\n \n if (this.currentState === 'notstarted' && this.params.autoplay) {\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n if (this.currentState === 'playing') this.onVideoPlay();\n \n if (this.currentState === 'paused') this.onVideoPause();\n\n this.dispatchEvent('video-background-state-change');\n }\n\n onVideoPlay() {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n\n const seconds = this.player.getCurrentTime();\n if (this.params['start-at'] && seconds < this.params['start-at'] ) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n if (!this.duration) {\n this.setDuration(this.player.getDuration());\n }\n\n this.dispatchEvent('video-background-play');\n this.startTimeUpdateTimer();\n }\n\n onVideoPause() {\n this.stopTimeUpdateTimer();\n this.dispatchEvent('video-background-pause');\n }\n\n onVideoEnded() {\n this.dispatchEvent('video-background-ended');\n\n if (!this.params.loop) return this.pause();\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage), true);\n }\n\n seekTo(seconds, allowSeekAhead = true) {\n if (!this.player) return;\n this.player.seekTo(seconds, allowSeekAhead);\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.stopTimeUpdateTimer();\n this.player.pauseVideo();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.playVideo();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n \n this.player.playVideo();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n this.stopTimeUpdateTimer();\n this.player.pauseVideo();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.player.unMute();\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.mute();\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.getVolume() / 100;\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.setVolume(volume * 100);\n this.dispatchEvent('video-background-volume-change');\n }\n}\n ", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_VIMEO } from 'book-of-spells';\n\nexport class VimeoBackground extends SuperVideoBackground {\n constructor(elem, params, id, uid, factoryInstance) {\n super(elem, params, id, uid, 'vimeo', factoryInstance);\n if (!id) return;\n if (this.is_mobile && !this.params.mobile) return;\n this.injectScript();\n\n this.player = null;\n\n this.injectPlayer();\n\n this.initVimeoPlayer();\n }\n\n injectScript() {\n if (window.hasOwnProperty('Vimeo') || document.querySelector('script[src=\"https://player.vimeo.com/api/player.js\"]')) return;\n const tag = document.createElement('script');\n if (window.hasOwnProperty('onVimeoIframeAPIReady') && typeof window.onVimeoIframeAPIReady === 'function') tag.addEventListener('load', () => {\n window.onVimeoIframeAPIReady();\n });\n tag.src = 'https://player.vimeo.com/api/player.js';\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n }\n\n initVimeoPlayer() {\n if (!window.hasOwnProperty('Vimeo') || this.player !== null) return;\n this.player = new Vimeo.Player(this.playerElement);\n \n this.player.on('loaded', this.onVideoPlayerReady.bind(this));\n this.player.on('ended', this.onVideoEnded.bind(this));\n this.player.on('play', this.onVideoPlay.bind(this));\n this.player.on('pause', this.onVideoPause.bind(this));\n this.player.on('bufferstart', this.onVideoBuffering.bind(this));\n this.player.on('timeupdate', this.onVideoTimeUpdate.bind(this));\n // this.player.on('error', this.onVideoError.bind(this));\n\n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n }\n\n onVideoError(event) {\n console.error(event);\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('iframe');\n playerElement.setAttribute('frameborder', 0);\n playerElement.setAttribute('allow', 'autoplay; mute');\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n generateSrcURL(id) {\n let src = 'https://player.vimeo.com/video/'+id+'?background=1&controls=0';\n \n if (this.params.muted) {\n src += '&muted=1';\n }\n \n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n src += '&autoplay=1';\n }\n\n if (this.params.loop) {\n src += '&loop=1&autopause=0';\n }\n \n if (this.params['no-cookie']) {\n src += '&dnt=1';\n }\n \n //WARN\u2757\uFE0F: this is a hash not a query param\n if (this.params['start-at']) {\n src += '#t=' + this.params['start-at'] + 's';\n }\n\n return src;\n }\n\n injectPlayer() {\n this.playerElement = this.generatePlayerElement();\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n this.playerElement.id = this.uid;\n \n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(this.playerElement);\n }\n\n updateState(state) {\n this.currentState = state;\n this.dispatchEvent('video-background-state-change');\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_VIMEO);\n if (!pts || !pts.length) return;\n\n this.id = pts[1];\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n this.loadBackground(this.id);\n }\n\n onVideoPlayerReady() {\n this.mobileLowBatteryAutoplayHack();\n\n if (this.params['start-at']) this.seekTo(this.params['start-at']);\n\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n this.player.play();\n }\n\n this.player.getDuration().then((duration) => {\n this.setDuration(duration);\n });\n\n this.dispatchEvent('video-background-ready');\n }\n\n onVideoEnded() {\n this.updateState('ended');\n this.dispatchEvent('video-background-ended');\n if (!this.params.loop) return this.pause();\n \n this.seekTo(this.params['start-at']);\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoTimeUpdate(event) {\n this.currentTime = event.seconds;\n this.percentComplete = this.timeToPercentage(event.seconds);\n this.dispatchEvent('video-background-time-update');\n this.setDuration(event.duration);\n\n if (this.params['end-at'] && this.duration && event.seconds >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n onVideoPlay(event) {\n this.setDuration(event.duration);\n\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n\n // gotta set loop manually, cause for some reason it's true by default\n this.player.setLoop(this.params.loop);\n\n //Hotfixing an issue that it automatically starts playing after buffering on the first load, sometimes, not always, for an unknown reason\n if (!(this.params.autoplay && (this.params['always-play'] || this.isIntersecting))) {\n return this.player.pause();\n }\n }\n\n const seconds = event.seconds;\n if (this.params['start-at'] && seconds < this.params['start-at']) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoPause() {\n this.updateState('paused');\n this.dispatchEvent('video-background-pause');\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage));\n }\n\n seekTo(time) {\n if (!this.player) return;\n this.player.setCurrentTime(time);\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.player.setMuted(false);\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.setMuted(true);\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.getVolume();\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.setVolume(volume);\n this.dispatchEvent('video-background-volume-change');\n }\n}\n", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_VIDEO } from 'book-of-spells';\n\nexport class VideoBackground extends SuperVideoBackground {\n constructor(elem, params, vid_data, uid, factoryInstance) {\n super(elem, params, vid_data.link, uid, 'video', factoryInstance);\n if (!vid_data || !vid_data.link) return;\n if (this.is_mobile && !this.params.mobile) return;\n\n this.src = vid_data.link;\n this.ext = /(?:\\.([^.]+))?$/.exec(vid_data.id)[1];\n this.uid = uid;\n this.element.setAttribute('data-vbg-uid', uid);\n this.player = null;\n this.buttons = {};\n\n this.MIME_MAP = {\n 'ogv' : 'video/ogg',\n 'ogm' : 'video/ogg',\n 'ogg' : 'video/ogg',\n 'avi' : 'video/avi',\n 'mp4' : 'video/mp4',\n 'webm' : 'video/webm'\n };\n\n this.mime = this.MIME_MAP[this.ext.toLowerCase()];\n\n this.injectPlayer();\n\n this.mobileLowBatteryAutoplayHack();\n this.dispatchEvent('video-background-ready');\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('video');\n playerElement.setAttribute('playsinline', '');\n if (this.params.loop) playerElement.setAttribute('loop', '');\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n playerElement.setAttribute('autoplay', '');\n playerElement.autoplay = true;\n }\n if (this.muted) {\n playerElement.setAttribute('muted', '');\n playerElement.muted = true;\n }\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n injectPlayer() {\n this.player = this.generatePlayerElement();\n this.playerElement = this.player;\n \n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n \n this.playerElement.setAttribute('id', this.uid)\n \n this.stylePlayerElement(this.playerElement);\n\n this.player.addEventListener('loadedmetadata', this.onVideoLoadedMetadata.bind(this));\n this.player.addEventListener('durationchange', this.onVideoLoadedMetadata.bind(this));\n this.player.addEventListener('canplay', this.onVideoCanPlay.bind(this));\n this.player.addEventListener('timeupdate', this.onVideoTimeUpdate.bind(this));\n this.player.addEventListener('play', this.onVideoPlay.bind(this));\n this.player.addEventListener('pause', this.onVideoPause.bind(this));\n this.player.addEventListener('waiting', this.onVideoBuffering.bind(this));\n this.player.addEventListener('ended', this.onVideoEnded.bind(this));\n\n this.element.appendChild(this.playerElement);\n const source = document.createElement('source');\n source.setAttribute('src', this.src);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n this.resize(this.playerElement);\n }\n\n updateState(state) {\n this.currentState = state;\n this.dispatchEvent('video-background-state-change');\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_VIDEO);\n if (!pts || !pts.length) return;\n this.id = pts[1];\n this.ext = /(?:\\.([^.]+))?$/.exec(this.id)[1];\n this.mime = this.MIME_MAP[this.ext.toLowerCase()];\n this.playerElement.innerHTML = '';\n const source = document.createElement('source');\n source.setAttribute('src', url);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n this.src = url;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n }\n\n onVideoLoadedMetadata() {\n this.setDuration(this.player.duration);\n }\n\n onVideoCanPlay() {\n this.setDuration(this.player.duration);\n }\n\n onVideoTimeUpdate() {\n this.currentTime = this.player.currentTime;\n this.percentComplete = this.timeToPercentage(this.player.currentTime);\n this.dispatchEvent('video-background-time-update');\n\n if (this.params['end-at'] && this.currentTime >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoPlay() {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n \n const seconds = this.player.currentTime;\n if (this.params['start-at'] && seconds <= this.params['start-at']) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoPause() {\n this.updateState('paused');\n this.dispatchEvent('video-background-pause');\n }\n\n onVideoEnded() {\n this.updateState('ended');\n this.dispatchEvent('video-background-ended');\n if (!this.params.loop) return this.pause();\n \n this.seekTo(this.params['start-at']);\n this.onVideoPlay();\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage));\n }\n\n seekTo(seconds) {\n if (!this.player) return;\n if (this.player.hasOwnProperty('fastSeek')) {\n this.player.fastSeek(seconds);\n return;\n }\n this.player.currentTime = seconds;\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n\n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n this.player.muted = false;\n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.muted = true;\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.volume;\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.volume = volume;\n this.dispatchEvent('video-background-volume-change');\n }\n}\n", "import { YoutubeBackground } from './lib/youtube-background.js';\nimport { VimeoBackground } from './lib/vimeo-background.js';\nimport { VideoBackground } from './lib/video-background.js';\n\nimport { randomIntInclusive, RE_VIMEO, RE_YOUTUBE, RE_VIDEO } from 'book-of-spells';\n\nexport class VideoBackgrounds {\n constructor(selector, params) {\n this.elements = selector;\n if (this.elements instanceof Element) this.elements = [this.elements];\n if (typeof this.elements === 'string') this.elements = document.querySelectorAll(selector);\n\n this.index = {};\n\n const self = this;\n\n this.intersectionObserver = null;\n\n if ('IntersectionObserver' in window) {\n this.intersectionObserver = new IntersectionObserver(function (entries) {\n entries.forEach(function (entry) {\n const uid = entry.target.getAttribute('data-vbg-uid');\n \n if (uid && self.index.hasOwnProperty(uid) && entry.isIntersecting) {\n self.index[uid].isIntersecting = true;\n try {\n if (self.index[uid].player && !self.index[uid].paused) self.index[uid].softPlay();\n } catch (e) {\n // console.log(e);\n }\n } else {\n self.index[uid].isIntersecting = false;\n try {\n if (self.index[uid].player) self.index[uid].softPause();\n } catch (e) {\n // console.log(e);\n }\n }\n });\n });\n }\n\n this.resizeObserver = null;\n\n if ('ResizeObserver' in window) {\n this.resizeObserver = new ResizeObserver(function (entries) {\n entries.forEach(function (entry) {\n const uid = entry.target.getAttribute('data-vbg-uid');\n\n if (uid && self.index.hasOwnProperty(uid)) {\n window.requestAnimationFrame(() => self.index[uid].resize());\n }\n });\n });\n } else {\n window.addEventListener('resize', function () {\n for (let k in self.index) {\n window.requestAnimationFrame(() => self.index[k].resize(self.index[k].playerElement));\n }\n });\n }\n \n this.initPlayers();\n\n if (!this.elements || !this.elements.length) return;\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n this.add(element, params);\n }\n\n document.addEventListener('visibilitychange', this.onVisibilityChange.bind(this));\n }\n\n onVisibilityChange() {\n if (document.hidden) return;\n\n for (let k in this.index) {\n const instance = this.index[k];\n if (instance.shouldPlay()) {\n instance.softPlay();\n }\n }\n }\n\n add(element, params) {\n if (!element) return;\n if (element.hasAttribute('data-vbg-uid')) return;\n\n if (!this.intersectionObserver) {\n if (!params) params = {};\n params['always-play'] = true;\n }\n\n const link = element.getAttribute('data-youtube') || element.getAttribute('data-vbg');\n const vid_data = this.getVidID(link);\n \n if (!vid_data) return;\n \n const uid = this.generateUID(vid_data.id);\n \n if (!uid) return;\n \n switch (vid_data.type) {\n case 'YOUTUBE':\n const yb = new YoutubeBackground(element, params, vid_data.id, uid, this);\n this.index[uid] = yb;\n break;\n case 'VIMEO':\n const vm = new VimeoBackground(element, params, vid_data.id, uid, this);\n this.index[uid] = vm;\n break;\n case 'VIDEO':\n const vid = new VideoBackground(element, params, vid_data, uid, this);\n this.index[uid] = vid;\n break;\n }\n\n if (this.resizeObserver) {\n this.resizeObserver.observe(element);\n }\n \n if (!this.index[uid].params['always-play'] && this.intersectionObserver) {\n this.intersectionObserver.observe(element);\n }\n }\n\n destroy(element) {\n const uid = element.uid || element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) {\n if (!this.index[uid].params['always-play'] && this.intersectionObserver) this.intersectionObserver.unobserve(element);\n if (this.resizeObserver) this.resizeObserver.unobserve(element);\n this.index[uid].destroy();\n delete this.index[uid];\n }\n }\n\n destroyAll() {\n for (let k in this.index) {\n this.destroy(this.index[k].playerElement);\n }\n }\n\n getVidID(link) {\n if (link === undefined && link === null) return;\n\n this.re = {};\n this.re.YOUTUBE = RE_YOUTUBE;\n this.re.VIMEO = RE_VIMEO;\n this.re.VIDEO = RE_VIDEO;\n \n for (let k in this.re) {\n const pts = link.match(this.re[k]);\n\n if (pts && pts.length) {\n this.re[k].lastIndex = 0;\n return {\n id: pts[1],\n type: k,\n regex_pts: pts,\n link: link\n };\n }\n }\n \n return;\n }\n\n generateUID(pref) {\n //index the instance\n pref = pref.replace(/[^a-zA-Z0-9\\-_]/g, '-'); //sanitize id\n pref = pref.replace(/-{2,}/g, '-'); //remove double dashes\n pref = pref.replace(/^-+/, '').replace(/-+$/, ''); //trim dashes\n pref = 'vbg-'+ pref; //prefix id with 'vbg-\n\n let uid = pref +'-'+ randomIntInclusive(0, 9999);\n while (this.index.hasOwnProperty(uid)) {\n uid = pref +'-'+ randomIntInclusive(0, 9999);\n }\n \n return uid;\n }\n\n get(element) {\n const uid = typeof element === 'string' ? element : element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) return this.index[uid];\n }\n\n pauseAll() {\n for (let k in this.index) {\n this.index[k].pause();\n }\n }\n\n playAll() {\n for (let k in this.index) {\n this.index[k].play();\n }\n }\n\n muteAll() {\n for (let k in this.index) {\n this.index[k].mute();\n }\n }\n\n unmuteAll() {\n for (let k in this.index) {\n this.index[k].unmute();\n }\n }\n\n setVolumeAll(volume) {\n for (let k in this.index) {\n this.index[k].setVolume(volume);\n }\n }\n\n initPlayers(callback) {\n const self = this;\n \n window.onYouTubeIframeAPIReady = function () {\n for (let k in self.index) {\n if (self.index[k] instanceof YoutubeBackground) {\n self.index[k].initYTPlayer();\n }\n }\n \n if (callback) {\n setTimeout(callback, 100);\n }\n };\n \n if (window.hasOwnProperty('YT') && window.YT.loaded) {\n window.onYouTubeIframeAPIReady();\n }\n \n window.onVimeoIframeAPIReady = function () {\n for (let k in self.index) {\n if (self.index[k] instanceof VimeoBackground) {\n self.index[k].initVimeoPlayer();\n }\n }\n \n if (callback) {\n setTimeout(callback, 100);\n }\n }\n \n if (window.hasOwnProperty('Vimeo') && window.Vimeo.hasOwnProperty('Player')) {\n window.onVimeoIframeAPIReady();\n }\n }\n}\n", "import { VideoBackgrounds } from './video-backgrounds.js';\n\nif (typeof jQuery == 'function') {\n (function ($) {\n $.fn.youtube_background = function (params) {\n const $this = $(this);\n if (window.hasOwnProperty('VIDEO_BACKGROUNDS')) {\n window.VIDEO_BACKGROUNDS.add($this, params);\n return $this;\n }\n window.VIDEO_BACKGROUNDS = new VideoBackgrounds(this, params);\n return $this;\n };\n })(jQuery);\n}\n\nwindow.VideoBackgrounds = VideoBackgrounds;\n"],
- "mappings": ";;;AACA,WAAS,SAAS,WAAW;AAC3B,QAAI,CAAC;AAAW;AAChB,cAAU,QAAQ,UAAU,IAAI,UAAU,cAAc;AACxD,cAAU,QAAQ,WAAW,UAAU,OAAO,UAAU,qBAAqB,CAAC,CAAC;AAC/E,cAAU,QAAQ,WAAW,UAAU,IAAI,UAAU,qBAAqB,CAAC,CAAC;AAC5E,cAAU,QAAQ,aAAa,gBAAgB,KAAK;AAAA,EACtD;AAEA,WAAS,UAAU,WAAW;AAC5B,QAAI,CAAC;AAAW;AAChB,cAAU,QAAQ,UAAU,OAAO,UAAU,cAAc;AAC3D,cAAU,QAAQ,WAAW,UAAU,IAAI,UAAU,qBAAqB,CAAC,CAAC;AAC5E,cAAU,QAAQ,WAAW,UAAU,OAAO,UAAU,qBAAqB,CAAC,CAAC;AAC/E,cAAU,QAAQ,aAAa,gBAAgB,IAAI;AAAA,EACrD;AAEO,WAAS,qBAAqB,KAAK,OAAO;AAC/C,UAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,QAAI,YAAY,MAAM;AACtB,QAAI,YAAY,MAAM;AACtB,QAAI,aAAa,QAAQ,QAAQ;AACjC,QAAI,WAAW,UAAU,IAAI,MAAM,qBAAqB,CAAC,CAAC;AAC1D,QAAI,aAAa,gBAAgB,CAAC,MAAM,YAAY;AACpD,UAAM,UAAU;AAEhB,QAAI,IAAI,OAAO,MAAM,mBAAmB,MAAM,MAAM,cAAc;AAChE,eAAS,KAAK;AAAA,IAChB;AAEA,QAAI,iBAAiB,SAAS,SAAS,GAAG;AACxC,UAAI,KAAK,UAAU,SAAS,MAAM,cAAc,GAAG;AACjD,kBAAU,KAAK;AACf,YAAI,MAAM,QAAQ,CAAC,CAAC,EAAE;AAAA,MACxB,OAAO;AACL,iBAAS,KAAK;AACd,YAAI,MAAM,QAAQ,CAAC,CAAC,EAAE;AAAA,MACxB;AAAA,IACF,CAAC;AAED,QAAI,QAAQ,MAAM,IAAI,IAAI;AAAA,MACxB,SAAS;AAAA,MACT,mBAAmB;AAAA,IACrB;AAEA,QAAI,iBAAiB,YAAY,GAAG;AAAA,EACtC;;;AC+FO,WAAS,gBAAgB,KAAK;AACnC,QAAI,wBAAwB,KAAK,GAAG;AAAG,aAAO,QAAQ;AAAA,EACxD;AAaO,WAAS,eAAe,KAAK;AAClC,QAAI,cAAc,KAAK,GAAG;AAAG,aAAO,SAAS,GAAG;AAChD,QAAI,iBAAiB,KAAK,GAAG;AAAG,aAAO,WAAW,GAAG;AAAA,EACvD;AAaO,WAAS,cAAc,KAAK;AACjC,QAAI,CAAC,iBAAiB,KAAK,GAAG;AAAG;AACjC,QAAI;AACF,aAAO,KAAK,MAAM,GAAG;AAAA,IACvB,SAAS,GAAG;AAAA,IAAC;AAAA,EACf;AAaO,WAAS,eAAe,KAAK;AAClC,QAAI,CAAC,iBAAiB,KAAK,GAAG;AAAG;AACjC,QAAI;AACF,aAAO,KAAK,MAAM,GAAG;AAAA,IACvB,SAAS,GAAG;AAAA,IAAC;AAAA,EACf;AAYO,WAAS,cAAc,KAAK;AACjC,QAAI,CAAC,qBAAqB,KAAK,GAAG;AAAG;AACrC,QAAI;AACF,aAAO,IAAI,OAAO,GAAG;AAAA,IACvB,SAAS,GAAG;AAAA,IAAC;AAAA,EACf;AAwCO,WAAS,aAAa,KAAK;AAChC,QAAI,eAAe,KAAK,GAAG;AAAG,aAAO;AACrC,UAAM,OAAO,gBAAgB,GAAG;AAChC,QAAI,SAAS;AAAW,aAAO;AAC/B,WAAO,eAAe,GAAG,KAAK,cAAc,GAAG,KAAK,eAAe,GAAG,KAAK,cAAc,GAAG,KAAK;AAAA,EACnG;AAyBO,WAAS,QAAQ,GAAG;AACzB,WAAO,MAAM,QAAQ,CAAC;AAAA,EACxB;AAWO,WAAS,SAAS,GAAG;AAC1B,WAAO,OAAO,MAAM;AAAA,EACtB;AAiOO,WAAS,mBAAmB,KAAK,KAAK,OAAO,OAAO;AACzD,UAAM,OAAO,GAAG;AAChB,UAAM,OAAO,GAAG;AAChB,QAAI,MAAM,GAAG,KAAK,MAAM,GAAG;AAAG,YAAM,IAAI,UAAU,kCAAkC;AACpF,QAAI,MAAM;AAAK,OAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;AACrC,QAAI,QAAQ;AAAK,aAAO;AACxB,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,OAAO,OAAO,OAAO,IAAI,KAAK,OAAO;AAC3C,WAAO,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,IAAI;AAAA,EAC9C;AAgBO,WAAS,MAAM,QAAQ,QAAQ;AACpC,QAAI,CAAC;AAAQ,aAAO,SAAS,MAAM;AACnC,WAAO,WAAW,OAAO,QAAQ,MAAM,CAAC;AAAA,EAC1C;AAeO,WAAS,WAAW,KAAK,OAAO;AACrC,QAAI,CAAC,OAAO,CAAC,SAAS,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,KAAK;AAAG,aAAO;AACvE,WAAO,MAAM,QAAQ;AAAA,EACvB;AA4JO,WAAS,SAAS;AACvB,QAAI,CAAC;AAAQ,aAAO,KAAK,OAAO;AAChC,QAAI,OAAO;AAAiB,aAAO,OAAO,gBAAgB,IAAI,YAAY,CAAC,CAAC,EAAE,CAAC,IAAI;AAAA,EACrF;;;ACjtBO,MAAM,aAAa;AAKnB,MAAM,WAAW;AAKjB,MAAM,WAAW;;;ACwKjB,WAAS,sBAAsB,KAAK;AACzC,UAAM,qBAAqB;AAC3B,QAAI,CAAC,OAAO,CAAC,IAAI,UAAU,mBAAmB,KAAK,GAAG;AAAG,aAAO;AAChE,UAAM,MAAM,IAAI,MAAM,qBAAqB;AAC3C,QAAI,IAAI,SAAS;AAAG,aAAO;AAE3B,UAAM,IAAI,SAAS,IAAI,CAAC,CAAC;AACzB,UAAM,IAAI,SAAS,IAAI,CAAC,CAAC;AAEzB,QAAI,MAAM,KAAK,MAAM;AAAG,aAAO;AAC/B,QAAI,MAAM,CAAC,KAAK,MAAM,CAAC;AAAG,aAAO;AAEjC,WAAO,IAAE;AAAA,EACX;;;ACrHO,WAAS,MAAM,UAAU,OAAO,UAAU;AAC/C,QAAI,oBAAoB,SAAS,oBAAoB;AAAU,aAAO;AACtE,QAAI,oBAAoB;AAAS,aAAO,CAAC,QAAQ;AACjD,QAAI,gBAAgB,WAAW,gBAAgB;AAAU,aAAO,KAAK,iBAAiB,QAAQ;AAC9F,QAAI,SAAS,IAAI;AAAG,aAAO,MAAM,IAAI;AACrC,QAAI,CAAC,gBAAgB,SAAU,CAAC,gBAAgB;AAAU,aAAO,CAAC;AAClE,UAAM,MAAM,CAAC;AACb,eAAW,WAAW,MAAM;AAC1B,UAAI,KAAK,GAAG,QAAQ,iBAAiB,QAAQ,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AA6dO,WAAS,8BAA8B,UAAU,QAAQ,GAAG,SAAS,GAAG;AAC7E,QAAI,oBAAoB;AAAS,iBAAW,CAAC,QAAQ;AACrD,QAAI,OAAO,aAAa;AAAU,iBAAW,MAAM,QAAQ;AAE3D,eAAW,WAAW,UAAU;AAC9B,YAAM,IAAI,QAAQ,WAAW,eAAe;AAC5C,YAAM,IAAI,QAAQ,WAAW,cAAc;AAE3C,UAAI,QAAQ,IAAE,GAAG;AACf,gBAAQ,MAAM,QAAQ,IAAE,QAAQ;AAChC,gBAAQ,MAAM,SAAS,IAAI;AAAA,MAC7B,OAAO;AACL,gBAAQ,MAAM,QAAQ,IAAI;AAC1B,gBAAQ,MAAM,SAAS,IAAE,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;;;AC/jBO,WAAS,kBAAkB,KAAK;AACrC,WAAO,0CAA0C,KAAK,GAAG,KACvD,yCAAyC,KAAK,GAAG;AAAA,EACrD;AAoBO,WAAS,WAAW;AACzB,QAAI,oBAAoB;AAAW,aAAO,UAAU,iBAAiB;AAErE,QAAI,gBAAgB;AAAQ,aAAO,CAAC,CAAC,WAAW,kBAAkB,EAAE;AAEpE,QAAI,iBAAiB;AAAQ,aAAO;AAEpC,WAAO,kBAAkB,UAAU,SAAS;AAAA,EAC9C;;;ACtCO,MAAM,uBAAN,MAA2B;AAAA,IAChC,YAAY,MAAM,QAAQ,IAAI,KAAK,MAAM,iBAAiB;AACxD,UAAI,CAAC;AAAI;AACT,WAAK,YAAY,SAAS;AAC1B,WAAK,OAAO;AACZ,WAAK,KAAK;AACV,WAAK,kBAAkB;AAEvB,WAAK,UAAU;AACf,WAAK,gBAAgB;AACrB,WAAK,MAAM;AACX,WAAK,QAAQ,aAAa,gBAAgB,GAAG;AAE7C,WAAK,UAAU,CAAC;AAChB,WAAK,iBAAiB;AAEtB,WAAK,SAAS;AACd,WAAK,QAAQ;AACb,WAAK,eAAe;AAEpB,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAErB,WAAK,SAAS;AAEd,WAAK,SAAS,CAAC;AAEf,YAAM,WAAW;AAAA,QACf,SAAS;AAAA;AAAA,QACT,eAAe;AAAA,QACf,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,mBAAmB;AAAA,QACnB,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,WAAW;AAAA,QACX,UAAU;AAAA;AAAA,QACV,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,UAAU;AAAA,QACV,eAAe;AAAA,QACf,UAAU;AAAA,QACV,aAAa;AAAA,QACb,wBAAwB;AAAA,QACxB,eAAe;AAAA,MACjB;AAEA,WAAK,SAAS,KAAK,gBAAgB,QAAQ,UAAU,KAAK,SAAS,CAAC,cAAc,WAAW,CAAC;AAG9F,UAAI,KAAK,OAAO,OAAO;AACrB,aAAK,OAAO,aAAa,IAAI,KAAK,OAAO;AAAA,MAC3C;AAEA,WAAK,OAAO,iBAAiB,sBAAsB,KAAK,OAAO,UAAU;AAEzE,WAAK,QAAQ,KAAK,OAAO;AAEzB,WAAK,SAAS,KAAK,OAAO;AAE1B,WAAK,cAAc,KAAK,OAAO,UAAU,KAAK;AAC9C,WAAK,WAAW,KAAK,OAAO,QAAQ,KAAK;AACzC,WAAK,kBAAkB;AACvB,UAAI,KAAK,OAAO,UAAU;AAAG,aAAK,kBAAkB,KAAK,iBAAiB,KAAK,OAAO,UAAU,CAAC;AAEjG,WAAK,iBAAiB;AAEtB,UAAI,KAAK,aAAa,CAAC,KAAK,OAAO;AAAQ;AAE3C,UAAI,KAAK,OAAO,aAAa,GAAG;AAC9B,6BAAqB,MAAM;AAAA,UACzB,MAAM;AAAA,UACN,WAAW;AAAA,UACX,WAAW;AAAA,UACX,cAAc,CAAC,KAAK;AAAA,UACpB,gBAAgB;AAAA,UAChB,qBAAqB;AAAA,UACrB,sBAAsB,CAAC,mBAAmB,gBAAgB;AAAA,UAC1D,SAAS,CAAC,QAAQ,OAAO;AAAA,QAC3B,CAAC;AAAA,MACH;AAEA,UAAI,KAAK,OAAO,aAAa,GAAG;AAC9B,6BAAqB,MAAM;AAAA,UACzB,MAAM;AAAA,UACN,WAAW;AAAA,UACX,WAAW;AAAA,UACX,cAAc,KAAK;AAAA,UACnB,gBAAgB;AAAA,UAChB,qBAAqB;AAAA,UACrB,sBAAsB,CAAC,gBAAgB,gBAAgB;AAAA,UACvD,SAAS,CAAC,UAAU,MAAM;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,iBAAiB,MAAM;AACrB,UAAI,QAAQ,KAAK,OAAO,UAAU;AAAG,eAAO;AAC5C,UAAI,QAAQ,KAAK;AAAU,eAAO;AAClC,UAAI,QAAQ;AAAG,eAAO;AACtB,cAAQ,KAAK,OAAO,UAAU;AAC9B,YAAM,WAAW,KAAK,WAAW,KAAK,OAAO,UAAU;AACvD,aAAO,WAAW,MAAM,QAAQ;AAAA,IAClC;AAAA,IAEA,iBAAiBA,aAAY;AAC3B,UAAI,CAAC,KAAK;AAAU,eAAO,KAAK,OAAO,UAAU,KAAK;AACtD,UAAIA,cAAa;AAAK,eAAO,KAAK;AAClC,UAAIA,eAAc;AAAG,eAAO,KAAK,OAAO,UAAU,KAAK;AACvD,YAAM,WAAW,KAAK,WAAW,KAAK,OAAO,UAAU;AACvD,UAAI,OAAOA,cAAa,WAAW;AACnC,aAAO,MAAM,MAAM,CAAC;AACpB,UAAI,OAAO;AAAU,eAAO;AAC5B,UAAI,KAAK,OAAO,UAAU;AAAG,gBAAQ,KAAK,OAAO,UAAU;AAC3D,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,SAAS;AACd,UAAI,CAAC,KAAK,OAAO,SAAS;AAAG,sCAA8B,WAAW,KAAK,eAAe,KAAK,OAAO,gBAAgB,KAAK,OAAO,MAAM;AACxI,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,mBAAmB,SAAS;AAC1B,UAAI,CAAC;AAAS;AAEd,UAAI,KAAK,OAAO,eAAe,GAAG;AAChC,gBAAQ,MAAM,MAAM;AACpB,gBAAQ,MAAM,OAAO;AACrB,gBAAQ,MAAM,YAAY;AAC1B,gBAAQ,MAAM,WAAW;AACzB,gBAAQ,MAAM,UAAU;AAAA,MAC1B;AAEA,UAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,gBAAQ,MAAM,QAAQ;AACtB,gBAAQ,MAAM,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,IAEA,mBAAmB;AACjB,YAAM,SAAS,KAAK,QAAQ;AAE5B,WAAK,QAAQ,UAAU,IAAI,sBAAsB,kBAAkB;AAGnE,YAAM,iBAAiB;AAAA,QACrB,UAAW;AAAA,QACX,SAAU;AAAA,QACV,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,OAAO;AAAA;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAEA,UAAI,CAAC,KAAK,OAAO,aAAa,GAAG;AAC/B,uBAAe,gBAAgB,IAAI;AAAA,MACrC;AAEA,UAAI,KAAK,OAAO,iBAAiB,KAAK,KAAK,OAAO,QAAQ,GAAG;AAC3D,aAAK,eAAe,KAAK,EAAE;AAC3B,YAAI,KAAK,OAAO,QAAQ;AAAG,yBAAe,kBAAkB,IAAI,OAAQ,KAAK,OAAO,QAAQ,CAAE;AAC9F,uBAAe,iBAAiB,IAAI;AACpC,uBAAe,mBAAmB,IAAI;AACtC,uBAAe,qBAAqB,IAAI;AAAA,MAC1C;AAEA,UAAI,KAAK,OAAO,eAAe,GAAG;AAChC,iBAAS,YAAY,gBAAgB;AACnC,eAAK,QAAQ,MAAM,QAAQ,IAAI,eAAe,QAAQ;AAAA,QACxD;AAEA,YAAI,CAAC,CAAC,YAAY,SAAS,YAAY,QAAQ,EAAE,QAAQ,OAAO,MAAM,QAAQ,GAAG;AAC/E,iBAAO,MAAM,WAAW;AAAA,QAC1B;AAAA,MACF;AAGA,UAAI,KAAK,OAAO,aAAa,KAAK,KAAK,OAAO,aAAa,GAAG;AAC5D,cAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,iBAAS,YAAY;AAErB,iBAAS,MAAM,WAAW;AAC1B,iBAAS,MAAM,MAAM;AACrB,iBAAS,MAAM,QAAQ;AACvB,iBAAS,MAAM,SAAS,IAAI;AAE5B,aAAK,mBAAmB;AACxB,eAAO,YAAY,QAAQ;AAAA,MAC7B;AAEA,aAAO,KAAK;AAAA,IACd;AAAA,IAEA,eAAe,IAAI;AACjB,UAAI,CAAC,KAAK,OAAO,iBAAiB;AAAG;AACrC,UAAI,CAAC;AAAI;AACT,UAAI,KAAK,SAAS;AAAW,aAAK,QAAQ,MAAM,kBAAkB,IAAI,kCAAkC,EAAE;AAC1G,UAAI,KAAK,SAAS;AAAS,aAAK,QAAQ,MAAM,kBAAkB,IAAI,4BAA4B,EAAE;AAAA,IACpG;AAAA,IAEA,UAAU;AACR,WAAK,cAAc,OAAO;AAC1B,WAAK,QAAQ,UAAU,OAAO,sBAAsB,kBAAkB;AACtE,WAAK,QAAQ,gBAAgB,cAAc;AAC3C,WAAK,QAAQ,QAAQ;AAErB,UAAI,KAAK,OAAO,aAAa,KAAK,KAAK,OAAO,aAAa,GAAG;AAC5D,aAAK,iBAAiB,OAAO;AAAA,MAC/B;AAEA,UAAI,KAAK;AAAiB,sBAAc,KAAK,eAAe;AAC5D,WAAK,cAAc,4BAA4B;AAAA,IACjD;AAAA,IAEA,YAAY,UAAU;AACpB,UAAI,KAAK,aAAa;AAAU;AAEhC,UAAI,KAAK,OAAO,QAAQ,GAAG;AACzB,YAAI,WAAW,KAAK,OAAO,QAAQ,GAAG;AACpC,eAAK,WAAW,KAAK,OAAO,QAAQ;AACpC;AAAA,QACF;AACA,YAAI,WAAW,KAAK,OAAO,QAAQ,GAAG;AACpC,eAAK,WAAW;AAChB;AAAA,QACF;AAAA,MACF,OAAO;AACL,aAAK,WAAW;AAChB;AAAA,MACF;AAEA,UAAI,YAAY;AAAG,aAAK,WAAW,KAAK,OAAO,QAAQ;AAAA,IACzD;AAAA,IAEA,WAAW,SAAS;AAClB,WAAK,OAAO,UAAU,IAAI;AAAA,IAC5B;AAAA,IAEA,SAAS,OAAO;AACd,WAAK,OAAO,QAAQ,IAAI;AACxB,UAAI,KAAK,WAAW;AAAO,aAAK,WAAW;AAC3C,UAAI,KAAK,cAAc;AAAO,aAAK,aAAa;AAAA,IAClD;AAAA,IAEA,cAAc,MAAM;AAClB,WAAK,QAAQ,cAAc,IAAI,YAAY,MAAM,EAAE,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IACnF;AAAA,IAEA,aAAa;AACX,UAAI,KAAK,iBAAiB,WAAW,CAAC,KAAK,OAAO;AAAM,eAAO;AAC/D,UAAI,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAAW,eAAO;AAC1E,UAAI,KAAK,kBAAkB,KAAK,OAAO,YAAY,KAAK,iBAAiB;AAAW,eAAO;AAC3F,aAAO;AAAA,IACT;AAAA,IAEA,+BAA+B;AAC7B,UAAI,CAAC,KAAK,OAAO,sBAAsB;AAAG;AAC1C,UAAI,CAAC,KAAK,aAAa,KAAK,OAAO;AAAQ;AAE3C,YAAM,gBAAgB,WAAW;AAC/B,YAAI,CAAC,KAAK,eAAe,KAAK,OAAO,YAAY,KAAK,OAAO,OAAO;AAClE,eAAK,SAAS;AAEd,cAAI,CAAC,KAAK,kBAAkB,CAAC,KAAK,OAAO,aAAa,GAAG;AACvD,iBAAK,UAAU;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAEA,eAAS,iBAAiB,cAAc,cAAc,KAAK,IAAI,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,IAClF;AAAA,IAEA,gBAAgB,QAAQ,UAAU,SAAS,aAAa;AACtD,UAAI,aAAa,CAAC;AAElB,UAAI,CAAC,QAAQ;AACX,qBAAa;AAAA,MACf,OAAO;AACL,iBAAS,KAAK,UAAU;AAEtB,qBAAW,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,IAAI,SAAS,CAAC,IAAI,OAAO,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,UAAI,CAAC;AAAS,eAAO;AAErB,eAAS,KAAK,YAAY;AACxB,YAAI;AAEJ,YAAI,QAAQ,WAAW,GAAG;AACxB,mBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,kBAAM,YAAY,QAAQ,aAAa,YAAY,CAAC,IAAE,CAAC;AACvD,gBAAI,WAAW;AACb,qBAAO;AACP;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,QAAQ,aAAa,cAAY,CAAC;AAAA,QAC3C;AAEA,YAAI,SAAS,UAAa,SAAS,MAAM;AACvC,qBAAW,CAAC,IAAI,aAAa,IAAI;AAAA,QACnC;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;;;AC1TO,MAAM,oBAAN,cAAgC,qBAAqB;AAAA,IAC1D,YAAY,MAAM,QAAQ,IAAI,KAAK,iBAAiB;AAClD,YAAM,MAAM,QAAQ,IAAI,KAAK,WAAW,eAAe;AAEvD,UAAI,CAAC;AAAI;AACT,UAAI,KAAK,aAAa,CAAC,KAAK,OAAO;AAAQ;AAC3C,WAAK,aAAa;AAElB,WAAK,SAAS;AAEd,WAAK,aAAa;AAElB,WAAK,SAAS;AAAA,QACZ,MAAM;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,WAAK,kBAAkB;AACvB,WAAK,qBAAqB;AAE1B,WAAK,aAAa;AAAA,IACpB;AAAA,IAEA,uBAAuB;AACrB,UAAI,KAAK;AAAiB;AAC1B,WAAK,kBAAkB,YAAY,KAAK,kBAAkB,KAAK,IAAI,GAAG,KAAK,kBAAkB;AAAA,IAC/F;AAAA,IAEA,sBAAsB;AACpB,oBAAc,KAAK,eAAe;AAClC,WAAK,kBAAkB;AAAA,IACzB;AAAA,IAEA,aAAa,OAAO;AAClB,aAAO,KAAK,OAAO,KAAK;AAAA,IAC1B;AAAA,IAEA,eAAe;AACb,UAAI,CAAC,OAAO,eAAe,IAAI,KAAK,KAAK,WAAW;AAAM;AAE1D,WAAK,SAAS,IAAI,GAAG,OAAO,KAAK,KAAK;AAAA,QACpC,QAAQ;AAAA,UACN,WAAW,KAAK,mBAAmB,KAAK,IAAI;AAAA,UAC5C,iBAAiB,KAAK,mBAAmB,KAAK,IAAI;AAAA;AAAA,QAEpD;AAAA,MACF,CAAC;AAED,UAAI,KAAK,WAAW,KAAK,CAAC,KAAK;AAAO,aAAK,UAAU,KAAK,MAAM;AAAA,IAClE;AAAA,IAEA,aAAa,OAAO;AAClB,cAAQ,MAAM,KAAK;AAAA,IACrB;AAAA,IAEA,eAAe;AACb,UAAI,OAAO,eAAe,IAAI,KAAK,SAAS,cAAc,kDAAkD;AAAG;AAC/G,YAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAI,MAAM;AACV,YAAM,iBAAiB,SAAS,qBAAqB,QAAQ,EAAE,CAAC;AAChE,qBAAe,WAAW,aAAa,KAAK,cAAc;AAAA,IAC5D;AAAA,IAEA,wBAAwB;AACtB,YAAM,gBAAgB,SAAS,cAAc,QAAQ;AACrD,oBAAc,aAAa,eAAe,CAAC;AAC3C,oBAAc,aAAa,SAAS,gBAAgB;AACpD,UAAI,KAAK,OAAO,aAAa;AAAG,sBAAc,aAAa,WAAW,MAAM;AAE5E,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,IAAI;AACjB,UAAI,OAAO;AACX,UAAI,KAAK,OAAO,WAAW,GAAG;AAC5B,eAAO;AAAA,MACT;AACA,UAAI,MAAM,GAAG,IAAI,GAAG,EAAE;AAEtB,UAAI,KAAK,OAAO,OAAO;AACrB,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAC/E,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,MAAM;AACpB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,eAAe;AACb,WAAK,gBAAgB,KAAK,sBAAsB;AAChD,WAAK,MAAM,KAAK,eAAe,KAAK,EAAE;AACtC,WAAK,cAAc,MAAM,KAAK;AAC9B,WAAK,cAAc,KAAK,KAAK;AAE7B,WAAK,mBAAmB,KAAK,aAAa;AAC1C,WAAK,QAAQ,YAAY,KAAK,aAAa;AAC3C,WAAK,OAAO,KAAK,aAAa;AAAA,IAChC;AAAA;AAAA,IAIA,UAAU,KAAK;AACb,YAAM,MAAM,IAAI,MAAM,UAAU;AAChC,UAAI,CAAC,OAAO,CAAC,IAAI;AAAQ;AAEzB,WAAK,KAAK,IAAI,CAAC;AACf,WAAK,MAAM,KAAK,eAAe,KAAK,EAAE;AACtC,WAAK,cAAc,MAAM,KAAK;AAE9B,UAAI,KAAK,QAAQ,aAAa,UAAU;AAAG,aAAK,QAAQ,aAAa,YAAY,KAAK,GAAG;AACzF,UAAI,KAAK,QAAQ,aAAa,WAAW;AAAG,aAAK,QAAQ,aAAa,aAAa,KAAK,GAAG;AAC3F,WAAK,eAAe,KAAK,EAAE;AAAA,IAC7B;AAAA,IAEA,oBAAoB;AAClB,YAAM,QAAQ,KAAK,OAAO,eAAe;AACzC,UAAI,UAAU,KAAK;AAAa;AAChC,WAAK,cAAc;AACnB,WAAK,kBAAkB,KAAK,iBAAiB,KAAK,WAAW;AAC7D,UAAI,KAAK,OAAO,QAAQ,KAAK,KAAK,YAAY,KAAK,eAAe,KAAK,UAAU;AAC/E,aAAK,eAAe;AACpB,aAAK,cAAc,+BAA+B;AAClD,aAAK,aAAa;AAClB,aAAK,oBAAoB;AACzB;AAAA,MACF;AACA,WAAK,cAAc,8BAA8B;AAAA,IACnD;AAAA,IAEA,qBAAqB;AACnB,WAAK,6BAA6B;AAElC,UAAI,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAC/E,YAAI,KAAK,OAAO,UAAU;AAAG,eAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAChE,aAAK,OAAO,UAAU;AAAA,MACxB;AAEA,WAAK,YAAY,KAAK,OAAO,YAAY,CAAC;AAE1C,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,mBAAmB,OAAO;AACxB,WAAK,eAAe,KAAK,aAAa,MAAM,IAAI;AAEhD,UAAI,KAAK,iBAAiB;AAAS,aAAK,aAAa;AAErD,UAAI,KAAK,iBAAiB,gBAAgB,KAAK,OAAO,UAAU;AAC9D,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,aAAK,OAAO,UAAU;AAAA,MACxB;AAEA,UAAI,KAAK,iBAAiB;AAAW,aAAK,YAAY;AAEtD,UAAI,KAAK,iBAAiB;AAAU,aAAK,aAAa;AAEtD,WAAK,cAAc,+BAA+B;AAAA,IACpD;AAAA,IAEA,cAAc;AACZ,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,cAAc;AACnB,aAAK,cAAc,MAAM,UAAU;AAAA,MACrC;AAEA,YAAM,UAAU,KAAK,OAAO,eAAe;AAC3C,UAAI,KAAK,OAAO,UAAU,KAAK,UAAU,KAAK,OAAO,UAAU,GAAI;AACjE,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,UAAI,KAAK,YAAY,WAAW,KAAK,UAAU;AAC7C,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,UAAI,CAAC,KAAK,UAAU;AAClB,aAAK,YAAY,KAAK,OAAO,YAAY,CAAC;AAAA,MAC5C;AAEA,WAAK,cAAc,uBAAuB;AAC1C,WAAK,qBAAqB;AAAA,IAC5B;AAAA,IAEA,eAAe;AACb,WAAK,oBAAoB;AACzB,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,eAAe;AACb,WAAK,cAAc,wBAAwB;AAE3C,UAAI,CAAC,KAAK,OAAO;AAAM,eAAO,KAAK,MAAM;AACzC,WAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,KAAKC,aAAY;AACf,WAAK,OAAO,KAAK,iBAAiBA,WAAU,GAAG,IAAI;AAAA,IACrD;AAAA,IAEA,OAAO,SAAS,iBAAiB,MAAM;AACrC,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,OAAO,OAAO,SAAS,cAAc;AAC1C,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAU;AACpD,WAAK,oBAAoB;AACzB,WAAK,OAAO,WAAW;AAAA,IACzB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAW;AACrD,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,QAAQ;AACN,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AACd,WAAK,oBAAoB;AACzB,WAAK,OAAO,WAAW;AAAA,IACzB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,UAAI,CAAC,KAAK,eAAe;AACvB,aAAK,gBAAgB;AACrB,aAAK,UAAU,KAAK,OAAO,MAAM;AAAA,MACnC;AACA,WAAK,OAAO,OAAO;AACnB,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,WAAK,OAAO,KAAK;AACjB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK;AAAQ;AAClB,aAAO,KAAK,OAAO,UAAU,IAAI;AAAA,IACnC;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,UAAU,SAAS,GAAG;AAClC,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AChRO,MAAM,kBAAN,cAA8B,qBAAqB;AAAA,IACxD,YAAY,MAAM,QAAQ,IAAI,KAAK,iBAAiB;AAClD,YAAM,MAAM,QAAQ,IAAI,KAAK,SAAS,eAAe;AACrD,UAAI,CAAC;AAAI;AACT,UAAI,KAAK,aAAa,CAAC,KAAK,OAAO;AAAQ;AAC3C,WAAK,aAAa;AAElB,WAAK,SAAS;AAEd,WAAK,aAAa;AAElB,WAAK,gBAAgB;AAAA,IACvB;AAAA,IAEA,eAAe;AACb,UAAI,OAAO,eAAe,OAAO,KAAK,SAAS,cAAc,sDAAsD;AAAG;AACtH,YAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAI,OAAO,eAAe,uBAAuB,KAAK,OAAO,OAAO,0BAA0B;AAAY,YAAI,iBAAiB,QAAQ,MAAM;AAC3I,iBAAO,sBAAsB;AAAA,QAC/B,CAAC;AACD,UAAI,MAAM;AACV,YAAM,iBAAiB,SAAS,qBAAqB,QAAQ,EAAE,CAAC;AAChE,qBAAe,WAAW,aAAa,KAAK,cAAc;AAAA,IAC5D;AAAA,IAEA,kBAAkB;AAChB,UAAI,CAAC,OAAO,eAAe,OAAO,KAAK,KAAK,WAAW;AAAM;AAC7D,WAAK,SAAS,IAAI,MAAM,OAAO,KAAK,aAAa;AAEjD,WAAK,OAAO,GAAG,UAAU,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAC3D,WAAK,OAAO,GAAG,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AACpD,WAAK,OAAO,GAAG,QAAQ,KAAK,YAAY,KAAK,IAAI,CAAC;AAClD,WAAK,OAAO,GAAG,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AACpD,WAAK,OAAO,GAAG,eAAe,KAAK,iBAAiB,KAAK,IAAI,CAAC;AAC9D,WAAK,OAAO,GAAG,cAAc,KAAK,kBAAkB,KAAK,IAAI,CAAC;AAG9D,UAAI,KAAK,WAAW,KAAK,CAAC,KAAK;AAAO,aAAK,UAAU,KAAK,MAAM;AAAA,IAClE;AAAA,IAEA,aAAa,OAAO;AAClB,cAAQ,MAAM,KAAK;AAAA,IACrB;AAAA,IAEA,wBAAwB;AACtB,YAAM,gBAAgB,SAAS,cAAc,QAAQ;AACrD,oBAAc,aAAa,eAAe,CAAC;AAC3C,oBAAc,aAAa,SAAS,gBAAgB;AACpD,UAAI,KAAK,OAAO,aAAa;AAAG,sBAAc,aAAa,WAAW,MAAM;AAE5E,aAAO;AAAA,IACT;AAAA,IAEA,eAAe,IAAI;AACjB,UAAI,MAAM,oCAAkC,KAAG;AAE/C,UAAI,KAAK,OAAO,OAAO;AACrB,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAC/E,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,MAAM;AACpB,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,OAAO,WAAW,GAAG;AAC5B,eAAO;AAAA,MACT;AAGA,UAAI,KAAK,OAAO,UAAU,GAAG;AAC3B,eAAO,QAAQ,KAAK,OAAO,UAAU,IAAI;AAAA,MAC3C;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,eAAe;AACb,WAAK,gBAAgB,KAAK,sBAAsB;AAChD,WAAK,MAAM,KAAK,eAAe,KAAK,EAAE;AACtC,WAAK,cAAc,MAAM,KAAK;AAC9B,WAAK,cAAc,KAAK,KAAK;AAE7B,WAAK,mBAAmB,KAAK,aAAa;AAC1C,WAAK,QAAQ,YAAY,KAAK,aAAa;AAC3C,WAAK,OAAO,KAAK,aAAa;AAAA,IAChC;AAAA,IAEA,YAAY,OAAO;AACjB,WAAK,eAAe;AACpB,WAAK,cAAc,+BAA+B;AAAA,IACpD;AAAA;AAAA,IAIA,UAAU,KAAK;AACb,YAAM,MAAM,IAAI,MAAM,QAAQ;AAC9B,UAAI,CAAC,OAAO,CAAC,IAAI;AAAQ;AAEzB,WAAK,KAAK,IAAI,CAAC;AACf,WAAK,MAAM,KAAK,eAAe,KAAK,EAAE;AACtC,WAAK,cAAc,MAAM,KAAK;AAE9B,UAAI,KAAK,QAAQ,aAAa,UAAU;AAAG,aAAK,QAAQ,aAAa,YAAY,KAAK,GAAG;AACzF,UAAI,KAAK,QAAQ,aAAa,WAAW;AAAG,aAAK,QAAQ,aAAa,aAAa,KAAK,GAAG;AAC3F,WAAK,eAAe,KAAK,EAAE;AAAA,IAC7B;AAAA,IAEA,qBAAqB;AACnB,WAAK,6BAA6B;AAElC,UAAI,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAEhE,UAAI,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAC/E,aAAK,OAAO,KAAK;AAAA,MACnB;AAEA,WAAK,OAAO,YAAY,EAAE,KAAK,CAAC,aAAa;AAC3C,aAAK,YAAY,QAAQ;AAAA,MAC3B,CAAC;AAED,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,eAAe;AACb,WAAK,YAAY,OAAO;AACxB,WAAK,cAAc,wBAAwB;AAC3C,UAAI,CAAC,KAAK,OAAO;AAAM,eAAO,KAAK,MAAM;AAEzC,WAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,WAAK,YAAY,SAAS;AAC1B,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,kBAAkB,OAAO;AACvB,WAAK,cAAc,MAAM;AACzB,WAAK,kBAAkB,KAAK,iBAAiB,MAAM,OAAO;AAC1D,WAAK,cAAc,8BAA8B;AACjD,WAAK,YAAY,MAAM,QAAQ;AAE/B,UAAI,KAAK,OAAO,QAAQ,KAAK,KAAK,YAAY,MAAM,WAAW,KAAK,UAAU;AAC5E,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,mBAAmB;AACjB,WAAK,YAAY,WAAW;AAAA,IAC9B;AAAA,IAEA,YAAY,OAAO;AACjB,WAAK,YAAY,MAAM,QAAQ;AAE/B,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,cAAc;AACnB,aAAK,cAAc,MAAM,UAAU;AAGnC,aAAK,OAAO,QAAQ,KAAK,OAAO,IAAI;AAGpC,YAAI,EAAE,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,kBAAkB;AAClF,iBAAO,KAAK,OAAO,MAAM;AAAA,QAC3B;AAAA,MACF;AAEA,YAAM,UAAU,MAAM;AACtB,UAAI,KAAK,OAAO,UAAU,KAAK,UAAU,KAAK,OAAO,UAAU,GAAG;AAChE,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,UAAI,KAAK,YAAY,WAAW,KAAK,UAAU;AAC7C,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,WAAK,YAAY,SAAS;AAC1B,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,eAAe;AACb,WAAK,YAAY,QAAQ;AACzB,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,KAAKC,aAAY;AACf,WAAK,OAAO,KAAK,iBAAiBA,WAAU,CAAC;AAAA,IAC/C;AAAA,IAEA,OAAO,MAAM;AACX,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,OAAO,eAAe,IAAI;AAC/B,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAU;AACpD,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAW;AACrD,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,QAAQ;AACN,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,UAAI,CAAC,KAAK,eAAe;AACvB,aAAK,gBAAgB;AACrB,aAAK,UAAU,KAAK,OAAO,MAAM;AAAA,MACnC;AACA,WAAK,OAAO,SAAS,KAAK;AAC1B,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,WAAK,OAAO,SAAS,IAAI;AACzB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK;AAAQ;AAClB,aAAO,KAAK,OAAO,UAAU;AAAA,IAC/B;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,UAAU,MAAM;AAC5B,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AC5PO,MAAM,kBAAN,cAA8B,qBAAqB;AAAA,IACxD,YAAY,MAAM,QAAQ,UAAU,KAAK,iBAAiB;AACxD,YAAM,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,eAAe;AAChE,UAAI,CAAC,YAAY,CAAC,SAAS;AAAM;AACjC,UAAI,KAAK,aAAa,CAAC,KAAK,OAAO;AAAQ;AAE3C,WAAK,MAAM,SAAS;AACpB,WAAK,MAAM,kBAAkB,KAAK,SAAS,EAAE,EAAE,CAAC;AAChD,WAAK,MAAM;AACX,WAAK,QAAQ,aAAa,gBAAgB,GAAG;AAC7C,WAAK,SAAS;AACd,WAAK,UAAU,CAAC;AAEhB,WAAK,WAAW;AAAA,QACd,OAAQ;AAAA,QACR,OAAQ;AAAA,QACR,OAAQ;AAAA,QACR,OAAQ;AAAA,QACR,OAAQ;AAAA,QACR,QAAS;AAAA,MACX;AAEA,WAAK,OAAO,KAAK,SAAS,KAAK,IAAI,YAAY,CAAC;AAEhD,WAAK,aAAa;AAElB,WAAK,6BAA6B;AAClC,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,wBAAwB;AACtB,YAAM,gBAAgB,SAAS,cAAc,OAAO;AACpD,oBAAc,aAAa,eAAe,EAAE;AAC5C,UAAI,KAAK,OAAO;AAAM,sBAAc,aAAa,QAAQ,EAAE;AAC3D,UAAI,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,iBAAiB;AAC/E,sBAAc,aAAa,YAAY,EAAE;AACzC,sBAAc,WAAW;AAAA,MAC3B;AACA,UAAI,KAAK,OAAO;AACd,sBAAc,aAAa,SAAS,EAAE;AACtC,sBAAc,QAAQ;AAAA,MACxB;AACA,UAAI,KAAK,OAAO,aAAa;AAAG,sBAAc,aAAa,WAAW,MAAM;AAE5E,aAAO;AAAA,IACT;AAAA,IAEA,eAAe;AACb,WAAK,SAAS,KAAK,sBAAsB;AACzC,WAAK,gBAAgB,KAAK;AAE1B,UAAI,KAAK,WAAW,KAAK,CAAC,KAAK;AAAO,aAAK,UAAU,KAAK,MAAM;AAEhE,WAAK,cAAc,aAAa,MAAM,KAAK,GAAG;AAE9C,WAAK,mBAAmB,KAAK,aAAa;AAE1C,WAAK,OAAO,iBAAiB,kBAAkB,KAAK,sBAAsB,KAAK,IAAI,CAAC;AACpF,WAAK,OAAO,iBAAiB,kBAAkB,KAAK,sBAAsB,KAAK,IAAI,CAAC;AACpF,WAAK,OAAO,iBAAiB,WAAW,KAAK,eAAe,KAAK,IAAI,CAAC;AACtE,WAAK,OAAO,iBAAiB,cAAc,KAAK,kBAAkB,KAAK,IAAI,CAAC;AAC5E,WAAK,OAAO,iBAAiB,QAAQ,KAAK,YAAY,KAAK,IAAI,CAAC;AAChE,WAAK,OAAO,iBAAiB,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AAClE,WAAK,OAAO,iBAAiB,WAAW,KAAK,iBAAiB,KAAK,IAAI,CAAC;AACxE,WAAK,OAAO,iBAAiB,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AAElE,WAAK,QAAQ,YAAY,KAAK,aAAa;AAC3C,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,aAAa,OAAO,KAAK,GAAG;AACnC,aAAO,aAAa,QAAQ,KAAK,IAAI;AACrC,WAAK,cAAc,YAAY,MAAM;AACrC,WAAK,OAAO,KAAK,aAAa;AAAA,IAChC;AAAA,IAEA,YAAY,OAAO;AACjB,WAAK,eAAe;AACpB,WAAK,cAAc,+BAA+B;AAAA,IACpD;AAAA;AAAA,IAIA,UAAU,KAAK;AACb,YAAM,MAAM,IAAI,MAAM,QAAQ;AAC9B,UAAI,CAAC,OAAO,CAAC,IAAI;AAAQ;AACzB,WAAK,KAAK,IAAI,CAAC;AACf,WAAK,MAAM,kBAAkB,KAAK,KAAK,EAAE,EAAE,CAAC;AAC5C,WAAK,OAAO,KAAK,SAAS,KAAK,IAAI,YAAY,CAAC;AAChD,WAAK,cAAc,YAAY;AAC/B,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,aAAa,OAAO,GAAG;AAC9B,aAAO,aAAa,QAAQ,KAAK,IAAI;AACrC,WAAK,cAAc,YAAY,MAAM;AACrC,WAAK,MAAM;AAEX,UAAI,KAAK,QAAQ,aAAa,UAAU;AAAG,aAAK,QAAQ,aAAa,YAAY,KAAK,GAAG;AACzF,UAAI,KAAK,QAAQ,aAAa,WAAW;AAAG,aAAK,QAAQ,aAAa,aAAa,KAAK,GAAG;AAAA,IAC7F;AAAA,IAEA,wBAAwB;AACtB,WAAK,YAAY,KAAK,OAAO,QAAQ;AAAA,IACvC;AAAA,IAEA,iBAAiB;AACf,WAAK,YAAY,KAAK,OAAO,QAAQ;AAAA,IACvC;AAAA,IAEA,oBAAoB;AAClB,WAAK,cAAc,KAAK,OAAO;AAC/B,WAAK,kBAAkB,KAAK,iBAAiB,KAAK,OAAO,WAAW;AACpE,WAAK,cAAc,8BAA8B;AAEjD,UAAI,KAAK,OAAO,QAAQ,KAAK,KAAK,eAAe,KAAK,UAAU;AAC9D,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,cAAc;AACZ,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,cAAc;AACnB,aAAK,cAAc,MAAM,UAAU;AAAA,MACrC;AAEA,YAAM,UAAU,KAAK,OAAO;AAC5B,UAAI,KAAK,OAAO,UAAU,KAAK,WAAW,KAAK,OAAO,UAAU,GAAG;AACjE,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,UAAI,KAAK,YAAY,WAAW,KAAK,UAAU;AAC7C,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAEA,WAAK,YAAY,SAAS;AAC1B,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,eAAe;AACb,WAAK,YAAY,QAAQ;AACzB,WAAK,cAAc,wBAAwB;AAAA,IAC7C;AAAA,IAEA,eAAe;AACb,WAAK,YAAY,OAAO;AACxB,WAAK,cAAc,wBAAwB;AAC3C,UAAI,CAAC,KAAK,OAAO;AAAM,eAAO,KAAK,MAAM;AAEzC,WAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,WAAK,YAAY;AAAA,IACnB;AAAA,IAEA,mBAAmB;AACjB,WAAK,YAAY,WAAW;AAAA,IAC9B;AAAA,IAEA,KAAKC,aAAY;AACf,WAAK,OAAO,KAAK,iBAAiBA,WAAU,CAAC;AAAA,IAC/C;AAAA,IAEA,OAAO,SAAS;AACd,UAAI,CAAC,KAAK;AAAQ;AAClB,UAAI,KAAK,OAAO,eAAe,UAAU,GAAG;AAC1C,aAAK,OAAO,SAAS,OAAO;AAC5B;AAAA,MACF;AACA,WAAK,OAAO,cAAc;AAC1B,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAU;AACpD,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,UAAU,KAAK,iBAAiB;AAAW;AACrD,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,QAAQ;AACN,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,WAAK,OAAO,QAAQ;AACpB,UAAI,CAAC,KAAK,eAAe;AACvB,aAAK,gBAAgB;AACrB,aAAK,UAAU,KAAK,OAAO,MAAM;AAAA,MACnC;AACA,WAAK,cAAc,yBAAyB;AAAA,IAC9C;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,QAAQ;AAEb,WAAK,OAAO,QAAQ;AACpB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK;AAAQ;AAClB,aAAO,KAAK,OAAO;AAAA,IACrB;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,SAAS;AAEd,WAAK,OAAO,SAAS;AACrB,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AC5NO,MAAM,mBAAN,MAAuB;AAAA,IAC5B,YAAY,UAAU,QAAQ;AAC5B,WAAK,WAAW;AAChB,UAAI,KAAK,oBAAoB;AAAS,aAAK,WAAW,CAAC,KAAK,QAAQ;AACpE,UAAI,OAAO,KAAK,aAAa;AAAU,aAAK,WAAW,SAAS,iBAAiB,QAAQ;AAEzF,WAAK,QAAQ,CAAC;AAEd,YAAM,OAAO;AAEb,WAAK,uBAAuB;AAE5B,UAAI,0BAA0B,QAAQ;AACpC,aAAK,uBAAuB,IAAI,qBAAqB,SAAU,SAAS;AACtE,kBAAQ,QAAQ,SAAU,OAAO;AAC/B,kBAAM,MAAM,MAAM,OAAO,aAAa,cAAc;AAEpD,gBAAI,OAAO,KAAK,MAAM,eAAe,GAAG,KAAK,MAAM,gBAAgB;AACjE,mBAAK,MAAM,GAAG,EAAE,iBAAiB;AACjC,kBAAI;AACF,oBAAI,KAAK,MAAM,GAAG,EAAE,UAAU,CAAC,KAAK,MAAM,GAAG,EAAE;AAAQ,uBAAK,MAAM,GAAG,EAAE,SAAS;AAAA,cAClF,SAAS,GAAG;AAAA,cAEZ;AAAA,YACF,OAAO;AACL,mBAAK,MAAM,GAAG,EAAE,iBAAiB;AACjC,kBAAI;AACF,oBAAI,KAAK,MAAM,GAAG,EAAE;AAAQ,uBAAK,MAAM,GAAG,EAAE,UAAU;AAAA,cACxD,SAAS,GAAG;AAAA,cAEZ;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAEA,WAAK,iBAAiB;AAEtB,UAAI,oBAAoB,QAAQ;AAC9B,aAAK,iBAAiB,IAAI,eAAe,SAAU,SAAS;AAC1D,kBAAQ,QAAQ,SAAU,OAAO;AAC/B,kBAAM,MAAM,MAAM,OAAO,aAAa,cAAc;AAEpD,gBAAI,OAAO,KAAK,MAAM,eAAe,GAAG,GAAG;AACzC,qBAAO,sBAAsB,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,CAAC;AAAA,YAC7D;AAAA,UACF,CAAC;AAAA,QACH,CAAC;AAAA,MACH,OAAO;AACL,eAAO,iBAAiB,UAAU,WAAY;AAC5C,mBAAS,KAAK,KAAK,OAAO;AACxB,mBAAO,sBAAsB,MAAM,KAAK,MAAM,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC,EAAE,aAAa,CAAC;AAAA,UACtF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,WAAK,YAAY;AAEjB,UAAI,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS;AAAQ;AAC7C,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,cAAM,UAAU,KAAK,SAAS,CAAC;AAC/B,aAAK,IAAI,SAAS,MAAM;AAAA,MAC1B;AAEA,eAAS,iBAAiB,oBAAoB,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAAA,IAClF;AAAA,IAEA,qBAAqB;AACnB,UAAI,SAAS;AAAQ;AAErB,eAAS,KAAK,KAAK,OAAO;AACxB,cAAM,WAAW,KAAK,MAAM,CAAC;AAC7B,YAAI,SAAS,WAAW,GAAG;AACzB,mBAAS,SAAS;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,IAEA,IAAI,SAAS,QAAQ;AACnB,UAAI,CAAC;AAAS;AACd,UAAI,QAAQ,aAAa,cAAc;AAAG;AAE1C,UAAI,CAAC,KAAK,sBAAsB;AAC9B,YAAI,CAAC;AAAQ,mBAAS,CAAC;AACvB,eAAO,aAAa,IAAI;AAAA,MAC1B;AAEA,YAAM,OAAO,QAAQ,aAAa,cAAc,KAAK,QAAQ,aAAa,UAAU;AACpF,YAAM,WAAW,KAAK,SAAS,IAAI;AAEnC,UAAI,CAAC;AAAU;AAEf,YAAM,MAAM,KAAK,YAAY,SAAS,EAAE;AAExC,UAAI,CAAC;AAAK;AAEV,cAAQ,SAAS,MAAM;AAAA,QACrB,KAAK;AACH,gBAAM,KAAK,IAAI,kBAAkB,SAAS,QAAQ,SAAS,IAAI,KAAK,IAAI;AACxE,eAAK,MAAM,GAAG,IAAI;AAClB;AAAA,QACF,KAAK;AACH,gBAAM,KAAK,IAAI,gBAAgB,SAAS,QAAQ,SAAS,IAAI,KAAK,IAAI;AACtE,eAAK,MAAM,GAAG,IAAI;AAClB;AAAA,QACF,KAAK;AACH,gBAAM,MAAM,IAAI,gBAAgB,SAAS,QAAQ,UAAU,KAAK,IAAI;AACpE,eAAK,MAAM,GAAG,IAAI;AAClB;AAAA,MACJ;AAEA,UAAI,KAAK,gBAAgB;AACvB,aAAK,eAAe,QAAQ,OAAO;AAAA,MACrC;AAEA,UAAI,CAAC,KAAK,MAAM,GAAG,EAAE,OAAO,aAAa,KAAK,KAAK,sBAAsB;AACvE,aAAK,qBAAqB,QAAQ,OAAO;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,QAAQ,SAAS;AACf,YAAM,MAAM,QAAQ,OAAO,QAAQ,aAAa,cAAc;AAC9D,UAAI,OAAO,KAAK,MAAM,eAAe,GAAG,GAAG;AACzC,YAAI,CAAC,KAAK,MAAM,GAAG,EAAE,OAAO,aAAa,KAAK,KAAK;AAAsB,eAAK,qBAAqB,UAAU,OAAO;AACpH,YAAI,KAAK;AAAgB,eAAK,eAAe,UAAU,OAAO;AAC9D,aAAK,MAAM,GAAG,EAAE,QAAQ;AACxB,eAAO,KAAK,MAAM,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,aAAa;AACX,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,QAAQ,KAAK,MAAM,CAAC,EAAE,aAAa;AAAA,MAC1C;AAAA,IACF;AAAA,IAEA,SAAS,MAAM;AACb,UAAI,SAAS,UAAa,SAAS;AAAM;AAEzC,WAAK,KAAK,CAAC;AACX,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,QAAQ;AAChB,WAAK,GAAG,QAAQ;AAEhB,eAAS,KAAK,KAAK,IAAI;AACrB,cAAM,MAAM,KAAK,MAAM,KAAK,GAAG,CAAC,CAAC;AAEjC,YAAI,OAAO,IAAI,QAAQ;AACrB,eAAK,GAAG,CAAC,EAAE,YAAY;AACvB,iBAAO;AAAA,YACL,IAAI,IAAI,CAAC;AAAA,YACT,MAAM;AAAA,YACN,WAAW;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA;AAAA,IACF;AAAA,IAEA,YAAY,MAAM;AAEhB,aAAO,KAAK,QAAQ,oBAAoB,GAAG;AAC3C,aAAO,KAAK,QAAQ,UAAU,GAAG;AACjC,aAAO,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,EAAE;AAChD,aAAO,SAAQ;AAEf,UAAI,MAAM,OAAM,MAAK,mBAAmB,GAAG,IAAI;AAC/C,aAAO,KAAK,MAAM,eAAe,GAAG,GAAG;AACrC,cAAM,OAAM,MAAK,mBAAmB,GAAG,IAAI;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,IAAI,SAAS;AACX,YAAM,MAAM,OAAO,YAAY,WAAW,UAAU,QAAQ,aAAa,cAAc;AACvF,UAAI,OAAO,KAAK,MAAM,eAAe,GAAG;AAAG,eAAO,KAAK,MAAM,GAAG;AAAA,IAClE;AAAA,IAEA,WAAW;AACT,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,IAEA,UAAU;AACR,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,UAAU;AACR,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,YAAY;AACV,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IAEA,aAAa,QAAQ;AACnB,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,UAAU,MAAM;AAAA,MAChC;AAAA,IACF;AAAA,IAEA,YAAY,UAAU;AACpB,YAAM,OAAO;AAEb,aAAO,0BAA0B,WAAY;AAC3C,iBAAS,KAAK,KAAK,OAAO;AACxB,cAAI,KAAK,MAAM,CAAC,aAAa,mBAAmB;AAC9C,iBAAK,MAAM,CAAC,EAAE,aAAa;AAAA,UAC7B;AAAA,QACF;AAEA,YAAI,UAAU;AACZ,qBAAW,UAAU,GAAG;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,OAAO,eAAe,IAAI,KAAK,OAAO,GAAG,QAAQ;AACnD,eAAO,wBAAwB;AAAA,MACjC;AAEA,aAAO,wBAAwB,WAAY;AACzC,iBAAS,KAAK,KAAK,OAAO;AACxB,cAAI,KAAK,MAAM,CAAC,aAAa,iBAAiB;AAC5C,iBAAK,MAAM,CAAC,EAAE,gBAAgB;AAAA,UAChC;AAAA,QACF;AAEA,YAAI,UAAU;AACZ,qBAAW,UAAU,GAAG;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,OAAO,eAAe,OAAO,KAAK,OAAO,MAAM,eAAe,QAAQ,GAAG;AAC3E,eAAO,sBAAsB;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;;;AC1PA,MAAI,OAAO,UAAU,YAAY;AAC/B,KAAC,SAAU,GAAG;AACZ,QAAE,GAAG,qBAAqB,SAAU,QAAQ;AAC1C,cAAM,QAAQ,EAAE,IAAI;AACpB,YAAI,OAAO,eAAe,mBAAmB,GAAG;AAC9C,iBAAO,kBAAkB,IAAI,OAAO,MAAM;AAC1C,iBAAO;AAAA,QACT;AACA,eAAO,oBAAoB,IAAI,iBAAiB,MAAM,MAAM;AAC5D,eAAO;AAAA,MACT;AAAA,IACF,GAAG,MAAM;AAAA,EACX;AAEA,SAAO,mBAAmB;",
+ "sourcesContent": ["\nfunction buttonOn(buttonObj) {\n if (!buttonObj) return;\n buttonObj.element.classList.add(buttonObj.stateClassName);\n buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[0]);\n buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[1]);\n buttonObj.element.setAttribute('aria-checked', false);\n}\n\nfunction buttonOff(buttonObj) {\n if (!buttonObj) return;\n buttonObj.element.classList.remove(buttonObj.stateClassName);\n buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[0]);\n buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[1]);\n buttonObj.element.setAttribute('aria-checked', true);\n}\n\nexport function generateActionButton(obj, props) {\n const btn = document.createElement('button');\n btn.className = props.className;\n btn.innerHTML = props.innerHtml;\n btn.setAttribute('role', 'switch');\n btn.firstChild.classList.add(props.stateChildClassNames[0]);\n btn.setAttribute('aria-checked', !props.initialState);\n props.element = btn;\n\n if (obj.params[props.condition_parameter] === props.initialState) {\n buttonOn(props);\n }\n\n btn.addEventListener('click', function(e) {\n if (this.classList.contains(props.stateClassName)) {\n buttonOff(props);\n obj[props.actions[0]]();\n } else {\n buttonOn(props);\n obj[props.actions[1]]();\n }\n });\n\n obj.buttons[props.name] = {\n element: btn,\n button_properties: props\n };\n\n obj.controls_element.appendChild(btn);\n};\n", "/**\n * Shallow merges two objects together. Used to pass simple options to functions.\n * \n * @param {object} target The target object to merge into\n * @param {object} source The source object to merge from\n * @returns object The merged object, in this case the target object with the source object's properties merged into it\n * @example\n * const target = { foo: 'bar' }\n * const source = { bar: 'baz' }\n * shallowMerge(target, source) // { foo: 'bar', bar: 'baz' }\n */\nexport function shallowMerge(target, source) {\n for (const key in source) {\n target[key] = source[key]\n }\n\n return target\n}\n\n/**\n * Deep merge function that's mindful of arrays and objects\n * \n * @param {object} target The target object to merge into\n * @param {object} source The source object to merge from\n * @returns object The merged object, in this case the target object with the source object's properties merged into it\n * @example\n * const target = { foo: 'bar' }\n * const source = { bar: 'baz' }\n * deepMerge(target, source) // { foo: 'bar', bar: 'baz' }\n */\nexport function deepMerge(target, source) {\n if (isObject(source) && isObject(target)) {\n for (const key in source) {\n target[key] = deepMerge(target[key], source[key])\n }\n } else if (isArray(source) && isArray(target)) {\n for (let i = 0; i < source.length; i++) {\n target[i] = deepMerge(target[i], source[i])\n }\n } else {\n target = source\n }\n return target\n}\n\n/**\n * Deep clone function that's mindful of nested arrays and objects\n * \n * @param {object} o The object to clone\n * @returns object The cloned object\n * @example\n * const obj = { foo: 'bar' }\n * const clone = clone(obj)\n * clone.foo = 'baz'\n * console.log(obj.foo) // 'bar'\n * console.log(clone.foo) // 'baz'\n * console.log(obj === clone) // false\n * console.log(JSON.stringify(obj) === JSON.stringify(clone)) // true\n * @todo Check if faster than assign. This function is pretty old...\n */ \nexport function clone(o) {\n let res = null\n if (isArray(o)) {\n res = []\n for (const i in o) {\n res[i] = clone(o[i])\n }\n } else if (isObject(o)) {\n res = {}\n for (const i in o) {\n res[i] = clone(o[i])\n }\n } else {\n res = o\n }\n return res\n}\n\n/**\n * Check if an object is empty\n * \n * @param {object} o The object to check\n * @returns boolean True if the object is empty, false otherwise\n * @example\n * isEmptyObject({}) // => true\n * isEmptyObject({ foo: 'bar' }) // => false\n */\nexport function isEmptyObject(o) {\n for (const i in o) {\n return false\n }\n return true\n}\n\n/**\n * Check if an array is empty, substitute for Array.length === 0\n * \n * @param {array} o The array to check\n * @returns boolean True if the array is empty, false otherwise\n * @example\n * isEmptyArray([]) // => true\n * isEmptyArray([1, 2, 3]) // => false\n */\nexport function isEmptyArray(o) {\n return o.length === 0\n}\n\n/**\n * Check if a variable is empty\n * \n * @param {any} o The variable to check\n * @returns boolean True if the variable is empty, false otherwise\n * @example\n * isEmpty({}) // => true\n * isEmpty([]) // => true\n * isEmpty('') // => true\n * isEmpty(null) // => false\n * isEmpty(undefined) // => false\n * isEmpty(0) // => false\n */\nexport function isEmpty(o) {\n if (isObject(o)) {\n return isEmptyObject(o)\n } else if (isArray(o)) {\n return isEmptyArray(o)\n } else if (isString(o)) {\n return o === ''\n }\n return false\n}\n\n/**\n * Try to convert a string to a boolean\n * \n * @param {string} str The string to convert\n * @returns boolean The converted boolean or undefined if conversion failed\n * @example\n * stringToBoolean('true') // => true\n * stringToBoolean('false') // => false\n * stringToBoolean('foo') // => null\n */\nexport function stringToBoolean(str) {\n if (/^\\s*(true|false)\\s*$/i.test(str)) return str === 'true'\n}\n\n/**\n * Try to convert a string to a number\n * \n * @param {string} str The string to convert\n * @returns number The converted number or undefined if conversion failed\n * @example\n * stringToNumber('1') // => 1\n * stringToNumber('1.5') // => 1.5\n * stringToNumber('foo') // => null\n * stringToNumber('1foo') // => null\n */\nexport function stringToNumber(str) {\n if (/^\\s*\\d+\\s*$/.test(str)) return parseInt(str)\n if (/^\\s*[\\d.]+\\s*$/.test(str)) return parseFloat(str)\n}\n\n/**\n * Try to convert a string to an array\n * \n * @param {string} str The string to convert\n * @returns array The converted array or undefined if conversion failed\n * @example\n * stringToArray('[1, 2, 3]') // => [1, 2, 3]\n * stringToArray('foo') // => null\n * stringToArray('1') // => null\n * stringToArray('{\"foo\": \"bar\"}') // => null\n */\nexport function stringToArray(str) {\n if (!/^\\s*\\[.*\\]\\s*$/.test(str)) return\n try {\n return JSON.parse(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to an object\n * \n * @param {string} str The string to convert\n * @returns object The converted object or undefined if conversion failed\n * @example\n * stringToObject('{ \"foo\": \"bar\" }') // => { foo: 'bar' }\n * stringToObject('foo') // => null\n * stringToObject('1') // => null\n * stringToObject('[1, 2, 3]') // => null\n */\nexport function stringToObject(str) {\n if (!/^\\s*\\{.*\\}\\s*$/.test(str)) return\n try {\n return JSON.parse(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to a regex\n * \n * @param {string} str The string to convert\n * @returns regex The converted regex or undefined if conversion failed\n * @example\n * stringToRegex('/foo/i') // => /foo/i\n * stringToRegex('foo') // => null\n * stringToRegex('1') // => null\n */\nexport function stringToRegex(str) {\n if (!/^\\s*\\/.*\\/g?i?\\s*$/.test(str)) return\n try {\n return new RegExp(str)\n } catch (e) {}\n}\n\n/**\n * Try to convert a string to a primitive\n * \n * @param {string} str The string to convert\n * @returns {null|boolean|int|float|string} The converted primitive or input string if conversion failed\n * @example\n * stringToPrimitive('null') // => null\n * stringToPrimitive('true') // => true\n * stringToPrimitive('false') // => false\n * stringToPrimitive('1') // => 1\n * stringToPrimitive('1.5') // => 1.5\n * stringToPrimitive('foo') // => 'foo'\n * stringToPrimitive('1foo') // => '1foo'\n */\nexport function stringToPrimitive(str) {\n if (/^\\s*null\\s*$/.test(str)) return null\n const bool = stringToBoolean(str)\n if (bool !== undefined) return bool\n return stringToNumber(str) || str\n}\n\n/**\n * Try to convert a string to a data type\n * \n * @param {string} str The string to convert\n * @returns any The converted data type or input string if conversion failed\n * @example\n * stringToData('null') // => null\n * stringToData('true') // => true\n * stringToData('false') // => false\n * stringToData('1') // => 1\n * stringToData('1.5') // => 1.5\n * stringToData('foo') // => 'foo'\n * stringToData('1foo') // => '1foo'\n * stringToData('[1, 2, 3]') // => [1, 2, 3]\n * stringToData('{ \"foo\": \"bar\" }') // => { foo: 'bar' }\n * stringToData('/foo/i') // => /foo/i\n */\nexport function stringToType(str) {\n if (/^\\s*null\\s*$/.test(str)) return null\n const bool = stringToBoolean(str)\n if (bool !== undefined) return bool\n return stringToNumber(str) || stringToArray(str) || stringToObject(str) || stringToRegex(str) || str\n}\n\n/**\n * If provided variable is an object\n * \n * @param {any} o \n * @returns boolean\n * @example\n * isObject({}) // => true\n * isObject([]) // => false\n * isObject(null) // => false\n */\nexport function isObject(o) {\n return typeof o === 'object' && !Array.isArray(o) && o !== null\n}\n\n/**\n * If provided variable is an array. Just a wrapper for Array.isArray\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isArray([]) // => true\n * isArray({}) // => false\n */\nexport function isArray(o) {\n return Array.isArray(o)\n}\n\n/**\n * If provided variable is a string. Just a wrapper for typeof === 'string'\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isString('foo') // => true\n * isString({}) // => false\n */\nexport function isString(o) {\n return typeof o === 'string'\n}\n\n/**\n * If provided variable is a function, substitute for typeof === 'function'\n * \n * @param {any} o\n * @returns boolean\n * @example\n * isFunction(function() {}) // => true\n * isFunction({}) // => false\n */\nexport function isFunction(o) {\n return typeof o === 'function'\n}\n\n/**\n * If object property is a function\n * \n * @param {object} obj\n * @param {string} propertyName\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: function() {} }\n * propertyIsFunction(obj, 'foo') // => false\n * propertyIsFunction(obj, 'baz') // => true\n */\nexport function propertyIsFunction(obj, propertyName) {\n return obj.hasOwnProperty(propertyName) && isFunction(obj[propertyName])\n}\n\n/**\n * If object property is a string\n * \n * @param {object} obj\n * @param {string} propertyName\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: function() {} }\n * propertyIsString(obj, 'foo') // => true\n * propertyIsString(obj, 'baz') // => false\n */\nexport function propertyIsString(obj, propertyName) {\n return obj.hasOwnProperty(propertyName) && isString(obj[propertyName])\n}\n\n/**\n * Transforms a dash separated string to camelCase\n *\n * @param {string} str\n * @returns boolean\n * @example\n * transformDashToCamelCase('foo-bar') // => 'fooBar'\n * transformDashToCamelCase('foo-bar-baz') // => 'fooBarBaz'\n * transformDashToCamelCase('foo') // => 'foo'\n * transformDashToCamelCase('fooBarBaz-qux') // => 'fooBarBazQux'\n */\nexport function transformDashToCamelCase(str) {\n return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase() });\n}\n\n/**\n * Transforms a camelCase string to dash separated string\n * \n * @param {string} str\n * @returns boolean\n * @example\n * transformCamelCaseToDash('fooBar') // => 'foo-bar'\n * transformCamelCaseToDash('fooBarBaz') // => 'foo-bar-baz'\n * transformCamelCaseToDash('foo') // => 'foo'\n * transformDashToCamelCase('fooBarBaz-qux') // => 'foo-bar-baz-qux'\n */\nexport function transformCamelCaseToDash(str) {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n}\n\n/**\n * Maps an array of objects by a property name\n * \n * @param {array} arr\n * @param {string} propertyName\n * @returns object\n * @example\n * const arr = [{ foo: 'bar' }, { foo: 'baz' }]\n * mapByProperty(arr, 'foo') // => { bar: { foo: 'bar' }, baz: { foo: 'baz' } }\n */\nexport function mapByProperty(arr, propertyName) {\n const res = {}\n for (let i = 0; i < arr.length; i++) {\n res[arr[i][propertyName]] = arr[i]\n }\n return res\n}\n\n/**\n * Maps an array of objects by a property name to another property name\n * \n * @param {array} arr\n * @param {string} keyPropertyName\n * @param {string} valuePropertyName\n * @returns object\n * @example\n * const arr = [{ foo: 'bar', baz: 'qux' }, { foo: 'quux', baz: 'corge' }]\n * mapPropertyToProperty(arr, 'foo', 'baz') // => { bar: 'qux', quux: 'corge' }\n */\nexport function mapPropertyToProperty(arr, keyPropertyName, valuePropertyName) {\n const res = {}\n for (let i = 0; i < arr.length; i++) {\n res[arr[i][keyPropertyName]] = arr[i][valuePropertyName]\n }\n return res\n}\n\n/**\n * Remove accents from a string\n * \n * @param {string} inputString\n * @returns string\n * @example\n * removeAccents('\u00E1\u00E9\u00ED\u00F3\u00FA') // => 'aeiou'\n * removeAccents('\u00C1\u00C9\u00CD\u00D3\u00DA') // => 'AEIOU'\n * removeAccents('se\u00F1or') // => 'senor'\n * removeAccents('\u0152') // => 'OE'\n */\nexport function removeAccents(inputString) {\n return inputString.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').replace(/\\\u0153/g, \"oe\").replace(/\\\u00E6/g, \"ae\").normalize('NFC')\n}\n\n/**\n * Strip HTML tags from a string\n * \n * @param {string} inputString\n * @returns string\n * @example\n * stripHTMLTags('foo ') // => 'foo'\n * stripHTMLTags('foo bar ') // => 'foo bar'\n */\nexport function stripHTMLTags(inputString) {\n return inputString.replace(/<[^>]*>/g, '')\n}\n\n/**\n * Slugify a string, e.g. 'Foo Bar' => 'foo-bar'. Similar to WordPress' sanitize_title(). Will remove accents and HTML tags.\n * \n * @param {string} str \n * @returns string\n * @example\n * slugify('Foo Bar') // => 'foo-bar'\n * slugify('Foo Bar baz ') // => 'foo-bar-baz'\n */\nexport function slugify(str) {\n str = str.trim().toLowerCase()\n str = removeAccents(str)\n str = stripHTMLTags(str)\n return str.replace(/\\s+|\\.+|\\/+|\\\\+|\u2014+|\u2013+/g, '-').replace(/[^\\w0-9\\-]+/g, '').replace(/-{2,}/g, '-').replace(/^-|-$/g, '')\n}\n\n/**\n * Check if object has multiple properties\n * \n * @param {object} obj\n * @param {string|array} properties\n * @returns boolean\n * @example\n * const obj = { foo: 'bar', baz: 'qux' }\n * hasOwnProperties(obj, ['foo', 'baz']) // => true\n * hasOwnProperties(obj, ['foo', 'baz', 'qux']) // => false\n */\nexport function hasOwnProperties(obj, properties) {\n if(!isArray(properties)) properties = [properties]\n for (let i = 0; i < properties.length; i++) {\n if (!obj.hasOwnProperty(properties[i])) return false\n }\n return true\n}\n\n/**\n * Finds the closest number to the set goal in an array to a given number\n * \n * @param {number} goal Number to search for\n * @param {array} arr Array of numbers to search in\n * @returns number\n * @example\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9]) // => 9\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]) // => 9\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 9.5]) // => 9.5\n * closestNumber(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) // => 10\n */\nexport function closestNumber(goal, arr) {\n return arr.reduce(function(prev, curr) {\n return Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev\n })\n}\n\n/**\n * Truncate a string to a given number of words\n * \n * @param {string} str String to truncate\n * @param {number} numWords Number of words to truncate to\n * @param {string} ellipsis Ellipsis to append to the end of the string\n * @returns string\n * @example\n * truncateString('foo bar baz', 2) // => 'foo bar\u2026'\n * truncateString('foo bar baz', 2, '...') // => 'foo bar...'\n * truncateString('foo bar. baz', 2, '...') // => 'foo bar. ...'\n */\nexport function truncateString(str, numWords, ellipsis = '\u2026') {\n const words = str.trim().split(' ')\n if (words.length <= numWords) return str\n if (numWords <= 0) return ''\n if (/[.?!]$/.test(words[numWords - 1]) && ellipsis.trim() !== '') ellipsis = ` ${ellipsis}`\n return words.slice(0, numWords).join(' ') + ellipsis\n}\n\n/**\n * Generates a random integer between two values, inclusive of both\n * \n * @param {number} min Minimum value\n * @param {number} max Maximum value\n * @param {boolean} safe Defaults to false, if true will use a cryptographically secure random number generator\n * @returns number\n * @example\n * randomIntInclusive(1, 10) // => 1\n * randomIntInclusive(1, 10) // => 10\n * randomIntInclusive(1, 10) // => 5\n */\nexport function randomIntInclusive(min, max, safe = false) {\n min = Number(min)\n max = Number(max)\n if (isNaN(min) || isNaN(max)) throw new TypeError('Both min and max must be numbers')\n if (min > max) [min, max] = [max, min]\n if (min === max) return min\n min = Math.round(min)\n max = Math.round(max)\n const rand = safe ? random() : Math.random()\n return Math.floor(rand * (max - min + 1)) + min\n}\n\n/**\n * Gets fixed number of digits after the decimal point\n * \n * @param {number} number Number to fix\n * @param {number} digits Number of digits to fix to\n * @returns number\n * @example\n * fixed(1.234, 2) // => 1.23\n * fixed(1.235, 2) // => 1.24\n * fixed(1.234) // => 1\n * fixed(1.234, 0) // => 1\n * fixed(1.234, 5) // => 1.234\n * @note Gotta ask myself why I wrote this function in the first place... \uD83E\uDD14 It's just not useful in a lot of cases lol...\n */\nexport function fixed(number, digits) {\n if (!digits) return parseInt(number)\n return parseFloat(number.toFixed(digits))\n}\n\n/**\n * Calculates the percentage of a number in relation to another number\n * \n * @param {number} num Number to calculate percentage of\n * @param {number} total Total number\n * @returns number\n * @example\n * percentage(1, 10) // => 10\n * percentage(5, 10) // => 50\n * percentage(10, 10) // => 100\n * percentage(0, 10) // => 0\n * percentage(10, 2) // => 500\n */\nexport function percentage(num, total) {\n if (!num || !total || Number.isNaN(num) || Number.isNaN(total)) return 0\n return num / total * 100\n}\n\nexport function pickProperties(obj, props) {\n const res = {}\n if (!props) return res\n if (!isArray(props)) props = [props]\n for (let i = 0; i < props.length; i++) {\n if (obj.hasOwnProperty(props[i])) res[props[i]] = obj[props[i]]\n }\n return res\n}\n\nexport function rejectProperties(obj, props, clone = true) {\n if (clone) obj = { ...obj }\n if (!props) return obj\n if (!isArray(props)) props = [props]\n for (let i = 0; i < props.length; i++) {\n if (obj.hasOwnProperty(props[i])) delete obj[props[i]]\n }\n return obj\n}\n\nexport function pickArrayElements(arr, indexes) {\n if (!isArray(arr)) return\n if (!isArray(indexes)) indexes = [indexes]\n const res = []\n for (let i = 0; i < indexes.length; i++) {\n if (arr.hasOwnProperty(indexes[i])) res.push(arr[indexes[i]])\n }\n return res\n}\n\nexport function rejectArrayElements(arr, indexes, clone = true) {\n if (clone) arr = [...arr]\n if (!isArray(arr)) return\n if (!isArray(indexes)) indexes = [indexes]\n for (let i = indexes.length - 1; i >= 0; i--) {\n if (arr.hasOwnProperty(indexes[i])) arr.splice(indexes[i], 1)\n }\n return arr\n}\n\n/**\n * Pick properties from an object or elements from an array\n * \n * @param {array} obj Object or array to pick properties or elements from\n * @param {array | string | number} props Properties to remove, can be an array of strings or a single string or number\n * @returns object | array | undefined\n * @example\n * \n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }) // => {}\n * pick({}, []) // => {}\n * pick(null, 'foo') // => undefined\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, undefined) // => {}\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, 'foo') // => { foo: 'bar'}\n * pick({ foo: 'bar', bar: 'baz', baz: 'qux' }, ['foo', 'baz']) // => { foo: 'bar', baz: 'qux' }\n * \n * pick(['foo', 'bar', 'baz'], []) // => []\n * pick([], []) // => []\n * pick(null, 0) // => undefined\n * pick(['foo', 'bar', 'baz'], undefined) // => []\n * pick(['foo', 'bar', 'baz'], 0) // => ['foo']\n * pick(['foo', 'bar', 'baz'], [0, 2]) // => ['foo', 'baz']\n * pick(['foo', 'bar', 'baz'], [0, 2, 3]) // => ['foo', 'baz']\n */\nexport function pick(obj, props) {\n return isObject(obj) ? pickProperties(obj, props) : pickArrayElements(obj, props)\n}\n\n/**\n * Remove properties from an object or elements from an array\n * \n * @param {array} obj Object or array to remove properties or elements from\n * @param {array | string | number} props Properties to remove, can be an array of strings or a single string or number\n * @param {boolean} clone Defaults to true, will clone the object or array before removing properties or elements.\n * @returns object | array | undefined\n * @example\n * \n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }) // => {}\n * reject({}, []) // => {}\n * reject(null, 'foo') // => undefined\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, undefined) // => {}\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, 'foo') // => { bar: 'baz', baz: 'qux' }\n * reject({ foo: 'bar', bar: 'baz', baz: 'qux' }, ['foo', 'baz']) // => { bar: 'baz' }\n * \n * reject(['foo', 'bar', 'baz'], []) // => []\n * reject([], []) // => []\n * reject(null, 0) // => undefined\n * reject(['foo', 'bar', 'baz'], undefined) // => []\n * reject(['foo', 'bar', 'baz'], 0) // => ['bar', 'baz']\n * reject(['foo', 'bar', 'baz'], [0, 2]) // => ['bar']\n * reject(['foo', 'bar', 'baz'], [0, 2, 3]) // => ['bar']\n */\nexport function reject(obj, props, clone = true) {\n return isObject(obj) ? rejectProperties(obj, props, clone) : rejectArrayElements(obj, props, clone)\n}\n\n/**\n * Basic timestamp first UID generator that's good enough for most use cases but not for security purposes.\n * There's an extremely small chance of collision, so create a map object to check for collisions if you're worried about that.\n * \n * - `Date.now().toString(16)` is used for the timestamp, which is a base16 representation of the current timestamp in milliseconds.\n * - `random().toString(16).substring(2)` is used for the random number, which is a base16 representation of a random number between 0 and 1, with the first two characters removed.\n * \n * @param {boolean} safe Defaults to false, if true will use a cryptographically secure random number generator for the random number improving security but reducing performance. If crypto is not available, will use Math.random() instead.\n * @returns string\n * @example\n * basicUID() // => '18d4613e4d2-750bf066ac6158'\n */\nexport function basicUID(safe = false) {\n const rand = safe ? random() : Math.random()\n return Date.now().toString(16)+'-'+rand.toString(16).substring(2)\n}\n\nfunction cryptoUUIDFallback() {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n (c ^ Math.random() * 16 >> c / 4).toString(16)\n )\n}\n\n// Taken from https://stackoverflow.com/a/2117523/5437943\nfunction cryptoRandomUUIDFallback() {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\n (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)\n )\n}\n\n/**\n * Generates a UUID v4\n * - Uses crypto.randomUUID if available\n * - Uses crypto.getRandomValues if available\n * - Uses a fallback if neither is available, which is not safe because it uses Math.random() instead of a cryptographically secure random number generator\n * \n * I'm bad at crypto and bitwise operations, not my cup of tea, so I had to rely on StackOverflow for the fallback: https://stackoverflow.com/a/2117523/5437943\n * \n * @param {boolean} safe Defaults to true, if false will use a fallback that's not cryptographically secure but significantly faster\n * @returns string\n * @example\n * generateUUID() // UUID v4, example 09ed0fe4-8eb6-4c2a-a8d3-a862b7513294\n */\nexport function generateUUID(safe = true) {\n if (!crypto || !safe) return cryptoUUIDFallback()\n if (crypto.randomUUID) return crypto.randomUUID()\n if (crypto.getRandomValues) return cryptoRandomUUIDFallback();\n}\n\n/**\n * Generates a random number between 0 and 1, inclusive of 0 but not inclusive of 1.\n * \n * - Uses crypto.getRandomValues if available\n * - Uses Math.random() if crypto.getRandomValues is not available\n * \n * @returns number\n * @example\n * random() // => 0.123456789\n */\nexport function random() {\n if (!crypto) return Math.random()\n if (crypto.getRandomValues) return crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295 // 2^32 - 1 = 4294967295\n}\n", "/**\n * @module regex\n */\n\n/**\n * Regular expression for matching a YouTube video links and extracting their ID, works with both embed and watch URLs\n */\nexport const RE_YOUTUBE = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/ ]{11})/i\n\n/**\n * Regular expression for matching a Vimeo video links and extracting their ID, works with both embed and watch URLs, channels and groups\n */\nexport const RE_VIMEO = /(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^\\/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|video\\/|)(\\d+)(?:[a-zA-Z0-9_\\-]+)?/i\n\n/**\n * Regular expression for matching a video URLs\n */\nexport const RE_VIDEO = /\\/([^\\/]+\\.(?:mp4|ogg|ogv|ogm|webm|avi))\\s*$/i\n\n/**\n * Regular expression for matching a image URLs\n */\nexport const RE_IMAGE = /\\/([^\\/]+\\.(?:jpg|jpeg|png|gif|svg|webp))\\s*$/i\n\n/**\n * Regular expression for matching a URL parameters\n */\nexport const RE_URL_PARAMETER = /([^\\s=&]+)=?([^&\\s]+)?/\n\n/**\n * Regular expression for matching a HTML attribute and tag names, also for matching shortcode attributes and names\n */\nexport const RE_ATTRIBUTES = /\\s*(?:([a-z_]{1}[a-z0-9\\-_]*)=?(?:\"([^\"]+)\"|'([^']+)')*)\\s*/gi\n\n/**\n * Regular expression for matching a single attribute without value\n */\nexport const RE_ATTRIBUTE_WITHOUT_VALUE = /^\\s*([a-z_]{1}[a-z0-9\\-_]*)\\s*$/i\n\n/**\n * Regular expression for matching a single attribute with value\n */\nexport const RE_ATTRIBUTE_WITH_VALUE = /^\\s*([a-z_]{1}[a-z0-9\\-_]*)=(\"[^\"]+\"|'[^']+')\\s*$/i\n\n/**\n * Regular expression for matching the first or last quote of a string used for removing them\n */\nexport const RE_FIRST_OR_LAST_QUOTE = /^[\"']|[\"']$/g\n", "/** @module parsers */\n\nimport { isArray, isObject, isString, stringToType } from './helpers.mjs'\nimport { RE_ATTRIBUTES, RE_ATTRIBUTE_WITHOUT_VALUE, RE_ATTRIBUTE_WITH_VALUE, RE_URL_PARAMETER, RE_FIRST_OR_LAST_QUOTE } from './regex.mjs'\nimport { decodeHTML, encodeHTML } from './dom.mjs'\n\n/**\n * Parse a string of attributes and return an object\n * \n * @param {string} str\n * @returns object\n * @example\n * parseAttributes('button text=\"Click me\" data='{\"key\": \\\"value\"}' class=\"btn btn-primary\"')\n * // => { button: null, text: 'Click me', data: '{\"key\": \"value\"}', class: 'btn btn-primary' }\n */\nexport function parseAttributes(str) {\n\tconst re = RE_ATTRIBUTES\n\tconst reWithoutValue = RE_ATTRIBUTE_WITHOUT_VALUE\n\tconst reHasValue = RE_ATTRIBUTE_WITH_VALUE\n\tconst reReplaceFirstAndLastQuote = RE_FIRST_OR_LAST_QUOTE\n\t\n\tconst res = {}\n\tconst match = str.match(re)\n\n\tfor (let i = 0; i < match.length; i++) {\n\t\tconst m = match[i]\n\t\tif (m === '') continue\n\n\t\tif (reWithoutValue.test(m)) {\n\t\t\tconst [, key] = m.match(reWithoutValue)\n\t\t\tres[key] = null\n\t\t\treWithoutValue.lastIndex = 0\n\t\t} else if (reHasValue.test(m)) {\n\t\t\tconst [, key, value] = m.match(reHasValue)\n\t\t\tres[key] = stringToType(decodeHTML(value.replace(reReplaceFirstAndLastQuote, '')))\n\t\t\treReplaceFirstAndLastQuote.lastIndex = 0\n\t\t\treHasValue.lastIndex = 0\n\t\t}\n\t}\n\n\treturn res\n}\n\n/**\n * Serialize an object of key value pairs into a string of attributes\n * \n * @param {object} obj - The object to serialize\n * @returns {string} of attributes\n * @example\n * serializeAttributes({ button: null, text: 'Click me', data: '{\"key\": \"value\"}', class: 'btn btn-primary' }) // button text=\"Click me\" data=\"{\\\"key\\\": \\\"value\\\"}\" class=\"btn btn-primary\"\n */\nexport function serializeAttributes(obj) {\n\tconst res = []\n\n\tObject.keys(obj).forEach((key) => {\n\t\tlet value = obj[key]\n\t\tif (isObject(value) || isArray(value)) value = JSON.stringify(value)\n\t\tif (isString(value)) value = encodeHTML(value)\n\t\tconst valueString = value === null || value === undefined ? '' : `=\"${value}\"`\n\t\tres.push(`${key}${valueString}`)\n\t})\n\n\treturn res.join(' ')\n}\n\n/**\n * Encodes HTML entities in a string using the following rules:\n * \n * - & (ampersand) becomes &\n * - \" (double quote) becomes "\n * - ' (single quote) becomes '\n * - < (less than) becomes <\n * - > (greater than) becomes >\n * \n * It is different than dom.encodeHTML, which encodes all characters using the browser's DOMParser. This function only encodes the characters listed above and should be used when DOMParser is not available.\n * @see {@link module:dom.encodeHTML}\n * \n * @param {string} str - The string to encode\n * @returns {string} The encoded string\n * @example\n * htmlEncode('Link ') // <a href="#">Link</a>\n */\nexport function encodeHtmlEntities(str) {\n\treturn str.replace(/[<>\"'\\&]/g, (m) => {\n\t\tswitch (m) {\n\t\t\tcase '<': return '<'\n\t\t\tcase '>': return '>'\n\t\t\tcase '\"': return '"'\n\t\t\tcase \"'\": return '''\n\t\t\tcase '&': return '&'\n\t\t}\n\t})\n}\n\n/**\n * Decodes HTML entities in a string using the following rules:\n * \n * - & becomes &\n * - " becomes \"\n * - ' becomes '\n * - < becomes <\n * - > becomes >\n * \n * It is different than dom.decodeHTML, which decodes all characters using the browser's DOMParser. This function only decodes the characters listed above and should be used when DOMParser is not available.\n * @see {@link module:dom.decodeHTML}\n * \n * @param {string} str - The string to decode\n * @returns {string} The decoded string\n * @example\n * htmlDecode('<a href="#">Link</a>') // Link \n */\nexport function decodeHtmlEntities(str) {\n\treturn str.replace(/<|>|"|'|&/g, (m) => {\n\t\tswitch (m) {\n\t\t\tcase '<': return '<'\n\t\t\tcase '>': return '>'\n\t\t\tcase '"': return '\"'\n\t\t\tcase ''': return \"'\"\n\t\t\tcase '&': return '&'\n\t\t}\n\t})\n}\n\n\n/**\n * Parses a string of url parameters into an object of key value pairs\n * \n * @param {string} paramString - The string to parse without ? or # and with & as separator\n * @param {boolean} [decode=true] - Whether to decode the values or not\n * @returns {object} of key value pairs\n * @example\n * parseUrlParams('foo=true&baz=555') // { foo: true, baz: 555 }\n * parseUrlParams('foo=bar&baz=qux', false) // { foo: 'true', baz: '555' }\n * parseUrlParams('foo&bar&baz=qux') // { foo: undefined, bar: undefined, baz: 'qux' }\n */\nexport function parseUrlParameters(paramString, decode = true) {\n const res = {}\n\n const paramParts = paramString.split('&')\n paramParts.forEach((part) => {\n const m = part.match(RE_URL_PARAMETER)\n\t\tif (!m) return\n const key = m[1]\n const value = m[2]\n res[key] = value !== undefined && decode ? stringToType(decodeURIComponent(value)) : stringToType(value)\n\t\tRE_URL_PARAMETER.lastIndex = 0\n })\n\n return res\n}\n\n/**\n * Serialize an object of key value pairs into a string of url parameters\n * \n * @param {object} obj - The object to serialize\n * @param {boolean} [encode=true] - Whether to encode the values or not\n * @returns {string} of url parameters\n * @example\n * serializeUrlParams({ foo: true, baz: 555 }) // foo=true&baz=555\n * serializeUrlParams({ bar: undefined, baz: 'qux' }, false) // bar=&baz=qux\n */\nexport function serializeUrlParameters(obj, encode = true) {\n\tconst res = []\n\n\tObject.keys(obj).forEach((key) => {\n\t\tconst value = obj[key]\n\t\tif (value === undefined) return res.push(key)\n\t\tconst encodedValue = encode ? encodeURIComponent(value) : value\n\t\tres.push(`${key}=${encodedValue}`)\n\t})\n\n\treturn res.join('&')\n}\n\n/**\n * Parses a resolution string into a number. Resolution string is in the format of 'width:height', e.g. '16:9' \n * \n * @param {string} res Resolution string. Format is 'width:height', e.g. '16:9', or 'widthxheight', e.g. '16x9', or 'width-height', e.g. '16-9', or 'width/height', e.g. '16/9'\n * @returns number\n * @example\n * parseResolutionString('16:9') // => 1.7777777778\n * parseResolutionString('4:3') // => 1.3333333333\n * parseResolutionString('4x3') // => 1.3333333333\n * parseResolutionString('4-3') // => 1.3333333333\n */\nexport function parseResolutionString(res) {\n const DEFAULT_RESOLUTION = 1.7777777778 // 16:9\n if (!res || !res.length || /16[\\:x\\-\\/]{1}9/i.test(res)) return DEFAULT_RESOLUTION\n const pts = res.split(/\\s?[\\:x\\-\\/]{1}\\s?/i)\n if (pts.length < 2) return DEFAULT_RESOLUTION\n\n const w = parseInt(pts[0])\n const h = parseInt(pts[1])\n\n if (w === 0 || h === 0) return DEFAULT_RESOLUTION\n if (isNaN(w) || isNaN(h)) return DEFAULT_RESOLUTION\n\n return w/h;\n}\n", "/** @module dom */\n\nimport { transformDashToCamelCase, isArray, isString } from './helpers.mjs'\nimport { encodeHtmlEntities, decodeHtmlEntities } from './parsers.mjs'\n\n/**\n * Checks if an element is empty\n * \n * @param {HTMLElement} element \n * @returns boolean\n * @example\n * document.body.innerHTML = `\n *
\n * foo
\n *
`\n * \n * isEmptyElement(document.getElementById('empty-element')) // => true\n * isEmptyElement(document.getElementById('non-empty-element1')) // => false\n * isEmptyElement(document.getElementById('non-empty-element2')) // => false\n */\nexport function isEmptyElement(element) {\n return element.innerHTML.trim() === ''\n}\n\n/**\n * Removes all elements matching a selector from the DOM\n * \n * @param {string|HTMLElement|Element} selector The selector to select elements to remove\n * @param {HTMLElement|Element} [from=document] The element to remove elements from\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * `\n * remove('#foo, #bar') // => removes #foo and #bar\n */\nexport function remove(selector, from = document) {\n const elements = query(selector, from)\n for (const element of elements) {\n element.remove()\n }\n}\n\n/**\n * Queries the DOM for a single element and returns it. Substitutes for `document.querySelector(selector)` and JQuery's `$(selector).first()`\n * \n * @param {string|HTMLElement|Element|Array|NodeList} selector The selector to select an element\n * @param {HTMLElement|Element} [from=document] The element to query from\n * @returns {HTMLElement|Element}\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * querySingle('#foo') // =>
\n * querySingle(document.getElementById('foo')) // =>
\n * querySingle(document.querySelector('#foo')) // =>
\n */\nexport function querySingle(selector, from = document) {\n if (selector instanceof Element) return selector\n return from.querySelector(selector)\n}\n\n/**\n * Queries the DOM for elements and returns them. Substitutes for `document.querySelectorAll(selector)` and JQuery's `$(selector)`\n * \n * @param {string|HTMLElement|Element|Array|NodeList} selector The selector to select elements\n * @param {HTMLElement|Element} [from=document] The element to query from\n * @returns {Array|NodeList}\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * query('#foo') // => [
]\n * query(document.getElementById('foo')) // => [
]\n * query('div') // => [
,
,
]\n */\nexport function query(selector, from = document) {\n if (selector instanceof Array || selector instanceof NodeList) return selector\n if (selector instanceof Element) return [selector]\n if (from instanceof Element || from instanceof Document) return from.querySelectorAll(selector)\n if (isString(from)) from = query(from)\n if (!from instanceof Array && !from instanceof NodeList) return []\n const res = []\n for (const element of from) {\n res.push(...element.querySelectorAll(selector))\n }\n return res\n}\n\n/**\n * Sets element styles from passed object of styles. Can also transform dash-case to camelCase for CSS properties\n * \n * @param {HTMLElement} element The element to set styles on\n * @param {object} styles The object of styles to set\n * @param {boolean} transform Whether to transform dash-case to camelCase for CSS properties\n * @example\n * css(document.getElementById('foo'), { 'background-color': 'red', 'font-size': '16px' }, true) // => sets background-color and font-size\n * css(document.getElementById('foo'), { backgroundColor: 'red', fontSize: '16px' }) // => sets background-color and font-size\n */\nexport function css(element, styles, transform = false) {\n if (!element || !styles) return\n for (let property in styles) {\n if (transform) property = transformDashToCamelCase(property)\n element.style[property] = styles[property]\n }\n}\n\n/**\n * Decodes HTML entities in a string using the browser's DOMParser. If the DOMParser is not available, it uses a regular expression to decode the basic entities.\n * \n * @see {@link module:parsers.decodeHtmlEntities}\n * \n * @param {string} html The HTML string to decode\n * @returns {string} The decoded HTML string\n * @example\n * decodeHTML('<div>foo</div>') // => 'foo
'\n * decodeHTML('<div>foo</div><div>bar</div>') // => 'foo
bar
'\n */\nexport function decodeHTML(html) {\n if (typeof document === 'undefined') return decodeHtmlEntities(html)\n const txt = document.createElement('textarea')\n txt.innerHTML = html\n const res = txt.value\n txt.remove()\n return res\n}\n\n/**\n * Encodes HTML entities in a string using the browser's DOMParser. If the DOMParser is not available, it uses a regular expression to encode the basic entities.\n * \n * @see {@link module:parsers.encodeHtmlEntities}\n * \n * @param {string} html The HTML string to encode\n * @returns {string} The encoded HTML string\n * @example\n * encodeHTML('foo
') // => '<div>foo</div>'\n * encodeHTML('foo
bar
') // => '<div>foo</div><div>bar</div>'\n */\nexport function encodeHTML(html) {\n if (typeof document === 'undefined') return encodeHtmlEntities(html)\n const txt = document.createElement('textarea')\n txt.textContent = html\n const res = txt.innerHTML\n txt.remove()\n return res\n}\n\n/**\n * Inserts an element before another element\n * \n * @param {HTMLElement} targetElement The element to insert before\n * @param {HTMLElement} newElement The element to insert\n * @example\n * const target = document.getElementById('target')\n * const newElement = document.createElement('div')\n * newElement.id = 'newElement'\n * insertBeforeElement(target, newElement)\n * //
\n * //
\n */\nexport function insertBeforeElement(targetElement, newElement) {\n if (!targetElement || !newElement) return\n targetElement.parentNode.insertBefore(newElement, targetElement);\n}\n\n/**\n * Toggles an attribute value on an element\n * \n * @param {HTMLElement} element The element to toggle the attribute on\n * @param {string} attribute The attribute to toggle\n * @param {string} on Default: 'true'\n * @param {string} off Default: 'false'\n * @example\n * toggleAttributeValue(element, 'aria-expanded', 'true', 'false')\n * toggleAttributeValue(element, 'aria-expanded')\n */\nexport function toggleAttributeValue(element, attribute, on = 'true', off = 'false') {\n if (!element.hasAttribute(attribute)) return\n\n if (element.getAttribute(attribute) === on) {\n element.setAttribute(attribute, off)\n } else {\n element.setAttribute(attribute, on)\n }\n}\n\n/**\n * Converts a duration string to milliseconds integer\n * \n * @param {string} duration The duration string to convert, e.g. '1s', '100ms', '0.5s'\n * @returns {number} The duration in milliseconds\n * @example\n * convertToMilliseconds('1s') // 1000\n * convertToMilliseconds('100ms') // 100\n * convertToMilliseconds('0.5s') // 500\n * convertToMilliseconds('0.5') // 0\n * convertToMilliseconds('foo') // 0\n */\nexport function cssTimeToMilliseconds(duration) {\n const regExp = new RegExp('([0-9.]+)([a-z]+)', 'i')\n const matches = regExp.exec(duration)\n if (!matches) return 0\n \n const unit = matches[2]\n switch (unit) {\n case 'ms':\n return parseFloat(matches[1])\n case 's':\n return parseFloat(matches[1]) * 1000\n default:\n return 0\n }\n}\n\n/**\n * Returns a map of transition properties and durations\n * \n * @param {HTMLElement} element The element to get the transition properties and durations from\n * @returns {object} A map of transition properties and durations\n * @example\n * getTransitionDurations(element) // { height: 1000 } if transition in CSS is set to 'height 1s'\n * getTransitionDurations(element) // { height: 500, opacity: 1000 } if transition in CSS is set to 'height 0.5s, opacity 1s'\n */\nexport function getTransitionDurations(element) {\n if (!element) {}\n const styles = getComputedStyle(element)\n const transitionProperties = styles.getPropertyValue('transition-property').split(',')\n const transitionDurations = styles.getPropertyValue('transition-duration').split(',')\n \n const map = {}\n \n for (let i = 0; i < transitionProperties.length; i++) {\n const property = transitionProperties[i].trim()\n map[property] = transitionDurations.hasOwnProperty(i) ? cssTimeToMilliseconds(transitionDurations[i].trim()) : null\n }\n \n return map\n}\n\n/**\n * Check a list of elements if any of them matches a selector\n * \n * @param {Array|NodeList|HTMLElement} elements The elements to check\n * @param {string} selector The selector to check\n * @returns {boolean} True if any of the elements matches the selector, false otherwise\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * matchesAny(document.querySelectorAll('div'), '#foo') // => true\n * matchesAny(document.querySelectorAll('div'), '#qux') // => false\n */\nexport function matchesAny(elements, selector) {\n if (!elements || !selector || !elements.length) return false\n if (elements instanceof Element) elements = [elements]\n if (isString(elements)) elements = query(elements)\n for (const element of elements) {\n if (element.matches(selector)) return true\n }\n return false\n}\n\n/**\n * Check a list of elements if all of them matches a selector\n * \n * @param {Array|NodeList|HTMLElement} elements The elements to check\n * @param {string} selector The selector to check\n * @returns {boolean} True if all of the elements matches the selector, false otherwise\n * @example\n * document.body.innerHTML = `\n *
\n *
\n *
`\n * \n * matchesAll(document.querySelectorAll('div'), 'div') // => true\n * matchesAll(document.querySelectorAll('div'), '#foo') // => false\n */\nexport function matchesAll(elements, selector) {\n if (!elements || !selector || !elements.length) return false\n if (elements instanceof Element) elements = [elements]\n if (isString(elements)) elements = query(elements)\n for (const element of elements) {\n if (!element.matches(selector)) return false\n }\n return true\n}\n\n\n/**\n * Detaches an element from the DOM and returns it\n * \n * @param {HTMLElement} element The element to detach\n * @example\n * detachElement(element)\n * // => element\n * console.log(element.parentNode) // => null\n */\nexport function detachElement(element) {\n if (element && element.parentNode) {\n element.parentNode.removeChild(element);\n }\n return element\n}\n\n/**\n * Gets table data from a table element, a simple regular table element, or a table like structure.\n * Useful for scraping data.\n * \n * @param {string} selector The selector to select the table element\n * @param {Array|string|null} headers The headers to use for the data. If 'auto' is passed, the row containing th or the first row will be used as headers\n * @param {string} [rowSelector='tr'] The selector to select the rows\n * @param {string} [cellSelector='td'] The selector to select the cells\n * @returns {Array} An array of objects with the properties as keys and the cell values as values\n * @example\n * document.body.innerHTML = `\n * \n * \n * \n * Foo \n * Bar \n * \n * \n * \n * \n * Foo 1 \n * Bar 1 \n * \n * \n * Foo 2 \n * Bar 2 \n * \n * \n *
`\n * \n * getTableData('#table', ['foo', 'bar'])\n * // => [\n * // { foo: 'Foo 1', bar: 'Bar 1' },\n * // { foo: 'Foo 2', bar: 'Bar 2' }\n * // ]\n */\nexport function getTableData(selector, headers, rowSelector = 'tr', cellSelector = 'td', headerCellSelector = 'th') {\n const table = typeof selector === 'string' ? document.querySelector(selector) : selector\n const res = []\n const rows = table.querySelectorAll(rowSelector)\n let start = 0\n\n function iterateHeaders(arr) {\n if (!arr || !arr.length) return\n const res = []\n for (let i = 0; i < arr.length; i++) {\n res.push(arr[i].textContent.trim())\n }\n return res\n }\n\n if (headers && isString(headers) && headers === 'auto') {\n let headerCells = table.querySelectorAll(headerCellSelector)\n \n if (headerCells && headerCells.length) {\n headers = iterateHeaders(headerCells)\n } else {\n headers = iterateHeaders(rows[0].querySelectorAll(cellSelector))\n start = 1\n }\n }\n\n for (let i = start; i < rows.length; i++) {\n const row = rows[i]\n const cells = row.querySelectorAll(cellSelector)\n if (!cells || !cells.length) continue\n\n let rowData = []\n if (headers && isArray(headers) && headers.length) {\n rowData = {}\n for (let j = 0; j < headers.length; j++) {\n rowData[headers[j]] = cells[j] ? cells[j].textContent.trim() : null\n }\n } else {\n for (let j = 0; j < cells.length; j++) {\n rowData.push(cells[j].textContent.trim())\n }\n }\n res.push(rowData)\n }\n return res\n}\n\n/**\n * Parses HTML string to a DOM Node\n * \n * @param {string} html The HTML string to parse\n * @param {boolean} [allChildren=false] If true, all children of the body will be returned, otherwise only the first child\n * @returns {Node} The parsed DOM Node\n * @example\n * parseDOM('foo
') // => foo
\n * parseDOM('foo
bar
', true) // => NodeList(2)\u00A0[div, div]\n * parseDOM(document.getElementById('foo')) // =>
\n * parseDOM(document.querySelectorAll('div')) // => NodeList(2)\u00A0[div, div]\n */\nexport function parseDOM(html, allChildren) {\n if (html instanceof Element || html instanceof NodeList) return html\n const parser = new DOMParser()\n const doc = parser.parseFromString(html, 'text/html')\n return !allChildren ? doc.body.firstChild : doc.body.childNodes\n}\n\n/**\n * Loads an image form a provided source url and calls a callback when it's loaded\n * \n * @param {string} src The source url of the image\n * @param {Function} [callback] The callback to call when the image is loaded\n * @example\n * loadImage('https://example.com/image.png', () => {\n * console.log('Image loaded')\n * })\n */\nexport function loadImage(src, callback) {\n const img = new Image()\n if (callback)\n img.addEventListener('load', callback, false);\n img.src = src\n}\n\n/**\n * Delegate DOM events using MutationObserver with a fallback to document.addEventListener\n * \n * @param {string} selector The selector to select the elements to delegate the event to\n * @param {string} eventType The event type to delegate, like `click`\n * @param {Function} handler The handler to call when the event is triggered.\n * @returns {MutationObserver | null} The MutationObserver instance\n * @example\n * delegateEvent('.foo', 'click', (e, target) => {\n * console.log('Clicked on', target)\n * })\n */\nexport function delegateEvent(selector, eventType, handler) {\n if (typeof MutationObserver === 'undefined') {\n document.addEventListener(eventType, (e) => {\n const target = e.target.closest(selector)\n if (target) handler(e, target)\n })\n\n return null\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (!node.matches(selector)) continue\n node.addEventListener(eventType, (e) => {\n handler(e, e.currentTarget)\n })\n }\n }\n })\n\n for (const node of document.querySelectorAll(selector)) {\n node.addEventListener(eventType, (e) => {\n handler(e, e.currentTarget)\n })\n }\n\n observer.observe(document.body, { childList: true, subtree: true })\n return observer\n}\n\n/**\n * Run a handler on selected elements and on elements added to the DOM with the same selector, \n * or can be delegateEvent alias.\n * \n * @param {string} selector The selector to select the elements to run the handler on\n * @param {string | Function} eventTypeOrHandler The event type to delegate, like `click`, or the handler to call on every element\n * @param {Function} [handler] The handler to call when the event is triggered.\n * @returns {MutationObserver | null} The MutationObserver instance\n * @see delegateEvent\n * @example\n * on('.foo', (el) => {\n * console.log('Element', el, 'added to the DOM')\n * })\n * \n * on('.foo', 'click', (e, target) => {\n * console.log('Clicked on', target)\n * })\n */\nexport function on(selector, eventTypeOrHandler, handler) {\n if (isString(eventTypeOrHandler)) {\n return delegateEvent(selector, eventTypeOrHandler, handler)\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (!node.matches(selector)) continue\n eventTypeOrHandler(node)\n }\n }\n })\n\n for (const node of document.querySelectorAll(selector)) {\n eventTypeOrHandler(node)\n }\n\n observer.observe(document.body, { childList: true, subtree: true })\n\n return observer\n}\n\n/**\n * Adds one listener to multiple events\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to add the event listeners to\n * @param {string|Array} events The event types to add the event listeners for, like `click mouseenter`\n * @param {Function} handler The handler to call when the event is triggered.\n * @param {object} [options] The options to pass to the event listeners\n * @example\n * addListenerForEvents('.foo', 'click mouseenter', (e) => { console.log(e.type) })\n */\nexport function addListenerForEvents(elements, events, handler, options) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n const eventTypes = isArray(events) ? events : events.split(' ')\n for (const element of elements) {\n for (const eventType of eventTypes) {\n element.addEventListener(eventType, handler, options)\n }\n }\n}\n\n/**\n * Removes one listener from multiple registered events\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to remove the event listeners from\n * @param {string|Array} events The event types to remove the event listeners for, like `click mouseenter`\n * @param {Function} handler The handler to remove\n * @param {object} [options] The options to pass to the event listeners\n * @example\n * removeListenerForEvents('.foo', 'click mouseenter', (e) => { console.log(e.type) })\n */\nexport function removeListenerForEvents(elements, events, handler, options) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n const eventTypes = isArray(events) ? events : events.split(' ')\n for (const element of elements) {\n for (const eventType of eventTypes) {\n element.removeEventListener(eventType, handler, options)\n }\n }\n}\n\n/**\n * Resizes an element to cover its parent element while maintaining the aspect ratio\n * \n * @param {string|HTMLElement|NodeList} elements The elements or a selector for elements to resize\n * @param {number} [ratio=1] The ratio to maintain\n * @param {number} [offset=0] An offset to add to the parent element's width and height\n * @example\n * proportionalParentCoverResize('.foo', 16/9, 10)\n */\nexport function proportionalParentCoverResize(elements, ratio = 1, offset = 0) {\n if (elements instanceof Element) elements = [elements]\n if (typeof elements === 'string') elements = query(elements)\n\n for (const element of elements) {\n const h = element.parentNode.offsetHeight + offset\n const w = element.parentNode.offsetWidth + offset\n\n if (ratio > w/h) {\n element.style.width = h*ratio + 'px'\n element.style.height = h + 'px'\n } else {\n element.style.width = w + 'px'\n element.style.height = w/ratio + 'px'\n }\n }\n}\n\n/**\n * If provided element is visible. Checks if the element is not visibility hidden or display none, has no opacity, and has a width and height.\n * \n * @param {HTMLElement} element The element to check\n * @returns {boolean} True if the element is visible, false otherwise\n * \n * @example\n * isVisible(document.getElementById('foo'))\n */\nexport function isVisible(element) {\n if (!element) return false;\n const computedStyle = getComputedStyle(element);\n if (computedStyle.getPropertyValue('display') === 'none') return false;\n if (element.getAttribute('hidden') !== null || computedStyle.getPropertyValue('visibility') === 'hidden' || computedStyle.getPropertyValue('opacity') == \"0\") return false;\n return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)\n}\n\n/**\n * Swipe event handler\n * \n * @param {HTMLElement} element The element to listen for swipe gestures on\n * @param {Function} callback The callback to call when a swipe gesture is detected\n * @param {number} [threshold=150] The threshold in pixels to trigger the callback.\n * @param {number} [timeThreshold=0] The threshold in milliseconds to trigger the callback. Defaults to 0, which means the callback will be called regardless of the time it took to swipe.\n * @event swipestart Fires when a swipe gesture starts\n * @event swipeend Fires when a swipe gesture ends\n * @event swipe Fires when a swipe gesture is detected based on the thresholds\n * @example\n * onSwipe(document.getElementById('foo'), (e) => {\n * console.log(e.direction)\n * console.log(e.deltaX)\n * console.log(e.deltaY)\n * console.log(e.startX)\n * console.log(e.startY)\n * console.log(e.endX)\n * console.log(e.endY)\n * console.log(e.threshold)\n * console.log(e.type)\n * console.log(e.target)\n * console.log(e.horizontal)\n * console.log(e.vertical)\n * console.log(e.horizontalDirection)\n * console.log(e.verticalDirection)\n * console.log(e.timeElapsed)\n * console.log(e.timeThreshold)\n * })\n */\nexport function onSwipe(element, callback, threshold = 150, timeThreshold = 0) {\n let startX = 0\n let startY = 0\n let endX = 0\n let endY = 0\n let startTime = 0\n let endTime = 0\n\n if (!element) return\n if (element.getAttribute('swipe-enabled') === 'true') return\n element.setAttribute('swipe-enabled', 'true')\n\n const handleStart = function(e) {\n const carrier = e.touches ? e.touches[0] : e\n startX = carrier.clientX\n startY = carrier.clientY\n startTime = Date.now();\n element.dispatchEvent(new CustomEvent('swipestart', { detail: { startX, startY, startTime } }))\n }\n\n const handleEnd = function(e) {\n const carrier = e.changedTouches ? e.changedTouches[0] : e\n endX = carrier.clientX\n endY = carrier.clientY\n endTime = Date.now();\n handleSwipeGesture()\n element.dispatchEvent(new CustomEvent('swipeend', { detail: { startX, startY, startTime, endX, endY, endTime } }))\n }\n\n const handleSwipeGesture = function() {\n const deltaX = Math.abs(endX - startX)\n const deltaY = Math.abs(endY - startY)\n const horizontal = deltaX > threshold\n const vertical = deltaY > threshold\n const left = endX < startX\n const up = endY < startY\n const direction = []\n const timeElapsed = endTime - startTime;\n \n if (horizontal) direction.push(left ? 'left' : 'right')\n if (vertical) direction.push(up ? 'up' : 'down')\n\n let condition = direction.length && callback\n if (timeThreshold) condition = condition && timeElapsed <= timeThreshold\n \n if (condition) {\n const res = {\n target: element,\n deltaX: deltaX,\n deltaY: deltaY,\n startX: startX,\n startY: startY,\n endX: endX,\n endY: endY,\n threshold: threshold,\n horizontal: horizontal,\n vertical: vertical,\n horizontalDirection: left ? 'left' : 'right',\n verticalDirection: up ? 'up' : 'down',\n direction: direction.length === 1 ? direction[0] : direction,\n timeElapsed: timeElapsed,\n timeThreshold: timeThreshold\n }\n\n callback(res)\n delete res.target\n element.dispatchEvent(new CustomEvent('swipe', { detail: res })) \n }\n }\n\n element.addEventListener('touchstart', handleStart)\n element.addEventListener('touchend', handleEnd)\n element.addEventListener('mousedown', handleStart)\n element.addEventListener('mouseup', handleEnd)\n\n return {\n destroy: function() {\n element.removeEventListener('touchstart', handleStart)\n element.removeEventListener('touchend', handleEnd)\n element.removeEventListener('mousedown', handleStart)\n element.removeEventListener('mouseup', handleEnd)\n }\n }\n}\n", "/** @module browser */\n\nimport { isEmpty, isFunction } from './helpers.mjs'\nimport { css } from './dom.mjs'\nimport { parseUrlParameters } from './parsers.mjs'\n\nexport function isUserAgentIOS(str) {\n return /iPad|iPhone|iPod/i.test(str)\n}\n\nexport function isUserAgentMobile(str) {\n return /\\b(BlackBerry|webOS|iPhone|IEMobile)\\b/i.test(str) ||\n /\\b(Android|Windows Phone|iPad|iPod)\\b/i.test(str)\n}\n\nexport function isUserAgentSafari(str) {\n return /^((?!chrome|android|crios|fxios).)*safari/i.test(str)\n}\n\n/**\n * Check if the device is an iOS device\n * \n * @returns boolean True if the device is an iOS device, false otherwise\n */\nexport function isIOS() {\n return isUserAgentIOS(navigator.userAgent) && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 1\n}\n\n/**\n * Check if the device is a mobile device\n * \n * @returns boolean True if the device is a mobile device, false otherwise\n */\nexport function isMobile() {\n if ('maxTouchPoints' in navigator) return navigator.maxTouchPoints > 0\n\n if ('matchMedia' in window) return !!matchMedia('(pointer:coarse)').matches\n\n if ('orientation' in window) return true\n\n return isUserAgentMobile(navigator.userAgent)\n}\n\n/**\n * Check if the browser is Safari\n *\n * @returns boolean True if the browser is Safari, false otherwise\n */\nexport function isSafari() {\n if (navigator.hasOwnProperty('vendor')) /apple/i.test(navigator.vendor)\n return isUserAgentSafari(navigator.userAgent)\n}\n\n/**\n * Check if the browser is Safari on iOS\n * \n * @returns boolean True if the browser is Safari on iOS, false otherwise\n */\nexport function isIOSSafari() {\n return isIOS() && isSafari()\n}\n\n/**\n * A wrapper for the matchMedia function, cause with `matchMedia` you can only either add a listener or check the media query\n * this function does both.\n * \n * @param {string} query The media query to check\n * @param {function} [callback] The callback function to call when the media query changes\n * @returns {boolean} The result of the media query\n * \n * @example\n * mediaMatcher('(min-width: 768px)', (matches) => {\n * if (matches) {\n * // Do something\n * } else {\n * // Do something else\n * }\n * })\n * \n * // Or\n * \n * const isDesktop = mediaMatcher('(min-width: 768px)')\n */\nexport function mediaMatcher(query, callback) {\n if (isFunction(callback)) {\n matchMedia(query).addEventListener('change', (e) => {\n callback(e.matches)\n })\n\n const mql = matchMedia(query)\n callback(mql.matches)\n\n return mql.matches\n }\n\n return matchMedia(query).matches\n}\n\n/**\n * Get the scrollbar width\n * \n * When preventing scroll with html overflow hidden the scroll bar will disappear and the whole page will shift (if the scroll bar is visible that is).\n * To substitute for the scrollbar width we can add a padding to the body element.\n * \n * @returns {number} The scrollbar width\n * \n * @example\n * const scrollbarWidth = getScrollbarWidth() // 15 (on MacOS X Safari)\n */\nexport function getScrollbarWidth() {\n const scrollDiv = document.createElement('div')\n \n css(scrollDiv, {\n width: '100px',\n height: '100px',\n position: 'absolute',\n left: '-9999px',\n zIndex: '0',\n overflowX: 'hidden',\n overflowY: 'scroll'\n })\n\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n}\n\n/**\n * Check if the vertical scrollbar is visible\n * \n * @param {number} [scrollbarWidth] The width of the scrollbar, defaults to getScrollbarWidth()\n * @returns {boolean} True if the vertical scrollbar is visible, false otherwise\n */\nexport function hasVerticalScrollbarVisible(scrollbarWidth) {\n if (scrollbarWidth === undefined) scrollbarWidth = getScrollbarWidth()\n return window.innerHeight < document.body.scrollHeight && scrollbarWidth > 0\n}\n\n/**\n * Check if the horizontal scrollbar is visible\n * \n * @param {number} [scrollbarWidth] The width of the scrollbar, defaults to getScrollbarWidth()\n * @returns {boolean} True if the horizontal scrollbar is visible, false otherwise\n */\nexport function hasHorizontalScrollbarVisible(scrollbarWidth) {\n if (scrollbarWidth === undefined) scrollbarWidth = getScrollbarWidth()\n return window.innerWidth < document.body.scrollWidth && scrollbarWidth > 0\n}\n\n/**\n * Disable the scroll on the page.\n * \n * @param {number} [shift=0] If greater than 0 the body will be shifted to the left by the width of the scrollbar, getScrollbarWidth() is used to provide this value \n */\nexport function disableScroll(shift) {\n const body = document.body\n if (shift && hasVerticalScrollbarVisible(shift)) body.style.paddingRight = `${shift}px`\n body.style.overflow = 'hidden'\n}\n\n/**\n * Enable the scroll on the page.\n * \n * @param {boolean} [shift=0] If greater than 0 the body will be shifted back to the left by the width of the scrollbar, getScrollbarWidth() is used to provide this value\n */\nexport function enableScroll(shift) {\n const body = document.body\n body.style.overflow = ''\n if (shift) body.style.paddingRight = ''\n}\n\n/**\n * Parses a string of url query parameters into an object of key value pairs. Converts the values to the correct type.\n * \n * @param {string} [entryQuery] - Optional query string to parse, without the starting ?, defaults to window.location.search without the starting ?\n * @returns {object} of key value pairs\n * @example\n * // url: https://example.com/?test&foo=bar&baz=qux\n * getQueryProperties() // { test: undefined, foo: 'bar', baz: 'qux' }\n */\nexport function getQueryProperties(entryQuery) {\n const query = entryQuery ? entryQuery : window.location.search.replace('?', '')\n if (isEmpty(query)) return {}\n\n return parseUrlParameters(query)\n}\n\n/**\n * Parses a string of url hash parameters into an object of key value pairs. Converts the values to the correct type.\n * \n * @param {string} [entryHash] - Optional hash string to parse, without the starting #, defaults to window.location.hash without the starting #\n * @returns {object} of key value pairs\n * @example\n * // url: https://example.com/#test&foo=bar&baz=qux\n * getHashProperties() // { test: undefined, foo: 'bar', baz: 'qux' }\n */\nexport function getHashProperties(entryHash) {\n const hash = entryHash ? entryHash : window.location.hash.replace('#', '')\n if (isEmpty(hash)) return {}\n\n return parseUrlParameters(hash)\n}\n\nfunction onHashChange(callback) {\n const hash = window.location.hash.replace('#', '')\n if (!isEmpty(hash)) callback(hash)\n}\n\n/**\n * Add a callback function to the hash change event\n * \n * @param {function} callback - The callback function to call when the hash changes\n * @param {string} [single] - Optional string to make sure the listener is initialized only once, defaults to window[single] which is set to true after the first call\n * @example\n * hashChange((hash) => {\n * // Do something with the hash\n * })\n */\nexport function hashChange(callback, single) {\n onHashChange(callback)\n \n if (single && window[single]) return\n if (single) window[single] = true\n \n window.addEventListener('hashchange', () => {\n onHashChange(callback)\n })\n}\n", "import { generateActionButton } from './buttons.js';\nimport { isArray, stringToType, isMobile, parseResolutionString, proportionalParentCoverResize, percentage, fixed } from 'book-of-spells';\n\nexport class SuperVideoBackground {\n constructor(elem, params, id, uid, type, factoryInstance) {\n if (!id) return;\n this.is_mobile = isMobile();\n this.type = type;\n this.id = id;\n this.factoryInstance = factoryInstance;\n\n this.element = elem;\n this.playerElement = null;\n this.uid = uid;\n this.element.setAttribute('data-vbg-uid', uid);\n\n this.buttons = {};\n this.isIntersecting = false;\n\n this.paused = false; // user requested pause. used for blocking intersection softPlay\n this.muted = false;\n this.currentState = 'notstarted';\n\n this.initialPlay = false;\n this.initialVolume = false;\n\n this.volume = 1;\n\n this.params = {};\n\n const DEFAULTS = {\n 'pause': false, //deprecated\n 'play-button': false,\n 'mute-button': false,\n 'autoplay': true,\n 'muted': true,\n 'loop': true,\n 'mobile': true,\n 'load-background': false,\n 'resolution': '16:9',\n 'inline-styles': true,\n 'fit-box': false,\n 'offset': 100, // since showinfo is deprecated and ignored after September 25, 2018. we add +100 to hide it in the overflow\n 'start-at': 0,\n 'end-at': 0,\n 'poster': null,\n 'always-play': false,\n 'volume': 1,\n 'no-cookie': true,\n 'force-on-low-battery': false,\n 'lazyloading': false,\n 'title': 'Video background'\n };\n\n this.params = this.parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']);\n\n //pause deprecated\n if (this.params.pause) {\n this.params['play-button'] = this.params.pause;\n }\n\n this.params.resolution_mod = parseResolutionString(this.params.resolution);\n\n this.muted = this.params.muted;\n\n this.volume = this.params.volume;\n\n this.currentTime = this.params['start-at'] || 0;\n this.duration = this.params['end-at'] || 0;\n this.percentComplete = 0;\n if (this.params['start-at']) this.percentComplete = this.timeToPercentage(this.params['start-at']);\n\n this.buildWrapperHTML();\n\n if (this.is_mobile && !this.params.mobile) return;\n\n if (this.params['play-button']) {\n generateActionButton(this, {\n name: 'playing',\n className: 'play-toggle',\n innerHtml: ' ',\n initialState: !this.paused,\n stateClassName: 'paused',\n condition_parameter: 'paused',\n stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'],\n actions: ['play', 'pause']\n });\n }\n\n if (this.params['mute-button']) {\n generateActionButton(this, {\n name: 'muted',\n className: 'mute-toggle',\n innerHtml: ' ',\n initialState: this.muted,\n stateClassName: 'muted',\n condition_parameter: 'muted',\n stateChildClassNames: ['fa-volume-up', 'fa-volume-mute'],\n actions: ['unmute', 'mute']\n });\n }\n }\n\n timeToPercentage(time) {\n if (time <= this.params['start-at']) return 0;\n if (time >= this.duration) return 100;\n if (time <= 0) return 0;\n time -= this.params['start-at']; // normalize\n const duration = this.duration - this.params['start-at']; // normalize\n return percentage(time, duration);\n }\n\n percentageToTime(percentage) {\n if (!this.duration) return this.params['start-at'] || 0;\n if (percentage > 100) return this.duration;\n if (percentage <= 0) return this.params['start-at'] || 0;\n const duration = this.duration - this.params['start-at']; // normalize\n let time = percentage * duration / 100;\n time = fixed(time, 3)\n if (time > duration) time = duration;\n if (this.params['start-at']) time += this.params['start-at']; // normalize\n return time;\n }\n\n resize(element) {\n if (!this.params['fit-box']) proportionalParentCoverResize(element || this.playerElement, this.params.resolution_mod, this.params.offset);\n this.dispatchEvent('video-background-resize');\n }\n\n stylePlayerElement(element) {\n if (!element) return;\n\n if (this.params['inline-styles']) {\n element.style.top = '50%';\n element.style.left = '50%';\n element.style.transform = 'translateX(-50%) translateY(-50%)';\n element.style.position = 'absolute';\n element.style.opacity = 0;\n }\n\n if (this.params['fit-box']) {\n element.style.width = '100%';\n element.style.height = '100%';\n }\n }\n\n buildWrapperHTML() {\n const parent = this.element.parentNode;\n // wrap\n this.element.classList.add('youtube-background', 'video-background');\n \n //set css rules\n const wrapper_styles = {\n \"height\" : \"100%\",\n \"width\" : \"100%\",\n \"z-index\": \"0\",\n \"position\": \"absolute\",\n \"overflow\": \"hidden\",\n \"top\": 0, // added by @insad\n \"left\": 0,\n \"bottom\": 0,\n \"right\": 0\n };\n \n if (!this.params['mute-button']) {\n wrapper_styles[\"pointer-events\"] = \"none\" // avoid right mouse click popup menu\n }\n \n if (this.params['load-background'] || this.params['poster']) {\n this.loadBackground(this.id);\n if (this.params['poster']) wrapper_styles['background-image'] = `url(${ this.params['poster'] })`;\n wrapper_styles['background-size'] = 'cover';\n wrapper_styles['background-repeat'] = 'no-repeat';\n wrapper_styles['background-position'] = 'center';\n }\n \n if (this.params['inline-styles']) {\n for (let property in wrapper_styles) {\n this.element.style[property] = wrapper_styles[property];\n }\n \n if (!['absolute', 'fixed', 'relative', 'sticky'].indexOf(parent.style.position)) {\n parent.style.position = 'relative';\n }\n }\n \n // set play/mute controls wrap\n if (this.params['play-button'] || this.params['mute-button']) {\n const controls = document.createElement('div');\n controls.className = 'video-background-controls';\n \n controls.style.position = 'absolute';\n controls.style.top = '10px';\n controls.style.right = '10px';\n controls.style['z-index'] = 2;\n \n this.controls_element = controls;\n parent.appendChild(controls);\n }\n \n return this.element;\n }\n\n loadBackground(id) {\n if (!this.params['load-background']) return;\n if (!id) return;\n if (this.type === 'youtube') this.element.style['background-image'] = `url(https://img.youtube.com/vi/${id}/hqdefault.jpg)`;\n if (this.type === 'vimeo') this.element.style['background-image'] = `url(https://vumbnail.com/${id}.jpg)`;\n }\n\n destroy() {\n this.playerElement.remove();\n this.element.classList.remove('youtube-background', 'video-background');\n this.element.removeAttribute('data-vbg-uid');\n this.element.style = '';\n\n if (this.params['play-button'] || this.params['mute-button']) {\n this.controls_element.remove();\n }\n\n if (this.timeUpdateTimer) clearInterval(this.timeUpdateTimer);\n this.dispatchEvent('video-background-destroyed');\n }\n\n setDuration(duration) {\n if (this.duration === duration) return;\n\n if (this.params['end-at']) {\n if (duration > this.params['end-at']) {\n this.duration = this.params['end-at'];\n return;\n }\n if (duration < this.params['end-at']) {\n this.duration = duration;\n return;\n }\n } else {\n this.duration = duration;\n return;\n }\n\n if (duration <= 0) this.duration = this.params['end-at'];\n }\n\n setStartAt(startAt) {\n this.params['start-at'] = startAt;\n }\n\n setEndAt(endAt) {\n this.params['end-at'] = endAt;\n if (this.duration > endAt) this.duration = endAt;\n if (this.currentTime > endAt) this.onVideoEnded();\n }\n\n dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n shouldPlay() {\n if (this.currentState === 'ended' && !this.params.loop) return false;\n if (this.params['always-play'] && this.currentState !== 'playing') return true;\n if (this.isIntersecting && this.params.autoplay && this.currentState !== 'playing') return true;\n return false;\n }\n\n mobileLowBatteryAutoplayHack() {\n if (!this.params['force-on-low-battery']) return;\n if (!this.is_mobile && this.params.mobile) return;\n\n const forceAutoplay = function() {\n if (!this.initialPlay && this.params.autoplay && this.params.muted) {\n this.softPlay();\n\n if (!this.isIntersecting && !this.params['always-play']) {\n this.softPause();\n }\n }\n }\n \n document.addEventListener('touchstart', forceAutoplay.bind(this), { once: true });\n }\n\n parseProperties(params, defaults, element, attr_prefix) {\n let res_params = {};\n \n if (!params) {\n res_params = defaults;\n } else {\n for (let k in defaults) {\n //load in defaults if the param hasn't been set\n res_params[k] = !params.hasOwnProperty(k) ? defaults[k] : params[k];\n }\n }\n \n if (!element) return res_params;\n // load params from data attributes\n for (let k in res_params) {\n let data;\n \n if (isArray(attr_prefix)) {\n for (let i = 0; i < attr_prefix.length; i++) {\n const temp_data = element.getAttribute(attr_prefix[i]+k);\n if (temp_data) {\n data = temp_data;\n break;\n }\n }\n } else {\n data = element.getAttribute(attr_prefix+k);\n }\n \n if (data !== undefined && data !== null) {\n res_params[k] = stringToType(data);\n }\n }\n \n return res_params;\n }\n}\n", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_YOUTUBE } from 'book-of-spells';\n\nexport class YoutubeBackground extends SuperVideoBackground {\n constructor(elem, params, id, uid, factoryInstance) {\n super(elem, params, id, uid, 'youtube', factoryInstance);\n\n if (!id) return;\n if (this.is_mobile && !this.params.mobile) return;\n this.injectScript();\n\n this.player = null;\n\n this.injectPlayer();\n\n this.STATES = {\n '-1': 'notstarted',\n '0': 'ended',\n '1': 'playing',\n '2': 'paused',\n '3': 'buffering',\n '5': 'cued'\n };\n\n this.timeUpdateTimer = null;\n this.timeUpdateInterval = 250;\n\n this.initYTPlayer();\n }\n\n startTimeUpdateTimer() {\n if (this.timeUpdateTimer) return;\n this.timeUpdateTimer = setInterval(this.onVideoTimeUpdate.bind(this), this.timeUpdateInterval);\n };\n\n stopTimeUpdateTimer() {\n clearInterval(this.timeUpdateTimer);\n this.timeUpdateTimer = null;\n };\n\n convertState(state) {\n return this.STATES[state];\n }\n\n initYTPlayer() {\n if (!window.hasOwnProperty('YT') || this.player !== null) return;\n\n this.player = new YT.Player(this.uid, {\n events: {\n 'onReady': this.onVideoPlayerReady.bind(this),\n 'onStateChange': this.onVideoStateChange.bind(this),\n // 'onError': this.onVideoError.bind(this)\n }\n });\n\n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n }\n\n onVideoError(event) {\n console.error(event);\n }\n\n injectScript() {\n if (window.hasOwnProperty('YT') || document.querySelector('script[src=\"https://www.youtube.com/player_api\"]')) return\n const tag = document.createElement('script');\n tag.src = \"https://www.youtube.com/player_api\";\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('iframe');\n if (this.params.title) playerElement.setAttribute('title', this.params.title);\n playerElement.setAttribute('frameborder', 0);\n playerElement.setAttribute('allow', 'autoplay; mute');\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n generateSrcURL(id) {\n let site = 'https://www.youtube.com/embed/';\n if (this.params['no-cookie']) {\n site = 'https://www.youtube-nocookie.com/embed/';\n }\n let src = `${site}${id}?&enablejsapi=1&disablekb=1&controls=0&rel=0&iv_load_policy=3&cc_load_policy=0&playsinline=1&showinfo=0&modestbranding=1&fs=0`;\n\n if (this.params.muted) {\n src += '&mute=1';\n }\n \n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n src += '&autoplay=1';\n }\n \n if (this.params.loop) {\n src += '&loop=1';\n }\n\n return src;\n }\n\n injectPlayer() {\n this.playerElement = this.generatePlayerElement();\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n this.playerElement.id = this.uid;\n\n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(this.playerElement);\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_YOUTUBE);\n if (!pts || !pts.length) return;\n\n this.id = pts[1];\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n this.loadBackground(this.id);\n }\n\n onVideoTimeUpdate() {\n const ctime = this.player.getCurrentTime();\n if (ctime === this.currentTime) return;\n this.currentTime = ctime;\n this.percentComplete = this.timeToPercentage(this.currentTime);\n if (this.params['end-at'] && this.duration && this.currentTime >= this.duration) {\n this.currentState = 'ended';\n this.dispatchEvent('video-background-state-change');\n this.onVideoEnded();\n this.stopTimeUpdateTimer();\n return;\n }\n this.dispatchEvent('video-background-time-update');\n }\n\n onVideoPlayerReady() {\n this.mobileLowBatteryAutoplayHack();\n\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n if (this.params['start-at']) this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n this.setDuration(this.player.getDuration());\n\n this.dispatchEvent('video-background-ready');\n }\n\n onVideoStateChange(event) {\n this.currentState = this.convertState(event.data);\n\n if (this.currentState === 'ended') this.onVideoEnded();\n \n if (this.currentState === 'notstarted' && this.params.autoplay) {\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n if (this.currentState === 'playing') this.onVideoPlay();\n \n if (this.currentState === 'paused') this.onVideoPause();\n\n this.dispatchEvent('video-background-state-change');\n }\n\n onVideoPlay() {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n\n const seconds = this.player.getCurrentTime();\n if (this.params['start-at'] && seconds < this.params['start-at'] ) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n if (!this.duration) {\n this.setDuration(this.player.getDuration());\n }\n\n this.dispatchEvent('video-background-play');\n this.startTimeUpdateTimer();\n }\n\n onVideoPause() {\n this.stopTimeUpdateTimer();\n this.dispatchEvent('video-background-pause');\n }\n\n onVideoEnded() {\n this.dispatchEvent('video-background-ended');\n\n if (!this.params.loop) return this.pause();\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage), true);\n }\n\n seekTo(seconds, allowSeekAhead = true) {\n if (!this.player) return;\n this.player.seekTo(seconds, allowSeekAhead);\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.stopTimeUpdateTimer();\n this.player.pauseVideo();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.playVideo();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n \n this.player.playVideo();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n this.stopTimeUpdateTimer();\n this.player.pauseVideo();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.player.unMute();\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.mute();\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.getVolume() / 100;\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.setVolume(volume * 100);\n this.dispatchEvent('video-background-volume-change');\n }\n}\n ", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_VIMEO } from 'book-of-spells';\n\nexport class VimeoBackground extends SuperVideoBackground {\n constructor(elem, params, id, uid, factoryInstance) {\n super(elem, params, id.id, uid, 'vimeo', factoryInstance);\n if (!id) return;\n this.unlisted = id.unlisted;\n\n if (this.is_mobile && !this.params.mobile) return;\n this.injectScript();\n\n this.player = null;\n\n this.injectPlayer();\n\n this.initVimeoPlayer();\n }\n\n injectScript() {\n if (window.hasOwnProperty('Vimeo') || document.querySelector('script[src=\"https://player.vimeo.com/api/player.js\"]')) return;\n const tag = document.createElement('script');\n if (window.hasOwnProperty('onVimeoIframeAPIReady') && typeof window.onVimeoIframeAPIReady === 'function') tag.addEventListener('load', () => {\n window.onVimeoIframeAPIReady();\n });\n tag.src = 'https://player.vimeo.com/api/player.js';\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n }\n\n initVimeoPlayer() {\n if (!window.hasOwnProperty('Vimeo') || this.player !== null) return;\n this.player = new Vimeo.Player(this.playerElement);\n \n this.player.on('loaded', this.onVideoPlayerReady.bind(this));\n this.player.on('ended', this.onVideoEnded.bind(this));\n this.player.on('play', this.onVideoPlay.bind(this));\n this.player.on('pause', this.onVideoPause.bind(this));\n this.player.on('bufferstart', this.onVideoBuffering.bind(this));\n this.player.on('timeupdate', this.onVideoTimeUpdate.bind(this));\n // this.player.on('error', this.onVideoError.bind(this));\n\n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n }\n\n onVideoError(event) {\n console.error(event);\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('iframe');\n if (this.params.title) playerElement.setAttribute('title', this.params.title);\n playerElement.setAttribute('frameborder', 0);\n playerElement.setAttribute('allow', 'autoplay; mute');\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n generateSrcURL(id, unlisted) {\n unlisted = unlisted ? `h=${unlisted}&` : ''\n let src = `https://player.vimeo.com/video/${id}?${unlisted}background=1&controls=0`;\n \n if (this.params.muted) {\n src += '&muted=1';\n }\n \n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n src += '&autoplay=1';\n }\n\n if (this.params.loop) {\n src += '&loop=1&autopause=0';\n }\n \n if (this.params['no-cookie']) {\n src += '&dnt=1';\n }\n \n //WARN\u2757\uFE0F: this is a hash not a query param\n if (this.params['start-at']) {\n src += '#t=' + this.params['start-at'] + 's';\n }\n\n return src;\n }\n\n injectPlayer() {\n this.playerElement = this.generatePlayerElement();\n this.src = this.generateSrcURL(this.id, this.unlisted);\n this.playerElement.src = this.src;\n this.playerElement.id = this.uid;\n \n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(this.playerElement);\n }\n\n updateState(state) {\n this.currentState = state;\n this.dispatchEvent('video-background-state-change');\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_VIMEO);\n if (!pts || !pts.length) return;\n\n this.id = pts[1];\n this.src = this.generateSrcURL(this.id);\n this.playerElement.src = this.src;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n this.loadBackground(this.id);\n }\n\n onVideoPlayerReady() {\n this.mobileLowBatteryAutoplayHack();\n\n if (this.params['start-at']) this.seekTo(this.params['start-at']);\n\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n this.player.play();\n }\n\n this.player.getDuration().then((duration) => {\n this.setDuration(duration);\n });\n\n this.dispatchEvent('video-background-ready');\n }\n\n onVideoEnded() {\n this.updateState('ended');\n this.dispatchEvent('video-background-ended');\n if (!this.params.loop) return this.pause();\n \n this.seekTo(this.params['start-at']);\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoTimeUpdate(event) {\n this.currentTime = event.seconds;\n this.percentComplete = this.timeToPercentage(event.seconds);\n this.dispatchEvent('video-background-time-update');\n this.setDuration(event.duration);\n\n if (this.params['end-at'] && this.duration && event.seconds >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n onVideoPlay(event) {\n this.setDuration(event.duration);\n\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n\n // gotta set loop manually, cause for some reason it's true by default\n this.player.setLoop(this.params.loop);\n\n //Hotfixing an issue that it automatically starts playing after buffering on the first load, sometimes, not always, for an unknown reason\n if (!(this.params.autoplay && (this.params['always-play'] || this.isIntersecting))) {\n return this.player.pause();\n }\n }\n\n const seconds = event.seconds;\n if (this.params['start-at'] && seconds < this.params['start-at']) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoPause() {\n this.updateState('paused');\n this.dispatchEvent('video-background-pause');\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage));\n }\n\n seekTo(time) {\n if (!this.player) return;\n this.player.setCurrentTime(time);\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.player.setMuted(false);\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.setMuted(true);\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.getVolume();\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.setVolume(volume);\n this.dispatchEvent('video-background-volume-change');\n }\n}\n", "import { SuperVideoBackground } from './super-video-background.js';\nimport { RE_VIDEO } from 'book-of-spells';\n\nexport class VideoBackground extends SuperVideoBackground {\n constructor(elem, params, vid_data, uid, factoryInstance) {\n super(elem, params, vid_data.link, uid, 'video', factoryInstance);\n if (!vid_data || !vid_data.link) return;\n if (this.is_mobile && !this.params.mobile) return;\n\n this.src = vid_data.link;\n this.ext = /(?:\\.([^.]+))?$/.exec(vid_data.id)[1];\n this.uid = uid;\n this.element.setAttribute('data-vbg-uid', uid);\n this.player = null;\n this.buttons = {};\n\n this.MIME_MAP = {\n 'ogv' : 'video/ogg',\n 'ogm' : 'video/ogg',\n 'ogg' : 'video/ogg',\n 'avi' : 'video/avi',\n 'mp4' : 'video/mp4',\n 'webm' : 'video/webm'\n };\n\n this.mime = this.MIME_MAP[this.ext.toLowerCase()];\n\n this.injectPlayer();\n\n this.mobileLowBatteryAutoplayHack();\n this.dispatchEvent('video-background-ready');\n }\n\n generatePlayerElement() {\n const playerElement = document.createElement('video');\n if (this.params.title) playerElement.setAttribute('title', this.params.title);\n playerElement.setAttribute('playsinline', '');\n if (this.params.loop) playerElement.setAttribute('loop', '');\n if (this.params.autoplay && (this.params['always-play'] || this.isIntersecting)) {\n playerElement.setAttribute('autoplay', '');\n playerElement.autoplay = true;\n }\n if (this.muted) {\n playerElement.setAttribute('muted', '');\n playerElement.muted = true;\n }\n if (this.params['lazyloading']) playerElement.setAttribute('loading', 'lazy');\n\n return playerElement;\n }\n\n injectPlayer() {\n this.player = this.generatePlayerElement();\n this.playerElement = this.player;\n \n if (this.volume !== 1 && !this.muted) this.setVolume(this.volume);\n \n this.playerElement.setAttribute('id', this.uid)\n \n this.stylePlayerElement(this.playerElement);\n\n this.player.addEventListener('loadedmetadata', this.onVideoLoadedMetadata.bind(this));\n this.player.addEventListener('durationchange', this.onVideoLoadedMetadata.bind(this));\n this.player.addEventListener('canplay', this.onVideoCanPlay.bind(this));\n this.player.addEventListener('timeupdate', this.onVideoTimeUpdate.bind(this));\n this.player.addEventListener('play', this.onVideoPlay.bind(this));\n this.player.addEventListener('pause', this.onVideoPause.bind(this));\n this.player.addEventListener('waiting', this.onVideoBuffering.bind(this));\n this.player.addEventListener('ended', this.onVideoEnded.bind(this));\n\n this.element.appendChild(this.playerElement);\n const source = document.createElement('source');\n source.setAttribute('src', this.src);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n this.resize(this.playerElement);\n }\n\n updateState(state) {\n this.currentState = state;\n this.dispatchEvent('video-background-state-change');\n }\n\n /* ===== API ===== */\n\n setSource(url) {\n const pts = url.match(RE_VIDEO);\n if (!pts || !pts.length) return;\n this.id = pts[1];\n this.ext = /(?:\\.([^.]+))?$/.exec(this.id)[1];\n this.mime = this.MIME_MAP[this.ext.toLowerCase()];\n this.playerElement.innerHTML = '';\n const source = document.createElement('source');\n source.setAttribute('src', url);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n this.src = url;\n\n if (this.element.hasAttribute('data-vbg')) this.element.setAttribute('data-vbg', this.src);\n if (this.element.hasAttribute('data-ytbg')) this.element.setAttribute('data-ytbg', this.src);\n }\n\n onVideoLoadedMetadata() {\n this.setDuration(this.player.duration);\n }\n\n onVideoCanPlay() {\n this.setDuration(this.player.duration);\n }\n\n onVideoTimeUpdate() {\n this.currentTime = this.player.currentTime;\n this.percentComplete = this.timeToPercentage(this.player.currentTime);\n this.dispatchEvent('video-background-time-update');\n\n if (this.params['end-at'] && this.currentTime >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoPlay() {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n \n const seconds = this.player.currentTime;\n if (this.params['start-at'] && seconds <= this.params['start-at']) {\n this.seekTo(this.params['start-at']);\n }\n\n if (this.duration && seconds >= this.duration) {\n this.seekTo(this.params['start-at']);\n }\n\n this.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoPause() {\n this.updateState('paused');\n this.dispatchEvent('video-background-pause');\n }\n\n onVideoEnded() {\n this.updateState('ended');\n this.dispatchEvent('video-background-ended');\n if (!this.params.loop) return this.pause();\n \n this.seekTo(this.params['start-at']);\n this.onVideoPlay();\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n seek(percentage) {\n this.seekTo(this.percentageToTime(percentage));\n }\n\n seekTo(seconds) {\n if (!this.player) return;\n if (this.player.hasOwnProperty('fastSeek')) {\n this.player.fastSeek(seconds);\n return;\n }\n this.player.currentTime = seconds;\n this.dispatchEvent('video-background-seeked');\n }\n\n softPause() {\n if (!this.player || this.currentState === 'paused') return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.player || this.currentState === 'playing') return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.paused = false;\n\n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.paused = true;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.muted = false;\n \n this.player.muted = false;\n if (!this.initialVolume) {\n this.initialVolume = true;\n this.setVolume(this.params.volume);\n }\n this.dispatchEvent('video-background-unmute');\n }\n\n mute() {\n if (!this.player) return;\n this.muted = true;\n \n this.player.muted = true;\n this.dispatchEvent('video-background-mute');\n }\n\n getVolume() {\n if (!this.player) return;\n return this.player.volume;\n }\n\n setVolume(volume) {\n if (!this.player) return;\n this.volume = volume;\n \n this.player.volume = volume;\n this.dispatchEvent('video-background-volume-change');\n }\n}\n", "import { YoutubeBackground } from './lib/youtube-background.js';\nimport { VimeoBackground } from './lib/vimeo-background.js';\nimport { VideoBackground } from './lib/video-background.js';\n\nimport { randomIntInclusive, RE_VIMEO, RE_YOUTUBE, RE_VIDEO } from 'book-of-spells';\n\nexport class VideoBackgrounds {\n constructor(selector, params) {\n this.elements = selector;\n if (this.elements instanceof Element) this.elements = [this.elements];\n if (typeof this.elements === 'string') this.elements = document.querySelectorAll(selector);\n\n this.index = {};\n\n const self = this;\n\n this.intersectionObserver = null;\n\n if ('IntersectionObserver' in window) {\n this.intersectionObserver = new IntersectionObserver(function (entries) {\n entries.forEach(function (entry) {\n const uid = entry.target.getAttribute('data-vbg-uid');\n \n if (uid && self.index.hasOwnProperty(uid) && entry.isIntersecting) {\n self.index[uid].isIntersecting = true;\n try {\n if (self.index[uid].player && !self.index[uid].paused) self.index[uid].softPlay();\n } catch (e) {\n // console.log(e);\n }\n } else {\n self.index[uid].isIntersecting = false;\n try {\n if (self.index[uid].player) self.index[uid].softPause();\n } catch (e) {\n // console.log(e);\n }\n }\n });\n });\n }\n\n this.resizeObserver = null;\n\n if ('ResizeObserver' in window) {\n this.resizeObserver = new ResizeObserver(function (entries) {\n entries.forEach(function (entry) {\n const uid = entry.target.getAttribute('data-vbg-uid');\n\n if (uid && self.index.hasOwnProperty(uid)) {\n window.requestAnimationFrame(() => self.index[uid].resize());\n }\n });\n });\n } else {\n window.addEventListener('resize', function () {\n for (let k in self.index) {\n window.requestAnimationFrame(() => self.index[k].resize(self.index[k].playerElement));\n }\n });\n }\n \n this.initPlayers();\n\n if (!this.elements || !this.elements.length) return;\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n this.add(element, params);\n }\n\n document.addEventListener('visibilitychange', this.onVisibilityChange.bind(this));\n }\n\n onVisibilityChange() {\n if (document.hidden) return;\n\n for (let k in this.index) {\n const instance = this.index[k];\n if (instance.shouldPlay()) {\n instance.softPlay();\n }\n }\n }\n\n add(element, params) {\n if (!element) return;\n if (element.hasAttribute('data-vbg-uid')) return;\n\n if (!this.intersectionObserver) {\n if (!params) params = {};\n params['always-play'] = true;\n }\n\n const link = element.getAttribute('data-youtube') || element.getAttribute('data-vbg');\n const vid_data = this.getVidID(link);\n \n if (!vid_data) return;\n \n const uid = this.generateUID(vid_data.id);\n \n if (!uid) return;\n \n switch (vid_data.type) {\n case 'YOUTUBE':\n const yb = new YoutubeBackground(element, params, vid_data.id, uid, this);\n this.index[uid] = yb;\n break;\n case 'VIMEO':\n const vm = new VimeoBackground(element, params, vid_data, uid, this);\n this.index[uid] = vm;\n break;\n case 'VIDEO':\n const vid = new VideoBackground(element, params, vid_data, uid, this);\n this.index[uid] = vid;\n break;\n }\n\n if (this.resizeObserver) {\n this.resizeObserver.observe(element);\n }\n \n if (!this.index[uid].params['always-play'] && this.intersectionObserver) {\n this.intersectionObserver.observe(element);\n }\n }\n\n destroy(element) {\n const uid = element.uid || element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) {\n if (!this.index[uid].params['always-play'] && this.intersectionObserver) this.intersectionObserver.unobserve(element);\n if (this.resizeObserver) this.resizeObserver.unobserve(element);\n this.index[uid].destroy();\n delete this.index[uid];\n }\n }\n\n destroyAll() {\n for (let k in this.index) {\n this.destroy(this.index[k].playerElement);\n }\n }\n\n getVidID(link) {\n if (link === undefined && link === null) return;\n\n this.re = {};\n this.re.YOUTUBE = RE_YOUTUBE;\n this.re.VIMEO = RE_VIMEO;\n this.re.VIDEO = RE_VIDEO;\n \n for (let k in this.re) {\n const pts = link.match(this.re[k]);\n\n if (pts && pts.length) {\n this.re[k].lastIndex = 0;\n const data = {\n id: pts[1],\n type: k,\n regex_pts: pts,\n link: link\n };\n \n if (k === 'VIMEO') {\n const unlistedQueryRegex = /(\\?|&)h=([^=?]+)/;\n const unlistedPathRegex = /\\/[^\\/\\:\\.]+(\\:|\\/)([^:?\\/]+)\\s?$/;\n const unlistedQuery = link.match(unlistedPathRegex) || link.match(unlistedQueryRegex);\n if (unlistedQuery) data.unlisted = unlistedQuery[2];\n }\n\n return data;\n }\n }\n \n return;\n }\n\n generateUID(pref) {\n //index the instance\n pref = pref.replace(/[^a-zA-Z0-9\\-_]/g, '-'); //sanitize id\n pref = pref.replace(/-{2,}/g, '-'); //remove double dashes\n pref = pref.replace(/^-+/, '').replace(/-+$/, ''); //trim dashes\n pref = 'vbg-'+ pref; //prefix id with 'vbg-\n\n let uid = pref +'-'+ randomIntInclusive(0, 9999);\n while (this.index.hasOwnProperty(uid)) {\n uid = pref +'-'+ randomIntInclusive(0, 9999);\n }\n \n return uid;\n }\n\n get(element) {\n const uid = typeof element === 'string' ? element : element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) return this.index[uid];\n }\n\n pauseAll() {\n for (let k in this.index) {\n this.index[k].pause();\n }\n }\n\n playAll() {\n for (let k in this.index) {\n this.index[k].play();\n }\n }\n\n muteAll() {\n for (let k in this.index) {\n this.index[k].mute();\n }\n }\n\n unmuteAll() {\n for (let k in this.index) {\n this.index[k].unmute();\n }\n }\n\n setVolumeAll(volume) {\n for (let k in this.index) {\n this.index[k].setVolume(volume);\n }\n }\n\n initPlayers(callback) {\n const self = this;\n \n window.onYouTubeIframeAPIReady = function () {\n for (let k in self.index) {\n if (self.index[k] instanceof YoutubeBackground) {\n self.index[k].initYTPlayer();\n }\n }\n \n if (callback) {\n setTimeout(callback, 100);\n }\n };\n \n if (window.hasOwnProperty('YT') && window.YT.loaded) {\n window.onYouTubeIframeAPIReady();\n }\n \n window.onVimeoIframeAPIReady = function () {\n for (let k in self.index) {\n if (self.index[k] instanceof VimeoBackground) {\n self.index[k].initVimeoPlayer();\n }\n }\n \n if (callback) {\n setTimeout(callback, 100);\n }\n }\n \n if (window.hasOwnProperty('Vimeo') && window.Vimeo.hasOwnProperty('Player')) {\n window.onVimeoIframeAPIReady();\n }\n }\n}\n", "import { VideoBackgrounds } from './video-backgrounds.js';\n\nif (typeof jQuery == 'function') {\n (function ($) {\n $.fn.youtube_background = function (params) {\n const $this = $(this);\n if (window.hasOwnProperty('VIDEO_BACKGROUNDS')) {\n window.VIDEO_BACKGROUNDS.add($this, params);\n return $this;\n }\n window.VIDEO_BACKGROUNDS = new VideoBackgrounds(this, params);\n return $this;\n };\n })(jQuery);\n}\n\nwindow.VideoBackgrounds = VideoBackgrounds;\n"],
+ "mappings": "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",
"names": ["percentage", "percentage", "percentage", "percentage"]
}
diff --git a/jquery.youtube-background.min.js b/jquery.youtube-background.min.js
index 6ed3d7c..716cfdf 100644
--- a/jquery.youtube-background.min.js
+++ b/jquery.youtube-background.min.js
@@ -1,2 +1,2 @@
/* youtube-background v1.1.5 | https://github.com/stamat/youtube-background | MIT License */
-(()=>{function l(t){t&&(t.element.classList.add(t.stateClassName),t.element.firstChild.classList.remove(t.stateChildClassNames[0]),t.element.firstChild.classList.add(t.stateChildClassNames[1]),t.element.setAttribute("aria-checked",!1))}function E(t){t&&(t.element.classList.remove(t.stateClassName),t.element.firstChild.classList.add(t.stateChildClassNames[0]),t.element.firstChild.classList.remove(t.stateChildClassNames[1]),t.element.setAttribute("aria-checked",!0))}function u(t,e){const i=document.createElement("button");i.className=e.className,i.innerHTML=e.innerHtml,i.setAttribute("role","switch"),i.firstChild.classList.add(e.stateChildClassNames[0]),i.setAttribute("aria-checked",!e.initialState),e.element=i,t.params[e.condition_parameter]===e.initialState&&l(e),i.addEventListener("click",function(s){this.classList.contains(e.stateClassName)?(E(e),t[e.actions[0]]()):(l(e),t[e.actions[1]]())}),t.buttons[e.name]={element:i,button_properties:e},t.controls_element.appendChild(i)}function w(t){if(/^\s*(true|false)\s*$/i.test(t))return t==="true"}function k(t){if(/^\s*\d+\s*$/.test(t))return parseInt(t);if(/^\s*[\d.]+\s*$/.test(t))return parseFloat(t)}function T(t){if(/^\s*\[.*\]\s*$/.test(t))try{return JSON.parse(t)}catch{}}function V(t){if(/^\s*\{.*\}\s*$/.test(t))try{return JSON.parse(t)}catch{}}function P(t){if(/^\s*\/.*\/g?i?\s*$/.test(t))try{return new RegExp(t)}catch{}}function A(t){if(/^\s*null\s*$/.test(t))return null;const e=w(t);return e!==void 0?e:k(t)||T(t)||V(t)||P(t)||t}function S(t){return Array.isArray(t)}function x(t){return typeof t=="string"}function d(t,e,i=!1){if(t=Number(t),e=Number(e),isNaN(t)||isNaN(e))throw new TypeError("Both min and max must be numbers");if(t>e&&([t,e]=[e,t]),t===e)return t;t=Math.round(t),e=Math.round(e);const s=i?N():Math.random();return Math.floor(s*(e-t+1))+t}function I(t,e){return e?parseFloat(t.toFixed(e)):parseInt(t)}function C(t,e){return!t||!e||Number.isNaN(t)||Number.isNaN(e)?0:t/e*100}function N(){if(!crypto)return Math.random();if(crypto.getRandomValues)return crypto.getRandomValues(new Uint32Array(1))[0]/4294967295}var p=/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,m=/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i,c=/\/([^\/]+\.(?:mp4|ogg|ogv|ogm|webm|avi))\s*$/i;function L(t){const e=1.7777777778;if(!t||!t.length||/16[\:x\-\/]{1}9/i.test(t))return e;const i=t.split(/\s?[\:x\-\/]{1}\s?/i);if(i.length<2)return e;const s=parseInt(i[0]),a=parseInt(i[1]);return s===0||a===0||isNaN(s)||isNaN(a)?e:s/a}function y(t,e=document){if(t instanceof Array||t instanceof NodeList)return t;if(t instanceof Element)return[t];if(e instanceof Element||e instanceof Document)return e.querySelectorAll(t);if(x(e)&&(e=y(e)),!e instanceof Array&&!e instanceof NodeList)return[];const i=[];for(const s of e)i.push(...s.querySelectorAll(t));return i}function U(t,e=1,i=0){t instanceof Element&&(t=[t]),typeof t=="string"&&(t=y(t));for(const s of t){const a=s.parentNode.offsetHeight+i,r=s.parentNode.offsetWidth+i;e>r/a?(s.style.width=a*e+"px",s.style.height=a+"px"):(s.style.width=r+"px",s.style.height=r/e+"px")}}function O(t){return/\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(t)||/\b(Android|Windows Phone|iPad|iPod)\b/i.test(t)}function B(){return"maxTouchPoints"in navigator?navigator.maxTouchPoints>0:"matchMedia"in window?!!matchMedia("(pointer:coarse)").matches:"orientation"in window?!0:O(navigator.userAgent)}var h=class{constructor(t,e,i,s,a,r){if(!i)return;this.is_mobile=B(),this.type=a,this.id=i,this.factoryInstance=r,this.element=t,this.playerElement=null,this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.buttons={},this.isIntersecting=!1,this.paused=!1,this.muted=!1,this.currentState="notstarted",this.initialPlay=!1,this.initialVolume=!1,this.volume=1,this.params={};const n={pause:!1,"play-button":!1,"mute-button":!1,autoplay:!0,muted:!0,loop:!0,mobile:!0,"load-background":!1,resolution:"16:9","inline-styles":!0,"fit-box":!1,offset:100,"start-at":0,"end-at":0,poster:null,"always-play":!1,volume:1,"no-cookie":!0,"force-on-low-battery":!1,lazyloading:!1};this.params=this.parseProperties(e,n,this.element,["data-ytbg-","data-vbg-"]),this.params.pause&&(this.params["play-button"]=this.params.pause),this.params.resolution_mod=L(this.params.resolution),this.muted=this.params.muted,this.volume=this.params.volume,this.currentTime=this.params["start-at"]||0,this.duration=this.params["end-at"]||0,this.percentComplete=0,this.params["start-at"]&&(this.percentComplete=this.timeToPercentage(this.params["start-at"])),this.buildWrapperHTML(),!(this.is_mobile&&!this.params.mobile)&&(this.params["play-button"]&&u(this,{name:"playing",className:"play-toggle",innerHtml:' ',initialState:!this.paused,stateClassName:"paused",condition_parameter:"paused",stateChildClassNames:["fa-pause-circle","fa-play-circle"],actions:["play","pause"]}),this.params["mute-button"]&&u(this,{name:"muted",className:"mute-toggle",innerHtml:' ',initialState:this.muted,stateClassName:"muted",condition_parameter:"muted",stateChildClassNames:["fa-volume-up","fa-volume-mute"],actions:["unmute","mute"]}))}timeToPercentage(t){if(t<=this.params["start-at"])return 0;if(t>=this.duration)return 100;if(t<=0)return 0;t-=this.params["start-at"];const e=this.duration-this.params["start-at"];return C(t,e)}percentageToTime(t){if(!this.duration)return this.params["start-at"]||0;if(t>100)return this.duration;if(t<=0)return this.params["start-at"]||0;const e=this.duration-this.params["start-at"];let i=t*e/100;return i=I(i,3),i>e&&(i=e),this.params["start-at"]&&(i+=this.params["start-at"]),i}resize(t){this.params["fit-box"]||U(t||this.playerElement,this.params.resolution_mod,this.params.offset),this.dispatchEvent("video-background-resize")}stylePlayerElement(t){t&&(this.params["inline-styles"]&&(t.style.top="50%",t.style.left="50%",t.style.transform="translateX(-50%) translateY(-50%)",t.style.position="absolute",t.style.opacity=0),this.params["fit-box"]&&(t.style.width="100%",t.style.height="100%"))}buildWrapperHTML(){const t=this.element.parentNode;this.element.classList.add("youtube-background","video-background");const e={height:"100%",width:"100%","z-index":"0",position:"absolute",overflow:"hidden",top:0,left:0,bottom:0,right:0};if(this.params["mute-button"]||(e["pointer-events"]="none"),(this.params["load-background"]||this.params.poster)&&(this.loadBackground(this.id),this.params.poster&&(e["background-image"]=`url(${this.params.poster})`),e["background-size"]="cover",e["background-repeat"]="no-repeat",e["background-position"]="center"),this.params["inline-styles"]){for(let i in e)this.element.style[i]=e[i];["absolute","fixed","relative","sticky"].indexOf(t.style.position)||(t.style.position="relative")}if(this.params["play-button"]||this.params["mute-button"]){const i=document.createElement("div");i.className="video-background-controls",i.style.position="absolute",i.style.top="10px",i.style.right="10px",i.style["z-index"]=2,this.controls_element=i,t.appendChild(i)}return this.element}loadBackground(t){this.params["load-background"]&&t&&(this.type==="youtube"&&(this.element.style["background-image"]=`url(https://img.youtube.com/vi/${t}/hqdefault.jpg)`),this.type==="vimeo"&&(this.element.style["background-image"]=`url(https://vumbnail.com/${t}.jpg)`))}destroy(){this.playerElement.remove(),this.element.classList.remove("youtube-background","video-background"),this.element.removeAttribute("data-vbg-uid"),this.element.style="",(this.params["play-button"]||this.params["mute-button"])&&this.controls_element.remove(),this.timeUpdateTimer&&clearInterval(this.timeUpdateTimer),this.dispatchEvent("video-background-destroyed")}setDuration(t){if(this.duration!==t){if(this.params["end-at"]){if(t>this.params["end-at"]){this.duration=this.params["end-at"];return}if(tt&&(this.duration=t),this.currentTime>t&&this.onVideoEnded()}dispatchEvent(t){this.element.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:this}))}shouldPlay(){return this.currentState==="ended"&&!this.params.loop?!1:!!(this.params["always-play"]&&this.currentState!=="playing"||this.isIntersecting&&this.params.autoplay&&this.currentState!=="playing")}mobileLowBatteryAutoplayHack(){if(!this.params["force-on-low-battery"]||!this.is_mobile&&this.params.mobile)return;const t=function(){!this.initialPlay&&this.params.autoplay&&this.params.muted&&(this.softPlay(),!this.isIntersecting&&!this.params["always-play"]&&this.softPause())};document.addEventListener("touchstart",t.bind(this),{once:!0})}parseProperties(t,e,i,s){let a={};if(!t)a=e;else for(let r in e)a[r]=t.hasOwnProperty(r)?t[r]:e[r];if(!i)return a;for(let r in a){let n;if(S(s))for(let o=0;o=this.duration){this.currentState="ended",this.dispatchEvent("video-background-state-change"),this.onVideoEnded(),this.stopTimeUpdateTimer();return}this.dispatchEvent("video-background-time-update")}}onVideoPlayerReady(){this.mobileLowBatteryAutoplayHack(),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.player.playVideo()),this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-ready")}onVideoStateChange(t){this.currentState=this.convertState(t.data),this.currentState==="ended"&&this.onVideoEnded(),this.currentState==="notstarted"&&this.params.autoplay&&(this.seekTo(this.params["start-at"]),this.player.playVideo()),this.currentState==="playing"&&this.onVideoPlay(),this.currentState==="paused"&&this.onVideoPause(),this.dispatchEvent("video-background-state-change")}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1);const t=this.player.getCurrentTime();this.params["start-at"]&&t=this.duration&&this.seekTo(this.params["start-at"]),this.duration||this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-play"),this.startTimeUpdateTimer()}onVideoPause(){this.stopTimeUpdateTimer(),this.dispatchEvent("video-background-pause")}onVideoEnded(){if(this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.player.playVideo()}seek(t){this.seekTo(this.percentageToTime(t),!0)}seekTo(t,e=!0){this.player&&(this.player.seekTo(t,e),this.dispatchEvent("video-background-seeked"))}softPause(){!this.player||this.currentState==="paused"||(this.stopTimeUpdateTimer(),this.player.pauseVideo())}softPlay(){!this.player||this.currentState==="playing"||this.player.playVideo()}play(){this.player&&(this.paused=!1,this.player.playVideo())}pause(){this.player&&(this.paused=!0,this.stopTimeUpdateTimer(),this.player.pauseVideo())}unmute(){this.player&&(this.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.player.unMute(),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.mute(),this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.getVolume()/100}setVolume(t){this.player&&(this.volume=t,this.player.setVolume(t*100),this.dispatchEvent("video-background-volume-change"))}},g=class extends h{constructor(t,e,i,s,a){super(t,e,i,s,"vimeo",a),i&&(this.is_mobile&&!this.params.mobile||(this.injectScript(),this.player=null,this.injectPlayer(),this.initVimeoPlayer()))}injectScript(){if(window.hasOwnProperty("Vimeo")||document.querySelector('script[src="https://player.vimeo.com/api/player.js"]'))return;const t=document.createElement("script");window.hasOwnProperty("onVimeoIframeAPIReady")&&typeof window.onVimeoIframeAPIReady=="function"&&t.addEventListener("load",()=>{window.onVimeoIframeAPIReady()}),t.src="https://player.vimeo.com/api/player.js";const e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}initVimeoPlayer(){!window.hasOwnProperty("Vimeo")||this.player!==null||(this.player=new Vimeo.Player(this.playerElement),this.player.on("loaded",this.onVideoPlayerReady.bind(this)),this.player.on("ended",this.onVideoEnded.bind(this)),this.player.on("play",this.onVideoPlay.bind(this)),this.player.on("pause",this.onVideoPause.bind(this)),this.player.on("bufferstart",this.onVideoBuffering.bind(this)),this.player.on("timeupdate",this.onVideoTimeUpdate.bind(this)),this.volume!==1&&!this.muted&&this.setVolume(this.volume))}onVideoError(t){console.error(t)}generatePlayerElement(){const t=document.createElement("iframe");return t.setAttribute("frameborder",0),t.setAttribute("allow","autoplay; mute"),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}generateSrcURL(t){let e="https://player.vimeo.com/video/"+t+"?background=1&controls=0";return this.params.muted&&(e+="&muted=1"),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(e+="&autoplay=1"),this.params.loop&&(e+="&loop=1&autopause=0"),this.params["no-cookie"]&&(e+="&dnt=1"),this.params["start-at"]&&(e+="#t="+this.params["start-at"]+"s"),e}injectPlayer(){this.playerElement=this.generatePlayerElement(),this.src=this.generateSrcURL(this.id),this.playerElement.src=this.src,this.playerElement.id=this.uid,this.stylePlayerElement(this.playerElement),this.element.appendChild(this.playerElement),this.resize(this.playerElement)}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(m);!e||!e.length||(this.id=e[1],this.src=this.generateSrcURL(this.id),this.playerElement.src=this.src,this.element.hasAttribute("data-vbg")&&this.element.setAttribute("data-vbg",this.src),this.element.hasAttribute("data-ytbg")&&this.element.setAttribute("data-ytbg",this.src),this.loadBackground(this.id))}onVideoPlayerReady(){this.mobileLowBatteryAutoplayHack(),this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&this.player.play(),this.player.getDuration().then(t=>{this.setDuration(t)}),this.dispatchEvent("video-background-ready")}onVideoEnded(){if(this.updateState("ended"),this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoTimeUpdate(t){this.currentTime=t.seconds,this.percentComplete=this.timeToPercentage(t.seconds),this.dispatchEvent("video-background-time-update"),this.setDuration(t.duration),this.params["end-at"]&&this.duration&&t.seconds>=this.duration&&this.onVideoEnded()}onVideoBuffering(){this.updateState("buffering")}onVideoPlay(t){if(this.setDuration(t.duration),!this.initialPlay&&(this.initialPlay=!0,this.playerElement.style.opacity=1,this.player.setLoop(this.params.loop),!(this.params.autoplay&&(this.params["always-play"]||this.isIntersecting))))return this.player.pause();const e=t.seconds;this.params["start-at"]&&e=this.duration&&this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}seek(t){this.seekTo(this.percentageToTime(t))}seekTo(t){this.player&&(this.player.setCurrentTime(t),this.dispatchEvent("video-background-seeked"))}softPause(){!this.player||this.currentState==="paused"||this.player.pause()}softPlay(){!this.player||this.currentState==="playing"||this.player.play()}play(){this.player&&(this.paused=!1,this.player.play())}pause(){this.player&&(this.paused=!0,this.player.pause())}unmute(){this.player&&(this.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.player.setMuted(!1),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.setMuted(!0),this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.getVolume()}setVolume(t){this.player&&(this.volume=t,this.player.setVolume(t),this.dispatchEvent("video-background-volume-change"))}},R=class extends h{constructor(t,e,i,s,a){super(t,e,i.link,s,"video",a),!(!i||!i.link)&&(this.is_mobile&&!this.params.mobile||(this.src=i.link,this.ext=/(?:\.([^.]+))?$/.exec(i.id)[1],this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.player=null,this.buttons={},this.MIME_MAP={ogv:"video/ogg",ogm:"video/ogg",ogg:"video/ogg",avi:"video/avi",mp4:"video/mp4",webm:"video/webm"},this.mime=this.MIME_MAP[this.ext.toLowerCase()],this.injectPlayer(),this.mobileLowBatteryAutoplayHack(),this.dispatchEvent("video-background-ready")))}generatePlayerElement(){const t=document.createElement("video");return t.setAttribute("playsinline",""),this.params.loop&&t.setAttribute("loop",""),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(t.setAttribute("autoplay",""),t.autoplay=!0),this.muted&&(t.setAttribute("muted",""),t.muted=!0),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}injectPlayer(){this.player=this.generatePlayerElement(),this.playerElement=this.player,this.volume!==1&&!this.muted&&this.setVolume(this.volume),this.playerElement.setAttribute("id",this.uid),this.stylePlayerElement(this.playerElement),this.player.addEventListener("loadedmetadata",this.onVideoLoadedMetadata.bind(this)),this.player.addEventListener("durationchange",this.onVideoLoadedMetadata.bind(this)),this.player.addEventListener("canplay",this.onVideoCanPlay.bind(this)),this.player.addEventListener("timeupdate",this.onVideoTimeUpdate.bind(this)),this.player.addEventListener("play",this.onVideoPlay.bind(this)),this.player.addEventListener("pause",this.onVideoPause.bind(this)),this.player.addEventListener("waiting",this.onVideoBuffering.bind(this)),this.player.addEventListener("ended",this.onVideoEnded.bind(this)),this.element.appendChild(this.playerElement);const t=document.createElement("source");t.setAttribute("src",this.src),t.setAttribute("type",this.mime),this.playerElement.appendChild(t),this.resize(this.playerElement)}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(c);if(!e||!e.length)return;this.id=e[1],this.ext=/(?:\.([^.]+))?$/.exec(this.id)[1],this.mime=this.MIME_MAP[this.ext.toLowerCase()],this.playerElement.innerHTML="";const i=document.createElement("source");i.setAttribute("src",t),i.setAttribute("type",this.mime),this.playerElement.appendChild(i),this.src=t,this.element.hasAttribute("data-vbg")&&this.element.setAttribute("data-vbg",this.src),this.element.hasAttribute("data-ytbg")&&this.element.setAttribute("data-ytbg",this.src)}onVideoLoadedMetadata(){this.setDuration(this.player.duration)}onVideoCanPlay(){this.setDuration(this.player.duration)}onVideoTimeUpdate(){this.currentTime=this.player.currentTime,this.percentComplete=this.timeToPercentage(this.player.currentTime),this.dispatchEvent("video-background-time-update"),this.params["end-at"]&&this.currentTime>=this.duration&&this.onVideoEnded()}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1);const t=this.player.currentTime;this.params["start-at"]&&t<=this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.duration&&t>=this.duration&&this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}onVideoEnded(){if(this.updateState("ended"),this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.onVideoPlay()}onVideoBuffering(){this.updateState("buffering")}seek(t){this.seekTo(this.percentageToTime(t))}seekTo(t){if(this.player){if(this.player.hasOwnProperty("fastSeek")){this.player.fastSeek(t);return}this.player.currentTime=t,this.dispatchEvent("video-background-seeked")}}softPause(){!this.player||this.currentState==="paused"||this.player.pause()}softPlay(){!this.player||this.currentState==="playing"||this.player.play()}play(){this.player&&(this.paused=!1,this.player.play())}pause(){this.player&&(this.paused=!0,this.player.pause())}unmute(){this.player&&(this.muted=!1,this.player.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.muted=!0,this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.volume}setVolume(t){this.player&&(this.volume=t,this.player.volume=t,this.dispatchEvent("video-background-volume-change"))}},b=class{constructor(t,e){this.elements=t,this.elements instanceof Element&&(this.elements=[this.elements]),typeof this.elements=="string"&&(this.elements=document.querySelectorAll(t)),this.index={};const i=this;if(this.intersectionObserver=null,"IntersectionObserver"in window&&(this.intersectionObserver=new IntersectionObserver(function(s){s.forEach(function(a){const r=a.target.getAttribute("data-vbg-uid");if(r&&i.index.hasOwnProperty(r)&&a.isIntersecting){i.index[r].isIntersecting=!0;try{i.index[r].player&&!i.index[r].paused&&i.index[r].softPlay()}catch{}}else{i.index[r].isIntersecting=!1;try{i.index[r].player&&i.index[r].softPause()}catch{}}})})),this.resizeObserver=null,"ResizeObserver"in window?this.resizeObserver=new ResizeObserver(function(s){s.forEach(function(a){const r=a.target.getAttribute("data-vbg-uid");r&&i.index.hasOwnProperty(r)&&window.requestAnimationFrame(()=>i.index[r].resize())})}):window.addEventListener("resize",function(){for(let s in i.index)window.requestAnimationFrame(()=>i.index[s].resize(i.index[s].playerElement))}),this.initPlayers(),!(!this.elements||!this.elements.length)){for(let s=0;s{function l(t){t&&(t.element.classList.add(t.stateClassName),t.element.firstChild.classList.remove(t.stateChildClassNames[0]),t.element.firstChild.classList.add(t.stateChildClassNames[1]),t.element.setAttribute("aria-checked",!1))}function E(t){t&&(t.element.classList.remove(t.stateClassName),t.element.firstChild.classList.add(t.stateChildClassNames[0]),t.element.firstChild.classList.remove(t.stateChildClassNames[1]),t.element.setAttribute("aria-checked",!0))}function u(t,e){const i=document.createElement("button");i.className=e.className,i.innerHTML=e.innerHtml,i.setAttribute("role","switch"),i.firstChild.classList.add(e.stateChildClassNames[0]),i.setAttribute("aria-checked",!e.initialState),e.element=i,t.params[e.condition_parameter]===e.initialState&&l(e),i.addEventListener("click",function(s){this.classList.contains(e.stateClassName)?(E(e),t[e.actions[0]]()):(l(e),t[e.actions[1]]())}),t.buttons[e.name]={element:i,button_properties:e},t.controls_element.appendChild(i)}function w(t){if(/^\s*(true|false)\s*$/i.test(t))return t==="true"}function k(t){if(/^\s*\d+\s*$/.test(t))return parseInt(t);if(/^\s*[\d.]+\s*$/.test(t))return parseFloat(t)}function T(t){if(/^\s*\[.*\]\s*$/.test(t))try{return JSON.parse(t)}catch{}}function V(t){if(/^\s*\{.*\}\s*$/.test(t))try{return JSON.parse(t)}catch{}}function P(t){if(/^\s*\/.*\/g?i?\s*$/.test(t))try{return new RegExp(t)}catch{}}function A(t){if(/^\s*null\s*$/.test(t))return null;const e=w(t);return e!==void 0?e:k(t)||T(t)||V(t)||P(t)||t}function S(t){return Array.isArray(t)}function x(t){return typeof t=="string"}function d(t,e,i=!1){if(t=Number(t),e=Number(e),isNaN(t)||isNaN(e))throw new TypeError("Both min and max must be numbers");if(t>e&&([t,e]=[e,t]),t===e)return t;t=Math.round(t),e=Math.round(e);const s=i?N():Math.random();return Math.floor(s*(e-t+1))+t}function I(t,e){return e?parseFloat(t.toFixed(e)):parseInt(t)}function C(t,e){return!t||!e||Number.isNaN(t)||Number.isNaN(e)?0:t/e*100}function N(){if(!crypto)return Math.random();if(crypto.getRandomValues)return crypto.getRandomValues(new Uint32Array(1))[0]/4294967295}var p=/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,m=/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i,c=/\/([^\/]+\.(?:mp4|ogg|ogv|ogm|webm|avi))\s*$/i;function L(t){const e=1.7777777778;if(!t||!t.length||/16[\:x\-\/]{1}9/i.test(t))return e;const i=t.split(/\s?[\:x\-\/]{1}\s?/i);if(i.length<2)return e;const s=parseInt(i[0]),a=parseInt(i[1]);return s===0||a===0||isNaN(s)||isNaN(a)?e:s/a}function y(t,e=document){if(t instanceof Array||t instanceof NodeList)return t;if(t instanceof Element)return[t];if(e instanceof Element||e instanceof Document)return e.querySelectorAll(t);if(x(e)&&(e=y(e)),!e instanceof Array&&!e instanceof NodeList)return[];const i=[];for(const s of e)i.push(...s.querySelectorAll(t));return i}function O(t,e=1,i=0){t instanceof Element&&(t=[t]),typeof t=="string"&&(t=y(t));for(const s of t){const a=s.parentNode.offsetHeight+i,r=s.parentNode.offsetWidth+i;e>r/a?(s.style.width=a*e+"px",s.style.height=a+"px"):(s.style.width=r+"px",s.style.height=r/e+"px")}}function U(t){return/\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(t)||/\b(Android|Windows Phone|iPad|iPod)\b/i.test(t)}function R(){return"maxTouchPoints"in navigator?navigator.maxTouchPoints>0:"matchMedia"in window?!!matchMedia("(pointer:coarse)").matches:"orientation"in window?!0:U(navigator.userAgent)}var h=class{constructor(t,e,i,s,a,r){if(!i)return;this.is_mobile=R(),this.type=a,this.id=i,this.factoryInstance=r,this.element=t,this.playerElement=null,this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.buttons={},this.isIntersecting=!1,this.paused=!1,this.muted=!1,this.currentState="notstarted",this.initialPlay=!1,this.initialVolume=!1,this.volume=1,this.params={};const n={pause:!1,"play-button":!1,"mute-button":!1,autoplay:!0,muted:!0,loop:!0,mobile:!0,"load-background":!1,resolution:"16:9","inline-styles":!0,"fit-box":!1,offset:100,"start-at":0,"end-at":0,poster:null,"always-play":!1,volume:1,"no-cookie":!0,"force-on-low-battery":!1,lazyloading:!1,title:"Video background"};this.params=this.parseProperties(e,n,this.element,["data-ytbg-","data-vbg-"]),this.params.pause&&(this.params["play-button"]=this.params.pause),this.params.resolution_mod=L(this.params.resolution),this.muted=this.params.muted,this.volume=this.params.volume,this.currentTime=this.params["start-at"]||0,this.duration=this.params["end-at"]||0,this.percentComplete=0,this.params["start-at"]&&(this.percentComplete=this.timeToPercentage(this.params["start-at"])),this.buildWrapperHTML(),!(this.is_mobile&&!this.params.mobile)&&(this.params["play-button"]&&u(this,{name:"playing",className:"play-toggle",innerHtml:' ',initialState:!this.paused,stateClassName:"paused",condition_parameter:"paused",stateChildClassNames:["fa-pause-circle","fa-play-circle"],actions:["play","pause"]}),this.params["mute-button"]&&u(this,{name:"muted",className:"mute-toggle",innerHtml:' ',initialState:this.muted,stateClassName:"muted",condition_parameter:"muted",stateChildClassNames:["fa-volume-up","fa-volume-mute"],actions:["unmute","mute"]}))}timeToPercentage(t){if(t<=this.params["start-at"])return 0;if(t>=this.duration)return 100;if(t<=0)return 0;t-=this.params["start-at"];const e=this.duration-this.params["start-at"];return C(t,e)}percentageToTime(t){if(!this.duration)return this.params["start-at"]||0;if(t>100)return this.duration;if(t<=0)return this.params["start-at"]||0;const e=this.duration-this.params["start-at"];let i=t*e/100;return i=I(i,3),i>e&&(i=e),this.params["start-at"]&&(i+=this.params["start-at"]),i}resize(t){this.params["fit-box"]||O(t||this.playerElement,this.params.resolution_mod,this.params.offset),this.dispatchEvent("video-background-resize")}stylePlayerElement(t){t&&(this.params["inline-styles"]&&(t.style.top="50%",t.style.left="50%",t.style.transform="translateX(-50%) translateY(-50%)",t.style.position="absolute",t.style.opacity=0),this.params["fit-box"]&&(t.style.width="100%",t.style.height="100%"))}buildWrapperHTML(){const t=this.element.parentNode;this.element.classList.add("youtube-background","video-background");const e={height:"100%",width:"100%","z-index":"0",position:"absolute",overflow:"hidden",top:0,left:0,bottom:0,right:0};if(this.params["mute-button"]||(e["pointer-events"]="none"),(this.params["load-background"]||this.params.poster)&&(this.loadBackground(this.id),this.params.poster&&(e["background-image"]=`url(${this.params.poster})`),e["background-size"]="cover",e["background-repeat"]="no-repeat",e["background-position"]="center"),this.params["inline-styles"]){for(let i in e)this.element.style[i]=e[i];["absolute","fixed","relative","sticky"].indexOf(t.style.position)||(t.style.position="relative")}if(this.params["play-button"]||this.params["mute-button"]){const i=document.createElement("div");i.className="video-background-controls",i.style.position="absolute",i.style.top="10px",i.style.right="10px",i.style["z-index"]=2,this.controls_element=i,t.appendChild(i)}return this.element}loadBackground(t){this.params["load-background"]&&t&&(this.type==="youtube"&&(this.element.style["background-image"]=`url(https://img.youtube.com/vi/${t}/hqdefault.jpg)`),this.type==="vimeo"&&(this.element.style["background-image"]=`url(https://vumbnail.com/${t}.jpg)`))}destroy(){this.playerElement.remove(),this.element.classList.remove("youtube-background","video-background"),this.element.removeAttribute("data-vbg-uid"),this.element.style="",(this.params["play-button"]||this.params["mute-button"])&&this.controls_element.remove(),this.timeUpdateTimer&&clearInterval(this.timeUpdateTimer),this.dispatchEvent("video-background-destroyed")}setDuration(t){if(this.duration!==t){if(this.params["end-at"]){if(t>this.params["end-at"]){this.duration=this.params["end-at"];return}if(tt&&(this.duration=t),this.currentTime>t&&this.onVideoEnded()}dispatchEvent(t){this.element.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:this}))}shouldPlay(){return this.currentState==="ended"&&!this.params.loop?!1:!!(this.params["always-play"]&&this.currentState!=="playing"||this.isIntersecting&&this.params.autoplay&&this.currentState!=="playing")}mobileLowBatteryAutoplayHack(){if(!this.params["force-on-low-battery"]||!this.is_mobile&&this.params.mobile)return;const t=function(){!this.initialPlay&&this.params.autoplay&&this.params.muted&&(this.softPlay(),!this.isIntersecting&&!this.params["always-play"]&&this.softPause())};document.addEventListener("touchstart",t.bind(this),{once:!0})}parseProperties(t,e,i,s){let a={};if(!t)a=e;else for(let r in e)a[r]=t.hasOwnProperty(r)?t[r]:e[r];if(!i)return a;for(let r in a){let n;if(S(s))for(let o=0;o=this.duration){this.currentState="ended",this.dispatchEvent("video-background-state-change"),this.onVideoEnded(),this.stopTimeUpdateTimer();return}this.dispatchEvent("video-background-time-update")}}onVideoPlayerReady(){this.mobileLowBatteryAutoplayHack(),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.player.playVideo()),this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-ready")}onVideoStateChange(t){this.currentState=this.convertState(t.data),this.currentState==="ended"&&this.onVideoEnded(),this.currentState==="notstarted"&&this.params.autoplay&&(this.seekTo(this.params["start-at"]),this.player.playVideo()),this.currentState==="playing"&&this.onVideoPlay(),this.currentState==="paused"&&this.onVideoPause(),this.dispatchEvent("video-background-state-change")}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1);const t=this.player.getCurrentTime();this.params["start-at"]&&t=this.duration&&this.seekTo(this.params["start-at"]),this.duration||this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-play"),this.startTimeUpdateTimer()}onVideoPause(){this.stopTimeUpdateTimer(),this.dispatchEvent("video-background-pause")}onVideoEnded(){if(this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.player.playVideo()}seek(t){this.seekTo(this.percentageToTime(t),!0)}seekTo(t,e=!0){this.player&&(this.player.seekTo(t,e),this.dispatchEvent("video-background-seeked"))}softPause(){!this.player||this.currentState==="paused"||(this.stopTimeUpdateTimer(),this.player.pauseVideo())}softPlay(){!this.player||this.currentState==="playing"||this.player.playVideo()}play(){this.player&&(this.paused=!1,this.player.playVideo())}pause(){this.player&&(this.paused=!0,this.stopTimeUpdateTimer(),this.player.pauseVideo())}unmute(){this.player&&(this.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.player.unMute(),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.mute(),this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.getVolume()/100}setVolume(t){this.player&&(this.volume=t,this.player.setVolume(t*100),this.dispatchEvent("video-background-volume-change"))}},g=class extends h{constructor(t,e,i,s,a){super(t,e,i.id,s,"vimeo",a),i&&(this.unlisted=i.unlisted,!(this.is_mobile&&!this.params.mobile)&&(this.injectScript(),this.player=null,this.injectPlayer(),this.initVimeoPlayer()))}injectScript(){if(window.hasOwnProperty("Vimeo")||document.querySelector('script[src="https://player.vimeo.com/api/player.js"]'))return;const t=document.createElement("script");window.hasOwnProperty("onVimeoIframeAPIReady")&&typeof window.onVimeoIframeAPIReady=="function"&&t.addEventListener("load",()=>{window.onVimeoIframeAPIReady()}),t.src="https://player.vimeo.com/api/player.js";const e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(t,e)}initVimeoPlayer(){!window.hasOwnProperty("Vimeo")||this.player!==null||(this.player=new Vimeo.Player(this.playerElement),this.player.on("loaded",this.onVideoPlayerReady.bind(this)),this.player.on("ended",this.onVideoEnded.bind(this)),this.player.on("play",this.onVideoPlay.bind(this)),this.player.on("pause",this.onVideoPause.bind(this)),this.player.on("bufferstart",this.onVideoBuffering.bind(this)),this.player.on("timeupdate",this.onVideoTimeUpdate.bind(this)),this.volume!==1&&!this.muted&&this.setVolume(this.volume))}onVideoError(t){console.error(t)}generatePlayerElement(){const t=document.createElement("iframe");return this.params.title&&t.setAttribute("title",this.params.title),t.setAttribute("frameborder",0),t.setAttribute("allow","autoplay; mute"),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}generateSrcURL(t,e){e=e?`h=${e}&`:"";let i=`https://player.vimeo.com/video/${t}?${e}background=1&controls=0`;return this.params.muted&&(i+="&muted=1"),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(i+="&autoplay=1"),this.params.loop&&(i+="&loop=1&autopause=0"),this.params["no-cookie"]&&(i+="&dnt=1"),this.params["start-at"]&&(i+="#t="+this.params["start-at"]+"s"),i}injectPlayer(){this.playerElement=this.generatePlayerElement(),this.src=this.generateSrcURL(this.id,this.unlisted),this.playerElement.src=this.src,this.playerElement.id=this.uid,this.stylePlayerElement(this.playerElement),this.element.appendChild(this.playerElement),this.resize(this.playerElement)}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(m);!e||!e.length||(this.id=e[1],this.src=this.generateSrcURL(this.id),this.playerElement.src=this.src,this.element.hasAttribute("data-vbg")&&this.element.setAttribute("data-vbg",this.src),this.element.hasAttribute("data-ytbg")&&this.element.setAttribute("data-ytbg",this.src),this.loadBackground(this.id))}onVideoPlayerReady(){this.mobileLowBatteryAutoplayHack(),this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&this.player.play(),this.player.getDuration().then(t=>{this.setDuration(t)}),this.dispatchEvent("video-background-ready")}onVideoEnded(){if(this.updateState("ended"),this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoTimeUpdate(t){this.currentTime=t.seconds,this.percentComplete=this.timeToPercentage(t.seconds),this.dispatchEvent("video-background-time-update"),this.setDuration(t.duration),this.params["end-at"]&&this.duration&&t.seconds>=this.duration&&this.onVideoEnded()}onVideoBuffering(){this.updateState("buffering")}onVideoPlay(t){if(this.setDuration(t.duration),!this.initialPlay&&(this.initialPlay=!0,this.playerElement.style.opacity=1,this.player.setLoop(this.params.loop),!(this.params.autoplay&&(this.params["always-play"]||this.isIntersecting))))return this.player.pause();const e=t.seconds;this.params["start-at"]&&e=this.duration&&this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}seek(t){this.seekTo(this.percentageToTime(t))}seekTo(t){this.player&&(this.player.setCurrentTime(t),this.dispatchEvent("video-background-seeked"))}softPause(){!this.player||this.currentState==="paused"||this.player.pause()}softPlay(){!this.player||this.currentState==="playing"||this.player.play()}play(){this.player&&(this.paused=!1,this.player.play())}pause(){this.player&&(this.paused=!0,this.player.pause())}unmute(){this.player&&(this.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.player.setMuted(!1),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.setMuted(!0),this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.getVolume()}setVolume(t){this.player&&(this.volume=t,this.player.setVolume(t),this.dispatchEvent("video-background-volume-change"))}},B=class extends h{constructor(t,e,i,s,a){super(t,e,i.link,s,"video",a),!(!i||!i.link)&&(this.is_mobile&&!this.params.mobile||(this.src=i.link,this.ext=/(?:\.([^.]+))?$/.exec(i.id)[1],this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.player=null,this.buttons={},this.MIME_MAP={ogv:"video/ogg",ogm:"video/ogg",ogg:"video/ogg",avi:"video/avi",mp4:"video/mp4",webm:"video/webm"},this.mime=this.MIME_MAP[this.ext.toLowerCase()],this.injectPlayer(),this.mobileLowBatteryAutoplayHack(),this.dispatchEvent("video-background-ready")))}generatePlayerElement(){const t=document.createElement("video");return this.params.title&&t.setAttribute("title",this.params.title),t.setAttribute("playsinline",""),this.params.loop&&t.setAttribute("loop",""),this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)&&(t.setAttribute("autoplay",""),t.autoplay=!0),this.muted&&(t.setAttribute("muted",""),t.muted=!0),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}injectPlayer(){this.player=this.generatePlayerElement(),this.playerElement=this.player,this.volume!==1&&!this.muted&&this.setVolume(this.volume),this.playerElement.setAttribute("id",this.uid),this.stylePlayerElement(this.playerElement),this.player.addEventListener("loadedmetadata",this.onVideoLoadedMetadata.bind(this)),this.player.addEventListener("durationchange",this.onVideoLoadedMetadata.bind(this)),this.player.addEventListener("canplay",this.onVideoCanPlay.bind(this)),this.player.addEventListener("timeupdate",this.onVideoTimeUpdate.bind(this)),this.player.addEventListener("play",this.onVideoPlay.bind(this)),this.player.addEventListener("pause",this.onVideoPause.bind(this)),this.player.addEventListener("waiting",this.onVideoBuffering.bind(this)),this.player.addEventListener("ended",this.onVideoEnded.bind(this)),this.element.appendChild(this.playerElement);const t=document.createElement("source");t.setAttribute("src",this.src),t.setAttribute("type",this.mime),this.playerElement.appendChild(t),this.resize(this.playerElement)}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(c);if(!e||!e.length)return;this.id=e[1],this.ext=/(?:\.([^.]+))?$/.exec(this.id)[1],this.mime=this.MIME_MAP[this.ext.toLowerCase()],this.playerElement.innerHTML="";const i=document.createElement("source");i.setAttribute("src",t),i.setAttribute("type",this.mime),this.playerElement.appendChild(i),this.src=t,this.element.hasAttribute("data-vbg")&&this.element.setAttribute("data-vbg",this.src),this.element.hasAttribute("data-ytbg")&&this.element.setAttribute("data-ytbg",this.src)}onVideoLoadedMetadata(){this.setDuration(this.player.duration)}onVideoCanPlay(){this.setDuration(this.player.duration)}onVideoTimeUpdate(){this.currentTime=this.player.currentTime,this.percentComplete=this.timeToPercentage(this.player.currentTime),this.dispatchEvent("video-background-time-update"),this.params["end-at"]&&this.currentTime>=this.duration&&this.onVideoEnded()}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1);const t=this.player.currentTime;this.params["start-at"]&&t<=this.params["start-at"]&&this.seekTo(this.params["start-at"]),this.duration&&t>=this.duration&&this.seekTo(this.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}onVideoEnded(){if(this.updateState("ended"),this.dispatchEvent("video-background-ended"),!this.params.loop)return this.pause();this.seekTo(this.params["start-at"]),this.onVideoPlay()}onVideoBuffering(){this.updateState("buffering")}seek(t){this.seekTo(this.percentageToTime(t))}seekTo(t){if(this.player){if(this.player.hasOwnProperty("fastSeek")){this.player.fastSeek(t);return}this.player.currentTime=t,this.dispatchEvent("video-background-seeked")}}softPause(){!this.player||this.currentState==="paused"||this.player.pause()}softPlay(){!this.player||this.currentState==="playing"||this.player.play()}play(){this.player&&(this.paused=!1,this.player.play())}pause(){this.player&&(this.paused=!0,this.player.pause())}unmute(){this.player&&(this.muted=!1,this.player.muted=!1,this.initialVolume||(this.initialVolume=!0,this.setVolume(this.params.volume)),this.dispatchEvent("video-background-unmute"))}mute(){this.player&&(this.muted=!0,this.player.muted=!0,this.dispatchEvent("video-background-mute"))}getVolume(){if(this.player)return this.player.volume}setVolume(t){this.player&&(this.volume=t,this.player.volume=t,this.dispatchEvent("video-background-volume-change"))}},b=class{constructor(t,e){this.elements=t,this.elements instanceof Element&&(this.elements=[this.elements]),typeof this.elements=="string"&&(this.elements=document.querySelectorAll(t)),this.index={};const i=this;if(this.intersectionObserver=null,"IntersectionObserver"in window&&(this.intersectionObserver=new IntersectionObserver(function(s){s.forEach(function(a){const r=a.target.getAttribute("data-vbg-uid");if(r&&i.index.hasOwnProperty(r)&&a.isIntersecting){i.index[r].isIntersecting=!0;try{i.index[r].player&&!i.index[r].paused&&i.index[r].softPlay()}catch{}}else{i.index[r].isIntersecting=!1;try{i.index[r].player&&i.index[r].softPause()}catch{}}})})),this.resizeObserver=null,"ResizeObserver"in window?this.resizeObserver=new ResizeObserver(function(s){s.forEach(function(a){const r=a.target.getAttribute("data-vbg-uid");r&&i.index.hasOwnProperty(r)&&window.requestAnimationFrame(()=>i.index[r].resize())})}):window.addEventListener("resize",function(){for(let s in i.index)window.requestAnimationFrame(()=>i.index[s].resize(i.index[s].playerElement))}),this.initPlayers(),!(!this.elements||!this.elements.length)){for(let s=0;s this.setProgress(this.vbgInstance.percentComplete));\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n requestAnimationFrame(() => this.setProgress(0));\n }\n\n onInput(event) {\n this.lock = true;\n requestAnimationFrame(() => this.setProgress(event.target.value));\n }\n\n onChange(event) {\n this.lock = false;\n requestAnimationFrame(() => this.setProgress(event.target.value));\n if (this.vbgInstance) {\n this.vbgInstance.seek(event.target.value);\n if (this.vbgInstance.playerElement && this.vbgInstance.playerElement.style.opacity === 0) this.vbgInstance.playerElement.style.opacity = 1;\n }\n}\n\n setProgress(value) {\n if (this.progressElem) this.progressElem.value = value;\n if (this.inputElem) this.inputElem.value = value;\n }\n}\n\nexport class VideoBackgroundGroup {\n constructor(selector, videoBackgroundSelector, videoBackgroundFactoryInstance) {\n this.element = selector;\n if (typeof this.element === 'string') this.element = document.querySelector(selector);\n if (!this.element) return;\n this.elements = this.element.querySelectorAll(videoBackgroundSelector || '[data-vbg]');\n if (!this.elements.length) return;\n\n this.videoBackgroundFactoryInstance = videoBackgroundFactoryInstance;\n this.stack = [];\n this.map = new Map();\n this.current = 0;\n this.currentElement = null;\n this.currentInstance = null;\n\n this.playing = false;\n this.muted = true;\n\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n if (!element.hasAttribute('data-vbg-uid') && this.videoBackgroundFactoryInstance) this.videoBackgroundFactoryInstance.add(element);\n this.stack.push(element);\n this.map.set(element, i);\n \n if (i === 0) {\n this.current = 0;\n this.currentElement = element;\n if (this.videoBackgroundFactoryInstance) this.currentInstance = this.videoBackgroundFactoryInstance.get(element);\n }\n element.addEventListener('video-background-ended', this.onVideoEnded.bind(this));\n element.addEventListener('video-background-seeked', this.onVideoSeeked.bind(this));\n element.addEventListener('video-background-pause', this.onVideoPause.bind(this));\n element.addEventListener('video-background-ready', this.onVideoReady.bind(this));\n element.addEventListener('video-background-state-change', this.setVideoBackgroundFactoryInstance.bind(this), { once: true });\n element.addEventListener('video-background-time-update', this.setVideoBackgroundFactoryInstance.bind(this), { once: true });\n }\n }\n\n setVideoBackgroundFactoryInstance(event) {\n if (this.videoBackgroundFactoryInstance) return;\n this.videoBackgroundFactoryInstance = event.detail.factoryInstance;\n if (!this.currentInstance) this.currentInstance = this.videoBackgroundFactoryInstance.get(this.currentElement);\n }\n\n onVideoReady(event) {\n if (this.stack[this.current] !== event.detail.element) return;\n this.setVideoBackgroundFactoryInstance(event);\n const videoBackground = event.detail;\n if (videoBackground.params.muted) this.muted = true;\n if (!videoBackground.isIntersecting) return;\n if (!videoBackground.params.autoplay) return;\n this.playing = true;\n if (videoBackground.currentState === 'playing') return;\n videoBackground.softPlay();\n }\n\n onVideoPause(event) {;\n this.setVideoBackgroundFactoryInstance(event);\n const stackIndex = this.map.get(event.detail.element);\n if (stackIndex === this.current) return;\n }\n\n levelSeekBars() {\n for (let i = 0; i < this.stack.length; i++) {\n if (i === this.current) continue;\n const seekBarElem = this.getSeekBar(this.videoBackgroundFactoryInstance.get(this.stack[i]));\n if (!seekBarElem) continue;\n if (i < this.current) {\n this.setProgress(seekBarElem, 100);\n } else {\n this.setProgress(seekBarElem, 0);\n }\n }\n }\n\n getSeekBar(currentInstance) {\n if (!currentInstance) return;\n const uid = currentInstance.uid;\n const element = document.querySelector(`.js-seek-bar-wrap[data-target-uid=\"${uid}\"]`);\n if (!element) return;\n return element;\n }\n\n setProgress(seekBarElem, value) {\n if (!seekBarElem) return;\n const progressElem = seekBarElem.querySelector('.js-seek-bar-progress');\n const inputElem = seekBarElem.querySelector('.js-seek-bar');\n if (progressElem) progressElem.value = value;\n if (inputElem) inputElem.value = value;\n }\n\n onVideoSeeked(event) {\n const current = this.map.get(event.detail.element);\n if (this.current !== current) this.setCurrent(current, true);\n }\n\n setCurrent(index, seek) {\n const previous = this.current;\n if (index >= this.stack.length) index = 0;\n if (index < 0) index = this.stack.length - 1;\n const previousInstance = this.videoBackgroundFactoryInstance.get(this.stack[previous]);\n this.current = index;\n this.currentInstance = this.videoBackgroundFactoryInstance.get(this.stack[this.current]);\n this.currentElement = this.stack[this.current];\n \n this.stack[previous].style.display = 'none';\n this.currentElement.style.display = 'block';\n\n if (!seek) {\n const seekBarElem = this.getSeekBar(this.currentInstance);\n if (seekBarElem) this.setProgress(seekBarElem, 0);\n this.currentInstance.seek(0);\n }\n\n setTimeout(() => {\n if (this.currentInstance.currentState !== 'playing') this.currentInstance.play();\n }, 100);\n if (previousInstance && previousInstance.currentState !== 'paused') previousInstance.pause();\n\n setTimeout(this.levelSeekBars.bind(this), 100);\n\n if (index >= this.stack.length) this.dispatchEvent('video-background-group-forward-rewind');\n if (index < 0) this.dispatchEvent('video-background-group-backward-rewind');\n }\n\n dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n onVideoEnded(event) {\n if (event.detail.element !== this.currentElement) return;\n this.next();\n }\n\n next() {\n this.setCurrent(this.current + 1);\n this.dispatchEvent('video-background-group-next');\n }\n\n prev() {\n this.setCurrent(this.current - 1);\n this.dispatchEvent('video-background-group-previous');\n }\n\n unmute() {\n for (let i = 0; i < this.stack.length; i++) {\n const instance = this.videoBackgroundFactoryInstance.get(this.stack[i]);\n if (!instance) continue;\n instance.unmute();\n }\n\n this.muted = false;\n this.dispatchEvent('video-background-group-umnute');\n }\n\n mute() {\n for (let i = 0; i < this.stack.length; i++) {\n const instance = this.videoBackgroundFactoryInstance.get(this.stack[i]);\n if (!instance) continue;\n instance.mute();\n }\n\n this.muted = true;\n this.dispatchEvent('video-background-group-mute');\n }\n\n pause() {\n this.currentInstance.pause();\n this.playing = false;\n this.dispatchEvent('video-background-group-previous');\n }\n\n play() {\n this.currentInstance.play();\n this.playing = true;\n this.dispatchEvent('video-background-group-previous');\n }\n\n destroy() {\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n element.removeEventListener('video-background-ended', this.onVideoEnded.bind(this));\n element.removeEventListener('video-background-seeked', this.onVideoSeeked.bind(this));\n element.removeEventListener('video-background-pause', this.onVideoPause.bind(this));\n element.removeEventListener('video-background-ready', this.onVideoReady.bind(this));\n element.removeEventListener('video-background-state-change', this.setVideoBackgroundFactoryInstance.bind(this));\n element.removeEventListener('video-background-time-update', this.setVideoBackgroundFactoryInstance.bind(this));\n }\n }\n}\n\nexport class PlayToggle {\n constructor(playToggleElem, vbgInstance) {\n if (!playToggleElem) return;\n \n this.element = playToggleElem;\n this.targetSelector = this.element.getAttribute('data-target');\n\n if (!this.targetSelector) return;\n this.active = false;\n\n if (this.element.hasAttribute('aria-checked')) {\n this.active = this.element.getAttribute('aria-checked') === 'true';\n } else {\n this.element.setAttribute('aria-checked', this.active);\n }\n\n this.element.setAttribute('role', 'switch');\n\n this.targetElem = document.querySelector(this.targetSelector);\n if (!this.targetElem) return;\n\n if (vbgInstance) this.vbgInstance = vbgInstance;\n\n this.targetElem.addEventListener('video-background-ready', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-state-change', this.onStateChange.bind(this));\n this.targetElem.addEventListener('video-background-play', this.onPlay.bind(this));\n this.targetElem.addEventListener('video-background-pause', this.onPause.bind(this));\n this.targetElem.addEventListener('video-background-destroyed', this.onDestroyed.bind(this));\n\n this.element.addEventListener('click', this.onClick.bind(this));\n }\n\n onReady(event) {\n this.vbgInstance = event.detail;\n }\n\n onStateChange(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = this.vbgInstance.currentState === 'playing' || this.vbgInstance.currentState === 'buffering';\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onPlay(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onPause(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onClick(event) {\n if (!this.vbgInstance) return;\n if (this.active) {\n this.vbgInstance.pause();\n } else {\n this.vbgInstance.play();\n }\n }\n}\n\nexport class MuteToggle {\n constructor(muteToggleElem, vbgInstance) {\n if (!muteToggleElem) return;\n \n this.element = muteToggleElem;\n this.targetSelector = this.element.getAttribute('data-target');\n\n if (!this.targetSelector) return;\n this.active = false;\n\n if (this.element.hasAttribute('aria-checked')) {\n this.active = this.element.getAttribute('aria-checked') === 'true';\n } else {\n this.element.setAttribute('aria-checked', this.active);\n }\n\n this.element.setAttribute('role', 'switch');\n\n this.targetElem = document.querySelector(this.targetSelector);\n if (!this.targetElem) return;\n\n if (vbgInstance) this.vbgInstance = vbgInstance;\n\n this.targetElem.addEventListener('video-background-ready', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-mute', this.onMute.bind(this));\n this.targetElem.addEventListener('video-background-unmute', this.onUnmute.bind(this));\n this.targetElem.addEventListener('video-background-destroyed', this.onDestroyed.bind(this));\n\n this.element.addEventListener('click', this.onClick.bind(this));\n }\n\n onReady(event) {\n this.vbgInstance = event.detail;\n if (this.vbgInstance.params.muted) {\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n }\n\n onMute(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onUnmute(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onClick(event) {\n if (!this.vbgInstance) return;\n if (this.active) {\n this.vbgInstance.unmute();\n } else {\n this.vbgInstance.mute();\n }\n }\n}\n\n// TODO: this can be achieved with custom elements... Maybe it's finally time to use them?\nclass GeneralFactory {\n constructor(selector, callback, uidAttribute = 'data-uid') {\n this.instances = {};\n this.selector = selector;\n this.elements = [];\n this.callback = callback;\n this.uidAttribute = uidAttribute;\n\n if (!callback || typeof callback !== 'function') return;\n\n if (typeof this.selector === 'string') {\n this.elements = document.querySelectorAll(this.selector);\n }\n\n if (this.selector instanceof Element) {\n this.elements = [this.selector];\n }\n\n if (this.selector instanceof NodeList) {\n this.elements = this.selector;\n }\n\n for (let i = 0; i < this.elements.length; i++) {\n this.add(this.elements[i]);\n\n // TODO: maybe manage elements array?\n }\n }\n\n basicUID() {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n }\n\n generateUID() {\n let tempuid = this.basicUID();\n if (!this.instances.hasOwnProperty(tempuid)) return tempuid;\n return this.generateUID();\n }\n\n add(element) {\n let id = element.getAttribute('id');\n if (!id || this.instances.hasOwnProperty(id)) {\n id = element.getAttribute(this.uidAttribute);\n\n if (!id || this.instances.hasOwnProperty(id)) {\n id = this.generateUID();\n element.setAttribute(this.uidAttribute, id);\n }\n }\n\n if (this.callback && typeof this.callback === 'function') \n this.instances[id] = this.callback(element, id, this);\n }\n\n getID(element) {\n if (!element) return;\n if (typeof element === 'string') return element;\n const id = element.getAttribute('id');\n if (id && this.instances.hasOwnProperty(id)) return id;\n const uid = element.getAttribute(this.uidAttribute);\n if (uid && this.instances.hasOwnProperty(uid)) return uid;\n }\n\n get(element) {\n if (!element) return;\n const id = this.getID(element);\n if (!id) return;\n return this.instances[id];\n }\n\n destroy(element) {\n if (!element) return;\n const id = this.getID(element);\n if (!id) return;\n const instance = this.instances[id];\n if (instance.hasOwnProperty('destroy') && typeof instance.destroy == 'function') this.instances[id].destroy();\n delete this.instances[id];\n }\n\n destroyAll() {\n for (const uid in this.instances) {\n const instance = this.instances[uid];\n if (instance.hasOwnProperty('destroy') && typeof instance.destroy == 'function') instance.destroy();\n delete this.instances[uid];\n }\n }\n}\n\nexport class VideoBackgroundGroups extends GeneralFactory {\n constructor(selector = '.js-vbg-group', videoBackgroundSelector, videoBackgroundFactoryInstance) {\n super(selector, (element, id, factoryInstance) => new VideoBackgroundGroup(element, videoBackgroundSelector, videoBackgroundFactoryInstance));\n }\n}\n", "import { SeekBar, PlayToggle, MuteToggle, VideoBackgroundGroup, VideoBackgroundGroups } from \"./lib/controls\";\n\nwindow.SeekBar = SeekBar;\nwindow.PlayToggle = PlayToggle;\nwindow.MuteToggle = MuteToggle;\nwindow.VideoBackgroundGroup = VideoBackgroundGroup;\nwindow.VideoBackgroundGroups = VideoBackgroundGroups;\n"],
- "mappings": "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",
+ "sourcesContent": ["export class SeekBar {\n constructor(element, vbgInstance) {\n this.lock = false;\n if (!element) return;\n this.element = element;\n if (this.element.hasAttribute('data-target-uid')) return;\n this.progressElem = this.element.querySelector('.js-seek-bar-progress');\n this.inputElem = this.element.querySelector('.js-seek-bar');\n this.targetSelector = this.element.getAttribute('data-target');\n if (this.targetSelector) this.targetElem = document.querySelector(this.targetSelector);\n if (!this.targetSelector && vbgInstance) this.targetElem = vbgInstance.element;\n if (!this.targetElem) return;\n\n if (vbgInstance) this.setVBGInstance(vbgInstance);\n \n this.targetElem.addEventListener('video-background-time-update', this.onTimeUpdate.bind(this));\n this.targetElem.addEventListener('video-background-play', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-ready', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-destroyed', this.onDestroyed.bind(this));\n\n this.inputElem.addEventListener('input', this.onInput.bind(this));\n this.inputElem.addEventListener('change', this.onChange.bind(this));\n }\n\n setVBGInstance(vbgInstance) {\n if (this.vbgInstance) return;\n this.vbgInstance = vbgInstance;\n this.element.setAttribute('data-target-uid', vbgInstance.uid);\n }\n\n onReady(event) {\n this.setVBGInstance(event.detail);\n }\n\n onTimeUpdate(event) {\n this.setVBGInstance(event.detail);\n if (!this.lock) requestAnimationFrame(() => this.setProgress(this.vbgInstance.percentComplete));\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n requestAnimationFrame(() => this.setProgress(0));\n }\n\n onInput(event) {\n this.lock = true;\n requestAnimationFrame(() => this.setProgress(event.target.value));\n }\n\n onChange(event) {\n this.lock = false;\n requestAnimationFrame(() => this.setProgress(event.target.value));\n if (this.vbgInstance) {\n this.vbgInstance.seek(event.target.value);\n if (this.vbgInstance.playerElement && this.vbgInstance.playerElement.style.opacity === 0) this.vbgInstance.playerElement.style.opacity = 1;\n }\n}\n\n setProgress(value) {\n if (this.progressElem) this.progressElem.value = value;\n if (this.inputElem) this.inputElem.value = value;\n }\n}\n\nexport class VideoBackgroundGroup {\n constructor(selector, videoBackgroundSelector, videoBackgroundFactoryInstance) {\n this.element = selector;\n if (typeof this.element === 'string') this.element = document.querySelector(selector);\n if (!this.element) return;\n this.elements = this.element.querySelectorAll(videoBackgroundSelector || '[data-vbg]');\n if (!this.elements.length) return;\n\n this.videoBackgroundFactoryInstance = videoBackgroundFactoryInstance;\n this.stack = [];\n this.map = new Map();\n this.current = 0;\n this.currentElement = null;\n this.currentInstance = null;\n\n this.playing = false;\n this.muted = true;\n\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n if (!element.hasAttribute('data-vbg-uid') && this.videoBackgroundFactoryInstance) this.videoBackgroundFactoryInstance.add(element);\n this.stack.push(element);\n this.map.set(element, i);\n \n if (i === 0) {\n this.current = 0;\n this.currentElement = element;\n if (this.videoBackgroundFactoryInstance) this.currentInstance = this.videoBackgroundFactoryInstance.get(element);\n }\n element.addEventListener('video-background-ended', this.onVideoEnded.bind(this));\n element.addEventListener('video-background-seeked', this.onVideoSeeked.bind(this));\n element.addEventListener('video-background-pause', this.onVideoPause.bind(this));\n element.addEventListener('video-background-ready', this.onVideoReady.bind(this));\n element.addEventListener('video-background-state-change', this.setVideoBackgroundFactoryInstance.bind(this), { once: true });\n element.addEventListener('video-background-time-update', this.setVideoBackgroundFactoryInstance.bind(this), { once: true });\n }\n }\n\n setVideoBackgroundFactoryInstance(event) {\n if (this.videoBackgroundFactoryInstance) return;\n this.videoBackgroundFactoryInstance = event.detail.factoryInstance;\n if (!this.currentInstance) this.currentInstance = this.videoBackgroundFactoryInstance.get(this.currentElement);\n }\n\n onVideoReady(event) {\n if (this.stack[this.current] !== event.detail.element) return;\n this.setVideoBackgroundFactoryInstance(event);\n const videoBackground = event.detail;\n if (videoBackground.params.muted) this.muted = true;\n if (!videoBackground.isIntersecting) return;\n if (!videoBackground.params.autoplay) return;\n this.playing = true;\n if (videoBackground.currentState === 'playing') return;\n videoBackground.softPlay();\n }\n\n onVideoPause(event) {;\n this.setVideoBackgroundFactoryInstance(event);\n const stackIndex = this.map.get(event.detail.element);\n if (stackIndex === this.current) return;\n }\n\n levelSeekBars() {\n for (let i = 0; i < this.stack.length; i++) {\n if (i === this.current) continue;\n const seekBarElem = this.getSeekBar(this.videoBackgroundFactoryInstance.get(this.stack[i]));\n if (!seekBarElem) continue;\n if (i < this.current) {\n this.setProgress(seekBarElem, 100);\n } else {\n this.setProgress(seekBarElem, 0);\n }\n }\n }\n\n getSeekBar(currentInstance) {\n if (!currentInstance) return;\n const uid = currentInstance.uid;\n const element = document.querySelector(`.js-seek-bar-wrap[data-target-uid=\"${uid}\"]`);\n if (!element) return;\n return element;\n }\n\n setProgress(seekBarElem, value) {\n if (!seekBarElem) return;\n const progressElem = seekBarElem.querySelector('.js-seek-bar-progress');\n const inputElem = seekBarElem.querySelector('.js-seek-bar');\n if (progressElem) progressElem.value = value;\n if (inputElem) inputElem.value = value;\n }\n\n onVideoSeeked(event) {\n const current = this.map.get(event.detail.element);\n if (this.current !== current) this.setCurrent(current, true);\n }\n\n setCurrent(index, seek) {\n const previous = this.current;\n if (index >= this.stack.length) index = 0;\n if (index < 0) index = this.stack.length - 1;\n const previousInstance = this.videoBackgroundFactoryInstance.get(this.stack[previous]);\n this.current = index;\n this.currentInstance = this.videoBackgroundFactoryInstance.get(this.stack[this.current]);\n this.currentElement = this.stack[this.current];\n \n this.stack[previous].style.display = 'none';\n this.currentElement.style.display = 'block';\n\n if (!seek) {\n const seekBarElem = this.getSeekBar(this.currentInstance);\n if (seekBarElem) this.setProgress(seekBarElem, 0);\n this.currentInstance.seek(0);\n }\n\n setTimeout(() => {\n if (this.currentInstance.currentState !== 'playing') this.currentInstance.play();\n }, 100);\n if (previousInstance && previousInstance.currentState !== 'paused') previousInstance.pause();\n\n setTimeout(this.levelSeekBars.bind(this), 100);\n\n if (index >= this.stack.length) this.dispatchEvent('video-background-group-forward-rewind');\n if (index < 0) this.dispatchEvent('video-background-group-backward-rewind');\n }\n\n dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n onVideoEnded(event) {\n if (event.detail.element !== this.currentElement) return;\n this.next();\n }\n\n next() {\n this.setCurrent(this.current + 1);\n this.dispatchEvent('video-background-group-next');\n }\n\n prev() {\n this.setCurrent(this.current - 1);\n this.dispatchEvent('video-background-group-previous');\n }\n\n unmute() {\n for (let i = 0; i < this.stack.length; i++) {\n const instance = this.videoBackgroundFactoryInstance.get(this.stack[i]);\n if (!instance) continue;\n instance.unmute();\n }\n\n this.muted = false;\n this.dispatchEvent('video-background-group-umnute');\n }\n\n mute() {\n for (let i = 0; i < this.stack.length; i++) {\n const instance = this.videoBackgroundFactoryInstance.get(this.stack[i]);\n if (!instance) continue;\n instance.mute();\n }\n\n this.muted = true;\n this.dispatchEvent('video-background-group-mute');\n }\n\n pause() {\n this.currentInstance.pause();\n this.playing = false;\n this.dispatchEvent('video-background-group-pause');\n }\n\n play() {\n this.currentInstance.play();\n this.playing = true;\n this.dispatchEvent('video-background-group-play');\n }\n\n destroy() {\n for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n element.removeEventListener('video-background-ended', this.onVideoEnded.bind(this));\n element.removeEventListener('video-background-seeked', this.onVideoSeeked.bind(this));\n element.removeEventListener('video-background-pause', this.onVideoPause.bind(this));\n element.removeEventListener('video-background-ready', this.onVideoReady.bind(this));\n element.removeEventListener('video-background-state-change', this.setVideoBackgroundFactoryInstance.bind(this));\n element.removeEventListener('video-background-time-update', this.setVideoBackgroundFactoryInstance.bind(this));\n }\n }\n}\n\nexport class PlayToggle {\n constructor(playToggleElem, vbgInstance) {\n if (!playToggleElem) return;\n \n this.element = playToggleElem;\n this.targetSelector = this.element.getAttribute('data-target');\n\n if (!this.targetSelector) return;\n this.active = false;\n\n if (this.element.hasAttribute('aria-checked')) {\n this.active = this.element.getAttribute('aria-checked') === 'true';\n } else {\n this.element.setAttribute('aria-checked', this.active);\n }\n\n this.element.setAttribute('role', 'switch');\n\n this.targetElem = document.querySelector(this.targetSelector);\n if (!this.targetElem) return;\n\n if (vbgInstance) this.vbgInstance = vbgInstance;\n\n this.targetElem.addEventListener('video-background-ready', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-state-change', this.onStateChange.bind(this));\n this.targetElem.addEventListener('video-background-play', this.onPlay.bind(this));\n this.targetElem.addEventListener('video-background-pause', this.onPause.bind(this));\n this.targetElem.addEventListener('video-background-destroyed', this.onDestroyed.bind(this));\n\n this.element.addEventListener('click', this.onClick.bind(this));\n }\n\n onReady(event) {\n this.vbgInstance = event.detail;\n }\n\n onStateChange(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = this.vbgInstance.currentState === 'playing' || this.vbgInstance.currentState === 'buffering';\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onPlay(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onPause(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onClick(event) {\n if (!this.vbgInstance) return;\n if (this.active) {\n this.vbgInstance.pause();\n } else {\n this.vbgInstance.play();\n }\n }\n}\n\nexport class MuteToggle {\n constructor(muteToggleElem, vbgInstance) {\n if (!muteToggleElem) return;\n \n this.element = muteToggleElem;\n this.targetSelector = this.element.getAttribute('data-target');\n\n if (!this.targetSelector) return;\n this.active = false;\n\n if (this.element.hasAttribute('aria-checked')) {\n this.active = this.element.getAttribute('aria-checked') === 'true';\n } else {\n this.element.setAttribute('aria-checked', this.active);\n }\n\n this.element.setAttribute('role', 'switch');\n\n this.targetElem = document.querySelector(this.targetSelector);\n if (!this.targetElem) return;\n\n if (vbgInstance) this.vbgInstance = vbgInstance;\n\n this.targetElem.addEventListener('video-background-ready', this.onReady.bind(this));\n this.targetElem.addEventListener('video-background-mute', this.onMute.bind(this));\n this.targetElem.addEventListener('video-background-unmute', this.onUnmute.bind(this));\n this.targetElem.addEventListener('video-background-destroyed', this.onDestroyed.bind(this));\n\n this.element.addEventListener('click', this.onClick.bind(this));\n }\n\n onReady(event) {\n this.vbgInstance = event.detail;\n if (this.vbgInstance.params.muted) {\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n }\n\n onMute(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = true;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onUnmute(event) {\n if (!this.vbgInstance) this.vbgInstance = event.detail;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onDestroyed(event) {\n this.vbgInstance = null;\n this.active = false;\n this.element.setAttribute('aria-checked', this.active);\n }\n\n onClick(event) {\n if (!this.vbgInstance) return;\n if (this.active) {\n this.vbgInstance.unmute();\n } else {\n this.vbgInstance.mute();\n }\n }\n}\n\n// TODO: this can be achieved with custom elements... Maybe it's finally time to use them?\nclass GeneralFactory {\n constructor(selector, callback, uidAttribute = 'data-uid') {\n this.instances = {};\n this.selector = selector;\n this.elements = [];\n this.callback = callback;\n this.uidAttribute = uidAttribute;\n\n if (!callback || typeof callback !== 'function') return;\n\n if (typeof this.selector === 'string') {\n this.elements = document.querySelectorAll(this.selector);\n }\n\n if (this.selector instanceof Element) {\n this.elements = [this.selector];\n }\n\n if (this.selector instanceof NodeList) {\n this.elements = this.selector;\n }\n\n for (let i = 0; i < this.elements.length; i++) {\n this.add(this.elements[i]);\n\n // TODO: maybe manage elements array?\n }\n }\n\n basicUID() {\n return Date.now().toString(36) + Math.random().toString(36).substring(2);\n }\n\n generateUID() {\n let tempuid = this.basicUID();\n if (!this.instances.hasOwnProperty(tempuid)) return tempuid;\n return this.generateUID();\n }\n\n add(element) {\n let id = element.getAttribute('id');\n if (!id || this.instances.hasOwnProperty(id)) {\n id = element.getAttribute(this.uidAttribute);\n\n if (!id || this.instances.hasOwnProperty(id)) {\n id = this.generateUID();\n element.setAttribute(this.uidAttribute, id);\n }\n }\n\n if (this.callback && typeof this.callback === 'function') \n this.instances[id] = this.callback(element, id, this);\n }\n\n getID(element) {\n if (!element) return;\n if (typeof element === 'string') return element;\n const id = element.getAttribute('id');\n if (id && this.instances.hasOwnProperty(id)) return id;\n const uid = element.getAttribute(this.uidAttribute);\n if (uid && this.instances.hasOwnProperty(uid)) return uid;\n }\n\n get(element) {\n if (!element) return;\n const id = this.getID(element);\n if (!id) return;\n return this.instances[id];\n }\n\n destroy(element) {\n if (!element) return;\n const id = this.getID(element);\n if (!id) return;\n const instance = this.instances[id];\n if (instance.hasOwnProperty('destroy') && typeof instance.destroy == 'function') this.instances[id].destroy();\n delete this.instances[id];\n }\n\n destroyAll() {\n for (const uid in this.instances) {\n const instance = this.instances[uid];\n if (instance.hasOwnProperty('destroy') && typeof instance.destroy == 'function') instance.destroy();\n delete this.instances[uid];\n }\n }\n}\n\nexport class VideoBackgroundGroups extends GeneralFactory {\n constructor(selector = '.js-vbg-group', videoBackgroundSelector, videoBackgroundFactoryInstance) {\n super(selector, (element, id, factoryInstance) => new VideoBackgroundGroup(element, videoBackgroundSelector, videoBackgroundFactoryInstance));\n }\n}\n", "import { SeekBar, PlayToggle, MuteToggle, VideoBackgroundGroup, VideoBackgroundGroups } from \"./lib/controls\";\n\nwindow.SeekBar = SeekBar;\nwindow.PlayToggle = PlayToggle;\nwindow.MuteToggle = MuteToggle;\nwindow.VideoBackgroundGroup = VideoBackgroundGroup;\nwindow.VideoBackgroundGroups = VideoBackgroundGroups;\n"],
+ "mappings": "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",
"names": []
}
diff --git a/youtube-background-experimental.min.js b/youtube-background-experimental.min.js
index 65dc410..7ab0eee 100644
--- a/youtube-background-experimental.min.js
+++ b/youtube-background-experimental.min.js
@@ -1,2 +1,2 @@
/* youtube-background v1.1.5 | https://github.com/stamat/youtube-background | MIT License */
-(()=>{var a=class{constructor(t,e){this.lock=!1,t&&(this.element=t,!this.element.hasAttribute("data-target-uid")&&(this.progressElem=this.element.querySelector(".js-seek-bar-progress"),this.inputElem=this.element.querySelector(".js-seek-bar"),this.targetSelector=this.element.getAttribute("data-target"),this.targetSelector&&(this.targetElem=document.querySelector(this.targetSelector)),!this.targetSelector&&e&&(this.targetElem=e.element),this.targetElem&&(e&&this.setVBGInstance(e),this.targetElem.addEventListener("video-background-time-update",this.onTimeUpdate.bind(this)),this.targetElem.addEventListener("video-background-play",this.onReady.bind(this)),this.targetElem.addEventListener("video-background-ready",this.onReady.bind(this)),this.targetElem.addEventListener("video-background-destroyed",this.onDestroyed.bind(this)),this.inputElem.addEventListener("input",this.onInput.bind(this)),this.inputElem.addEventListener("change",this.onChange.bind(this)))))}setVBGInstance(t){this.vbgInstance||(this.vbgInstance=t,this.element.setAttribute("data-target-uid",t.uid))}onReady(t){this.setVBGInstance(t.detail)}onTimeUpdate(t){this.setVBGInstance(t.detail),this.lock||requestAnimationFrame(()=>this.setProgress(this.vbgInstance.percentComplete))}onDestroyed(t){this.vbgInstance=null,requestAnimationFrame(()=>this.setProgress(0))}onInput(t){this.lock=!0,requestAnimationFrame(()=>this.setProgress(t.target.value))}onChange(t){this.lock=!1,requestAnimationFrame(()=>this.setProgress(t.target.value)),this.vbgInstance&&(this.vbgInstance.seek(t.target.value),this.vbgInstance.playerElement&&this.vbgInstance.playerElement.style.opacity===0&&(this.vbgInstance.playerElement.style.opacity=1))}setProgress(t){this.progressElem&&(this.progressElem.value=t),this.inputElem&&(this.inputElem.value=t)}},r=class{constructor(t,e,i){if(this.element=t,typeof this.element=="string"&&(this.element=document.querySelector(t)),!!this.element&&(this.elements=this.element.querySelectorAll(e||"[data-vbg]"),!!this.elements.length)){this.videoBackgroundFactoryInstance=i,this.stack=[],this.map=new Map,this.current=0,this.currentElement=null,this.currentInstance=null,this.playing=!1,this.muted=!0;for(let s=0;s=this.stack.length&&(t=0),t<0&&(t=this.stack.length-1);const s=this.videoBackgroundFactoryInstance.get(this.stack[i]);if(this.current=t,this.currentInstance=this.videoBackgroundFactoryInstance.get(this.stack[this.current]),this.currentElement=this.stack[this.current],this.stack[i].style.display="none",this.currentElement.style.display="block",!e){const n=this.getSeekBar(this.currentInstance);n&&this.setProgress(n,0),this.currentInstance.seek(0)}setTimeout(()=>{this.currentInstance.currentState!=="playing"&&this.currentInstance.play()},100),s&&s.currentState!=="paused"&&s.pause(),setTimeout(this.levelSeekBars.bind(this),100),t>=this.stack.length&&this.dispatchEvent("video-background-group-forward-rewind"),t<0&&this.dispatchEvent("video-background-group-backward-rewind")}dispatchEvent(t){this.element.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:this}))}onVideoEnded(t){t.detail.element===this.currentElement&&this.next()}next(){this.setCurrent(this.current+1),this.dispatchEvent("video-background-group-next")}prev(){this.setCurrent(this.current-1),this.dispatchEvent("video-background-group-previous")}unmute(){for(let t=0;tnew r(s,e,i))}};window.SeekBar=a,window.PlayToggle=h,window.MuteToggle=c,window.VideoBackgroundGroup=r,window.VideoBackgroundGroups=d})();
+(()=>{var a=class{constructor(t,e){this.lock=!1,t&&(this.element=t,!this.element.hasAttribute("data-target-uid")&&(this.progressElem=this.element.querySelector(".js-seek-bar-progress"),this.inputElem=this.element.querySelector(".js-seek-bar"),this.targetSelector=this.element.getAttribute("data-target"),this.targetSelector&&(this.targetElem=document.querySelector(this.targetSelector)),!this.targetSelector&&e&&(this.targetElem=e.element),this.targetElem&&(e&&this.setVBGInstance(e),this.targetElem.addEventListener("video-background-time-update",this.onTimeUpdate.bind(this)),this.targetElem.addEventListener("video-background-play",this.onReady.bind(this)),this.targetElem.addEventListener("video-background-ready",this.onReady.bind(this)),this.targetElem.addEventListener("video-background-destroyed",this.onDestroyed.bind(this)),this.inputElem.addEventListener("input",this.onInput.bind(this)),this.inputElem.addEventListener("change",this.onChange.bind(this)))))}setVBGInstance(t){this.vbgInstance||(this.vbgInstance=t,this.element.setAttribute("data-target-uid",t.uid))}onReady(t){this.setVBGInstance(t.detail)}onTimeUpdate(t){this.setVBGInstance(t.detail),this.lock||requestAnimationFrame(()=>this.setProgress(this.vbgInstance.percentComplete))}onDestroyed(t){this.vbgInstance=null,requestAnimationFrame(()=>this.setProgress(0))}onInput(t){this.lock=!0,requestAnimationFrame(()=>this.setProgress(t.target.value))}onChange(t){this.lock=!1,requestAnimationFrame(()=>this.setProgress(t.target.value)),this.vbgInstance&&(this.vbgInstance.seek(t.target.value),this.vbgInstance.playerElement&&this.vbgInstance.playerElement.style.opacity===0&&(this.vbgInstance.playerElement.style.opacity=1))}setProgress(t){this.progressElem&&(this.progressElem.value=t),this.inputElem&&(this.inputElem.value=t)}},r=class{constructor(t,e,i){if(this.element=t,typeof this.element=="string"&&(this.element=document.querySelector(t)),!!this.element&&(this.elements=this.element.querySelectorAll(e||"[data-vbg]"),!!this.elements.length)){this.videoBackgroundFactoryInstance=i,this.stack=[],this.map=new Map,this.current=0,this.currentElement=null,this.currentInstance=null,this.playing=!1,this.muted=!0;for(let s=0;s=this.stack.length&&(t=0),t<0&&(t=this.stack.length-1);const s=this.videoBackgroundFactoryInstance.get(this.stack[i]);if(this.current=t,this.currentInstance=this.videoBackgroundFactoryInstance.get(this.stack[this.current]),this.currentElement=this.stack[this.current],this.stack[i].style.display="none",this.currentElement.style.display="block",!e){const n=this.getSeekBar(this.currentInstance);n&&this.setProgress(n,0),this.currentInstance.seek(0)}setTimeout(()=>{this.currentInstance.currentState!=="playing"&&this.currentInstance.play()},100),s&&s.currentState!=="paused"&&s.pause(),setTimeout(this.levelSeekBars.bind(this),100),t>=this.stack.length&&this.dispatchEvent("video-background-group-forward-rewind"),t<0&&this.dispatchEvent("video-background-group-backward-rewind")}dispatchEvent(t){this.element.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:this}))}onVideoEnded(t){t.detail.element===this.currentElement&&this.next()}next(){this.setCurrent(this.current+1),this.dispatchEvent("video-background-group-next")}prev(){this.setCurrent(this.current-1),this.dispatchEvent("video-background-group-previous")}unmute(){for(let t=0;tnew r(s,e,i))}};window.SeekBar=a,window.PlayToggle=h,window.MuteToggle=c,window.VideoBackgroundGroup=r,window.VideoBackgroundGroups=d})();