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