mirror of
				https://github.com/Theodor-Springmann-Stiftung/musenalm.git
				synced 2025-11-03 19:55:31 +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()()
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  })
 | 
						|
})()
 |