use maud::{PreEscaped, Render, html}; use crate::ui::{ UIWidget, htmx::{Event, HTMXAttributes, SwapStrategy}, prelude::Div, }; pub fn ClickToLoad(reference: &str, widget: T) -> PreEscaped { html! { button hx-get=(reference) hx-target="this" hx-swap="outerHTML" { (widget) }; } } pub fn LazyLoad(reference: &str, widget: T) -> PreEscaped { html! { div hx-get=(reference) hx-trigger="load" { div class="htmx-indicator" { (widget) } }; } } pub fn InfinityScroll(content: T, fetch_url: &str) -> PreEscaped { html! { (content) (Div() .hx_get(fetch_url) .hx_swap(SwapStrategy::outerHTML) .hx_trigger(Event::on_revealed())) } } // TODO : htmx elements /* Progress Bar This example shows how to implement a smoothly scrolling progress bar. We start with an initial state with a button that issues a POST to /start to begin the job:

Start Progress

This div is then replaced with a new div containing status and a progress bar that reloads itself every 600ms:

Running

This progress bar is updated every 600 milliseconds, with the “width” style attribute and aria-valuenow attributed set to current progress value. Because there is an id on the progress bar div, htmx will smoothly transition between requests by settling the style attribute into its new value. This, when coupled with CSS transitions, makes the visual transition continuous rather than jumpy. Finally, when the process is complete, a server returns HX-Trigger: done header, which triggers an update of the UI to “Complete” state with a restart button added to the UI (we are using the class-tools extension in this example to add fade-in effect on the button):

Complete

This example uses styling cribbed from the bootstrap progress bar: .progress { height: 20px; margin-bottom: 20px; overflow: hidden; background-color: #f5f5f5; border-radius: 4px; box-shadow: inset 0 1px 2px rgba(0,0,0,.1); } .progress-bar { float: left; width: 0%; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #337ab7; -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); -webkit-transition: width .6s ease; -o-transition: width .6s ease; transition: width .6s ease; } */ /* Cascading Selects In this example we show how to make the values in one select depend on the value selected in another select. To begin we start with a default value for the make select: Audi. We render the model select for this make. We then have the make select trigger a GET to /models to retrieve the models options and target the models select. Here is the code:
When a request is made to the /models end point, we return the models for that make: And they become available in the model select. */ /* Sortable In this example we show how to integrate the Sortable javascript library with htmx. To begin we initialize the .sortable class with the Sortable javascript library: htmx.onLoad(function(content) { var sortables = content.querySelectorAll(".sortable"); for (var i = 0; i < sortables.length; i++) { var sortable = sortables[i]; var sortableInstance = new Sortable(sortable, { animation: 150, ghostClass: 'blue-background-class', // Make the `.htmx-indicator` unsortable filter: ".htmx-indicator", onMove: function (evt) { return evt.related.className.indexOf('htmx-indicator') === -1; }, // Disable sorting on the `end` event onEnd: function (evt) { this.option("disabled", true); } }); // Re-enable sorting on the `htmx:afterSwap` event sortable.addEventListener("htmx:afterSwap", function() { sortableInstance.option("disabled", false); }); } }) Next, we create a form that has some sortable divs within it, and we trigger an ajax request on the end event, fired by Sortable.js:
Updating...
Item 1
Item 2
Item 3
Item 4
Item 5
Note that each div has a hidden input inside of it that specifies the item id for that row. When the list is reordered via the Sortable.js drag-and-drop, the end event will be fired. htmx will then post the item ids in the new order to /items, to be persisted by the server. That’s it! */