Update web/templates/entry_add.html
This commit is contained in:
parent
908e8bd03e
commit
e2a2b7239d
@ -112,6 +112,10 @@
|
|||||||
@media (max-width: 860px) {
|
@media (max-width: 860px) {
|
||||||
.form-row.two, .form-row.three { grid-template-columns: 1fr; }
|
.form-row.two, .form-row.three { grid-template-columns: 1fr; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Subtle validation colors for Scripture field --- */
|
||||||
|
.scripture-valid { background-color: hsl(140 80% 92% / 0.8); transition: background-color .15s ease; }
|
||||||
|
.scripture-invalid { background-color: hsl(0 80% 94% / 0.8); transition: background-color .15s ease; }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -169,11 +173,105 @@
|
|||||||
dateAddedEl.value = `${yyyy}-${mm}-${dd}`;
|
dateAddedEl.value = `${yyyy}-${mm}-${dd}`;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// ----- Prefill Entry Code with current username -----
|
// ----- Prefill Entry Code with current username -----
|
||||||
const entryCodeEl = document.getElementById("id_entry_code");
|
const entryCodeEl = document.getElementById("id_entry_code");
|
||||||
if (entryCodeEl && !entryCodeEl.value) {
|
if (entryCodeEl && !entryCodeEl.value) {
|
||||||
entryCodeEl.value = "{{ request.user.username }}";
|
entryCodeEl.value = "{{ request.user.username }}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===========================
|
||||||
|
Live Scripture Validation
|
||||||
|
=========================== */
|
||||||
|
(function () {
|
||||||
|
const el = document.getElementById("id_scripture_raw");
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
// Exact WOL abbreviations (case-sensitive)
|
||||||
|
const WOL = new Set([
|
||||||
|
// OT
|
||||||
|
"Ge","Ex","Le","Nu","De","Jos","Jg","Ru","1Sa","2Sa","1Ki","2Ki","1Ch","2Ch","Ezr","Ne","Es","Job","Ps","Pr","Ec","Ca","Isa","Jer","La","Eze","Da","Ho","Joe","Am","Ob","Jon","Mic","Na","Hab","Zep","Hag","Zec","Mal",
|
||||||
|
// NT
|
||||||
|
"Mt","Mr","Lu","Joh","Ac","Ro","1Co","2Co","Ga","Eph","Php","Col","1Th","2Th","1Ti","2Ti","Tit","Phm","Heb","Jas","1Pe","2Pe","1Jo","2Jo","3Jo","Jude","Re"
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Normalize some gentle user quirks:
|
||||||
|
// - Allow trailing dot after the book token: "Ps." -> "Ps"
|
||||||
|
// - Allow a space after the number in numbered books: "1 Pe" -> "1Pe"
|
||||||
|
function normalizeBookToken(raw) {
|
||||||
|
let t = raw.trim();
|
||||||
|
// collapse internal multiple spaces
|
||||||
|
t = t.replace(/\s+/g, " ");
|
||||||
|
// remove trailing period on the book token
|
||||||
|
t = t.replace(/\.$/, "");
|
||||||
|
// join patterns like "1 Pe" or "2 Co" -> "1Pe" / "2Co"
|
||||||
|
t = t.replace(/^([1-3])\s+([A-Za-z]+)/, (_, n, b) => n + b);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate one reference like:
|
||||||
|
// "Ro 12" (chapter only)
|
||||||
|
// "Ro 12:1" (single verse)
|
||||||
|
// "Ro 12:1, 3, 5-7" (lists and ranges)
|
||||||
|
// "Joh 3:16-4:2" (cross-chapter range)
|
||||||
|
// "Ps. 23" (trailing dot on book handled by normalization)
|
||||||
|
function isValidSingleRef(ref) {
|
||||||
|
const s = ref.trim();
|
||||||
|
if (!s) return false;
|
||||||
|
|
||||||
|
// Split book token from the rest (book is everything before first space)
|
||||||
|
const firstSpace = s.indexOf(" ");
|
||||||
|
if (firstSpace < 0) return false;
|
||||||
|
|
||||||
|
const rawBook = s.slice(0, firstSpace);
|
||||||
|
const book = normalizeBookToken(rawBook);
|
||||||
|
|
||||||
|
if (!WOL.has(book)) return false;
|
||||||
|
|
||||||
|
const rest = s.slice(firstSpace + 1).trim();
|
||||||
|
if (!rest) return false;
|
||||||
|
|
||||||
|
// Accept "chapter" only (e.g., "Ps 23")
|
||||||
|
if (/^\d{1,3}$/.test(rest)) return true;
|
||||||
|
|
||||||
|
// Accept "chapter:verses" where verses can be:
|
||||||
|
// - n
|
||||||
|
// - n-m
|
||||||
|
// - n, m, p-q
|
||||||
|
// and allow a cross-chapter range like 3:16-4:2
|
||||||
|
// Pattern:
|
||||||
|
// chap: ( part(, part)* )
|
||||||
|
// where part is either:
|
||||||
|
// v -> \d{1,3}
|
||||||
|
// v-v -> \d{1,3}\s*-\s*\d{1,3}
|
||||||
|
// v-ch:v2 -> \d{1,3}\s*-\s*\d{1,3}:\d{1,3}
|
||||||
|
const re = /^(\d{1,3}):\s*(\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?(?:\s*,\s*\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?)*)$/;
|
||||||
|
if (re.test(rest)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAll() {
|
||||||
|
const raw = el.value || "";
|
||||||
|
// split by ';' as multiple references
|
||||||
|
const parts = raw.split(";").map(t => t.trim()).filter(Boolean);
|
||||||
|
if (parts.length === 0) {
|
||||||
|
el.classList.remove("scripture-valid","scripture-invalid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const allValid = parts.every(isValidSingleRef);
|
||||||
|
el.classList.toggle("scripture-valid", allValid);
|
||||||
|
el.classList.toggle("scripture-invalid", !allValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wire events
|
||||||
|
el.addEventListener("input", validateAll);
|
||||||
|
el.addEventListener("change", validateAll);
|
||||||
|
// Run once on load (in case form is prefilled)
|
||||||
|
validateAll();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
Reference in New Issue
Block a user