@juggle/resize-observer
Advanced tools
Comparing version 0.4.3 to 0.5.0
import ResizeObservation from './ResizeObservation'; | ||
import ResizeObserverEntry from './ResizeObserverEntry'; | ||
import DOMInteractions from './DOMInteractions'; | ||
import ResizeError from './ResizeError'; | ||
const resizeObservers = []; | ||
const calculateDepthForNode = (node) => { | ||
let depth = 0; | ||
let parent = node.parentNode; | ||
while (parent) { | ||
depth += 1; | ||
parent = parent.parentNode; | ||
} | ||
return depth; | ||
}; | ||
const gatherActiveObservationsAtDepth = (depth) => { | ||
resizeObservers.forEach((ro) => { | ||
ro.activeTargets.splice(0, ro.activeTargets.length); | ||
ro.skippedTargets.splice(0, ro.skippedTargets.length); | ||
ro.observationTargets.forEach((ot) => { | ||
if (ot.isActive()) { | ||
if (calculateDepthForNode(ot.target) > depth) { | ||
ro.activeTargets.push(ot); | ||
} | ||
else { | ||
ro.skippedTargets.push(ot); | ||
} | ||
} | ||
}); | ||
}); | ||
}; | ||
const hasActiveObservations = () => { | ||
return resizeObservers.some((ro) => ro.activeTargets.length > 0); | ||
}; | ||
const hasSkippedObservations = () => { | ||
return resizeObservers.some((ro) => ro.skippedTargets.length > 0); | ||
}; | ||
const broadcastActiveObservations = () => { | ||
let shallowestDepth = Infinity; | ||
const callbacks = []; | ||
resizeObservers.forEach((ro) => { | ||
if (ro.activeTargets.length === 0) { | ||
return; | ||
} | ||
const entries = []; | ||
ro.activeTargets.forEach((ot) => { | ||
const entry = new ResizeObserverEntry(ot.target); | ||
const targetDepth = calculateDepthForNode(ot.target); | ||
entries.push(entry); | ||
ot.broadcastWidth = entry.contentRect.width; | ||
ot.broadcastHeight = entry.contentRect.height; | ||
if (targetDepth < shallowestDepth) { | ||
shallowestDepth = targetDepth; | ||
} | ||
}); | ||
callbacks.push(() => ro.callback(entries, ro.observer)); | ||
ro.activeTargets.splice(0, ro.activeTargets.length); | ||
}); | ||
callbacks.forEach(callback => callback()); | ||
return shallowestDepth; | ||
}; | ||
const deliverResizeLoopError = () => { | ||
const msg = 'ResizeObserver loop completed with undelivered notifications.'; | ||
window.dispatchEvent(ResizeError.Event(msg)); | ||
}; | ||
const process = () => { | ||
let depth = 0; | ||
gatherActiveObservationsAtDepth(depth); | ||
while (hasActiveObservations()) { | ||
depth = broadcastActiveObservations(); | ||
gatherActiveObservationsAtDepth(depth); | ||
} | ||
if (hasSkippedObservations()) { | ||
deliverResizeLoopError(); | ||
} | ||
return depth > 0; | ||
}; | ||
let frameId; | ||
let extraFrames = 0; | ||
const notify = () => { | ||
cancelAnimationFrame(frameId); | ||
frameId = requestAnimationFrame(() => { | ||
if (process()) { | ||
extraFrames = 0; | ||
notify(); | ||
} | ||
else if (extraFrames < 60) { | ||
extraFrames += 1; | ||
notify(); | ||
} | ||
}); | ||
}; | ||
const find = function (checkFn) { | ||
@@ -19,3 +107,2 @@ for (let i = 0; i < this.length; i += 1) { | ||
}; | ||
const resizeObservers = []; | ||
class ResizeObserverDetail { | ||
@@ -64,33 +151,2 @@ constructor(resizeObserver, callback) { | ||
} | ||
let frameId; | ||
let extraFrames = 0; | ||
const notify = () => { | ||
cancelAnimationFrame(frameId); | ||
frameId = requestAnimationFrame(() => { | ||
if (dispatch()) { | ||
extraFrames = 0; | ||
notify(); | ||
} | ||
else if (extraFrames < 60) { | ||
extraFrames += 1; | ||
notify(); | ||
} | ||
}); | ||
}; | ||
const dispatch = () => { | ||
let count = 0; | ||
resizeObservers.forEach((ro) => { | ||
const observationTargets = ro.observationTargets.filter(ot => ot.isActive()); | ||
if (observationTargets.length) { | ||
count += observationTargets.length; | ||
ro.callback(observationTargets.map(ot => { | ||
const entry = new ResizeObserverEntry(ot.target); | ||
ot.broadcastWidth = entry.contentRect.width; | ||
ot.broadcastHeight = entry.contentRect.height; | ||
return entry; | ||
}), ro.observer); | ||
} | ||
}); | ||
return count; | ||
}; | ||
DOMInteractions.watch(notify); |
{ | ||
"name": "@juggle/resize-observer", | ||
"version": "0.4.3", | ||
"version": "0.5.0", | ||
"description": "ResizeObserver - Based on the official draft specification", | ||
"main": "./lib/ResizeObserver.js", | ||
"files": [ | ||
"lib/*", | ||
"src/*" | ||
"lib/**/*.{js,ts}", | ||
"src/**/*.ts" | ||
], | ||
"scripts": { | ||
"build": "tsc", | ||
"build": "rm -rf lib && tsc", | ||
"ci-tests": "npm test -- --ci --runInBand && cat coverage/lcov.info | coveralls", | ||
@@ -13,0 +13,0 @@ "test": "jest --coverage", |
@@ -6,3 +6,103 @@ import ResizeObserver from './ResizeObserver'; | ||
import DOMInteractions from './DOMInteractions'; | ||
import ResizeError from './ResizeError'; | ||
const resizeObservers: ResizeObserverDetail[] = []; | ||
const calculateDepthForNode = (node: Element): number => { | ||
let depth = 0; | ||
let parent = node.parentNode; | ||
while (parent) { | ||
depth += 1; | ||
parent = parent.parentNode; | ||
} | ||
return depth; | ||
} | ||
const gatherActiveObservationsAtDepth = (depth: number): void => { | ||
resizeObservers.forEach((ro: ResizeObserverDetail) => { | ||
ro.activeTargets.splice(0, ro.activeTargets.length); | ||
ro.skippedTargets.splice(0, ro.skippedTargets.length); | ||
ro.observationTargets.forEach((ot: ResizeObservation) => { | ||
if (ot.isActive()) { | ||
if (calculateDepthForNode(ot.target) > depth) { | ||
ro.activeTargets.push(ot); | ||
} | ||
else { | ||
ro.skippedTargets.push(ot); | ||
} | ||
} | ||
}) | ||
}) | ||
} | ||
const hasActiveObservations = (): boolean => { | ||
return resizeObservers.some((ro: ResizeObserverDetail) => ro.activeTargets.length > 0); | ||
} | ||
const hasSkippedObservations = (): boolean => { | ||
return resizeObservers.some((ro: ResizeObserverDetail) => ro.skippedTargets.length > 0); | ||
} | ||
const broadcastActiveObservations = (): number => { | ||
let shallowestDepth: number = Infinity; | ||
const callbacks: (() => void)[] = []; | ||
resizeObservers.forEach((ro: ResizeObserverDetail) => { | ||
if (ro.activeTargets.length === 0) { | ||
return; | ||
} | ||
const entries: ResizeObserverEntry[] = []; | ||
ro.activeTargets.forEach((ot: ResizeObservation) => { | ||
const entry = new ResizeObserverEntry(ot.target); | ||
const targetDepth = calculateDepthForNode(ot.target); | ||
entries.push(entry); | ||
ot.broadcastWidth = entry.contentRect.width; | ||
ot.broadcastHeight = entry.contentRect.height; | ||
if (targetDepth < shallowestDepth) { | ||
shallowestDepth = targetDepth; | ||
} | ||
}) | ||
// Gather all entries before firing callbacks | ||
// otherwise entries may change in the same loop | ||
callbacks.push(() => ro.callback(entries, ro.observer)); | ||
ro.activeTargets.splice(0, ro.activeTargets.length); | ||
}) | ||
callbacks.forEach(callback => callback()); | ||
return shallowestDepth; | ||
} | ||
const deliverResizeLoopError = (): void => { | ||
const msg = 'ResizeObserver loop completed with undelivered notifications.'; | ||
window.dispatchEvent(ResizeError.Event(msg)); | ||
} | ||
const process = (): boolean => { | ||
let depth = 0; | ||
gatherActiveObservationsAtDepth(depth); | ||
while (hasActiveObservations()) { | ||
depth = broadcastActiveObservations(); | ||
gatherActiveObservationsAtDepth(depth); | ||
} | ||
if (hasSkippedObservations()) { | ||
deliverResizeLoopError(); | ||
} | ||
return depth > 0; | ||
} | ||
let frameId: number; | ||
let extraFrames: number = 0; | ||
const notify = () => { | ||
cancelAnimationFrame(frameId); | ||
frameId = requestAnimationFrame(() => { | ||
if (process()) { | ||
extraFrames = 0; | ||
notify(); | ||
} | ||
else if (extraFrames < 60) { | ||
extraFrames += 1; | ||
notify(); | ||
} | ||
}); | ||
} | ||
// Basic find function, to support IE | ||
const find = function (this: any[], checkFn: any) { | ||
@@ -16,2 +116,3 @@ for (let i = 0; i < this.length; i += 1) { | ||
// Basic findIndex function, to support IE | ||
const findIndex = function (this: any[], checkFn: any) { | ||
@@ -26,9 +127,7 @@ for (let i = 0; i < this.length; i += 1) { | ||
const resizeObservers: ResizeObserverDetail[] = []; | ||
class ResizeObserverDetail { | ||
public callback: ResizeObserverCallback; | ||
public observer: ResizeObserver; | ||
public activeTargets: [] = []; | ||
public skippedTargets: [] = []; | ||
public activeTargets: ResizeObservation[] = []; | ||
public skippedTargets: ResizeObservation[] = []; | ||
public observationTargets: ResizeObservation[] = []; | ||
@@ -77,35 +176,2 @@ | ||
let frameId: number; | ||
let extraFrames = 0; | ||
const notify = () => { | ||
cancelAnimationFrame(frameId); | ||
frameId = requestAnimationFrame(() => { | ||
if (dispatch()) { | ||
extraFrames = 0; | ||
notify(); | ||
} | ||
else if (extraFrames < 60) { | ||
extraFrames += 1; | ||
notify(); | ||
} | ||
}); | ||
} | ||
const dispatch = () => { | ||
let count = 0; | ||
resizeObservers.forEach((ro: ResizeObserverDetail) => { | ||
const observationTargets = ro.observationTargets.filter(ot => ot.isActive()); | ||
if (observationTargets.length) { | ||
count += observationTargets.length; | ||
ro.callback(observationTargets.map(ot => { | ||
const entry = new ResizeObserverEntry(ot.target); | ||
ot.broadcastWidth = entry.contentRect.width; | ||
ot.broadcastHeight = entry.contentRect.height; | ||
return entry; | ||
}), ro.observer); | ||
} | ||
}); | ||
return count; | ||
} | ||
DOMInteractions.watch(notify); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26
624
25199