mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 09:05:30 +00:00
185 lines
5.4 KiB
JavaScript
185 lines
5.4 KiB
JavaScript
;(function() {
|
|
const loadingStatesUndoQueue = []
|
|
|
|
function loadingStateContainer(target) {
|
|
return htmx.closest(target, '[data-loading-states]') || document.body
|
|
}
|
|
|
|
function mayProcessUndoCallback(target, callback) {
|
|
if (document.body.contains(target)) {
|
|
callback()
|
|
}
|
|
}
|
|
|
|
function mayProcessLoadingStateByPath(elt, requestPath) {
|
|
const pathElt = htmx.closest(elt, '[data-loading-path]')
|
|
if (!pathElt) {
|
|
return true
|
|
}
|
|
|
|
return pathElt.getAttribute('data-loading-path') === requestPath
|
|
}
|
|
|
|
function queueLoadingState(sourceElt, targetElt, doCallback, undoCallback) {
|
|
const delayElt = htmx.closest(sourceElt, '[data-loading-delay]')
|
|
if (delayElt) {
|
|
const delayInMilliseconds =
|
|
delayElt.getAttribute('data-loading-delay') || 200
|
|
const timeout = setTimeout(function() {
|
|
doCallback()
|
|
|
|
loadingStatesUndoQueue.push(function() {
|
|
mayProcessUndoCallback(targetElt, undoCallback)
|
|
})
|
|
}, delayInMilliseconds)
|
|
|
|
loadingStatesUndoQueue.push(function() {
|
|
mayProcessUndoCallback(targetElt, function() { clearTimeout(timeout) })
|
|
})
|
|
} else {
|
|
doCallback()
|
|
loadingStatesUndoQueue.push(function() {
|
|
mayProcessUndoCallback(targetElt, undoCallback)
|
|
})
|
|
}
|
|
}
|
|
|
|
function getLoadingStateElts(loadingScope, type, path) {
|
|
return Array.from(htmx.findAll(loadingScope, '[' + type + ']')).filter(
|
|
function(elt) { return mayProcessLoadingStateByPath(elt, path) }
|
|
)
|
|
}
|
|
|
|
function getLoadingTarget(elt) {
|
|
if (elt.getAttribute('data-loading-target')) {
|
|
return Array.from(
|
|
htmx.findAll(elt.getAttribute('data-loading-target'))
|
|
)
|
|
}
|
|
return [elt]
|
|
}
|
|
|
|
htmx.defineExtension('loading-states', {
|
|
onEvent: function(name, evt) {
|
|
if (name === 'htmx:beforeRequest') {
|
|
const container = loadingStateContainer(evt.target)
|
|
|
|
const loadingStateTypes = [
|
|
'data-loading',
|
|
'data-loading-class',
|
|
'data-loading-class-remove',
|
|
'data-loading-disable',
|
|
'data-loading-aria-busy'
|
|
]
|
|
|
|
const loadingStateEltsByType = {}
|
|
|
|
loadingStateTypes.forEach(function(type) {
|
|
loadingStateEltsByType[type] = getLoadingStateElts(
|
|
container,
|
|
type,
|
|
evt.detail.pathInfo.requestPath
|
|
)
|
|
})
|
|
|
|
loadingStateEltsByType['data-loading'].forEach(function(sourceElt) {
|
|
getLoadingTarget(sourceElt).forEach(function(targetElt) {
|
|
queueLoadingState(
|
|
sourceElt,
|
|
targetElt,
|
|
function() {
|
|
targetElt.style.display =
|
|
sourceElt.getAttribute('data-loading') ||
|
|
'inline-block'
|
|
},
|
|
function() { targetElt.style.display = 'none' }
|
|
)
|
|
})
|
|
})
|
|
|
|
loadingStateEltsByType['data-loading-class'].forEach(
|
|
function(sourceElt) {
|
|
const classNames = sourceElt
|
|
.getAttribute('data-loading-class')
|
|
.split(' ')
|
|
|
|
getLoadingTarget(sourceElt).forEach(function(targetElt) {
|
|
queueLoadingState(
|
|
sourceElt,
|
|
targetElt,
|
|
function() {
|
|
classNames.forEach(function(className) {
|
|
targetElt.classList.add(className)
|
|
})
|
|
},
|
|
function() {
|
|
classNames.forEach(function(className) {
|
|
targetElt.classList.remove(className)
|
|
})
|
|
}
|
|
)
|
|
})
|
|
}
|
|
)
|
|
|
|
loadingStateEltsByType['data-loading-class-remove'].forEach(
|
|
function(sourceElt) {
|
|
const classNames = sourceElt
|
|
.getAttribute('data-loading-class-remove')
|
|
.split(' ')
|
|
|
|
getLoadingTarget(sourceElt).forEach(function(targetElt) {
|
|
queueLoadingState(
|
|
sourceElt,
|
|
targetElt,
|
|
function() {
|
|
classNames.forEach(function(className) {
|
|
targetElt.classList.remove(className)
|
|
})
|
|
},
|
|
function() {
|
|
classNames.forEach(function(className) {
|
|
targetElt.classList.add(className)
|
|
})
|
|
}
|
|
)
|
|
})
|
|
}
|
|
)
|
|
|
|
loadingStateEltsByType['data-loading-disable'].forEach(
|
|
function(sourceElt) {
|
|
getLoadingTarget(sourceElt).forEach(function(targetElt) {
|
|
queueLoadingState(
|
|
sourceElt,
|
|
targetElt,
|
|
function() { targetElt.disabled = true },
|
|
function() { targetElt.disabled = false }
|
|
)
|
|
})
|
|
}
|
|
)
|
|
|
|
loadingStateEltsByType['data-loading-aria-busy'].forEach(
|
|
function(sourceElt) {
|
|
getLoadingTarget(sourceElt).forEach(function(targetElt) {
|
|
queueLoadingState(
|
|
sourceElt,
|
|
targetElt,
|
|
function() { targetElt.setAttribute('aria-busy', 'true') },
|
|
function() { targetElt.removeAttribute('aria-busy') }
|
|
)
|
|
})
|
|
}
|
|
)
|
|
}
|
|
|
|
if (name === 'htmx:beforeOnLoad') {
|
|
while (loadingStatesUndoQueue.length > 0) {
|
|
loadingStatesUndoQueue.shift()()
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})()
|