122 lines
No EOL
4.2 KiB
JavaScript
122 lines
No EOL
4.2 KiB
JavaScript
<script src="https://cdn.jsdelivr.net/npm/hanzi-writer@3.5/dist/hanzi-writer.min.js"></script>
|
|
<script>
|
|
const hanziApp = (() => {
|
|
|
|
// ---------------------------------------------------------
|
|
// CRÉE LE HTML D'UN WIDGET et retourne les IDs
|
|
// ---------------------------------------------------------
|
|
function newWidget(rootID) {
|
|
const root = document.getElementById(rootID);
|
|
const uid = rootID;
|
|
|
|
root.innerHTML = `
|
|
<div id="challenge_${uid}"></div>
|
|
<div id="canvas_${uid}"></div>
|
|
<button id="valid_${uid}">Vérifier</button>
|
|
<p id="feedback_${uid}"></p>
|
|
`;
|
|
|
|
return {
|
|
challengeID: `challenge_${uid}`,
|
|
canvasID: `canvas_${uid}`,
|
|
feedbackID: `feedback_${uid}`,
|
|
button_OK_ID: `valid_${uid}`
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// INITIALISE UN WIDGET
|
|
// ---------------------------------------------------------
|
|
function init(options = {}) {
|
|
let iNb = 0;
|
|
const datas = options.datas;
|
|
let writers = [], okArray = [];
|
|
|
|
function loadNext() {
|
|
displayChallenge(options.challengeID, datas[iNb]);
|
|
const res = initMultiCanvas(options.canvasID, datas[iNb].hanzi, options.view_settings);
|
|
writers = res.writers;
|
|
okArray = res.okArray;
|
|
startMultiQuiz(writers, okArray);
|
|
}
|
|
|
|
function handleClick() {
|
|
const allOK = checkAll(okArray, options.feedbackID);
|
|
if (!allOK) return;
|
|
iNb++;
|
|
if (iNb >= datas.length) {
|
|
document.getElementById(options.feedbackID).textContent = "Fini !";
|
|
document.getElementById(options.button_OK_ID).removeEventListener("click", handleClick);
|
|
return;
|
|
}
|
|
loadNext();
|
|
}
|
|
|
|
loadNext();
|
|
document.getElementById(options.button_OK_ID).addEventListener("click", handleClick);
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// AFFICHAGE DU CHALLENGE
|
|
// ---------------------------------------------------------
|
|
function displayChallenge(divID, item) {
|
|
document.getElementById(divID).textContent =
|
|
"Écrire : " + item.valeur + " / " + item.pinyin;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// CRÉATION MULTI-CANVAS
|
|
// ---------------------------------------------------------
|
|
function initMultiCanvas(containerID, hanzi, view_settings) {
|
|
const CHAR_SIZE = 150;
|
|
const chars = [...hanzi];
|
|
const container = document.getElementById(containerID);
|
|
container.innerHTML = "";
|
|
container.style.cssText = "display:flex;flex-direction:row;flex-wrap:nowrap;align-items:flex-start;gap:12px";
|
|
|
|
const okArray = new Array(chars.length).fill(false);
|
|
const writers = chars.map((char, index) => {
|
|
const div = document.createElement("div");
|
|
div.id = `${containerID}_${index}`;
|
|
container.appendChild(div);
|
|
const hw = HanziWriter.create(div.id, char, {
|
|
width: CHAR_SIZE, height: CHAR_SIZE,
|
|
showCharacter: view_settings?.showCharacter ?? true,
|
|
showOutline: view_settings?.showOutline ?? true,
|
|
showHintAfterMisses: 1, highlightOnComplete: false, padding: 5
|
|
});
|
|
div.style.cssText = `display:inline-block;width:${CHAR_SIZE}px;height:${CHAR_SIZE}px;flex-shrink:0`;
|
|
return hw;
|
|
});
|
|
return { writers, okArray };
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// LANCER UN QUIZ PAR CANVAS
|
|
// ---------------------------------------------------------
|
|
function startMultiQuiz(writers, okArray) {
|
|
writers.forEach((hw, idx) => {
|
|
hw.quiz({
|
|
onMistake: () => { okArray[idx] = false; },
|
|
onComplete: () => { okArray[idx] = true; }
|
|
});
|
|
});
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// CHECK GLOBAL
|
|
// ---------------------------------------------------------
|
|
function checkAll(okArray, feedbackId) {
|
|
const el = document.getElementById(feedbackId);
|
|
const allOK = okArray.every(Boolean);
|
|
el.textContent = allOK ? "✔️ Bravo !" : "❌ Incorrect, continuez !";
|
|
el.style.color = allOK ? "green" : "red";
|
|
return allOK;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// EXPORT
|
|
// ---------------------------------------------------------
|
|
return { newWidget, init };
|
|
})();
|
|
</script> |