From ce630ba7e336dd243abe6b6c00536be6cf1ba603 Mon Sep 17 00:00:00 2001 From: Nikola Stamatovic Date: Tue, 7 Nov 2023 23:08:18 +0100 Subject: [PATCH] fix VideoBackgrounds constructor --- jquery.youtube-background.js | 7 +++++-- jquery.youtube-background.js.map | 4 ++-- jquery.youtube-background.min.js | 2 +- src/video-backgrounds.js | 7 +++---- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/jquery.youtube-background.js b/jquery.youtube-background.js index 553fdf2..958a138 100644 --- a/jquery.youtube-background.js +++ b/jquery.youtube-background.js @@ -1031,9 +1031,10 @@ var VideoBackgrounds = class { constructor(selector, params) { this.elements = selector; - if (typeof selector === "string") { + if (this.elements instanceof Element) + this.elements = [this.elements]; + if (typeof this.elements === "string") this.elements = document.querySelectorAll(selector); - } this.index = {}; const self2 = this; this.intersectionObserver = new IntersectionObserver(function(entries) { @@ -1074,6 +1075,8 @@ }); } this.initPlayers(); + if (!this.elements || !this.elements.length) + return; for (let i = 0; i < this.elements.length; i++) { const element = this.elements[i]; this.add(element, params); diff --git a/jquery.youtube-background.js.map b/jquery.youtube-background.js.map index f13041b..1a0544e 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/dom.mjs", "node_modules/book-of-spells/src/regex.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 //TODO: solve this with ARIA toggle states\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\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\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\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 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 * @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) {\n if (min > max) [min, max] = [max, min]\n if (min === max) return min\n min = Math.ceil(min)\n max = Math.floor(max)\n return Math.floor(Math.random() * (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\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'\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\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 const txt = document.createElement('textarea')\n txt.innerHTML = html\n const res = txt.value\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 * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n *
FooBar
Foo 1Bar 1
Foo 2Bar 2
`\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
')\n */\nexport function parseDOM(html, allChildren) {\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 * @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 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 } from 'book-of-spells';\n\nexport class SuperVideoBackground {\n constructor(elem, params, id, uid, type) {\n if (!id) return;\n this.is_mobile = isMobile();\n this.type = type;\n this.id = id;\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.state = {};\n this.state.playing = false;\n this.state.muted = false;\n this.currentState = 'notstarted';\n\n this.initialPlay = false;\n this.initialVolume = false;\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 this.state.playing = this.params.autoplay;\n this.state.muted = this.params.muted;\n\n this.currentTime = 0 || this.params['start-at'];\n this.duration = 0 || this.params['end-at'];\n\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.state.playing,\n stateClassName: 'paused',\n condition_parameter: 'autoplay',\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.state.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 (!this.duration) return 0;\n if (this.params['start-at']) time -= this.params['start-at']; // normalize\n if (time >= this.duration) return 100;\n if (this.params['end-at'] && time >= this.params['end-at']) return 100;\n if (time <= 0) return 0;\n if (this.params['start-at'] && time <= this.params['start-at']) return 0;\n return percentage(time, this.duration);\n }\n\n percentageToTime(percentage) {\n if (!this.duration) return 0;\n if (percentage > 100) return this.duration;\n if (percentage < 0) return 0;\n let time = percentage * this.duration / 100;\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']) return;\n proportionalParentCoverResize(element || this.playerElement, this.params.resolution_mod, this.params.offset);\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'] = 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']);\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 }\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 dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n mobileLowBatteryAutoplayHack() {\n if (!this.params['force-on-low-battery']) return;\n if (!this.is_mobile && this.params.mobile) return;\n document.addEventListener('touchstart', () => {\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 }, { 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 if (!params.hasOwnProperty(k)) {\n //load in defaults if the param hasn't been set\n res_params[k] = defaults[k];\n }\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) {\n super(elem, params, id, uid, 'youtube');\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 }\n });\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']) {\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 if (this.duration && this.currentTime >= this.duration) {\n this.currentState = 'ended';\n this.dispatchEvent('video-background-state-change');\n this.onVideoEnded();\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') {\n this.onVideoEnded();\n }\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') {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n \n if (!this.duration) {\n this.setDuration(this.player.getDuration());\n }\n this.dispatchEvent('video-background-play');\n this.startTimeUpdateTimer();\n } else {\n this.dispatchEvent('video-background-pause');\n this.stopTimeUpdateTimer();\n }\n\n this.dispatchEvent('video-background-state-change');\n }\n\n onVideoEnded() {\n this.dispatchEvent('video-background-ended');\n\n if (!this.params.loop) return this.player.pause();\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n seekTo(seconds, allowSeekAhead = true) {\n this.player.seekTo(seconds, allowSeekAhead);\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pauseVideo();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.playVideo();\n }\n\n play() {\n if (!this.player) return;\n this.state.playing = true;\n \n if (this.params['start-at'] && this.player.getCurrentTime() < this.params['start-at'] ) {\n this.seekTo(this.params['start-at']);\n }\n this.player.playVideo();\n }\n\n pause() {\n this.state.playing = false;\n this.player.pauseVideo();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.mute();\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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) {\n super(elem, params, id, uid, 'vimeo');\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\n if (this.params.volume !== 1 && !this.params.muted) this.setVolume(this.params.volume);\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']) {\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.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoTimeUpdate(event) {\n this.currentTime = event.seconds;\n this.dispatchEvent('video-background-time-update');\n\n if (this.duration && event.seconds >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n onVideoPlay(event) {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n\n this.setDuration(event.duration);\n\n const seconds = event.seconds;\n if (self.params['start-at'] && seconds < self.params['start-at']) {\n self.seekTo(self.params['start-at']);\n }\n\n if (self.duration && seconds >= self.duration) {\n self.seekTo(self.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 seekTo(time) {\n this.player.setCurrentTime(time);\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.state.playing = true;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.state.playing = false;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.setMuted(true);\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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) {\n super(elem, params, vid_data.link, uid, 'video');\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.toggleAttribute('playsinline', true);\n playerElement.toggleAttribute('loop', this.params.loop);\n playerElement.toggleAttribute('autoplay', this.params.autoplay && (this.params['always-play'] || this.isIntersecting));\n playerElement.toggleAttribute('muted', this.params.muted);\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.params.volume !== 1 && !this.params.muted) this.setVolume(this.params.volume);\n \n this.playerElement.setAttribute('id', this.uid)\n\n const source = document.createElement('source');\n source.setAttribute('src', this.src);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n \n \n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(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\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 if (this.params['start-at'] && this.params.autoplay) {\n this.seekTo(this.params['start-at']);\n }\n }\n\n onVideoTimeUpdate() {\n this.currentTime = this.player.currentTime;\n this.dispatchEvent('video-background-time-update');\n\n if (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 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 seekTo(seconds) {\n if (this.player.hasOwnProperty('fastSeek')) {\n this.player.fastSeek(seconds);\n return;\n }\n this.player.currentTime = seconds;\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n \n const seconds = this.player.currentTime;\n \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.state.playing = true;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.state.playing = false;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.muted = true;\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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\n if (typeof selector === 'string') {\n this.elements = document.querySelectorAll(selector);\n }\n\n this.index = {};\n\n const self = this;\n\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].params.autoplay) 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 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 for (let i = 0; i < this.elements.length; i++) {\n const element = this.elements[i];\n this.add(element, params);\n }\n }\n\n add(element, params) {\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);\n this.index[uid] = yb;\n break;\n case 'VIMEO':\n const vm = new VimeoBackground(element, params, vid_data.id, uid);\n this.index[uid] = vm;\n break;\n case 'VIDEO':\n const vid = new VideoBackground(element, params, vid_data, uid);\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']) {\n this.intersectionObserver.observe(element);\n }\n }\n\n destroy(element) {\n const uid = element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) {\n if (!this.index[uid].params['always-play']) 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 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 pauseVideos() {\n for (let k in this.index) {\n this.index[k].pause();\n }\n }\n\n playVideos() {\n for (let k in this.index) {\n this.index[k].play();\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;AAGhB,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;;;AC4FO,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;AAgOO,WAAS,mBAAmB,KAAK,KAAK;AAC3C,QAAI,MAAM;AAAK,OAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;AACrC,QAAI,QAAQ;AAAK,aAAO;AACxB,UAAM,KAAK,KAAK,GAAG;AACnB,UAAM,KAAK,MAAM,GAAG;AACpB,WAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AAAA,EACvD;AAkCO,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;AAaO,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;;;AC5fO,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;AAkcO,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;;;ACtiBO,MAAM,aAAa;AAKnB,MAAM,WAAW;AAKjB,MAAM,WAAW;;;ACPjB,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;AACvC,UAAI,CAAC;AAAI;AACT,WAAK,YAAY,SAAS;AAC1B,WAAK,OAAO;AACZ,WAAK,KAAK;AAEV,WAAK,UAAU;AACf,WAAK,gBAAgB;AACrB,WAAK,MAAM;AACX,WAAK,QAAQ,aAAa,gBAAgB,GAAG;AAE7C,WAAK,UAAU,CAAC;AAChB,WAAK,iBAAiB;AAEtB,WAAK,QAAQ,CAAC;AACd,WAAK,MAAM,UAAU;AACrB,WAAK,MAAM,QAAQ;AACnB,WAAK,eAAe;AAEpB,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAErB,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;AACzE,WAAK,MAAM,UAAU,KAAK,OAAO;AACjC,WAAK,MAAM,QAAQ,KAAK,OAAO;AAE/B,WAAK,cAAmB,KAAK,OAAO,UAAU;AAC9C,WAAK,WAAgB,KAAK,OAAO,QAAQ;AAGzC,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,MAAM;AAAA,UAC1B,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,MAAM;AAAA,UACzB,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,CAAC,KAAK;AAAU,eAAO;AAC3B,UAAI,KAAK,OAAO,UAAU;AAAG,gBAAQ,KAAK,OAAO,UAAU;AAC3D,UAAI,QAAQ,KAAK;AAAU,eAAO;AAClC,UAAI,KAAK,OAAO,QAAQ,KAAK,QAAQ,KAAK,OAAO,QAAQ;AAAG,eAAO;AACnE,UAAI,QAAQ;AAAG,eAAO;AACtB,UAAI,KAAK,OAAO,UAAU,KAAK,QAAQ,KAAK,OAAO,UAAU;AAAG,eAAO;AACvE,aAAO,WAAW,MAAM,KAAK,QAAQ;AAAA,IACvC;AAAA,IAEA,iBAAiBA,aAAY;AAC3B,UAAI,CAAC,KAAK;AAAU,eAAO;AAC3B,UAAIA,cAAa;AAAK,eAAO,KAAK;AAClC,UAAIA,cAAa;AAAG,eAAO;AAC3B,UAAI,OAAOA,cAAa,KAAK,WAAW;AACxC,UAAI,KAAK,OAAO,UAAU;AAAG,gBAAQ,KAAK,OAAO,UAAU;AAC3D,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,SAAS;AACd,UAAI,KAAK,OAAO,SAAS;AAAG;AAC5B,oCAA8B,WAAW,KAAK,eAAe,KAAK,OAAO,gBAAgB,KAAK,OAAO,MAAM;AAAA,IAC7G;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,KAAK,OAAO,QAAQ;AACpF,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;AAAE;AACpC,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;AAAA,IAC9D;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,cAAc,MAAM;AAClB,WAAK,QAAQ,cAAc,IAAI,YAAY,MAAM,EAAE,SAAS,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IACnF;AAAA,IAEA,+BAA+B;AAC7B,UAAI,CAAC,KAAK,OAAO,sBAAsB;AAAG;AAC1C,UAAI,CAAC,KAAK,aAAa,KAAK,OAAO;AAAQ;AAC3C,eAAS,iBAAiB,cAAc,MAAM;AAC5C,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,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,IACnB;AAAA,IAEA,gBAAgB,QAAQ,UAAU,SAAS,aAAa;AACtD,UAAI,aAAa,CAAC;AAElB,UAAI,CAAC,QAAQ;AACX,qBAAa;AAAA,MACf,OAAO;AACL,iBAAS,KAAK,UAAU;AACtB,cAAI,CAAC,OAAO,eAAe,CAAC,GAAG;AAE7B,uBAAW,CAAC,IAAI,SAAS,CAAC;AAAA,UAC5B;AAAA,QACF;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;;;AChSO,MAAM,oBAAN,cAAgC,qBAAqB;AAAA,IAC1D,YAAY,MAAM,QAAQ,IAAI,KAAK;AACjC,YAAM,MAAM,QAAQ,IAAI,KAAK,SAAS;AAEtC,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,QACpD;AAAA,MACF,CAAC;AAAA,IACH;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,YAAY,KAAK,OAAO,aAAa,GAAG;AACtD,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,UAAI,KAAK,YAAY,KAAK,eAAe,KAAK,UAAU;AACtD,aAAK,eAAe;AACpB,aAAK,cAAc,+BAA+B;AAClD,aAAK,aAAa;AAAA,MACpB;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,SAAS;AACjC,aAAK,aAAa;AAAA,MACpB;AAEA,UAAI,KAAK,iBAAiB,gBAAgB,KAAK,OAAO,UAAU;AAC9D,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,aAAK,OAAO,UAAU;AAAA,MACxB;AAEA,UAAI,KAAK,iBAAiB,WAAW;AACnC,YAAI,CAAC,KAAK,aAAa;AACrB,eAAK,cAAc;AACnB,eAAK,cAAc,MAAM,UAAU;AAAA,QACrC;AAEA,YAAI,CAAC,KAAK,UAAU;AAClB,eAAK,YAAY,KAAK,OAAO,YAAY,CAAC;AAAA,QAC5C;AACA,aAAK,cAAc,uBAAuB;AAC1C,aAAK,qBAAqB;AAAA,MAC5B,OAAO;AACL,aAAK,cAAc,wBAAwB;AAC3C,aAAK,oBAAoB;AAAA,MAC3B;AAEA,WAAK,cAAc,+BAA+B;AAAA,IACpD;AAAA,IAEA,eAAe;AACb,WAAK,cAAc,wBAAwB;AAE3C,UAAI,CAAC,KAAK,OAAO;AAAM,eAAO,KAAK,OAAO,MAAM;AAChD,WAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AACnC,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,OAAO,SAAS,iBAAiB,MAAM;AACrC,WAAK,OAAO,OAAO,SAAS,cAAc;AAAA,IAC5C;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,WAAW;AAAA,IACzB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,UAAU;AAErB,UAAI,KAAK,OAAO,UAAU,KAAK,KAAK,OAAO,eAAe,IAAI,KAAK,OAAO,UAAU,GAAI;AACtF,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AACA,WAAK,OAAO,UAAU;AAAA,IACxB;AAAA,IAEA,QAAQ;AACN,WAAK,MAAM,UAAU;AACrB,WAAK,OAAO,WAAW;AAAA,IACzB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,QAAQ;AAEnB,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,MAAM,QAAQ;AAEnB,WAAK,OAAO,KAAK;AACjB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAElB,WAAK,OAAO,UAAU,SAAS,GAAG;AAClC,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AC5OO,MAAM,kBAAN,cAA8B,qBAAqB;AAAA,IACxD,YAAY,MAAM,QAAQ,IAAI,KAAK;AACjC,YAAM,MAAM,QAAQ,IAAI,KAAK,OAAO;AACpC,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;AAE9D,UAAI,KAAK,OAAO,WAAW,KAAK,CAAC,KAAK,OAAO;AAAO,aAAK,UAAU,KAAK,OAAO,MAAM;AAAA,IACvF;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,YAAY,KAAK,OAAO,aAAa,GAAG;AACtD,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,YAAY,SAAS;AAC1B,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,kBAAkB,OAAO;AACvB,WAAK,cAAc,MAAM;AACzB,WAAK,cAAc,8BAA8B;AAEjD,UAAI,KAAK,YAAY,MAAM,WAAW,KAAK,UAAU;AACnD,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,mBAAmB;AACjB,WAAK,YAAY,WAAW;AAAA,IAC9B;AAAA,IAEA,YAAY,OAAO;AACjB,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,cAAc;AACnB,aAAK,cAAc,MAAM,UAAU;AAAA,MACrC;AAEA,WAAK,YAAY,MAAM,QAAQ;AAE/B,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,OAAO,MAAM;AACX,WAAK,OAAO,eAAe,IAAI;AAAA,IACjC;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,UAAU;AAErB,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,QAAQ;AACN,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,UAAU;AAErB,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,QAAQ;AAEnB,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,MAAM,QAAQ;AAEnB,WAAK,OAAO,SAAS,IAAI;AACzB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAElB,WAAK,OAAO,UAAU,MAAM;AAC5B,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AChOO,MAAM,kBAAN,cAA8B,qBAAqB;AAAA,IACxD,YAAY,MAAM,QAAQ,UAAU,KAAK;AACvC,YAAM,MAAM,QAAQ,SAAS,MAAM,KAAK,OAAO;AAC/C,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,gBAAgB,eAAe,IAAI;AACjD,oBAAc,gBAAgB,QAAQ,KAAK,OAAO,IAAI;AACtD,oBAAc,gBAAgB,YAAY,KAAK,OAAO,aAAa,KAAK,OAAO,aAAa,KAAK,KAAK,eAAe;AACrH,oBAAc,gBAAgB,SAAS,KAAK,OAAO,KAAK;AACxD,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,OAAO,WAAW,KAAK,CAAC,KAAK,OAAO;AAAO,aAAK,UAAU,KAAK,OAAO,MAAM;AAErF,WAAK,cAAc,aAAa,MAAM,KAAK,GAAG;AAE9C,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,aAAa,OAAO,KAAK,GAAG;AACnC,aAAO,aAAa,QAAQ,KAAK,IAAI;AACrC,WAAK,cAAc,YAAY,MAAM;AAGrC,WAAK,mBAAmB,KAAK,aAAa;AAC1C,WAAK,QAAQ,YAAY,KAAK,aAAa;AAC3C,WAAK,OAAO,KAAK,aAAa;AAE9B,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;AAAA,IACpE;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;AAErC,UAAI,KAAK,OAAO,UAAU,KAAK,KAAK,OAAO,UAAU;AACnD,aAAK,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,IAEA,oBAAoB;AAClB,WAAK,cAAc,KAAK,OAAO;AAC/B,WAAK,cAAc,8BAA8B;AAEjD,UAAI,KAAK,eAAe,KAAK,UAAU;AACrC,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,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,OAAO,SAAS;AACd,UAAI,KAAK,OAAO,eAAe,UAAU,GAAG;AAC1C,aAAK,OAAO,SAAS,OAAO;AAC5B;AAAA,MACF;AACA,WAAK,OAAO,cAAc;AAAA,IAC5B;AAAA,IAEA,YAAY;AACV,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,WAAW;AACT,UAAI,CAAC,KAAK,MAAM,WAAW,CAAC,KAAK;AAAQ;AACzC,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,OAAO;AACL,UAAI,CAAC,KAAK;AAAQ;AAElB,YAAM,UAAU,KAAK,OAAO;AAE5B,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,MAAM,UAAU;AAErB,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,IAEA,QAAQ;AACN,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,UAAU;AAErB,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,IAEA,SAAS;AACP,UAAI,CAAC,KAAK;AAAQ;AAClB,WAAK,MAAM,QAAQ;AAEnB,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,MAAM,QAAQ;AAEnB,WAAK,OAAO,QAAQ;AACpB,WAAK,cAAc,uBAAuB;AAAA,IAC5C;AAAA,IAEA,UAAU,QAAQ;AAChB,UAAI,CAAC,KAAK;AAAQ;AAElB,WAAK,OAAO,SAAS;AACrB,WAAK,cAAc,gCAAgC;AAAA,IACrD;AAAA,EACF;;;AChNO,MAAM,mBAAN,MAAuB;AAAA,IAC5B,YAAY,UAAU,QAAQ;AAC5B,WAAK,WAAW;AAEhB,UAAI,OAAO,aAAa,UAAU;AAChC,aAAK,WAAW,SAAS,iBAAiB,QAAQ;AAAA,MACpD;AAEA,WAAK,QAAQ,CAAC;AAEd,YAAMC,QAAO;AAEb,WAAK,uBAAuB,IAAI,qBAAqB,SAAU,SAAS;AACtE,gBAAQ,QAAQ,SAAU,OAAO;AAC/B,gBAAM,MAAM,MAAM,OAAO,aAAa,cAAc;AAEpD,cAAI,OAAOA,MAAK,MAAM,eAAe,GAAG,KAAK,MAAM,gBAAgB;AACjE,YAAAA,MAAK,MAAM,GAAG,EAAE,iBAAiB;AACjC,gBAAI;AACF,kBAAIA,MAAK,MAAM,GAAG,EAAE,UAAUA,MAAK,MAAM,GAAG,EAAE,OAAO;AAAU,gBAAAA,MAAK,MAAM,GAAG,EAAE,SAAS;AAAA,YAC1F,SAAS,GAAG;AAAA,YAEZ;AAAA,UACF,OAAO;AACL,YAAAA,MAAK,MAAM,GAAG,EAAE,iBAAiB;AACjC,gBAAI;AACF,kBAAIA,MAAK,MAAM,GAAG,EAAE;AAAQ,gBAAAA,MAAK,MAAM,GAAG,EAAE,UAAU;AAAA,YACxD,SAAS,GAAG;AAAA,YAEZ;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,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,OAAOA,MAAK,MAAM,eAAe,GAAG,GAAG;AACzC,qBAAO,sBAAsB,MAAMA,MAAK,MAAM,GAAG,EAAE,OAAO,CAAC;AAAA,YAC7D;AAAA,UACF,CAAC;AAAA,QACH,CAAC;AAAA,MACH,OAAO;AACL,eAAO,iBAAiB,UAAU,WAAY;AAC5C,mBAAS,KAAKA,MAAK,OAAO;AACxB,mBAAO,sBAAsB,MAAMA,MAAK,MAAM,CAAC,EAAE,OAAOA,MAAK,MAAM,CAAC,EAAE,aAAa,CAAC;AAAA,UACtF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,WAAK,YAAY;AAEjB,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,cAAM,UAAU,KAAK,SAAS,CAAC;AAC/B,aAAK,IAAI,SAAS,MAAM;AAAA,MAC1B;AAAA,IACF;AAAA,IAEA,IAAI,SAAS,QAAQ;AACnB,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,GAAG;AAClE,eAAK,MAAM,GAAG,IAAI;AAClB;AAAA,QACF,KAAK;AACH,gBAAM,KAAK,IAAI,gBAAgB,SAAS,QAAQ,SAAS,IAAI,GAAG;AAChE,eAAK,MAAM,GAAG,IAAI;AAClB;AAAA,QACF,KAAK;AACH,gBAAM,MAAM,IAAI,gBAAgB,SAAS,QAAQ,UAAU,GAAG;AAC9D,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,GAAG;AAC1C,aAAK,qBAAqB,QAAQ,OAAO;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,QAAQ,SAAS;AACf,YAAM,MAAM,QAAQ,aAAa,cAAc;AAC/C,UAAI,OAAO,KAAK,MAAM,eAAe,GAAG,GAAG;AACzC,YAAI,CAAC,KAAK,MAAM,GAAG,EAAE,OAAO,aAAa;AAAG,eAAK,qBAAqB,UAAU,OAAO;AACvF,YAAI,KAAK;AAAgB,eAAK,eAAe,UAAU,OAAO;AAC9D,aAAK,MAAM,GAAG,EAAE,QAAQ;AACxB,eAAO,KAAK,MAAM,GAAG;AAAA,MACvB;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,cAAc;AACZ,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,IAEA,aAAa;AACX,eAAS,KAAK,KAAK,OAAO;AACxB,aAAK,MAAM,CAAC,EAAE,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,YAAY,UAAU;AACpB,YAAMA,QAAO;AAEb,aAAO,0BAA0B,WAAY;AAC3C,iBAAS,KAAKA,MAAK,OAAO;AACxB,cAAIA,MAAK,MAAM,CAAC,aAAa,mBAAmB;AAC9C,YAAAA,MAAK,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,KAAKA,MAAK,OAAO;AACxB,cAAIA,MAAK,MAAM,CAAC,aAAa,iBAAiB;AAC5C,YAAAA,MAAK,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;;;AC1MA,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 //TODO: solve this with ARIA toggle states\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\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\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\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 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 * @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) {\n if (min > max) [min, max] = [max, min]\n if (min === max) return min\n min = Math.ceil(min)\n max = Math.floor(max)\n return Math.floor(Math.random() * (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\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'\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\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 const txt = document.createElement('textarea')\n txt.innerHTML = html\n const res = txt.value\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 * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n *
FooBar
Foo 1Bar 1
Foo 2Bar 2
`\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
')\n */\nexport function parseDOM(html, allChildren) {\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 * @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 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 } from 'book-of-spells';\n\nexport class SuperVideoBackground {\n constructor(elem, params, id, uid, type) {\n if (!id) return;\n this.is_mobile = isMobile();\n this.type = type;\n this.id = id;\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.state = {};\n this.state.playing = false;\n this.state.muted = false;\n this.currentState = 'notstarted';\n\n this.initialPlay = false;\n this.initialVolume = false;\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 this.state.playing = this.params.autoplay;\n this.state.muted = this.params.muted;\n\n this.currentTime = 0 || this.params['start-at'];\n this.duration = 0 || this.params['end-at'];\n\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.state.playing,\n stateClassName: 'paused',\n condition_parameter: 'autoplay',\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.state.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 (!this.duration) return 0;\n if (this.params['start-at']) time -= this.params['start-at']; // normalize\n if (time >= this.duration) return 100;\n if (this.params['end-at'] && time >= this.params['end-at']) return 100;\n if (time <= 0) return 0;\n if (this.params['start-at'] && time <= this.params['start-at']) return 0;\n return percentage(time, this.duration);\n }\n\n percentageToTime(percentage) {\n if (!this.duration) return 0;\n if (percentage > 100) return this.duration;\n if (percentage < 0) return 0;\n let time = percentage * this.duration / 100;\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']) return;\n proportionalParentCoverResize(element || this.playerElement, this.params.resolution_mod, this.params.offset);\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'] = 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']);\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 }\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 dispatchEvent(name) {\n this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this }));\n }\n\n mobileLowBatteryAutoplayHack() {\n if (!this.params['force-on-low-battery']) return;\n if (!this.is_mobile && this.params.mobile) return;\n document.addEventListener('touchstart', () => {\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 }, { 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 if (!params.hasOwnProperty(k)) {\n //load in defaults if the param hasn't been set\n res_params[k] = defaults[k];\n }\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) {\n super(elem, params, id, uid, 'youtube');\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 }\n });\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']) {\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 if (this.duration && this.currentTime >= this.duration) {\n this.currentState = 'ended';\n this.dispatchEvent('video-background-state-change');\n this.onVideoEnded();\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') {\n this.onVideoEnded();\n }\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') {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n \n if (!this.duration) {\n this.setDuration(this.player.getDuration());\n }\n this.dispatchEvent('video-background-play');\n this.startTimeUpdateTimer();\n } else {\n this.dispatchEvent('video-background-pause');\n this.stopTimeUpdateTimer();\n }\n\n this.dispatchEvent('video-background-state-change');\n }\n\n onVideoEnded() {\n this.dispatchEvent('video-background-ended');\n\n if (!this.params.loop) return this.player.pause();\n this.seekTo(this.params['start-at']);\n this.player.playVideo();\n }\n\n seekTo(seconds, allowSeekAhead = true) {\n this.player.seekTo(seconds, allowSeekAhead);\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pauseVideo();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.playVideo();\n }\n\n play() {\n if (!this.player) return;\n this.state.playing = true;\n \n if (this.params['start-at'] && this.player.getCurrentTime() < this.params['start-at'] ) {\n this.seekTo(this.params['start-at']);\n }\n this.player.playVideo();\n }\n\n pause() {\n this.state.playing = false;\n this.player.pauseVideo();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.mute();\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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) {\n super(elem, params, id, uid, 'vimeo');\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\n if (this.params.volume !== 1 && !this.params.muted) this.setVolume(this.params.volume);\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']) {\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.updateState('playing');\n this.dispatchEvent('video-background-play');\n }\n\n onVideoTimeUpdate(event) {\n this.currentTime = event.seconds;\n this.dispatchEvent('video-background-time-update');\n\n if (this.duration && event.seconds >= this.duration) {\n this.onVideoEnded();\n }\n }\n\n onVideoBuffering() {\n this.updateState('buffering');\n }\n\n onVideoPlay(event) {\n if (!this.initialPlay) {\n this.initialPlay = true;\n this.playerElement.style.opacity = 1;\n }\n\n this.setDuration(event.duration);\n\n const seconds = event.seconds;\n if (self.params['start-at'] && seconds < self.params['start-at']) {\n self.seekTo(self.params['start-at']);\n }\n\n if (self.duration && seconds >= self.duration) {\n self.seekTo(self.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 seekTo(time) {\n this.player.setCurrentTime(time);\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n this.state.playing = true;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.state.playing = false;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.setMuted(true);\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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) {\n super(elem, params, vid_data.link, uid, 'video');\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.toggleAttribute('playsinline', true);\n playerElement.toggleAttribute('loop', this.params.loop);\n playerElement.toggleAttribute('autoplay', this.params.autoplay && (this.params['always-play'] || this.isIntersecting));\n playerElement.toggleAttribute('muted', this.params.muted);\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.params.volume !== 1 && !this.params.muted) this.setVolume(this.params.volume);\n \n this.playerElement.setAttribute('id', this.uid)\n\n const source = document.createElement('source');\n source.setAttribute('src', this.src);\n source.setAttribute('type', this.mime);\n this.playerElement.appendChild(source);\n \n \n this.stylePlayerElement(this.playerElement);\n this.element.appendChild(this.playerElement);\n this.resize(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\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 if (this.params['start-at'] && this.params.autoplay) {\n this.seekTo(this.params['start-at']);\n }\n }\n\n onVideoTimeUpdate() {\n this.currentTime = this.player.currentTime;\n this.dispatchEvent('video-background-time-update');\n\n if (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 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 seekTo(seconds) {\n if (this.player.hasOwnProperty('fastSeek')) {\n this.player.fastSeek(seconds);\n return;\n }\n this.player.currentTime = seconds;\n }\n\n softPause() {\n if (!this.state.playing || !this.player) return;\n this.player.pause();\n }\n\n softPlay() {\n if (!this.state.playing || !this.player) return;\n this.player.play();\n }\n\n play() {\n if (!this.player) return;\n \n const seconds = this.player.currentTime;\n \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.state.playing = true;\n \n this.player.play();\n }\n\n pause() {\n if (!this.player) return;\n this.state.playing = false;\n \n this.player.pause();\n }\n\n unmute() {\n if (!this.player) return;\n this.state.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.state.muted = true;\n \n this.player.muted = true;\n this.dispatchEvent('video-background-mute');\n }\n\n setVolume(volume) {\n if (!this.player) return;\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 = 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].params.autoplay) 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 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\n add(element, params) {\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);\n this.index[uid] = yb;\n break;\n case 'VIMEO':\n const vm = new VimeoBackground(element, params, vid_data.id, uid);\n this.index[uid] = vm;\n break;\n case 'VIDEO':\n const vid = new VideoBackground(element, params, vid_data, uid);\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']) {\n this.intersectionObserver.observe(element);\n }\n }\n\n destroy(element) {\n const uid = element.getAttribute('data-vbg-uid');\n if (uid && this.index.hasOwnProperty(uid)) {\n if (!this.index[uid].params['always-play']) 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 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 pauseVideos() {\n for (let k in this.index) {\n this.index[k].pause();\n }\n }\n\n playVideos() {\n for (let k in this.index) {\n this.index[k].play();\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", "self"] } diff --git a/jquery.youtube-background.min.js b/jquery.youtube-background.min.js index e8174d0..38d010e 100644 --- a/jquery.youtube-background.min.js +++ b/jquery.youtube-background.min.js @@ -1,2 +1,2 @@ /* youtube-background v1.0.22 | 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 d(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 P(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 T(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)||P(t)||V(t)||T(t)||t}function S(t){return Array.isArray(t)}function x(t){return typeof t=="string"}function u(t,e){return t>e&&([t,e]=[e,t]),t===e?t:(t=Math.ceil(t),e=Math.floor(e),Math.floor(Math.random()*(e-t+1))+t)}function I(t,e){return!t||!e||Number.isNaN(t)||Number.isNaN(e)?0:t/e*100}function C(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 p(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=p(e)),!e instanceof Array&&!e instanceof NodeList)return[];const i=[];for(const s of e)i.push(...s.querySelectorAll(t));return i}function L(t,e=1,i=0){t instanceof Element&&(t=[t]),typeof t=="string"&&(t=p(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")}}var m=/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,c=/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i,y=/\/([^\/]+\.(?:mp4|ogg|ogv|ogm|webm|avi))\s*$/i;function N(t){return/\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(t)||/\b(Android|Windows Phone|iPad|iPod)\b/i.test(t)}function U(){return"maxTouchPoints"in navigator?navigator.maxTouchPoints>0:"matchMedia"in window?!!matchMedia("(pointer:coarse)").matches:"orientation"in window?!0:N(navigator.userAgent)}var h=class{constructor(t,e,i,s,a){if(!i)return;this.is_mobile=U(),this.type=a,this.id=i,this.element=t,this.playerElement=null,this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.buttons={},this.isIntersecting=!1,this.state={},this.state.playing=!1,this.state.muted=!1,this.currentState="notstarted",this.initialPlay=!1,this.initialVolume=!1,this.params={};const r={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,r,this.element,["data-ytbg-","data-vbg-"]),this.params.pause&&(this.params["play-button"]=this.params.pause),this.params.resolution_mod=C(this.params.resolution),this.state.playing=this.params.autoplay,this.state.muted=this.params.muted,this.currentTime=this.params["start-at"],this.duration=this.params["end-at"],this.buildWrapperHTML(),!(this.is_mobile&&!this.params.mobile)&&(this.params["play-button"]&&d(this,{name:"playing",className:"play-toggle",innerHtml:'',initialState:!this.state.playing,stateClassName:"paused",condition_parameter:"autoplay",stateChildClassNames:["fa-pause-circle","fa-play-circle"],actions:["play","pause"]}),this.params["mute-button"]&&d(this,{name:"muted",className:"mute-toggle",innerHtml:'',initialState:this.state.muted,stateClassName:"muted",condition_parameter:"muted",stateChildClassNames:["fa-volume-up","fa-volume-mute"],actions:["unmute","mute"]}))}timeToPercentage(t){return this.duration?(this.params["start-at"]&&(t-=this.params["start-at"]),t>=this.duration||this.params["end-at"]&&t>=this.params["end-at"]?100:t<=0||this.params["start-at"]&&t<=this.params["start-at"]?0:I(t,this.duration)):0}percentageToTime(t){if(!this.duration)return 0;if(t>100)return this.duration;if(t<0)return 0;let e=t*this.duration/100;return this.params["start-at"]&&(e+=this.params["start-at"]),e}resize(t){this.params["fit-box"]||L(t||this.playerElement,this.params.resolution_mod,this.params.offset)}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"]=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)}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(t{!this.initialPlay&&this.params.autoplay&&this.params.muted&&(this.softPlay(),!this.isIntersecting&&!this.params["always-play"]&&this.softPause())},{once:!0}))}parseProperties(t,e,i,s){let a={};if(!t)a=e;else for(let r in e)t.hasOwnProperty(r)||(a[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.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.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),this.duration||this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-play"),this.startTimeUpdateTimer()):(this.dispatchEvent("video-background-pause"),this.stopTimeUpdateTimer()),this.dispatchEvent("video-background-state-change")}onVideoEnded(){if(this.dispatchEvent("video-background-ended"),!this.params.loop)return this.player.pause();this.seekTo(this.params["start-at"]),this.player.playVideo()}seekTo(t,e=!0){this.player.seekTo(t,e)}softPause(){!this.state.playing||!this.player||this.player.pauseVideo()}softPlay(){!this.state.playing||!this.player||this.player.playVideo()}play(){this.player&&(this.state.playing=!0,this.params["start-at"]&&this.player.getCurrentTime(){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.params.volume!==1&&!this.params.muted&&this.setVolume(this.params.volume))}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"]&&(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(c);!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.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoTimeUpdate(t){this.currentTime=t.seconds,this.dispatchEvent("video-background-time-update"),this.duration&&t.seconds>=this.duration&&this.onVideoEnded()}onVideoBuffering(){this.updateState("buffering")}onVideoPlay(t){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),this.setDuration(t.duration);const e=t.seconds;self.params["start-at"]&&e=self.duration&&self.seekTo(self.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}seekTo(t){this.player.setCurrentTime(t)}softPause(){!this.state.playing||!this.player||this.player.pause()}softPlay(){!this.state.playing||!this.player||this.player.play()}play(){this.player&&(this.state.playing=!0,this.player.play())}pause(){this.player&&(this.state.playing=!1,this.player.pause())}unmute(){this.player&&(this.state.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.state.muted=!0,this.player.setMuted(!0),this.dispatchEvent("video-background-mute"))}setVolume(t){this.player&&(this.player.setVolume(t),this.dispatchEvent("video-background-volume-change"))}},O=class extends h{constructor(t,e,i,s){super(t,e,i.link,s,"video"),!(!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.toggleAttribute("playsinline",!0),t.toggleAttribute("loop",this.params.loop),t.toggleAttribute("autoplay",this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)),t.toggleAttribute("muted",this.params.muted),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}injectPlayer(){this.player=this.generatePlayerElement(),this.playerElement=this.player,this.params.volume!==1&&!this.params.muted&&this.setVolume(this.params.volume),this.playerElement.setAttribute("id",this.uid);const t=document.createElement("source");t.setAttribute("src",this.src),t.setAttribute("type",this.mime),this.playerElement.appendChild(t),this.stylePlayerElement(this.playerElement),this.element.appendChild(this.playerElement),this.resize(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))}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(y);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),this.params["start-at"]&&this.params.autoplay&&this.seekTo(this.params["start-at"])}onVideoTimeUpdate(){this.currentTime=this.player.currentTime,this.dispatchEvent("video-background-time-update"),this.currentTime>=this.duration&&this.onVideoEnded()}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),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")}seekTo(t){if(this.player.hasOwnProperty("fastSeek")){this.player.fastSeek(t);return}this.player.currentTime=t}softPause(){!this.state.playing||!this.player||this.player.pause()}softPlay(){!this.state.playing||!this.player||this.player.play()}play(){if(!this.player)return;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.state.playing=!0,this.player.play()}pause(){this.player&&(this.state.playing=!1,this.player.pause())}unmute(){this.player&&(this.state.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.state.muted=!0,this.player.muted=!0,this.dispatchEvent("video-background-mute"))}setVolume(t){this.player&&(this.player.volume=t,this.dispatchEvent("video-background-volume-change"))}},b=class{constructor(t,e){this.elements=t,typeof t=="string"&&(this.elements=document.querySelectorAll(t)),this.index={};const i=this;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].params.autoplay&&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();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 d(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 P(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 T(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)||P(t)||V(t)||T(t)||t}function S(t){return Array.isArray(t)}function x(t){return typeof t=="string"}function u(t,e){return t>e&&([t,e]=[e,t]),t===e?t:(t=Math.ceil(t),e=Math.floor(e),Math.floor(Math.random()*(e-t+1))+t)}function I(t,e){return!t||!e||Number.isNaN(t)||Number.isNaN(e)?0:t/e*100}function C(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 p(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=p(e)),!e instanceof Array&&!e instanceof NodeList)return[];const i=[];for(const s of e)i.push(...s.querySelectorAll(t));return i}function L(t,e=1,i=0){t instanceof Element&&(t=[t]),typeof t=="string"&&(t=p(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")}}var m=/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i,c=/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i,y=/\/([^\/]+\.(?:mp4|ogg|ogv|ogm|webm|avi))\s*$/i;function N(t){return/\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(t)||/\b(Android|Windows Phone|iPad|iPod)\b/i.test(t)}function U(){return"maxTouchPoints"in navigator?navigator.maxTouchPoints>0:"matchMedia"in window?!!matchMedia("(pointer:coarse)").matches:"orientation"in window?!0:N(navigator.userAgent)}var h=class{constructor(t,e,i,s,a){if(!i)return;this.is_mobile=U(),this.type=a,this.id=i,this.element=t,this.playerElement=null,this.uid=s,this.element.setAttribute("data-vbg-uid",s),this.buttons={},this.isIntersecting=!1,this.state={},this.state.playing=!1,this.state.muted=!1,this.currentState="notstarted",this.initialPlay=!1,this.initialVolume=!1,this.params={};const r={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,r,this.element,["data-ytbg-","data-vbg-"]),this.params.pause&&(this.params["play-button"]=this.params.pause),this.params.resolution_mod=C(this.params.resolution),this.state.playing=this.params.autoplay,this.state.muted=this.params.muted,this.currentTime=this.params["start-at"],this.duration=this.params["end-at"],this.buildWrapperHTML(),!(this.is_mobile&&!this.params.mobile)&&(this.params["play-button"]&&d(this,{name:"playing",className:"play-toggle",innerHtml:'',initialState:!this.state.playing,stateClassName:"paused",condition_parameter:"autoplay",stateChildClassNames:["fa-pause-circle","fa-play-circle"],actions:["play","pause"]}),this.params["mute-button"]&&d(this,{name:"muted",className:"mute-toggle",innerHtml:'',initialState:this.state.muted,stateClassName:"muted",condition_parameter:"muted",stateChildClassNames:["fa-volume-up","fa-volume-mute"],actions:["unmute","mute"]}))}timeToPercentage(t){return this.duration?(this.params["start-at"]&&(t-=this.params["start-at"]),t>=this.duration||this.params["end-at"]&&t>=this.params["end-at"]?100:t<=0||this.params["start-at"]&&t<=this.params["start-at"]?0:I(t,this.duration)):0}percentageToTime(t){if(!this.duration)return 0;if(t>100)return this.duration;if(t<0)return 0;let e=t*this.duration/100;return this.params["start-at"]&&(e+=this.params["start-at"]),e}resize(t){this.params["fit-box"]||L(t||this.playerElement,this.params.resolution_mod,this.params.offset)}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"]=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)}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(t{!this.initialPlay&&this.params.autoplay&&this.params.muted&&(this.softPlay(),!this.isIntersecting&&!this.params["always-play"]&&this.softPause())},{once:!0}))}parseProperties(t,e,i,s){let a={};if(!t)a=e;else for(let r in e)t.hasOwnProperty(r)||(a[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.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.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),this.duration||this.setDuration(this.player.getDuration()),this.dispatchEvent("video-background-play"),this.startTimeUpdateTimer()):(this.dispatchEvent("video-background-pause"),this.stopTimeUpdateTimer()),this.dispatchEvent("video-background-state-change")}onVideoEnded(){if(this.dispatchEvent("video-background-ended"),!this.params.loop)return this.player.pause();this.seekTo(this.params["start-at"]),this.player.playVideo()}seekTo(t,e=!0){this.player.seekTo(t,e)}softPause(){!this.state.playing||!this.player||this.player.pauseVideo()}softPlay(){!this.state.playing||!this.player||this.player.playVideo()}play(){this.player&&(this.state.playing=!0,this.params["start-at"]&&this.player.getCurrentTime(){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.params.volume!==1&&!this.params.muted&&this.setVolume(this.params.volume))}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"]&&(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(c);!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.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoTimeUpdate(t){this.currentTime=t.seconds,this.dispatchEvent("video-background-time-update"),this.duration&&t.seconds>=this.duration&&this.onVideoEnded()}onVideoBuffering(){this.updateState("buffering")}onVideoPlay(t){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),this.setDuration(t.duration);const e=t.seconds;self.params["start-at"]&&e=self.duration&&self.seekTo(self.params["start-at"]),this.updateState("playing"),this.dispatchEvent("video-background-play")}onVideoPause(){this.updateState("paused"),this.dispatchEvent("video-background-pause")}seekTo(t){this.player.setCurrentTime(t)}softPause(){!this.state.playing||!this.player||this.player.pause()}softPlay(){!this.state.playing||!this.player||this.player.play()}play(){this.player&&(this.state.playing=!0,this.player.play())}pause(){this.player&&(this.state.playing=!1,this.player.pause())}unmute(){this.player&&(this.state.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.state.muted=!0,this.player.setMuted(!0),this.dispatchEvent("video-background-mute"))}setVolume(t){this.player&&(this.player.setVolume(t),this.dispatchEvent("video-background-volume-change"))}},O=class extends h{constructor(t,e,i,s){super(t,e,i.link,s,"video"),!(!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.toggleAttribute("playsinline",!0),t.toggleAttribute("loop",this.params.loop),t.toggleAttribute("autoplay",this.params.autoplay&&(this.params["always-play"]||this.isIntersecting)),t.toggleAttribute("muted",this.params.muted),this.params.lazyloading&&t.setAttribute("loading","lazy"),t}injectPlayer(){this.player=this.generatePlayerElement(),this.playerElement=this.player,this.params.volume!==1&&!this.params.muted&&this.setVolume(this.params.volume),this.playerElement.setAttribute("id",this.uid);const t=document.createElement("source");t.setAttribute("src",this.src),t.setAttribute("type",this.mime),this.playerElement.appendChild(t),this.stylePlayerElement(this.playerElement),this.element.appendChild(this.playerElement),this.resize(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))}updateState(t){this.currentState=t,this.dispatchEvent("video-background-state-change")}setSource(t){const e=t.match(y);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),this.params["start-at"]&&this.params.autoplay&&this.seekTo(this.params["start-at"])}onVideoTimeUpdate(){this.currentTime=this.player.currentTime,this.dispatchEvent("video-background-time-update"),this.currentTime>=this.duration&&this.onVideoEnded()}onVideoPlay(){this.initialPlay||(this.initialPlay=!0,this.playerElement.style.opacity=1),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")}seekTo(t){if(this.player.hasOwnProperty("fastSeek")){this.player.fastSeek(t);return}this.player.currentTime=t}softPause(){!this.state.playing||!this.player||this.player.pause()}softPlay(){!this.state.playing||!this.player||this.player.play()}play(){if(!this.player)return;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.state.playing=!0,this.player.play()}pause(){this.player&&(this.state.playing=!1,this.player.pause())}unmute(){this.player&&(this.state.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.state.muted=!0,this.player.muted=!0,this.dispatchEvent("video-background-mute"))}setVolume(t){this.player&&(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=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].params.autoplay&&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