109 lines
2.3 KiB
JavaScript
109 lines
2.3 KiB
JavaScript
(function(){
|
|
const defaultDebounceTimeInMs = 500;
|
|
|
|
let isReady = false
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
isReady = true
|
|
})
|
|
function onReady(fn) {
|
|
if (isReady || document.readyState === 'complete') {
|
|
fn()
|
|
} else {
|
|
document.addEventListener('DOMContentLoaded', fn)
|
|
}
|
|
}
|
|
|
|
htmx.defineExtension("resize", {
|
|
init: (api) => {
|
|
function hasResizeTrigger(elt) {
|
|
for (spec of api.getTriggerSpecs(elt)) {
|
|
if (spec.trigger === 'resize') {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function getDebounceTimeInMs(elt) {
|
|
const amountAttr = elt.attributes['hx-resize-debounce'];
|
|
if (!amountAttr) {
|
|
return defaultDebounceTimeInMs
|
|
}
|
|
const amountStr = amountAttr.value
|
|
if (!amountStr) {
|
|
return defaultDebounceTimeInMs
|
|
}
|
|
|
|
try {
|
|
return parseInt(amountStr);
|
|
} catch (err) {
|
|
console.warn('invalid debounce time on trigger:', trigger);
|
|
console.error(err);
|
|
return defaultDebounceTimeInMs;
|
|
}
|
|
}
|
|
|
|
let nextID = 1;
|
|
let timeoutIDs = {};
|
|
let observers = {};
|
|
function processNode(elt) {
|
|
if (!hasResizeTrigger(elt)) {
|
|
return;
|
|
}
|
|
|
|
let data = elt['hx-resize-internal-data'];
|
|
if (!data) {
|
|
data = {
|
|
id: nextID,
|
|
};
|
|
nextID += 1;
|
|
|
|
elt['hx-resize-internal-data'] = data;
|
|
}
|
|
|
|
const obs = new ResizeObserver(() => {
|
|
if (timeoutIDs[data.id]) {
|
|
return;
|
|
}
|
|
|
|
const debounceTime = getDebounceTimeInMs(elt);
|
|
timeoutIDs[data.id] = setTimeout(() => {
|
|
elt.dispatchEvent(new Event('resize'));
|
|
delete timeoutIDs[data.id];
|
|
}, debounceTime);
|
|
});
|
|
|
|
obs.observe(elt);
|
|
|
|
observers[data.id] = obs;
|
|
}
|
|
|
|
function cleanupNode(elt) {
|
|
if (!hasResizeTrigger(elt)) {
|
|
return;
|
|
}
|
|
|
|
let data = elt['hx-resize-internal-data'];
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
const obs = observers[data.id];
|
|
if (obs) {
|
|
obs.disconnect();
|
|
}
|
|
|
|
delete observers[data.id];
|
|
delete timeoutIDs[data.id];
|
|
}
|
|
|
|
// process nodes
|
|
htmx.on('htmx:beforeProcessNode', evt => processNode(evt.target));
|
|
htmx.on('htmx:beforeCleanupElement', evt => cleanupNode(evt.target));
|
|
onReady(function() {
|
|
document.querySelectorAll('[hx-trigger]').forEach(processNode);
|
|
})
|
|
}
|
|
});
|
|
})()
|