SizeHelper

SizeHelper

This is a set of methods used to handle element size in DOM in an efficient manner.

getSize(domElement): object

Compute all the size/offset information from the given DOM element or return
a cached version if the window size did not changed since the last request.

isListening()

Return true only if the SizeHelper has started to listen on Window size change.

onSizeChange()

Register a callback to be aware when the size of the Window is changing with automatic debouncing.

startListening()

Start listening on Window size change.

stopListening()

Stop listening on Window size change.

triggerChange()

Trigger a fake window size change to invalidate cache and trigger any listener.

Source

index.js
import Observable from 'paraviewweb/src/Common/Misc/Observable';
import { debounce } from 'paraviewweb/src/Common/Misc/Debounce';

/* eslint-disable no-use-before-define */

const observableInstance = new Observable();
const TOPIC = 'window.size.change';
const domSizes = new WeakMap();
const sizeProperties = [
'scrollWidth',
'scrollHeight',
'clientWidth',
'clientHeight',
];
const windowListener = debounce(invalidateSize, 250);

let timestamp = 0;
let listenerAttached = false;

// ------ internal functions ------

function updateSize(domElement, cacheObj) {
if (cacheObj.timestamp < timestamp) {
sizeProperties.forEach((prop) => {
cacheObj[prop] = domElement[prop];
});
cacheObj.clientRect = domElement.getClientRects()[0];
}
}

// ------ New API ------

function getSize(domElement, clearCache = false) {
let cachedSize = domSizes.get(domElement);
if (!cachedSize || clearCache) {
cachedSize = { timestamp: -1 };
domSizes.set(domElement, cachedSize);
}
updateSize(domElement, cachedSize);

return cachedSize;
}

function onSizeChange(callback) {
return observableInstance.on(TOPIC, callback);
}

function triggerChange() {
observableInstance.emit(TOPIC);
}

function isListening() {
return listenerAttached;
}

function startListening() {
if (!listenerAttached) {
window.addEventListener('resize', windowListener);
listenerAttached = true;
}
}

function stopListening() {
if (listenerAttached) {
window.removeEventListener('resize', windowListener);
listenerAttached = false;
}
}

// ------ internal functions ------

function invalidateSize() {
timestamp += 1;
triggerChange();
}

// Export
export default {
getSize,
isListening,
onSizeChange,
startListening,
stopListening,
triggerChange,
};