Compare commits
No commits in common. "afe12787c9e731e62ab87cedf6bd63486155598e" and "cc941860c8d14e48be5891d8ead6370d2cc38554" have entirely different histories.
afe12787c9
...
cc941860c8
5 changed files with 3 additions and 110 deletions
|
|
@ -13,8 +13,6 @@ htmx = HTMX(app)
|
||||||
|
|
||||||
@app.template_filter()
|
@app.template_filter()
|
||||||
def format_datetime(value):
|
def format_datetime(value):
|
||||||
if not value:
|
|
||||||
return value
|
|
||||||
return datetime.fromtimestamp(value).isoformat()
|
return datetime.fromtimestamp(value).isoformat()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
flask
|
|
||||||
flask-htmx
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
const elementTimers = new Map;
|
|
||||||
|
|
||||||
function addTimer(element, timerId) {
|
|
||||||
const timers = elementTimers.get(element) || [];
|
|
||||||
timers.push(timerId)
|
|
||||||
elementTimers.set(element, timers);
|
|
||||||
}
|
|
||||||
function removeTimerElement(element) {
|
|
||||||
const timers = elementTimers.get(element) || [];
|
|
||||||
for (const timer of timers) {
|
|
||||||
clearInterval(timer);
|
|
||||||
}
|
|
||||||
elementTimers.delete(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
function handleEvent(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
handleTrigger(e.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {String} duration
|
|
||||||
*/
|
|
||||||
function parseDuration(duration) {
|
|
||||||
const parsed = duration.match(/(\d+(?:\.\d+)?(s|ms))/);
|
|
||||||
if (!parsed) throw new Error("Unknown duration");
|
|
||||||
const num = parseFloat(parsed[1]);
|
|
||||||
const type = parsed[2];
|
|
||||||
const length = { "s": 1000, "ms": 1 };
|
|
||||||
return num * length[type];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element|Document} element
|
|
||||||
*/
|
|
||||||
function registerHandlers(element) {
|
|
||||||
const elements = element.querySelectorAll("[hx-get],[hx-trigger],[hx-target]");
|
|
||||||
|
|
||||||
for (const element of elements) {
|
|
||||||
const trigger = element.getAttribute("hx-trigger");
|
|
||||||
if (trigger) {
|
|
||||||
const [key, duration, ...rest] = trigger.split(" ");
|
|
||||||
if (rest.length) throw new Error("Unknown trigger: " + rest);
|
|
||||||
const parsedDuration = parseDuration(duration);
|
|
||||||
if (key !== "every") throw new Error("Unknown trigger: " + key);
|
|
||||||
addTimer(element, setInterval(handleTrigger.bind(null, element), parsedDuration));
|
|
||||||
} else {
|
|
||||||
if ("onclick" in element) {
|
|
||||||
element.onclick = handleEvent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Element} element
|
|
||||||
*/
|
|
||||||
async function handleTrigger(element) {
|
|
||||||
const replaceUrl = element.getAttribute("hx-replace-url");
|
|
||||||
const get = element.getAttribute("hx-get");
|
|
||||||
const targetSelector = element.getAttribute("hx-target");
|
|
||||||
const targetElement = document.querySelector(targetSelector) || element;
|
|
||||||
|
|
||||||
if (replaceUrl && replaceUrl !== "false") {
|
|
||||||
const targetUrl = replaceUrl == "true" ? get : replaceUrl;
|
|
||||||
if (targetUrl) {
|
|
||||||
window.history.replaceState({}, "", targetUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get) {
|
|
||||||
const res = await fetch(get, {
|
|
||||||
headers: {
|
|
||||||
"HX-Request": "true",
|
|
||||||
"HX-Trigger": element.id,
|
|
||||||
"HX-Target": targetSelector,
|
|
||||||
"HX-Current-URL": document.location.href
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const data = await res.text();
|
|
||||||
|
|
||||||
if (!targetElement) {
|
|
||||||
console.error("Target element not found! Attempted:", targetSelector);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const elements = [targetElement, ...targetElement.querySelectorAll("*")];
|
|
||||||
for (const element of elements) {
|
|
||||||
removeTimerElement(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
targetElement.innerHTML = data;
|
|
||||||
|
|
||||||
registerHandlers(targetElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = () => registerHandlers(document);
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
>
|
>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js" integrity="sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js" integrity="sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz" crossorigin="anonymous"></script>
|
||||||
{#<script src="/static/htmlx-smol.js"></script>#}
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="bg-gradient"></div>
|
<div class="bg-gradient"></div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<div hx-get="/measurements?page={{page}}&htmx" hx-trigger="every 2s" hx-target="main"></div>
|
<div hx-get="/measurements?htmx" hx-trigger="every 2s" hx-target="main"></div>
|
||||||
|
|
||||||
<h1>Measurements</h1>
|
<h1>Measurements</h1>
|
||||||
<p>Page {{page}}</p>
|
<p>Page {{page}}</p>
|
||||||
|
|
@ -21,10 +21,10 @@
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{% if page > 1 %}
|
{% if page > 1 %}
|
||||||
<a href="/measurements?page={{page-1}}" hx-replace-url="/measurements?page={{page-1}}" hx-get="/measurements?page={{page-1}}&htmx" hx-target="main" class="btn btn-link">Previous page</a>
|
<a href="/measurements?page={{page-1}}" hx-get="/measurements?page={{page-1}}&htmx" hx-target="main" class="btn btn-link">Previous page</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if has_next_page %}
|
{% if has_next_page %}
|
||||||
<a href="/measurements?page={{page+1}}" hx-replace-url="/measurements?page={{page+1}}" hx-get="/measurements?page={{page+1}}&htmx" hx-target="main" class="btn btn-link">Next page</a>
|
<a href="/measurements?page={{page+1}}" hx-get="/measurements?page={{page+1}}&htmx" hx-target="main" class="btn btn-link">Next page</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a href="/" class="btn btn-link">View statistics</a>
|
<a href="/" class="btn btn-link">View statistics</a>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue