This commit is contained in:
mark committed 2026-09-09 09:08:19 -04:00
1 parent 37ac9c2757
commit ce73c76126
6 files changed
+158 -38

No files matched your search

+29 -10
View File
@@ -28,7 +28,6 @@
<label class="visually-hidden" for="verse-dialog-url">Link to {{ verse.ref }}</label>
<input class="verse-dialog-url form-control form-control-sm" id="verse-dialog-url"
type="text" readonly value="{{ verse.url }}">
{% include "status.njk" %}
</div>
<div class="modal-footer">
{# The form is the bookmark write and nothing else. ref and href are hidden
@@ -40,20 +39,40 @@
<input type="hidden" name="href" value="{{ verse.href }}">
{# Selected first, written second: the selection is what makes the field
useful when the write is refused, and it costs nothing when it is not.
The status line is only told once the clipboard has actually taken it,
which is why the promise is answered rather than assumed. #}
The toast is only raised once the clipboard has actually taken the link,
which is why the promise is answered rather than assumed.
Both outcomes are a toast, and neither is written here: api/toast is
asked for one by name, so the wording lives in the worker with the rest
of the app's words rather than in the middle of an attribute. It is the
same request the dialog itself arrives on -- htmx, the worker, a
fragment -- with the container in base.njk as the target.
Only a copy that happened ends the dialog. A refused one leaves it
standing, because the field above it, selected, is the whole of what is
left to copy with. #}
<button class="btn btn-outline-secondary" type="button"
hx-on:click="var field = document.getElementById('verse-dialog-url');
var line = document.getElementById('verse-dialog-status');
hx-on:click="var button = this;
var field = document.getElementById('verse-dialog-url');
var toast = function (say) {
htmx.ajax('GET', 'api/toast?say=' + say,
{ target: '#toasts', swap: 'beforeend' });
};
var copied = function () {
toast('copied');
button.dispatchEvent(
new CustomEvent('verse-done', { bubbles: true }));
};
var refused = function () { toast('copy-refused'); };
field.focus();
field.select();
if (navigator.clipboard) {
navigator.clipboard.writeText(field.value).then(
function () { line.textContent = 'Link copied.'; },
function () { line.textContent = 'Copy the link above.'; });
navigator.clipboard.writeText(field.value)
.then(copied, refused);
} else if (document.execCommand('copy')) {
copied();
} else {
line.textContent = document.execCommand('copy')
? 'Link copied.' : 'Copy the link above.';
refused();
}">Copy link</button>
<button class="btn btn-primary" type="submit">Set bookmark</button>
</form>