Remove comments
This commit is contained in:
1 parent
872175153a
commit
057b4be7d7
18 files changed
+66
-1350
No files matched your search
@@ -1,52 +1,14 @@
|
||||
{# The shell every page is wrapped in. Rendered by sw.js, not by the build,
|
||||
so editing this file changes every page without regenerating any of them.
|
||||
|
||||
Context: title, content (safe HTML fragment), mark (bookmark or null),
|
||||
reference (the navbar picker's model, or null).
|
||||
|
||||
Bootstrap is the whole stylesheet. The fragments carry semantic USFM
|
||||
classes and no Bootstrap ones, so the body text is styled by Reboot; the
|
||||
chrome here is what uses the framework. #}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
{# No viewport-fit=cover, deliberately. It extends the page into the notch
|
||||
and the home indicator, which only makes sense paired with safe-area-inset
|
||||
padding in the stylesheet -- and without that padding on iOS the first line
|
||||
of scripture sits under the clock. Paired with the status bar style below:
|
||||
change one and the other has to change too. #}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}{{ title | safe }}{% endblock %}</title>
|
||||
{# Vendored rather than linked from a CDN: sw.js only caches same-origin
|
||||
responses, so a CDN stylesheet would leave the app unstyled offline. #}
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
{# app.css comes second so its variable overrides win. It styles the
|
||||
scripture; Bootstrap styles the chrome. #}
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
{# History entries are whole books, and htmx keeps its history cache in
|
||||
localStorage -- a couple of them would blow the quota. Turned off, so every
|
||||
back or forward is a cache miss, and refreshOnHistoryMiss decides what a
|
||||
miss does.
|
||||
|
||||
False on purpose. True makes htmx call location.reload(true) -- a forced
|
||||
reload, which is exactly the kind of navigation a browser takes past the
|
||||
service worker, so it reaches server.py and comes back as boot.html: the
|
||||
spinner flashes by and then reloads into the real page. False makes htmx
|
||||
fetch the page over XHR instead, which the worker answers itself, from its
|
||||
own cache when offline. No navigation, no boot page, nothing to flash.
|
||||
|
||||
That request carries HX-History-Restore-Request, and the worker answers it
|
||||
with a whole composed document; htmx lifts the element marked
|
||||
hx-history-elt out of the response and puts it back in the page. #}
|
||||
<meta name="htmx-config"
|
||||
content='{"historyCacheSize":0,"refreshOnHistoryMiss":false}'>
|
||||
{# The bundle carries Popper, which the navbar collapse and the modal do not
|
||||
need -- but a dropdown or tooltip added later would, and this is one file
|
||||
in the precache either way. Deferred scripts run in order, so `bootstrap`
|
||||
is defined by the time app.js runs. #}
|
||||
<script src="js/bootstrap.bundle.min.js" defer></script>
|
||||
{# htmx is not deferred: hx-boost has to be in place before the first click. #}
|
||||
<script src="js/htmx.min.js"></script>
|
||||
<script src="js/app.js" defer></script>
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
@@ -54,22 +16,9 @@
|
||||
<link rel="apple-touch-icon" href="icons/apple-touch-icon.png">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
{# black, not black-translucent. Translucent makes iOS draw the status bar
|
||||
over the web view and reserve no space for it, so the navbar starts at the
|
||||
very top of the screen with the clock and battery on top of it. black keeps
|
||||
the status bar opaque and the view below it, which is what this app wants:
|
||||
there is no full-bleed artwork here to show through. #}
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="Bible">
|
||||
</head>
|
||||
{# Boosted links swap only the fragment, so the navbar, the modal and the
|
||||
scripts above survive navigation and never reload.
|
||||
|
||||
No show: modifier, deliberately. htmx adds show:top itself for a boosted
|
||||
link, but skips it when the href carries a fragment identifier and scrolls
|
||||
to that anchor after the swap instead. Spelling show:top out here overrides
|
||||
that decision for every link, which leaves a cross-reference like ISA#v61_6
|
||||
sitting at the top of Isaiah. #}
|
||||
<body class="{% block body_class %}{% endblock %} bg-body-tertiary"
|
||||
hx-boost="true" hx-target="#content" hx-swap="innerHTML">
|
||||
|
||||
@@ -94,31 +43,8 @@
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{# col-xl-8 keeps a line of verse near a readable measure instead of running
|
||||
the full width of a desktop window. #}
|
||||
<main class="container-xl my-4">
|
||||
<div class="row justify-content-center">
|
||||
{# The swap target. hx-target on <body> names this id, so every boosted
|
||||
link lands here -- remove it and a click does nothing at all while a
|
||||
full navigation still works.
|
||||
|
||||
It is also where a verse click becomes a request. htmx's bootstrap-modal
|
||||
example puts hx-get on the element that opens the dialog; the element
|
||||
here is a verse number in a generated book, and there are 38,000 of
|
||||
them -- an attribute apiece would cost more than the whole shell, and a
|
||||
listener apiece more than the reading. So one handler sits on the
|
||||
container they all swap into, and names the verse it found. Delegated,
|
||||
so it survives every swap: this element is never replaced, only filled.
|
||||
|
||||
hx-vals cannot do this. htmx evaluates it as Function("return (...)")()
|
||||
with nothing passed in, so an expression there can read the document but
|
||||
not the click -- and which verse was clicked is the one thing that has
|
||||
to travel.
|
||||
|
||||
Enter and space go through the same door rather than a second one:
|
||||
compile_bible.py writes role=button and tabindex on every verse, and a
|
||||
button that answers the keyboard by being clicked is a button with one
|
||||
behaviour instead of two. #}
|
||||
<div id="content" class="col-12 col-xl-8" hx-history-elt
|
||||
hx-on:click="var verse = event.target.closest('.v[id]');
|
||||
if (verse) htmx.ajax('GET', 'api/verse?at=' + verse.id,
|
||||
@@ -131,37 +57,8 @@
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "version.njk" %}
|
||||
</main>
|
||||
|
||||
{# The verse dialog: empty in the page, filled per request. Bootstrap owns
|
||||
showing it, dismissing it, the backdrop and Escape; sw.js owns everything
|
||||
inside, and templates/verse.njk is what lands in the modal-content below.
|
||||
|
||||
Opened by the arrival of the content rather than by data-bs-toggle on
|
||||
whatever was clicked. The example puts that attribute on its trigger, which
|
||||
is not available here for the same reason hx-get is not -- see #content
|
||||
above -- and the swap is the honest signal anyway: there is nothing worth
|
||||
showing until it is here. A verse the corpus does not have is answered 204,
|
||||
which swaps nothing, which opens nothing.
|
||||
|
||||
after-swap and not after-settle: settling is the 20ms attribute pass and
|
||||
this dialog has nothing to settle. Only the modal-content swap can reach
|
||||
here -- the bookmark write targets the navbar slot, and the toast it sends
|
||||
back rides in out of band, which fires its own event and not this one.
|
||||
|
||||
verse-done is the dialog saying it has finished its job, and it arrives
|
||||
from both of the things in it: sw.js sends it as a trigger header on a
|
||||
bookmark write that committed, and the copy button dispatches it when the
|
||||
clipboard has actually taken the link. Neither sends it when the action
|
||||
failed -- the field in the dialog is the fallback for a copy that was
|
||||
refused, and there is nothing to take down the dialog for when there is
|
||||
nothing to celebrate.
|
||||
|
||||
Closed at once rather than after a pause. The pause was there to let the
|
||||
status line inside be read before the dialog took it away; the line is a
|
||||
toast now, outside and above all of this, so it outlives the dialog and
|
||||
there is nothing left to wait for. #}
|
||||
<div class="modal fade" id="verse-dialog" tabindex="-1"
|
||||
aria-labelledby="verse-dialog-ref" aria-hidden="true"
|
||||
hx-on::after-swap="bootstrap.Modal.getOrCreateInstance(this).show();"
|
||||
@@ -171,21 +68,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Where confirmations land. Empty in the page and filled a toast at a time:
|
||||
api/toast appends one when the copy button asks for it, and a bookmark
|
||||
write sends one out of band on its own answer. templates/toast.njk is what
|
||||
lands here, and each one shows and then removes itself, so this is empty
|
||||
again a few seconds later.
|
||||
|
||||
Fixed, and outside #content, for the same reason the dialog is: it has to
|
||||
survive the swap under it. It also has to survive the dialog -- a copy
|
||||
confirmed by a toast inside the modal would go when the modal did.
|
||||
|
||||
Bottom right, and last in the document, so it covers the text rather than
|
||||
moving it, and so nothing in the reading order comes after it. It sits
|
||||
above the modal without being asked to: Bootstrap gives .toast a z-index of
|
||||
1090 against the modal's 1055, and this container takes none of its own,
|
||||
which is what leaves that comparison to the toast. #}
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3" id="toasts"></div>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in new issue
Block a user