AnkiNoteTemplate/templates/Japanese sentences/Recognition/front.html
2024-03-29 14:24:57 +03:00

207 lines
7.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
mpvacious cards, version 16.0
Wed Feb 7 08:30:09 PM UTC 2024
-->
<div class="wrap">
<header>
{{#Focus}}
<div class="tags">{{Focus}}</div>
{{/Focus}} {{#Tags}}
<div class="tags">{{Tags}}</div>
{{/Tags}}
</header>
<div class="sent-center" id="tsc" visible="true">
<!-- this tag is hidden on the front. -->
<div class="jpsentence" lang="ja">
{{edit:furigana:SentKanji}} {{^SentKanji}}
<nokana>{{edit:kanji:SentFurigana}}</nokana>
{{/SentKanji}}
</div>
</div>
<div class="sent-center" id="jp1k-tsc" visible="false">
<!-- JP1K mode is active only if note has been tagged as jp1k. -->
<div class="jpsentence" lang="ja">{{furigana:SentFurigana}}</div>
<button class="toggle_furigana_button" onclick="toggle_jp1k_furigana();">Toggle Readings</button>
</div>
{{#Image}}
<details class="images-on-front images-details">
<summary>Image</summary>
<div class="images">{{Image}}</div>
</details>
{{/Image}}
</div>
<!-- /wrap -->
<div style="display: none">
<div id="vocab_kanji_hidden">{{VocabKanji}}</div>
<div id="pitchnum_hidden">{{VocabPitchNum}}</div>
<div id="kanaword_hidden">{{kana:VocabFurigana}}</div>
</div>
<script>
/* Paints the question word according to its Pitch Accent number.
* blue for 平板
* red for 頭高
* orange for 中高
* green for 尾高
*/
function markPitch() {
let pitchNumber = document.getElementById("pitchnum_hidden");
if (pitchNumber === null) {
return;
}
pitchNumber = pitchNumber.innerHTML.match(/\d/);
if (pitchNumber === null) {
return;
}
pitchNumber = Number(pitchNumber);
/* Then decide what color to use and change font color accordingly. */
if (pitchNumber == 0) {
// use blue for 平板
paintTargetWord("#3366CC");
} else if (pitchNumber == 1) {
// use red for 頭高
paintTargetWord("red");
} else if (pitchNumber > 1) {
if (is_odaka(pitchNumber)) {
// use green for 尾高
paintTargetWord("green");
} else {
// use orange for 中高
paintTargetWord("#ff6207");
}
}
}
function paintTargetWord(color) {
for (const word of document.querySelectorAll(".jpsentence b, .jpsentence strong")) {
word.style.color = color;
}
}
function is_odaka(pitch_num) {
// word is odaka if number of moras is equal to pitch accent position
const moras = document
.getElementById("kanaword_hidden")
.innerText.replace(/[(].*[)]/, "") // remove (お), (する), <する>, <な>, etc
.replace(/[ャュョゃゅょ]/g, "") // small っ is one mora; ゃゅょ are parts of single mora
.trim();
// first determine if な is part of pronunciation or な-adjective (e.g. 女)
const vocab_kanji = document.getElementById("vocab_kanji_hidden").innerText.trim();
// な-adjectives don't change pitch
const n_moras = /な$/.test(vocab_kanji) ? moras.replace(/な$/, "").length : moras.length;
return n_moras == pitch_num;
}
/* Splits tags into separate divs */
function splitTagDiv() {
const header = document.querySelector("header");
if (!header) {
return;
}
const split = `{{Focus}} {{Tags}}`.split(" ");
const dont_show = ["imageonfront", "tolearn", "marked"];
header.innerHTML = "";
for (const tag of split) {
if (tag.length < 1 || dont_show.includes(tag)) continue;
const tag_elem = document.createElement("div");
tag_elem.className = "tags";
tag_elem.innerText = tag;
header.appendChild(tag_elem);
}
}
function formatNewRuby(kanji, readings) {
if (readings.length > 1) {
return `<ruby>${formatNewRuby(kanji, readings.slice(0, -1))}</ruby><rt>${readings.slice(-1)}</rt>`;
} else {
return `<rb>${kanji}</rb><rt>${readings.join("")}</rt>`;
}
}
function reformatMultiFurigana() {
const separators = /[\s;,.、・。]+/iu;
const max_inline = 2;
document.querySelectorAll("ruby:not(ruby ruby)").forEach((ruby) => {
try {
const kanji = (ruby.querySelector("rb") || ruby.firstChild).textContent.trim();
const readings = ruby
.querySelector("rt")
.textContent.split(separators)
.map((str) => str.trim())
.filter((str) => str.length);
if (readings.length > 1) {
ruby.innerHTML = formatNewRuby(kanji, readings.slice(0, max_inline));
}
if (readings.length > max_inline) {
const sequence = readings
.map((reading) => `<span class="tooltip-reading">${reading}</span>`)
.join("");
const wrapper = document.createElement("span");
wrapper.classList.add("tooltip");
wrapper.innerHTML += `<span class="tooltip-text">${sequence}</span>`;
ruby.replaceWith(wrapper);
wrapper.appendChild(ruby);
}
} catch (error) {
console.error(error);
}
});
}
function isMobile() {
return document.getElementsByTagName("html")[0].classList.contains("mobile");
}
/* If a card has the "imageonfront" tag set, show images on the front side. */
function setVisibleImageOnFront() {
if (`{{Tags}}`.split(" ").includes("imageonfront")) {
for (const frontImg of document.querySelectorAll(".images-on-front")) {
frontImg.setAttribute("visible", true);
}
}
}
/* Hide images on mobile devices. */
function toggleImageDetails() {
for (const detailsElement of document.querySelectorAll(".images-details")) {
detailsElement.toggleAttribute("open", !isMobile());
}
}
function toggle_jp1k_furigana() {
for (const element of document.querySelectorAll("#jp1k-tsc ruby rt")) {
element.style.visibility = !element.style.visibility ? "visible" : "";
}
}
function toggle_JP1K_mode() {
const tsc_el = document.querySelector("#tsc");
const jp1k_el = document.querySelector("#jp1k-tsc");
const is_jp1k_mode = `{{Tags}}`.toLowerCase().split(" ").includes("jp1k");
jp1k_el.setAttribute("visible", is_jp1k_mode);
tsc_el.setAttribute("visible", !is_jp1k_mode);
}
markPitch();
splitTagDiv();
reformatMultiFurigana();
setVisibleImageOnFront();
toggleImageDetails();
toggle_JP1K_mode();
document.addEventListener("keydown", (event) => {
/* Press "P" to reveal furigana for all words */
const P_KEY = 80;
if (event.keyCode === P_KEY) {
toggle_jp1k_furigana();
}
});
</script>