From a1ec6e49e3bb3dc55c21327ccae18d0d204b56f2 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 13 Feb 2018 13:42:53 +0100 Subject: [PATCH 01/35] Fix cross-domain cssRules access breaking code (#214) When @import rule points to an other domain, accessing the style sheet with .cssRules will cause trouble on Chrome and Firefox (at least, haven't tested on other browsers). Firefox will raise a "Security error code: 1000" while Chrome will raise "Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules" which (I d'ont know why) can't be caught with a regular try catch statement and will break the for loop and thus not parse the other rules if any. I had this problem while having a @import rule for google fonts. I fixed the issue by checking first if the property cssRules actually exist. --- src/ElementQueries.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 2bd723c..0a46486 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -384,7 +384,9 @@ } else if (4 === rules[i].type) { readRules(rules[i].cssRules || rules[i].rules); } else if (3 === rules[i].type) { - readRules(rules[i].styleSheet.cssRules); + if(rules[i].styleSheet.hasOwnProperty("cssRules")) { + readRules(rules[i].styleSheet.cssRules); + } } } } From 529c704eab273d095d5c5a9ea629d23217cfd9a8 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 23 Feb 2018 14:32:51 +0100 Subject: [PATCH 02/35] fixed typo in findElementQueriesElements --- src/ElementQueries.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 0a46486..65dc3c3 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -224,7 +224,7 @@ function findElementQueriesElements(container) { var query = getQuery(container); - for (var selector in allQueries) if (allQueries.hasOwnProperty(mode)) { + for (var selector in allQueries) if (allQueries.hasOwnProperty(selector)) { // find all elements based on the extract query selector from the element query rule var elements = query(selector, container); @@ -447,7 +447,6 @@ } } - // findElementQueriesElements(); findResponsiveImages(); }; From decc2b769a7d909c0727bfc0c793e1fd128cd813 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 23 Feb 2018 14:36:16 +0100 Subject: [PATCH 03/35] tag 1.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b6a3d3..28c459f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.0.1", + "version": "1.0.2", "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { From 0cd66f61eee3d01dd2ce29eb1bb201482e311221 Mon Sep 17 00:00:00 2001 From: movedoa Date: Thu, 1 Mar 2018 17:33:07 +0100 Subject: [PATCH 04/35] Use ResizeObserver when available and check for initial invisible elements (#213) ResizeObserver is Chrome only at the moment. When a resize sensor has been added to an invisible element, then we check coming with this commit every frame whether it is actually visible (rendered) and then start the sensor process. Otherwise the sensor would just not work on initial invisible elements. --- src/ResizeSensor.js | 106 +++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 0846014..d03e17d 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -83,6 +83,9 @@ * @constructor */ var ResizeSensor = function(element, callback) { + + var observer; + /** * * @constructor @@ -94,9 +97,9 @@ }; var i, j; - this.call = function() { + this.call = function(sizeInfo) { for (i = 0, j = q.length; i < j; i++) { - q[i].call(); + q[i].call(this, sizeInfo); } }; @@ -152,32 +155,50 @@ var expand = element.resizeSensor.childNodes[0]; var expandChild = expand.childNodes[0]; var shrink = element.resizeSensor.childNodes[1]; - var dirty, rafId, newWidth, newHeight; + + var dirty, rafId; var size = getElementSize(element); var lastWidth = size.width; var lastHeight = size.height; - - var reset = function() { - //set display to block, necessary otherwise hidden elements won't ever work - var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; - - if (invisible) { - var saveDisplay = element.style.display; - element.style.display = 'block'; - } - + var initialHiddenCheck = true, resetRAF_id; + + + var resetExpandShrink = function () { expandChild.style.width = '100000px'; expandChild.style.height = '100000px'; - + expand.scrollLeft = 100000; expand.scrollTop = 100000; - + shrink.scrollLeft = 100000; shrink.scrollTop = 100000; + }; - if (invisible) { - element.style.display = saveDisplay; + var reset = function() { + // Check if element is hidden + if (initialHiddenCheck) { + if (!expand.scrollTop && !expand.scrollLeft) { + + // reset + resetExpandShrink(); + + // Check in next frame + if (!resetRAF_id){ + resetRAF_id = requestAnimationFrame(function(){ + resetRAF_id = 0; + + reset(); + }); + } + + return; + } else { + // Stop checking + initialHiddenCheck = false; + } } + + resetExpandShrink(); }; element.resizeSensor.resetSensor = reset; @@ -186,19 +207,17 @@ if (!dirty) return; - lastWidth = newWidth; - lastHeight = newHeight; + lastWidth = size.width; + lastHeight = size.height; if (element.resizedAttached) { - element.resizedAttached.call(); + element.resizedAttached.call(size); } }; var onScroll = function() { - var size = getElementSize(element); - var newWidth = size.width; - var newHeight = size.height; - dirty = newWidth != lastWidth || newHeight != lastHeight; + size = getElementSize(element); + dirty = size.width !== lastWidth || size.height !== lastHeight; if (dirty && !rafId) { rafId = requestAnimationFrame(onResized); @@ -218,16 +237,41 @@ addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); - // Fix for custom Elements - requestAnimationFrame(reset); + // Fix for custom Elements + requestAnimationFrame(reset); + } + + if (typeof ResizeObserver !== "undefined") { + observer = new ResizeObserver(function(element){ + forEachElement(element, function (elem) { + callback.call( + this, + { + width: elem.contentRect.width, + height: elem.contentRect.height + } + ); + }); + }); + if (element !== undefined) { + forEachElement(element, function(elem){ + observer.observe(elem); + }); + } + } + else { + forEachElement(element, function(elem){ + attachResizeEvent(elem, callback); + }); } - - forEachElement(element, function(elem){ - attachResizeEvent(elem, callback); - }); this.detach = function(ev) { - ResizeSensor.detach(element, ev); + if (typeof ResizeObserver != "undefined") { + observer.unobserve(element); + } + else { + ResizeSensor.detach(element, ev); + } }; this.reset = function() { From cbc9d1afd4a04926b389079af4802bac9cd08ab6 Mon Sep 17 00:00:00 2001 From: Ben Beckford Date: Tue, 20 Mar 2018 14:17:09 +0000 Subject: [PATCH 05/35] Fixed ResizeObserver detach error (#221) Fixes error on detach: Uncaught TypeError: Failed to execute 'unobserve' on 'ResizeObserver': parameter 1 is not of type 'Element'. --- src/ResizeSensor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index d03e17d..fcc6597 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -267,7 +267,9 @@ this.detach = function(ev) { if (typeof ResizeObserver != "undefined") { - observer.unobserve(element); + forEachElement(element, function(elem){ + observer.unobserve(elem); + }); } else { ResizeSensor.detach(element, ev); From eff187ee4931296b089f457071e8e3990e38c6d3 Mon Sep 17 00:00:00 2001 From: Juuso Palander Date: Thu, 5 Jul 2018 17:38:21 +0300 Subject: [PATCH 06/35] Added sanity check to window.getComputedStyle in ResizeSensor (#234) --- src/ResizeSensor.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index fcc6597..8ef42b1 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -83,9 +83,9 @@ * @constructor */ var ResizeSensor = function(element, callback) { - + var observer; - + /** * * @constructor @@ -147,7 +147,8 @@ ''; element.appendChild(element.resizeSensor); - var position = window.getComputedStyle(element).getPropertyValue('position'); + var computedStyle = window.getComputedStyle(element); + var position = computedStyle ? computedStyle.getPropertyValue('position') : null; if ('absolute' !== position && 'relative' !== position && 'fixed' !== position) { element.style.position = 'relative'; } @@ -161,15 +162,15 @@ var lastWidth = size.width; var lastHeight = size.height; var initialHiddenCheck = true, resetRAF_id; - - + + var resetExpandShrink = function () { expandChild.style.width = '100000px'; expandChild.style.height = '100000px'; - + expand.scrollLeft = 100000; expand.scrollTop = 100000; - + shrink.scrollLeft = 100000; shrink.scrollTop = 100000; }; @@ -186,11 +187,11 @@ if (!resetRAF_id){ resetRAF_id = requestAnimationFrame(function(){ resetRAF_id = 0; - + reset(); }); } - + return; } else { // Stop checking @@ -236,11 +237,11 @@ addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); - + // Fix for custom Elements requestAnimationFrame(reset); } - + if (typeof ResizeObserver !== "undefined") { observer = new ResizeObserver(function(element){ forEachElement(element, function (elem) { From e1f3e0475a52b830d4b6490abd7b2984fbc8553f Mon Sep 17 00:00:00 2001 From: Sagiv ben giat Date: Mon, 23 Jul 2018 22:54:19 +0300 Subject: [PATCH 07/35] max-width 100% for resize-sensor element (#238) --- src/ResizeSensor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 8ef42b1..c8fcfd6 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -134,7 +134,7 @@ element.resizeSensor = document.createElement('div'); element.resizeSensor.dir = 'ltr'; element.resizeSensor.className = 'resize-sensor'; - var style = 'position: absolute; left: -10px; top: -10px; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;'; + var style = 'position: absolute; left: -10px; top: -10px; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%'; var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;'; element.resizeSensor.style.cssText = style; From 5aa2dfcf2abc6489e00f48946ccd076fb6842747 Mon Sep 17 00:00:00 2001 From: Pauan Date: Tue, 16 Oct 2018 00:11:41 -1000 Subject: [PATCH 08/35] Fixing to work with more recent versions of TypeScript (#243) Without this change I get this error from TypeScript: ``` Module '"node_modules/css-element-queries/src/ResizeSensor"' has no default export. 24 import ResizeSensor from "css-element-queries/src/ResizeSensor"; ~~~~~~~~~~~~ ``` --- src/ResizeSensor.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index fe5bb03..6255ccf 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -3,4 +3,4 @@ declare class ResizeSensor { detach(callback: Function): void; } -export = ResizeSensor; +export default ResizeSensor; From cd88cc057568565589cff02c97b3c3778bc79a23 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 16 Oct 2018 12:15:01 +0200 Subject: [PATCH 09/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28c459f..719efab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.0.2", + "version": "1.0.3", "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { From 45334e9f36ede5e037d2749ff398daa20dc5ae22 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 16 Oct 2018 12:32:42 +0200 Subject: [PATCH 10/35] Reverted: #213 Use resizeobserver when available due to incompatibility with dom elements detection --- package.json | 2 +- src/ElementQueries.js | 8 ++-- src/ResizeSensor.js | 87 +++++++++++-------------------------------- 3 files changed, 26 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 719efab..f65e95d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.0.3", + "version": "1.0.4", "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 65dc3c3..9ea9a0f 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -324,7 +324,7 @@ } } - element.resizeSensor = new ResizeSensor(element, check); + element.resizeSensorInstance = new ResizeSensor(element, check); check(); } @@ -482,11 +482,11 @@ delete element.elementQueriesSetupInformation; delete element.elementQueriesSensor; - } else if (element.resizeSensor) { + } else if (element.resizeSensorInstance) { //responsive image - element.resizeSensor.detach(); - delete element.resizeSensor; + element.resizeSensorInstance.detach(); + delete element.resizeSensorInstance; } }; diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index c8fcfd6..e26dcad 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -83,9 +83,6 @@ * @constructor */ var ResizeSensor = function(element, callback) { - - var observer; - /** * * @constructor @@ -156,15 +153,21 @@ var expand = element.resizeSensor.childNodes[0]; var expandChild = expand.childNodes[0]; var shrink = element.resizeSensor.childNodes[1]; - - var dirty, rafId; + var dirty, rafId, newWidth, newHeight; var size = getElementSize(element); var lastWidth = size.width; var lastHeight = size.height; var initialHiddenCheck = true, resetRAF_id; + var reset = function() { + //set display to block, necessary otherwise hidden elements won't ever work + var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; + + if (invisible) { + var saveDisplay = element.style.display; + element.style.display = 'block'; + } - var resetExpandShrink = function () { expandChild.style.width = '100000px'; expandChild.style.height = '100000px'; @@ -173,33 +176,10 @@ shrink.scrollLeft = 100000; shrink.scrollTop = 100000; - }; - var reset = function() { - // Check if element is hidden - if (initialHiddenCheck) { - if (!expand.scrollTop && !expand.scrollLeft) { - - // reset - resetExpandShrink(); - - // Check in next frame - if (!resetRAF_id){ - resetRAF_id = requestAnimationFrame(function(){ - resetRAF_id = 0; - - reset(); - }); - } - - return; - } else { - // Stop checking - initialHiddenCheck = false; - } + if (invisible) { + element.style.display = saveDisplay; } - - resetExpandShrink(); }; element.resizeSensor.resetSensor = reset; @@ -208,8 +188,8 @@ if (!dirty) return; - lastWidth = size.width; - lastHeight = size.height; + lastWidth = newWidth; + lastHeight = newHeight; if (element.resizedAttached) { element.resizedAttached.call(size); @@ -217,8 +197,10 @@ }; var onScroll = function() { - size = getElementSize(element); - dirty = size.width !== lastWidth || size.height !== lastHeight; + var size = getElementSize(element); + var newWidth = size.width; + var newHeight = size.height; + dirty = newWidth !== lastWidth || newHeight !== lastHeight; if (dirty && !rafId) { rafId = requestAnimationFrame(onResized); @@ -242,39 +224,12 @@ requestAnimationFrame(reset); } - if (typeof ResizeObserver !== "undefined") { - observer = new ResizeObserver(function(element){ - forEachElement(element, function (elem) { - callback.call( - this, - { - width: elem.contentRect.width, - height: elem.contentRect.height - } - ); - }); - }); - if (element !== undefined) { - forEachElement(element, function(elem){ - observer.observe(elem); - }); - } - } - else { - forEachElement(element, function(elem){ - attachResizeEvent(elem, callback); - }); - } + forEachElement(element, function(elem){ + attachResizeEvent(elem, callback); + }); this.detach = function(ev) { - if (typeof ResizeObserver != "undefined") { - forEachElement(element, function(elem){ - observer.unobserve(elem); - }); - } - else { - ResizeSensor.detach(element, ev); - } + ResizeSensor.detach(element, ev); }; this.reset = function() { From 74791b6d41b4eff89c72edf4cc573c97aa4552be Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 16 Oct 2018 18:34:14 +0200 Subject: [PATCH 11/35] fixed resize sensor with elements that start hidden --- src/ResizeSensor.js | 49 +++++++++++++++++++++++++---------------- tests/late-trigger.html | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 tests/late-trigger.html diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index e26dcad..32e6a1d 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -153,21 +153,14 @@ var expand = element.resizeSensor.childNodes[0]; var expandChild = expand.childNodes[0]; var shrink = element.resizeSensor.childNodes[1]; - var dirty, rafId, newWidth, newHeight; + var dirty, rafId; var size = getElementSize(element); var lastWidth = size.width; var lastHeight = size.height; - var initialHiddenCheck = true, resetRAF_id; - - var reset = function() { - //set display to block, necessary otherwise hidden elements won't ever work - var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; - - if (invisible) { - var saveDisplay = element.style.display; - element.style.display = 'block'; - } + var initialHiddenCheck = true; + var lastAnimationFrame = 0; + var resetExpandShrink = function () { expandChild.style.width = '100000px'; expandChild.style.height = '100000px'; @@ -176,10 +169,30 @@ shrink.scrollLeft = 100000; shrink.scrollTop = 100000; + }; - if (invisible) { - element.style.display = saveDisplay; + var reset = function() { + // Check if element is hidden + if (initialHiddenCheck) { + var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; + if (invisible) { + // Check in next frame + if (!lastAnimationFrame){ + lastAnimationFrame = requestAnimationFrame(function(){ + lastAnimationFrame = 0; + + reset(); + }); + } + + return; + } else { + // Stop checking + initialHiddenCheck = false; + } } + + resetExpandShrink(); }; element.resizeSensor.resetSensor = reset; @@ -188,8 +201,8 @@ if (!dirty) return; - lastWidth = newWidth; - lastHeight = newHeight; + lastWidth = size.width; + lastHeight = size.height; if (element.resizedAttached) { element.resizedAttached.call(size); @@ -197,10 +210,8 @@ }; var onScroll = function() { - var size = getElementSize(element); - var newWidth = size.width; - var newHeight = size.height; - dirty = newWidth !== lastWidth || newHeight !== lastHeight; + size = getElementSize(element); + dirty = size.width !== lastWidth || size.height !== lastHeight; if (dirty && !rafId) { rafId = requestAnimationFrame(onResized); diff --git a/tests/late-trigger.html b/tests/late-trigger.html new file mode 100644 index 0000000..71a2b17 --- /dev/null +++ b/tests/late-trigger.html @@ -0,0 +1,48 @@ + + + + + + + + + + + \ No newline at end of file From b4f79b37c16871d6442135f53453cc28f4b3e0e9 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 16 Oct 2018 18:34:26 +0200 Subject: [PATCH 12/35] bump version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f65e95d..93c85c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "css-element-queries", - "version": "1.0.4", - "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.", + "version": "1.0.5", + "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { "test": "test" From da5f446f5b7dc847f3f26198154a7782aff85743 Mon Sep 17 00:00:00 2001 From: Nikita Skazki Date: Thu, 18 Oct 2018 22:44:39 +0300 Subject: [PATCH 13/35] don't explode if an old browser can't provide element, computed style, or style property (#241) --- src/ElementQueries.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 9ea9a0f..23038d0 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -409,9 +409,11 @@ document.body.addEventListener(animationStart, function (e) { var element = e.target; - var styles = window.getComputedStyle(element, null); + var styles = element && window.getComputedStyle(element, null); + var animationName = styles && styles.getPropertyValue('animation-name'); + var requiresSetup = animationName && (-1 !== animationName.indexOf('element-queries')); - if (-1 !== styles.getPropertyValue('animation-name').indexOf('element-queries')) { + if (requiresSetup) { element.elementQueriesSensor = new ResizeSensor(element, function () { if (element.elementQueriesSetupInformation) { element.elementQueriesSetupInformation.call(); From f6144fb52192efc6371aaebf0c72f7408fea17d3 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 6 Nov 2018 18:33:12 +0100 Subject: [PATCH 14/35] Added mutationobserver to detect DOM movements and reset sensor accordingly. fixed a bug in Safari where dragdrop doesn't work with huge sensors dimensions. --- src/ResizeSensor.d.ts | 1 + src/ResizeSensor.js | 41 ++++++++++++++++----- tests/mutation/app.js | 75 ++++++++++++++++++++++++++++++++++++++ tests/mutation/app.ts | 56 +++++++++++++++++++++++++++++ tests/mutation/index.html | 76 +++++++++++++++++++++++++++++++++++++++ tsconfig.json | 7 ++++ 6 files changed, 248 insertions(+), 8 deletions(-) create mode 100644 tests/mutation/app.js create mode 100644 tests/mutation/app.ts create mode 100644 tests/mutation/index.html create mode 100644 tsconfig.json diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index 6255ccf..82215ca 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -1,6 +1,7 @@ declare class ResizeSensor { constructor(element: (Element | Element[]), callback: Function); detach(callback: Function): void; + reset(element: Element | Element[]): void; } export default ResizeSensor; diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 32e6a1d..a83d0f6 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -131,7 +131,8 @@ element.resizeSensor = document.createElement('div'); element.resizeSensor.dir = 'ltr'; element.resizeSensor.className = 'resize-sensor'; - var style = 'position: absolute; left: -10px; top: -10px; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%'; + var style = 'pointer-events: none; position: absolute; left: 0px; top: 0px; right: 0; bottom: 0; ' + + 'overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%;'; var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;'; element.resizeSensor.style.cssText = style; @@ -161,14 +162,17 @@ var lastAnimationFrame = 0; var resetExpandShrink = function () { - expandChild.style.width = '100000px'; - expandChild.style.height = '100000px'; + var width = element.offsetWidth; + var height = element.offsetHeight; - expand.scrollLeft = 100000; - expand.scrollTop = 100000; + expandChild.style.width = (width + 10) + 'px'; + expandChild.style.height = (height + 10) + 'px'; - shrink.scrollLeft = 100000; - shrink.scrollTop = 100000; + expand.scrollLeft = width + 10; + expand.scrollTop = height + 10; + + shrink.scrollLeft = width + 10; + shrink.scrollTop = height + 10; }; var reset = function() { @@ -248,7 +252,7 @@ }; }; - ResizeSensor.reset = function(element, ev) { + ResizeSensor.reset = function(element) { forEachElement(element, function(elem){ elem.resizeSensor.resetSensor(); }); @@ -271,6 +275,27 @@ }); }; + if (typeof MutationObserver !== "undefined") { + var observer = new MutationObserver(function (mutations) { + for (var i in mutations) { + var items = mutations[i].addedNodes; + for (var j = 0; j < items.length; j++) { + if (items[j].resizeSensor) { + ResizeSensor.reset(items[j]); + } + } + + } + }); + + document.addEventListener("DOMContentLoaded", function (event) { + observer.observe(document.body, { + childList: true, + subtree: true, + }); + }); + } + return ResizeSensor; })); diff --git a/tests/mutation/app.js b/tests/mutation/app.js new file mode 100644 index 0000000..2100612 --- /dev/null +++ b/tests/mutation/app.js @@ -0,0 +1,75 @@ +var __values = (this && this.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; +var e_1, _a, e_2, _b; +var state = { + dragged: null +}; +var i = 0; +try { + for (var _c = __values(document.getElementsByClassName('drag')), _d = _c.next(); !_d.done; _d = _c.next()) { + var item = _d.value; + i++; + item.setAttribute('draggable', 'true'); + item.setAttribute('id', 'drag-' + i); + (function (element) { + var title = 'Drag me #' + i; + element.setAttribute('data-label', title); + new ResizeSensor(element, function (size) { + element.setAttribute('data-label', title + " (" + size.width + "x" + size.height + ")"); + }); + })(item); + item.addEventListener('dragstart', function (event) { + state.dragged = event.target; + event.dataTransfer.setData('text', 'thanks firefox'); + event.dataTransfer.dropEffect = 'move'; + }); + } +} +catch (e_1_1) { e_1 = { error: e_1_1 }; } +finally { + try { + if (_d && !_d.done && (_a = _c.return)) _a.call(_c); + } + finally { if (e_1) throw e_1.error; } +} +var _loop_1 = function (item) { + (function (element) { + item.addEventListener('drop', function (event) { + event.preventDefault(); + item.classList.remove('drag-hover'); + state.dragged.parentNode.removeChild(state.dragged); + element.appendChild(state.dragged); + state.dragged = null; + }); + })(item); + item.addEventListener('dragleave', function (event) { + item.classList.remove('drag-hover'); + }); + item.addEventListener('dragover', function (event) { + item.classList.add('drag-hover'); + }); + item.addEventListener('dragover', function (event) { + event.preventDefault(); + }); +}; +try { + for (var _e = __values(document.getElementsByClassName('container')), _f = _e.next(); !_f.done; _f = _e.next()) { + var item = _f.value; + _loop_1(item); + } +} +catch (e_2_1) { e_2 = { error: e_2_1 }; } +finally { + try { + if (_f && !_f.done && (_b = _e.return)) _b.call(_e); + } + finally { if (e_2) throw e_2.error; } +} diff --git a/tests/mutation/app.ts b/tests/mutation/app.ts new file mode 100644 index 0000000..15974f7 --- /dev/null +++ b/tests/mutation/app.ts @@ -0,0 +1,56 @@ +declare const ResizeSensor; + +const state: { + dragged: Element +} = { + dragged: null +}; + +let i = 0; + +for (const item of document.getElementsByClassName('drag')) { + i++; + item.setAttribute('draggable', 'true'); + item.setAttribute('id', 'drag-' + i); + + (element => { + const title = 'Drag me #' + i; + element.setAttribute('data-label', title); + + new ResizeSensor(element, (size) => { + element.setAttribute('data-label', `${title} (${size.width}x${size.height})`); + }); + })(item); + + item.addEventListener('dragstart', (event: DragEvent) => { + state.dragged = event.target; + event.dataTransfer.setData('text', 'thanks firefox'); + event.dataTransfer.dropEffect = 'move'; + }); +} + +for (const item of document.getElementsByClassName('container')) { + (element => { + item.addEventListener('drop', (event) => { + event.preventDefault(); + item.classList.remove('drag-hover'); + + state.dragged.parentNode.removeChild(state.dragged); + element.appendChild(state.dragged); + + state.dragged = null; + }); + })(item); + + item.addEventListener('dragleave', (event) => { + item.classList.remove('drag-hover'); + }); + + item.addEventListener('dragover', (event) => { + item.classList.add('drag-hover'); + }); + + item.addEventListener('dragover', (event) => { + event.preventDefault(); + }); +} diff --git a/tests/mutation/index.html b/tests/mutation/index.html new file mode 100644 index 0000000..6d2ddce --- /dev/null +++ b/tests/mutation/index.html @@ -0,0 +1,76 @@ + + + + + + + + +
+
+
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7b56f0e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "target": "es5", + "downlevelIteration": true, + "lib" : ["dom","es6","dom.iterable","scripthost", "es2015.iterable", "es2015.collection"] + } +} \ No newline at end of file From 8bc290cceb2dec934a0081c5e33d124eef7042e8 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Tue, 6 Nov 2018 18:34:17 +0100 Subject: [PATCH 15/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 93c85c9..6376d58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.0.5", + "version": "1.1.0", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { From 9cb667d81324cd4cecc10022b83be6d011a7b90f Mon Sep 17 00:00:00 2001 From: Michael Coleman Date: Thu, 8 Nov 2018 10:25:09 -0500 Subject: [PATCH 16/35] =?UTF-8?q?added=20ResizeCallback=20to=20ResizeSenso?= =?UTF-8?q?r.d.ts=20and=20added=20static=20functions=20=E2=80=A6=20(#248)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added ResizeCallback to ResizeSensor.d.ts and added static functions to ResizeSensor class * renaming ResizeCallback to ResizeSensorCallback * added optional type to callback for detach methods on ResizeSensor --- src/ResizeSensor.d.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index 82215ca..b0a5fdf 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -1,7 +1,12 @@ +export declare type ResizeSensorCallback = (size: { width: number; height: number; }) => void; + declare class ResizeSensor { - constructor(element: (Element | Element[]), callback: Function); - detach(callback: Function): void; - reset(element: Element | Element[]): void; + constructor(element: Element | Element[], callback: ResizeSensorCallback); + detach(callback?: ResizeSensorCallback): void; + reset(): void; + + static detach(element: Element | Element[], callback?: ResizeSensorCallback): void; + static reset(element: Element | Element[]): void; } export default ResizeSensor; From 09d4cf12a2bf2c143274bbe4e4bc04060e55880f Mon Sep 17 00:00:00 2001 From: Andreas Lubbe Date: Fri, 9 Nov 2018 12:16:54 +0100 Subject: [PATCH 17/35] Make the MutationObserver of ResizeSensor compatible with new Chrome version (#249) The for-in loop over the `NodeList` now goes through the prototype chain, so we check `hasOwnProperty` first --- src/ResizeSensor.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index a83d0f6..555a906 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -278,13 +278,14 @@ if (typeof MutationObserver !== "undefined") { var observer = new MutationObserver(function (mutations) { for (var i in mutations) { - var items = mutations[i].addedNodes; - for (var j = 0; j < items.length; j++) { - if (items[j].resizeSensor) { - ResizeSensor.reset(items[j]); + if (mutations.hasOwnProperty(i)) { + var items = mutations[i].addedNodes; + for (var j = 0; j < items.length; j++) { + if (items[j].resizeSensor) { + ResizeSensor.reset(items[j]); + } } } - } }); From 31cabb56fb2af08470159251f6e535e2c3577758 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 9 Nov 2018 12:18:52 +0100 Subject: [PATCH 18/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6376d58..154a842 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.1.0", + "version": "1.1.1", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "directories": { From 7587a6553a8a240fe20479703bbd9d971571b51f Mon Sep 17 00:00:00 2001 From: Stephen Lautier Date: Thu, 9 May 2019 11:13:38 +0200 Subject: [PATCH 19/35] feat(typings): export TS typings (#266) --- css-element-queries.d.ts | 1 + package.json | 1 + src/ResizeSensor.d.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 css-element-queries.d.ts diff --git a/css-element-queries.d.ts b/css-element-queries.d.ts new file mode 100644 index 0000000..0ca3bc3 --- /dev/null +++ b/css-element-queries.d.ts @@ -0,0 +1 @@ +export { ResizeSensor, ResizeSensorCallback } from "./src/ResizeSensor"; \ No newline at end of file diff --git a/package.json b/package.json index 154a842..8c38109 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.1.1", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", + "typings": "css-element-queries.d.ts", "directories": { "test": "test" }, diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index b0a5fdf..634ced0 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -1,6 +1,6 @@ export declare type ResizeSensorCallback = (size: { width: number; height: number; }) => void; -declare class ResizeSensor { +export declare class ResizeSensor { constructor(element: Element | Element[], callback: ResizeSensorCallback); detach(callback?: ResizeSensorCallback): void; reset(): void; From 0cadf8d661208028768ec25be239e1c78cfba9ea Mon Sep 17 00:00:00 2001 From: resurtm Date: Thu, 9 May 2019 11:14:37 +0200 Subject: [PATCH 20/35] Fix Firefox extension content script #257 (#258) --- src/ResizeSensor.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 555a906..03fb2e9 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -19,14 +19,21 @@ if (typeof window === "undefined") { return null; } + // https://github.com/Semantic-Org/Semantic-UI/issues/3855 + // https://github.com/marcj/css-element-queries/issues/257 + var globalWindow = typeof window != 'undefined' && window.Math == Math + ? window + : typeof self != 'undefined' && self.Math == Math + ? self + : Function('return this')(); // Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor. // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and // would generate too many unnecessary events. - var requestAnimationFrame = window.requestAnimationFrame || - window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || + var requestAnimationFrame = globalWindow.requestAnimationFrame || + globalWindow.mozRequestAnimationFrame || + globalWindow.webkitRequestAnimationFrame || function (fn) { - return window.setTimeout(fn, 20); + return globalWindow.setTimeout(fn, 20); }; /** From 389ca9900ca65a9104b2e965946b9f7f77c165bc Mon Sep 17 00:00:00 2001 From: jelhan Date: Thu, 9 May 2019 11:15:35 +0200 Subject: [PATCH 21/35] fix: do not require Content-Secruity-Policy style-src 'unsafe-inline' (#256) --- src/ResizeSensor.js | 68 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 03fb2e9..32451e3 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -81,6 +81,18 @@ } } + /** + * Apply CSS styles to element. + * + * @param {HTMLElement} element + * @param {Object} style + */ + function setStyle(element, style) { + Object.keys(style).forEach(function(key) { + element.style[key] = style[key]; + }); + } + /** * Class for dimension change detection. * @@ -138,18 +150,47 @@ element.resizeSensor = document.createElement('div'); element.resizeSensor.dir = 'ltr'; element.resizeSensor.className = 'resize-sensor'; - var style = 'pointer-events: none; position: absolute; left: 0px; top: 0px; right: 0; bottom: 0; ' + - 'overflow: hidden; z-index: -1; visibility: hidden; max-width: 100%;'; - var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;'; - - element.resizeSensor.style.cssText = style; - element.resizeSensor.innerHTML = - '
' + - '
' + - '
' + - '
' + - '
' + - '
'; + + var style = { + pointerEvents: 'none', + position: 'absolute', + left: '0px', + top: '0px', + right: '0px', + bottom: '0px', + overflow: 'hidden', + zIndex: '-1', + visibility: 'hidden', + maxWidth: '100%' + }; + var styleChild = { + position: 'absolute', + left: '0px', + top: '0px', + transition: '0s', + }; + + setStyle(element.resizeSensor, style); + + var expand = document.createElement('div'); + expand.className = 'resize-sensor-expand'; + setStyle(expand, style); + + var expandChild = document.createElement('div'); + setStyle(expandChild, styleChild); + expand.appendChild(expandChild); + + var shrink = document.createElement('div'); + shrink.className = 'resize-sensor-shrink'; + setStyle(shrink, style); + + var shrinkChild = document.createElement('div'); + setStyle(shrinkChild, styleChild); + setStyle(shrinkChild, { width: '200%', height: '200%' }); + shrink.appendChild(shrinkChild); + + element.resizeSensor.appendChild(expand); + element.resizeSensor.appendChild(shrink); element.appendChild(element.resizeSensor); var computedStyle = window.getComputedStyle(element); @@ -158,9 +199,6 @@ element.style.position = 'relative'; } - var expand = element.resizeSensor.childNodes[0]; - var expandChild = expand.childNodes[0]; - var shrink = element.resizeSensor.childNodes[1]; var dirty, rafId; var size = getElementSize(element); var lastWidth = size.width; From eab5e1b51904d2570f979c941fded6b86dd3e7b0 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Thu, 9 May 2019 11:43:55 +0200 Subject: [PATCH 22/35] Trigger initially the resize sensor, fixes #265 --- src/ElementQueries.js | 5 ++--- src/ResizeSensor.d.ts | 21 +++++++++++++++++++++ src/ResizeSensor.js | 4 ++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 23038d0..4fe4298 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -170,13 +170,12 @@ if (!element.elementQueriesSetupInformation) { element.elementQueriesSetupInformation = new SetupInformation(element, id); } + if (!element.elementQueriesSensor) { element.elementQueriesSensor = new ResizeSensor(element, function () { element.elementQueriesSetupInformation.call(); }); } - - element.elementQueriesSetupInformation.call(); } /** @@ -441,7 +440,7 @@ for (var i = 0, j = document.styleSheets.length; i < j; i++) { try { if (document.styleSheets[i].href && 0 === document.styleSheets[i].href.indexOf('file://')) { - console.log("CssElementQueries: unable to parse local css files, " + document.styleSheets[i].href); + console.warn("CssElementQueries: unable to parse local css files, " + document.styleSheets[i].href); } readRules(document.styleSheets[i].cssRules || document.styleSheets[i].rules || document.styleSheets[i].cssText); diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index 634ced0..ad6c412 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -1,11 +1,32 @@ export declare type ResizeSensorCallback = (size: { width: number; height: number; }) => void; export declare class ResizeSensor { + /** + * Creates a new resize sensor on given elements. The provided callback is called max 1 times per requestAnimationFrame and + * is called initially. + */ constructor(element: Element | Element[], callback: ResizeSensorCallback); + + /** + * Removes the resize sensor, and stops listening to resize events. + */ detach(callback?: ResizeSensorCallback): void; + + /** + * Resets the resize sensors, so for the next element resize is correctly detected. This is rare cases necessary + * when the resize sensor isn't initialised correctly or is in a broken state due to DOM modifications. + */ reset(): void; + /** + * Removes the resize sensor, and stops listening to resize events. + */ static detach(element: Element | Element[], callback?: ResizeSensorCallback): void; + + /** + * Resets the resize sensors, so for the next element resize is correctly detected. This is rare cases necessary + * when the resize sensor isn't initialised correctly or is in a broken state due to DOM modifications. + */ static reset(element: Element | Element[]): void; } diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 32451e3..ed4ef54 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -201,8 +201,8 @@ var dirty, rafId; var size = getElementSize(element); - var lastWidth = size.width; - var lastHeight = size.height; + var lastWidth = 0; + var lastHeight = 0; var initialHiddenCheck = true; var lastAnimationFrame = 0; From c4f7808afb490d81b7210b0b756ef3bda99d4cc5 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Thu, 9 May 2019 11:45:33 +0200 Subject: [PATCH 23/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c38109..6aefde2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.1.1", + "version": "1.2.0", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "typings": "css-element-queries.d.ts", From 5d92e05e136137d11e0203c9d5ca06a99645f601 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Thu, 9 May 2019 11:47:18 +0200 Subject: [PATCH 24/35] added npmignore file --- .npmignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4f29079 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +.idea +tests From d1816ad53474b06e2d4c20fbaa5e3b00e46a0aaf Mon Sep 17 00:00:00 2001 From: ThibaudAV Date: Wed, 17 Jul 2019 18:33:53 +0200 Subject: [PATCH 25/35] feat(typings): export ElementQueries typings (#267) --- css-element-queries.d.ts | 3 ++- src/ElementQueries.d.ts | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/ElementQueries.d.ts diff --git a/css-element-queries.d.ts b/css-element-queries.d.ts index 0ca3bc3..97ee144 100644 --- a/css-element-queries.d.ts +++ b/css-element-queries.d.ts @@ -1 +1,2 @@ -export { ResizeSensor, ResizeSensorCallback } from "./src/ResizeSensor"; \ No newline at end of file +export { ResizeSensor, ResizeSensorCallback } from "./src/ResizeSensor"; +export { ElementQueries } from './src/ElementQueries'; \ No newline at end of file diff --git a/src/ElementQueries.d.ts b/src/ElementQueries.d.ts new file mode 100644 index 0000000..00c5d93 --- /dev/null +++ b/src/ElementQueries.d.ts @@ -0,0 +1,14 @@ +export declare class ElementQueries { + /** + * Attaches to DOMLoadContent + */ + static listen(): void; + + /** + * Parses all available CSS and attach ResizeSensor to those elements which have rules attached. + * Make sure this is called after 'load' event, because CSS files are not ready when domReady is fired. + */ + static init(): void; +} + +export default ElementQueries; From 7d0ffa0c8955f72be9650ce36ab4205d14ebeb29 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Wed, 17 Jul 2019 18:36:01 +0200 Subject: [PATCH 26/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6aefde2..36a73d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.2.0", + "version": "1.2.1", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "typings": "css-element-queries.d.ts", From 9fe2fbf47d1ab8b2f7ddc7765c46a8f23656af0b Mon Sep 17 00:00:00 2001 From: Julien Pradelle Date: Wed, 2 Oct 2019 17:43:36 +0200 Subject: [PATCH 27/35] Add support of sticky position on ResizeSensor (#277) --- src/ResizeSensor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index ed4ef54..163292e 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -195,7 +195,7 @@ var computedStyle = window.getComputedStyle(element); var position = computedStyle ? computedStyle.getPropertyValue('position') : null; - if ('absolute' !== position && 'relative' !== position && 'fixed' !== position) { + if ('absolute' !== position && 'relative' !== position && 'fixed' !== position && 'sticky' !== position) { element.style.position = 'relative'; } From 4b06648bae36250ea6843a13a56ed5621e55d168 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Mon, 7 Oct 2019 14:42:36 +0200 Subject: [PATCH 28/35] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7e45dcf --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: marcj From 1e406129f7112681d956eb36db0b0a3966e2ea7b Mon Sep 17 00:00:00 2001 From: Ruhao Gao Date: Fri, 22 Nov 2019 23:57:44 +0800 Subject: [PATCH 29/35] cancelAnimationFrame for reset when detach is called (#282) In ResizeSensor, we use requestAnimationFrame for reset. However, if an element is added to DOM and removed from DOM very quickly (even before the first reset happens), the reset itself will stuck in an infinite loop. It also causes memory leak because the reset function holds the element forever. --- src/ResizeSensor.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 163292e..2909cd0 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -102,6 +102,8 @@ * @constructor */ var ResizeSensor = function(element, callback) { + var lastAnimationFrame = 0; + /** * * @constructor @@ -204,7 +206,7 @@ var lastWidth = 0; var lastHeight = 0; var initialHiddenCheck = true; - var lastAnimationFrame = 0; + lastAnimationFrame = 0; var resetExpandShrink = function () { var width = element.offsetWidth; @@ -281,7 +283,7 @@ addEvent(shrink, 'scroll', onScroll); // Fix for custom Elements - requestAnimationFrame(reset); + lastAnimationFrame = requestAnimationFrame(reset); } forEachElement(element, function(elem){ @@ -289,6 +291,11 @@ }); this.detach = function(ev) { + // clean up the unfinished animation frame to prevent a potential endless requestAnimationFrame of reset + if (!lastAnimationFrame) { + window.cancelAnimationFrame(lastAnimationFrame); + lastAnimationFrame = 0; + } ResizeSensor.detach(element, ev); }; From 8f127c7c96cb8c21253cbe07cf2f1a826ac0b575 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 22 Nov 2019 17:13:16 +0100 Subject: [PATCH 30/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 36a73d7..62e68f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.2.1", + "version": "1.2.2", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "typings": "css-element-queries.d.ts", From 72adc49c52dc8bbc34de4e494952220fdae2af9e Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 3 Jan 2020 17:23:18 +0100 Subject: [PATCH 31/35] Fixed #282, #285 - fix issue with detecting invisible elements. --- src/ResizeSensor.js | 39 ++++++++++++++++++++++++++------------- tests/demo.html | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 2909cd0..12985d0 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -36,6 +36,13 @@ return globalWindow.setTimeout(fn, 20); }; + var cancelAnimationFrame = globalWindow.cancelAnimationFrame || + globalWindow.mozCancelAnimationFrame || + globalWindow.webkitCancelAnimationFrame || + function (timer) { + globalWindow.clearTimeout(timer); + }; + /** * Iterate over each of the provided element(s). * @@ -102,8 +109,9 @@ * @constructor */ var ResizeSensor = function(element, callback) { - var lastAnimationFrame = 0; - + //Is used when checking in reset() only for invisible elements + var lastAnimationFrameForInvisibleCheck = 0; + /** * * @constructor @@ -201,12 +209,15 @@ element.style.position = 'relative'; } - var dirty, rafId; + var dirty = false; + + //last request animation frame id used in onscroll event + var rafId = 0; var size = getElementSize(element); var lastWidth = 0; var lastHeight = 0; var initialHiddenCheck = true; - lastAnimationFrame = 0; + lastAnimationFrameForInvisibleCheck = 0; var resetExpandShrink = function () { var width = element.offsetWidth; @@ -228,10 +239,9 @@ var invisible = element.offsetWidth === 0 && element.offsetHeight === 0; if (invisible) { // Check in next frame - if (!lastAnimationFrame){ - lastAnimationFrame = requestAnimationFrame(function(){ - lastAnimationFrame = 0; - + if (!lastAnimationFrameForInvisibleCheck){ + lastAnimationFrameForInvisibleCheck = requestAnimationFrame(function(){ + lastAnimationFrameForInvisibleCheck = 0; reset(); }); } @@ -282,8 +292,11 @@ addEvent(expand, 'scroll', onScroll); addEvent(shrink, 'scroll', onScroll); - // Fix for custom Elements - lastAnimationFrame = requestAnimationFrame(reset); + // Fix for custom Elements and invisible elements + lastAnimationFrameForInvisibleCheck = requestAnimationFrame(function(){ + lastAnimationFrameForInvisibleCheck = 0; + reset(); + }); } forEachElement(element, function(elem){ @@ -292,9 +305,9 @@ this.detach = function(ev) { // clean up the unfinished animation frame to prevent a potential endless requestAnimationFrame of reset - if (!lastAnimationFrame) { - window.cancelAnimationFrame(lastAnimationFrame); - lastAnimationFrame = 0; + if (!lastAnimationFrameForInvisibleCheck) { + cancelAnimationFrame(lastAnimationFrameForInvisibleCheck); + lastAnimationFrameForInvisibleCheck = 0; } ResizeSensor.detach(element, ev); }; diff --git a/tests/demo.html b/tests/demo.html index d8a75c2..22968f0 100644 --- a/tests/demo.html +++ b/tests/demo.html @@ -97,6 +97,15 @@ .example-2[min-width~="400px"] .example-2-box { background-color: gray; } + + #example-invisible { + display: none; + } + + #example-invisible[min-width~="100px"]{ + color: red; + font-weight: bold; + } + + +

Performance Demo

@@ -393,4 +422,4 @@

Performance Demo

- \ No newline at end of file + From df88b1e9a738206cb0e624da424a19699d14638d Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 3 Jan 2020 17:25:48 +0100 Subject: [PATCH 32/35] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 62e68f0..964230f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-element-queries", - "version": "1.2.2", + "version": "1.2.3", "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", "typings": "css-element-queries.d.ts", From 97da8b71f90aa82d42ba61ebf2f05cf56f12cd24 Mon Sep 17 00:00:00 2001 From: Acinho <53146324+Acinho@users.noreply.github.com> Date: Tue, 14 Apr 2020 01:12:01 +0200 Subject: [PATCH 33/35] Fixed check for canceling last animation frame for invisible check (#289) Co-authored-by: Aleksandar Adamovic --- src/ResizeSensor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 12985d0..2bae953 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -305,7 +305,7 @@ this.detach = function(ev) { // clean up the unfinished animation frame to prevent a potential endless requestAnimationFrame of reset - if (!lastAnimationFrameForInvisibleCheck) { + if (lastAnimationFrameForInvisibleCheck) { cancelAnimationFrame(lastAnimationFrameForInvisibleCheck); lastAnimationFrameForInvisibleCheck = 0; } From ee21dfe74f096e8733183296ad34af89a18992ba Mon Sep 17 00:00:00 2001 From: Achara Date: Mon, 13 Apr 2020 19:14:10 -0400 Subject: [PATCH 34/35] fix invoking element.resizeSensor.resetSensor when it is undefined to cause js error (#291) Co-authored-by: akelley --- src/ResizeSensor.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ResizeSensor.js b/src/ResizeSensor.js index 2bae953..9a25503 100755 --- a/src/ResizeSensor.js +++ b/src/ResizeSensor.js @@ -313,13 +313,19 @@ }; this.reset = function() { - element.resizeSensor.resetSensor(); + //To prevent invoking element.resizeSensor.resetSensor if it's undefined + if (element.resizeSensor.resetSensor) { + element.resizeSensor.resetSensor(); + } }; }; ResizeSensor.reset = function(element) { forEachElement(element, function(elem){ - elem.resizeSensor.resetSensor(); + //To prevent invoking element.resizeSensor.resetSensor if it's undefined + if (element.resizeSensor.resetSensor) { + elem.resizeSensor.resetSensor(); + } }); }; From 4eae4654f4683923153d8dd8f5c0d1bc2067b2a8 Mon Sep 17 00:00:00 2001 From: Maksym Kobieliev Date: Fri, 3 Jul 2020 18:51:03 +0300 Subject: [PATCH 35/35] Add a Size interface to the typings (#293) Co-authored-by: Maksym Kobieliev --- css-element-queries.d.ts | 2 +- src/ResizeSensor.d.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/css-element-queries.d.ts b/css-element-queries.d.ts index 97ee144..3fe0706 100644 --- a/css-element-queries.d.ts +++ b/css-element-queries.d.ts @@ -1,2 +1,2 @@ -export { ResizeSensor, ResizeSensorCallback } from "./src/ResizeSensor"; +export { ResizeSensor, ResizeSensorCallback, Size } from "./src/ResizeSensor"; export { ElementQueries } from './src/ElementQueries'; \ No newline at end of file diff --git a/src/ResizeSensor.d.ts b/src/ResizeSensor.d.ts index ad6c412..3fba8c6 100644 --- a/src/ResizeSensor.d.ts +++ b/src/ResizeSensor.d.ts @@ -1,4 +1,9 @@ -export declare type ResizeSensorCallback = (size: { width: number; height: number; }) => void; +export declare interface Size { + width: number; + height: number; +} + +export declare type ResizeSensorCallback = (size: Size) => void; export declare class ResizeSensor { /**