1

I do update a html fragment via htmx.

How to load a JS library which is needed for this new snippet?

How to execute a function after the snippet got loaded?

Example:

I want to show an joyful animation (confetti) after the html snippet got added to the page.

This means the browser needs to load this:

<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.4.0/dist/confetti.browser.min.js"></script>

After loading above lib a JS function needs to get executed.

How to do this with htmx?

guettli
  • 25,042
  • 81
  • 346
  • 663

3 Answers3

3

I found a solution. I guess it could get improved. Please leave a comment if you know a simpler way.

// lala.js 
// this file gets loaded in the page (before the hx-post call)

function loadScript(url, callback) {
    // https://stackoverflow.com/a/950146/633961
    // Adding the script tag to the head as suggested before
    var head = document.head;
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
};

document.body.addEventListener("confetti", function(evt){
    var target = document.getElementsByClassName('htmx-settling')[0];
    loadScript('https://cdn.jsdelivr.net/npm/canvas-confetti@1.4.0/dist/confetti.browser.min.js',
        function () {
            var myCanvas = document.createElement('canvas');
            var rect = target.getBoundingClientRect();
            myCanvas.setAttribute('style', 'position: absolute; top:' +
                rect.top + 'px; left:' + rect.left + 'px');
            target.appendChild(myCanvas);

            var myConfetti = confetti.create(myCanvas, {
                resize: true,
                useWorker: true
            });
            myConfetti({
                particleCount: 100,
                spread: 160
                // any other options from the global
                // confetti function
            })
        })
})

On the server side I return the response like this (Django):

def confetti_hx(request):
    ...  
    response = HttpResponse(html)
    response['HX-Trigger-After-Swap'] = 'confetti'
    return response
guettli
  • 25,042
  • 81
  • 346
  • 663
2

Right now there is no way to load a new library on a page built in to htmx (this is a necessary feature IMO, please log an issue for it) so the confetti library should be included initially as part of your main site.

After you have included the external library in the main website, you can include a normal script tag that executes the confetti code necessary inline:

<script>
var myCanvas = document.createElement('canvas');
document.appendChild(myCanvas);

var myConfetti = confetti.create(myCanvas, {
  resize: true,
  useWorker: true
});
myConfetti({
  particleCount: 100,
  spread: 160
  // any other options from the global
  // confetti function
});
</script>
1cg
  • 1,392
  • 3
  • 8
1

What I've been doing is use some Hyperscript to do something like this:

<script
  src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.4.0/dist/confetti.browser.min.js"
  _="
    on load
      js
        <enter code here>
      end
    end
  "
></script>
Ironbeard
  • 467
  • 4
  • 8