PageSourceSearch

https://codecommun.tibillet.coop/static/mvt_htmx/js/loading-states.js

js tibillet.coop collected 2026-10-03 21:30:04 UTC 5,116 bytes, 183 lines download raw bytes

vendor: 5,112 bytes, lines 1-183
1;(function () {
2	let loadingStatesUndoQueue = []
3
4	function loadingStateContainer(target) {
5		return htmx.closest(target, '[data-loading-states]') || document.body
6	}
7
8	function mayProcessUndoCallback(target, callback) {
9		if (document.body.contains(target)) {
10			callback()
11		}
12	}
13
14	function mayProcessLoadingStateByPath(elt, requestPath) {
15		const pathElt = htmx.closest(elt, '[data-loading-path]')
16		if (!pathElt) {
17			return true
18		}
19
20		return pathElt.getAttribute('data-loading-path') === requestPath
21	}
22
23	function queueLoadingState(sourceElt, targetElt, doCallback, undoCallback) {
24		const delayElt = htmx.closest(sourceElt, '[data-loading-delay]')
25		if (delayElt) {
26			const delayInMilliseconds =
27				delayElt.getAttribute('data-loading-delay') || 200
28			const timeout = setTimeout(function () {
29				doCallback()
30
31				loadingStatesUndoQueue.push(function () {
32					mayProcessUndoCallback(targetElt, undoCallback)
33				})
34			}, delayInMilliseconds)
35
36			loadingStatesUndoQueue.push(function () {
37				mayProcessUndoCallback(targetElt, function () { clearTimeout(timeout) })
38			})
39		} else {
40			doCallback()
41			loadingStatesUndoQueue.push(function () {
42				mayProcessUndoCallback(targetElt, undoCallback)
43			})
44		}
45	}
46
47	function getLoadingStateElts(loadingScope, type, path) {
48		return Array.from(htmx.findAll(loadingScope, "[" + type + "]")).filter(
49			function (elt) { return mayProcessLoadingStateByPath(elt, path) }
50		)
51	}
52
53	function getLoadingTarget(elt) {
54		if (elt.getAttribute('data-loading-target')) {
55			return Array.from(
56				htmx.findAll(elt.getAttribute('data-loading-target'))
57			)
58		}
59		return [elt]
60	}
61
62	htmx.defineExtension('loading-states', {
63		onEvent: function (name, evt) {
64			if (name === 'htmx:beforeRequest') {
65				const container = loadingStateContainer(evt.target)
66
67				const loadingStateTypes = [
68					'data-loading',
69					'data-loading-class',
70					'data-loading-class-remove',
71					'data-loading-disable',
72					'data-loading-aria-busy',
73				]
74
75				let loadingStateEltsByType = {}
76
77				loadingStateTypes.forEach(function (type) {
78					loadingStateEltsByType[type] = getLoadingStateElts(
79						container,
80						type,
81						evt.detail.pathInfo.requestPath
82					)
83				})
84
85				loadingStateEltsByType['data-loading'].forEach(function (sourceElt) {
86					getLoadingTarget(sourceElt).forEach(function (targetElt) {
87						queueLoadingState(
88							sourceElt,
89							targetElt,
90							function () {
91								targetElt.style.display =
92									sourceElt.getAttribute('data-loading') ||
93									'inline-block' },
94							function () { targetElt.style.display = 'none' }
95						)
96					})
97				})
98
99				loadingStateEltsByType['data-loading-class'].forEach(
100					function (sourceElt) {
101						const classNames = sourceElt
102							.getAttribute('data-loading-class')
103							.split(' ')
104
105						getLoadingTarget(sourceElt).forEach(function (targetElt) {
106							queueLoadingState(
107								sourceElt,
108								targetElt,
109								function () {
110									classNames.forEach(function (className) {
111                                        targetElt.classList.add(className)
112                                    })
113                                },
114								function() {
115									classNames.forEach(function (className) {
116                                        targetElt.classList.remove(className)
117                                    })
118                                }
119							)
120						})
121					}
122				)
123
124				loadingStateEltsByType['data-loading-class-remove'].forEach(
125					function (sourceElt) {
126						const classNames = sourceElt
127							.getAttribute('data-loading-class-remove')
128							.split(' ')
129
130						getLoadingTarget(sourceElt).forEach(function (targetElt) {
131							queueLoadingState(
132								sourceElt,
133								targetElt,
134								function () {
135									classNames.forEach(function (className) {
136                                        targetElt.classList.remove(className)
137                                    })
138                                },
139								function() {
140									classNames.forEach(function (className) {
141                                        targetElt.classList.add(className)
142                                    })
143                                }
144							)
145						})
146					}
147				)
148
149				loadingStateEltsByType['data-loading-disable'].forEach(
150					function (sourceElt) {
151						getLoadingTarget(sourceElt).forEach(function (targetElt) {
152							queueLoadingState(
153								sourceElt,
154								targetElt,
155								function() { targetElt.disabled = true },
156                                function() { targetElt.disabled = false }
157							)
158						})
159					}
160				)
161
162				loadingStateEltsByType['data-loading-aria-busy'].forEach(
163					function (sourceElt) {
164						getLoadingTarget(sourceElt).forEach(function (targetElt) {
165							queueLoadingState(
166								sourceElt,
167								targetElt,
168								function () { targetElt.setAttribute("aria-busy", "true") },
169								function () { targetElt.removeAttribute("aria-busy") }
170							)
171						})
172					}
173				)
174			}
175
176			if (name === 'htmx:beforeOnLoad') {
177				while (loadingStatesUndoQueue.length > 0) {
178					loadingStatesUndoQueue.shift()()
179				}
180			}
181		},
182	})
183}
183)()

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.