Update web/templates/entry_add.html
This commit is contained in:
parent
3c6995460b
commit
90fea77226
@ -181,103 +181,10 @@ if (entryCodeEl && !entryCodeEl.value) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- ===========================
|
<!-- Use shared Scripture Validator -->
|
||||||
Live Scripture Validation (WOL + full names; space allowed in numbered)
|
<script src="{% static 'js/scripture-validator.v1.js' %}"></script>
|
||||||
=========================== -->
|
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
ScriptureValidator.attach('#id_scripture_raw');
|
||||||
const el = document.getElementById("id_scripture_raw");
|
|
||||||
if (!el) return;
|
|
||||||
|
|
||||||
// WOL abbreviations (must match exactly; numbered allow optional space before letters)
|
|
||||||
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"
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Full canonical names → WOL abbreviation (accept full names case-insensitively)
|
|
||||||
const FULL = new Map([
|
|
||||||
// OT
|
|
||||||
["genesis","Ge"],["exodus","Ex"],["leviticus","Le"],["numbers","Nu"],["deuteronomy","De"],
|
|
||||||
["joshua","Jos"],["judges","Jg"],["ruth","Ru"],
|
|
||||||
["1 samuel","1Sa"],["2 samuel","2Sa"],["1 kings","1Ki"],["2 kings","2Ki"],
|
|
||||||
["1 chronicles","1Ch"],["2 chronicles","2Ch"],
|
|
||||||
["ezra","Ezr"],["nehemiah","Ne"],["esther","Es"],["job","Job"],["psalms","Ps"],["psalm","Ps"],
|
|
||||||
["proverbs","Pr"],["ecclesiastes","Ec"],["song of solomon","Ca"],["song of songs","Ca"],
|
|
||||||
["isaiah","Isa"],["jeremiah","Jer"],["lamentations","La"],["ezekiel","Eze"],["daniel","Da"],
|
|
||||||
["hosea","Ho"],["joel","Joe"],["amos","Am"],["obadiah","Ob"],["jonah","Jon"],["micah","Mic"],
|
|
||||||
["nahum","Na"],["habakkuk","Hab"],["zephaniah","Zep"],["haggai","Hag"],["zechariah","Zec"],["malachi","Mal"],
|
|
||||||
// NT
|
|
||||||
["matthew","Mt"],["mark","Mr"],["luke","Lu"],["john","Joh"],["acts","Ac"],["romans","Ro"],
|
|
||||||
["1 corinthians","1Co"],["2 corinthians","2Co"],["galatians","Ga"],["ephesians","Eph"],
|
|
||||||
["philippians","Php"],["colossians","Col"],
|
|
||||||
["1 thessalonians","1Th"],["2 thessalonians","2Th"],
|
|
||||||
["1 timothy","1Ti"],["2 timothy","2Ti"],
|
|
||||||
["titus","Tit"],["philemon","Phm"],["hebrews","Heb"],["james","Jas"],
|
|
||||||
["1 peter","1Pe"],["2 peter","2Pe"],
|
|
||||||
["1 john","1Jo"],["2 john","2Jo"],["3 john","3Jo"],
|
|
||||||
["jude","Jude"],["revelation","Re"]
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Split: (book) + (chapter[:verses…])
|
|
||||||
function splitBookAndRest(s) {
|
|
||||||
const m = s.match(/^(.+?)\s+(\d{1,3}(?:\s*:\s*.*)?)$/);
|
|
||||||
return m ? {book: m[1], rest: m[2]} : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept either exact WOL abbr (with optional space between leading number and letters),
|
|
||||||
// or the full canonical name (case-insensitive).
|
|
||||||
function lookupBookCode(bookRaw) {
|
|
||||||
let b = bookRaw.trim();
|
|
||||||
|
|
||||||
// 1) Full name check (case-insensitive, as typed, including numbered with a space)
|
|
||||||
const fullKey = b.toLowerCase().replace(/\s+/g, " ");
|
|
||||||
if (FULL.has(fullKey)) return FULL.get(fullKey);
|
|
||||||
|
|
||||||
// 2) Abbreviation check
|
|
||||||
// Allow optional space between leading number and letters: e.g., "1 Pe" → "1Pe"
|
|
||||||
const maybeAbbr = b.replace(/^([1-3])\s+([A-Za-z]+)/, (_, n, letters) => n + letters);
|
|
||||||
if (WOL.has(maybeAbbr)) return maybeAbbr;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verse pattern: chapter only | chapter:verses (lists/ranges) | cross-chapter range
|
|
||||||
const versesRe = /^(\d{1,3})$|^(\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}))?)*)$/;
|
|
||||||
|
|
||||||
function isValidSingleRef(ref) {
|
|
||||||
const s = ref.trim();
|
|
||||||
if (!s) return false;
|
|
||||||
const parts = splitBookAndRest(s);
|
|
||||||
if (!parts) return false;
|
|
||||||
|
|
||||||
const code = lookupBookCode(parts.book);
|
|
||||||
if (!code) return false;
|
|
||||||
|
|
||||||
const rest = (parts.rest || "").trim();
|
|
||||||
if (!rest) return false;
|
|
||||||
|
|
||||||
return versesRe.test(rest);
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateAll() {
|
|
||||||
const raw = el.value || "";
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
el.addEventListener("input", validateAll);
|
|
||||||
el.addEventListener("change", validateAll);
|
|
||||||
validateAll();
|
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
Reference in New Issue
Block a user