Skip to content
This repository was archived by the owner on Jan 17, 2023. It is now read-only.

Commit 653e739

Browse files
committed
0.3.2
1 parent 81f32f1 commit 653e739

File tree

5 files changed

+24
-20
lines changed

5 files changed

+24
-20
lines changed

dist/element-queries.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ return /******/ (function(modules) { // webpackBootstrap
104104
/***/ (function(module, __webpack_exports__, __webpack_require__) {
105105

106106
"use strict";
107-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return ElementQueries; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\n\nconst DEFAULT_OPTS = {\n htmlAttrBreakpoints: 'data-eq-breakpoints',\n htmlAttrActive: 'data-eq-active',\n}\n\nclass ElementQueries {\n constructor(opts) {\n this.opts = Object.freeze({ ...DEFAULT_OPTS, ...opts })\n\n this.observer = new ResizeObserver(this.onResize.bind(this))\n this.elements = new WeakMap()\n\n document.addEventListener('DOMContentLoaded', () => {\n this.init()\n\n this.domObserver = new MutationObserver(this.onDomMutation.bind(this))\n this.domObserver.observe(document.body, { childList: true, subtree: true })\n }, { once: true })\n }\n\n // Internal\n init() {\n const elements = document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`)\n\n for (const element of elements) {\n try {\n this.watch(element)\n } catch (error) {\n console.error(error, element)\n }\n }\n }\n\n onResize(entries) {\n const toUpdate = new Set()\n\n // eslint-disable-next-line no-var\n for (var i = entries.length - 1; i >= 0; i--) {\n const { target: element, borderBoxSize } = entries[i]\n\n if (this.elements.has(element)) {\n let width\n let height\n\n if (borderBoxSize && borderBoxSize[0]) {\n width = borderBoxSize[0].inlineSize\n height = borderBoxSize[0].blockSize\n } else {\n // fallback for Safari\n const rect = element.getBoundingClientRect()\n width = rect.width\n height = rect.height\n }\n\n const elementsEntry = this.elements.get(element)\n this.elements.set(element, { ...elementsEntry, ...{ width, height } })\n toUpdate.add(element)\n }\n }\n\n this.update([...toUpdate])\n }\n\n onDomMutation(mutations) {\n // eslint-disable-next-line no-var\n for (var i = mutations.length - 1; i >= 0; i--) {\n if (mutations[i].addedNodes.length) {\n // eslint-disable-next-line no-var\n for (var k = mutations[i].addedNodes.length - 1; k >= 0; k--) {\n const element = mutations[i].addedNodes[k]\n if (\n element instanceof HTMLElement\n && element.hasAttribute(this.opts.htmlAttrBreakpoints)\n ) {\n try {\n this.watch(element)\n } catch (e) {\n console.error(e, element)\n }\n }\n }\n }\n }\n }\n\n // Methods & Helpers\n /**\n * Watch an element manually\n * @param {HTMLElement} element The DOM element you would like to watch\n */\n watch(element) {\n if (!element || !(element instanceof HTMLElement)) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENT)\n if (!element.hasAttribute(this.opts.htmlAttrBreakpoints)) {\n throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n }\n\n const breakpointString = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"removeWhitespace\"])(element.getAttribute(this.opts.htmlAttrBreakpoints))\n const breakpointMatches = [...breakpointString.matchAll(_utils__WEBPACK_IMPORTED_MODULE_0__[\"BREAKPOINT_REGEX\"])]\n\n if (!breakpointMatches.length) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n\n const breakpoints = breakpointMatches.reduce((acc, match) => {\n if (!match[1] || !match[2]) return acc\n\n acc[match[1]] = +match[2]\n return acc\n }, {})\n\n this.elements.set(element, { breakpoints })\n this.observer.observe(element, { box: 'border-box' })\n }\n\n /**\n * Updates the given elements according to their internal state (eq.elements)\n * @param {Array} elements Array of DOM elements\n */\n update(elements) {\n if (\n !elements\n || !Array.isArray(elements)\n || !elements.length\n || !elements.every(el => el instanceof HTMLElement)\n ) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENTS)\n\n // eslint-disable-next-line no-var\n for (var i = elements.length - 1; i >= 0; i--) {\n const element = elements[i]\n\n const entry = this.elements.get(element)\n if (entry && entry.breakpoints) {\n const { width } = entry\n let active = null\n\n const bpsFlipped = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"flipObject\"])(entry.breakpoints)\n const bpWidths = Object.values(entry.breakpoints).sort() // sort ASC\n const bpLargest = bpWidths[bpWidths.length - 1]\n\n if (width >= bpLargest) {\n active = bpsFlipped[bpLargest]\n } else if (width > bpWidths[0]) {\n for (let k = 0; k < bpWidths.length; k++) {\n const bpWidth = bpWidths[k]\n\n if (width >= bpWidth) {\n active = bpsFlipped[bpWidth]\n }\n }\n }\n\n if (active) {\n element.setAttribute(this.opts.htmlAttrActive, active)\n continue\n }\n }\n\n element.removeAttribute(this.opts.htmlAttrActive)\n }\n }\n\n /**\n * Disconnects all observers and clears element references\n */\n destroy() {\n this.observer.disconnect()\n this.domObserver.disconnect()\n this.elements = new WeakMap()\n }\n}\n\n\n//# sourceURL=webpack:///./src/ElementQueries.js?");
107+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return ElementQueries; });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\n\nconst DEFAULT_OPTS = {\n htmlAttrBreakpoints: 'data-eq-breakpoints',\n htmlAttrActive: 'data-eq-active',\n}\n\nclass ElementQueries {\n constructor(opts) {\n this.opts = Object.freeze({ ...DEFAULT_OPTS, ...opts })\n\n this.observer = new ResizeObserver(this.onResize.bind(this))\n this.elements = new WeakMap()\n\n // wait for document load\n if (/complete|interactive|loaded/.test(document.readyState)) {\n this.onDocumentLoad()\n } else {\n document.addEventListener('DOMContentLoaded', this.onDocumentLoad.bind(this), { once: true })\n }\n }\n\n // Internal\n onDocumentLoad() {\n this.init()\n\n this.domObserver = new MutationObserver(this.onDomMutation.bind(this))\n this.domObserver.observe(document.body, { childList: true, subtree: true })\n }\n\n init() {\n const elements = document.querySelectorAll(`[${this.opts.htmlAttrBreakpoints}]`)\n\n for (const element of elements) {\n try {\n this.watch(element)\n } catch (error) {\n console.error(error, element)\n }\n }\n }\n\n onResize(entries) {\n const toUpdate = new Set()\n\n // eslint-disable-next-line no-var\n for (var i = entries.length - 1; i >= 0; i--) {\n const { target: element, borderBoxSize } = entries[i]\n\n if (this.elements.has(element)) {\n let width\n let height\n\n if (borderBoxSize && borderBoxSize[0]) {\n width = borderBoxSize[0].inlineSize\n height = borderBoxSize[0].blockSize\n } else {\n // fallback for Safari\n const rect = element.getBoundingClientRect()\n width = rect.width\n height = rect.height\n }\n\n const elementsEntry = this.elements.get(element)\n this.elements.set(element, { ...elementsEntry, ...{ width, height } })\n toUpdate.add(element)\n }\n }\n\n this.update([...toUpdate])\n }\n\n onDomMutation(mutations) {\n // eslint-disable-next-line no-var\n for (var i = mutations.length - 1; i >= 0; i--) {\n if (mutations[i].addedNodes.length) {\n // eslint-disable-next-line no-var\n for (var k = mutations[i].addedNodes.length - 1; k >= 0; k--) {\n const element = mutations[i].addedNodes[k]\n if (\n element instanceof HTMLElement\n && element.hasAttribute(this.opts.htmlAttrBreakpoints)\n ) {\n try {\n this.watch(element)\n } catch (e) {\n console.error(e, element)\n }\n }\n }\n }\n }\n }\n\n // Methods & Helpers\n /**\n * Watch an element manually\n * @param {HTMLElement} element The DOM element you would like to watch\n */\n watch(element) {\n if (!element || !(element instanceof HTMLElement)) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENT)\n if (!element.hasAttribute(this.opts.htmlAttrBreakpoints)) {\n throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n }\n\n const breakpointString = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"removeWhitespace\"])(element.getAttribute(this.opts.htmlAttrBreakpoints))\n const breakpointMatches = [...breakpointString.matchAll(_utils__WEBPACK_IMPORTED_MODULE_0__[\"BREAKPOINT_REGEX\"])]\n\n if (!breakpointMatches.length) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].BREAKPOINTS_MISSING)\n\n const breakpoints = breakpointMatches.reduce((acc, match) => {\n if (!match[1] || !match[2]) return acc\n\n acc[match[1]] = +match[2]\n return acc\n }, {})\n\n this.elements.set(element, { breakpoints })\n this.observer.observe(element, { box: 'border-box' })\n }\n\n /**\n * Updates the given elements according to their internal state (eq.elements)\n * @param {Array} elements Array of DOM elements\n */\n update(elements) {\n if (\n !elements\n || !Array.isArray(elements)\n || !elements.length\n || !elements.every(el => el instanceof HTMLElement)\n ) throw new Error(_utils__WEBPACK_IMPORTED_MODULE_0__[\"Errors\"].INVALID_ELEMENTS)\n\n // eslint-disable-next-line no-var\n for (var i = elements.length - 1; i >= 0; i--) {\n const element = elements[i]\n\n const entry = this.elements.get(element)\n if (entry && entry.breakpoints) {\n const { width } = entry\n let active = null\n\n const bpsFlipped = Object(_utils__WEBPACK_IMPORTED_MODULE_0__[\"flipObject\"])(entry.breakpoints)\n const bpWidths = Object.values(entry.breakpoints).sort() // sort ASC\n const bpLargest = bpWidths[bpWidths.length - 1]\n\n if (width >= bpLargest) {\n active = bpsFlipped[bpLargest]\n } else if (width > bpWidths[0]) {\n for (let k = 0; k < bpWidths.length; k++) {\n const bpWidth = bpWidths[k]\n\n if (width >= bpWidth) {\n active = bpsFlipped[bpWidth]\n }\n }\n }\n\n if (active) {\n element.setAttribute(this.opts.htmlAttrActive, active)\n continue\n }\n }\n\n element.removeAttribute(this.opts.htmlAttrActive)\n }\n }\n\n /**\n * Disconnects all observers and clears element references\n */\n destroy() {\n if (this.observer) this.observer.disconnect()\n if (this.domObserver) this.domObserver.disconnect()\n\n this.elements = new WeakMap()\n }\n}\n\n\n//# sourceURL=webpack:///./src/ElementQueries.js?");
108108

109109
/***/ }),
110110

@@ -116,7 +116,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
116116
/***/ (function(module, __webpack_exports__, __webpack_require__) {
117117

118118
"use strict";
119-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ElementQueries__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ElementQueries */ \"./src/ElementQueries.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return _ElementQueries__WEBPACK_IMPORTED_MODULE_0__[\"ElementQueries\"]; });\n\n\n\n/** TODOs\n * TODO move this out of here :)\n * TODO allow passing breakpoint object to .watch() which overrides htmlAttrBreakpoints\n * TODO Support HTMLElement *AND* SVGElement\n * TODO disable if ResizeObserver isnt supported\n * NOTE general browser-support checks (MutationObserver, etc)\n * NOTE batching resize updates?\n * NOTE throttle observer?\n * NOTE debounce updates on a per-element basis?\n * NOTE use requestAnimationFrame on resize callback?\n * NOTE what do if user changes htmlAttrBreakpoints dynamically\n */\n\n\n//# sourceURL=webpack:///./src/index.js?");
119+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ElementQueries__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ElementQueries */ \"./src/ElementQueries.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"ElementQueries\", function() { return _ElementQueries__WEBPACK_IMPORTED_MODULE_0__[\"ElementQueries\"]; });\n\n\n\n/** TODOs\n * TODO move this out of here :)\n * TODO allow passing breakpoint object to .watch() which overrides htmlAttrBreakpoints\n * TODO Support HTMLElement *AND* SVGElement\n * TODO disable if ResizeObserver isnt supported\n * TODO config option: dom observing on/off\n * NOTE general browser-support checks (MutationObserver, etc)\n * NOTE batching resize updates?\n * NOTE throttle observer?\n * NOTE debounce updates on a per-element basis?\n * NOTE use requestAnimationFrame on resize callback?\n * NOTE what do if user changes htmlAttrBreakpoints dynamically\n */\n\n\n//# sourceURL=webpack:///./src/index.js?");
120120

121121
/***/ }),
122122

0 commit comments

Comments
 (0)