Open Atmos4 opened 6 months ago
Hello! I couldn't see where it says it's supposed to behave exactly the same as htmx's loader. Is that a goal?
I couldn't see where it says it's supposed to behave exactly the same as htmx's loader
Not quite what I wrote. That's an oversimplification of my issue :) (Huge Gleam fan btw)
Wow! Thank you. It's weird being recognised on unrelated projects 😅
To bring a bit more details:
hx-indicator
. But maybe there is a simpler way to achieve this 🤔Thank you
I didn't realize that unload
has been deprecated. I'll look into it.
@Kalabasa you wrote: // The initial about:blank page also counts when unloading.
So the loader
class should be added before the new iframe's src
starts to load.
Maybe using onbeforeunload
will fire it even earlier?
@niutech the problem with onbeforeunload
is that it will only access the unloading url. So you can't access the hash and can't apply the loading state properly :/
Can't you get the hash inside onbeforeunload
using document.activeElement.href
?
That will only work with links. I don't think it will work with a form...
The solution I have is this:
<progress><iframe name="htmz" onload="htmz(this)"></iframe></progress>
everything inside progress
is hidden by default so no need for the hidden
tag anymore.
Then the extension would look like this:
function htmz(){
frame.contentWindow.addEventListener("beforeunload", () => {
setTimeout(() => {
frame.parentElement.style.opacity = 1;
});
});
frame.parentElement.style.opacity = 0;
// main htmz code
}
The obvious downside is that you can have only one loader per target iframe.
I have a solution that doesn't work for all scenarios, but I think that's the one I'm going to roll with for my own project:
click
event on the documenthref
attribute, try to split its value with '#'
to get the selector of the container that will be replaced with the HTML responseUsing the :empty
pseudo-class you can detect if the destination container is empty and choose to fill it with content to indicate status. This code is incomplete and makes a lot of assumptions (e.g. only covers links, not submit buttons within forms, assumes you will only have '#' in your href for htmz, etc.) but just so you have an idea:
document.addEventListener('click', (e) => {
const dest = e.target?.href?.split('#')[1]
if (dest) { document.querySelector(`#${dest}`).classList.add('htmz-load') }
})
And here is what it looks like with some CSS:
https://github.com/user-attachments/assets/dca33e9a-5087-46af-839e-83f15ff2f705
EDIT. Here is a completed version that handles both forms and links. I managed to get it down to 279 bytes minified.
Here's the readable version
document.addEventListener('click', (e) => {
if (e.target.target == 'htmz') {
document.querySelector('#' + e.target.href.split('#')[1]).classList.add('htmz-load')
}
})
document.addEventListener('submit', (e) => {
if (e.srcElement.target == 'htmz') {
document.querySelector('#' + e.srcElement.action.split('#')[1]).classList.add('htmz-load')
}
})
Here's the minified version
((a,q)=>{a("click",t=>"htmz"==t.target.target&&q("#"+t.target.href.split("#")[1]).classList.add("htmz-load"));a("submit",t=>"htmz"==t.srcElement.target&&q("#"+t.srcElement.action.split("#")[1]).classList.add("htmz-load"))})(document.addEventListener,s=>document.querySelector(s))
The loader extension is a bit too shallow: it will only show a loading spinner once the server has begun sending the first byte.
This means it is not a true loading indicator (like htmx's
hx-indicator
), which is fine but quite limiting in terms of functionality, especially when trying to mitigate the "laggy" feeling of hypermedia-driven applications.(the loader extension also uses
onload
, which is deprecated. It should rather useonbeforeload
).I have two proposed solutions:
What would you prefer? Depending on what you like best I can submit a PR!