Merge pull request #330 from benpate/pullrequest-preload-resources

Preload Resources

Awesome work @benpate !
This commit is contained in:
1cg 2021-02-05 11:13:40 -07:00 committed by GitHub
commit 4a6ce115b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 15 deletions

View File

@ -13,16 +13,26 @@ htmx.defineExtension("preload", {
// SOME HELPER FUNCTIONS WE'LL NEED ALONG THE WAY
// config gets the closest non-empty value from the preload="" attribute. (default = "mousedown")
var config = function(node) {
// attr gets the closest non-empty value from the attribute.
var attr = function(node, property) {
if (node == undefined) {return undefined;}
return node.getAttribute("preload") || node.getAttribute("data-preload") || config(node.parentElement) || "mousedown"
return node.getAttribute(property) || node.getAttribute("data-" + property) || attr(node.parentElement, property)
}
// load handles the actual HTTP fetch, and uses htmx.ajax in cases where we're
// preloading an htmx resource (this sends the same HTTP headers as a regular htmx request)
var load = function(node) {
// Called after a successful AJAX request, to mark the
// content as loaded (and prevent additional AJAX calls.)
var done = function(html) {
node.preloadState = "DONE"
if (attr(node, "preload-images") == "true") {
document.createElement("div").innerHTML = html // create and populate a node to load linked resources, too.
}
}
return function() {
// If this value has already been loaded, then do not try again.
@ -30,18 +40,15 @@ htmx.defineExtension("preload", {
return;
}
// This is used after a successful AJAX request, to mark the
// content as loaded (and prevent additional AJAX calls.)
var done = function() {
node.preloadState = "DONE"
}
// Special handling for HX-GET - use built-in htmx.ajax function
// so that headers match other htmx requests, then set
// node.preloadState = TRUE so that requests are not duplicated
// in the future
if (node.getAttribute("hx-get")) {
htmx.ajax("GET", node.getAttribute("hx-get"), {handler:done});
var hxGet = node.getAttribute("hx-get") || node.getAttribute("data-hx-get")
if (hxGet) {
htmx.ajax("GET", hxGet, {handler:function(elt, info) {
done(info.xhr.responseText);
}});
return;
}
@ -51,7 +58,7 @@ htmx.defineExtension("preload", {
if (node.getAttribute("href")) {
var r = new XMLHttpRequest();
r.open("GET", node.getAttribute("href"));
r.onload = done;
r.onload = function() {done(r.responseText);};
r.send();
return;
}
@ -73,7 +80,7 @@ htmx.defineExtension("preload", {
}
// Get event name from config.
var on = config(node)
var on = attr(node, "preload") || "mousedown"
// FALL THROUGH to here means we need to add an EventListener

View File

@ -1 +1,10 @@
111
<script src="script.js"></script>
<img src="/images/image.gif">
<img src="/images/image.png">
<img src="/images/image.jpg">
<style href="stylsheet-from-style.css"></style>
<link rel="stylesheet" href="stylesheet-from-link.css">
<script>
alert("javascript executed")
</script>

View File

@ -14,7 +14,7 @@
<body hx-ext="preload">
<div class="container" preload="preload:init">
<div class="container" preload="preload:init" preload-images="true">
<h4>Triggered by: preload:init</h4>
<a href="preload-fragment.html?init=xhr1">Trigger on load (xhr)</a><br>
<a href="preload-fragment.html?init=xhr2">Trigger on load (xhr)</a><br>

View File

@ -36,6 +36,17 @@ You can add the `preload` attribute to the top-level element that contains sever
<li><a href="/server/2">This will also be preloaded for the same reason.</a>
<li><a href="/server/3">This will be preloaded, too. Lorem ipsum.</a>
</ul>
</body>
```
### Preloading of Linked Images
After an HTML page (or page fragment) is preloaded, this extension can also preload linked image resources. It will not load or run linked Javascript or Cascading Stylesheet content, whether linked or embedded in the preloaded HTML. To preload images as well, use the following syntax.
```html
<div hx-ext="preload">
<a href="/my-next-page" preload="mouseover" preload-images="true">Next Page</a>
</div>
```
### Configuration