1
0
Fork 0

Compare commits

...

2 commits

Author SHA1 Message Date
093efbe357
Indented and sorted data 2024-12-09 20:23:31 +01:00
6a41d56a82
Suffixes (for verb conjugations) 2024-12-09 20:23:18 +01:00
4 changed files with 10538 additions and 19 deletions

View file

@ -69,6 +69,11 @@
Meaning:
<input id="word_meaning" class="button"/>
</label>
<label class="spacing section">
Suffix:
<input id="word_suffix_meaning" class="button" />
<input id="word_suffix_length" type="number" class="button" value="0" min="0" max="99" />
</label>
<textarea id="word_notes" class="button spacing section" placeholder="Notes"></textarea>
</div>

File diff suppressed because one or more lines are too long

View file

@ -30,6 +30,8 @@ const wordSymbols = /** @type {SVGElement} */(/** @type {unknown} */(document.qu
const wordSymbolTemplate = /** @type {SVGSVGElement} */(wordSymbols.querySelector('svg'));
const wordMeaningInput = /** @type {HTMLInputElement} */(document.getElementById('word_meaning'));
const wordNotesTextarea = /** @type {HTMLTextAreaElement} */(document.getElementById('word_notes'));
const wordSuffixMeaningInput = /** @type {HTMLInputElement} */(document.getElementById('word_suffix_meaning'));
const wordSuffixLengthInput = /** @type {HTMLInputElement} */(document.getElementById('word_suffix_length'));
const symbolOuterTopLeftPath = /** @type {SVGPathElement} */(/** @type {unknown} */(document.getElementById('outer_top_left')));
const symbolOuterTopRightPath = /** @type {SVGPathElement} */(/** @type {unknown} */(document.getElementById('outer_top_right')));
@ -441,7 +443,7 @@ panBy(0, 0);
/** @typedef {string} GUID */
/** @typedef {{ x: number, y: number, w: number, h: number }} WordData */
/** @typedef {{ x: number, y: number, w: number, h: number, suf?: number }} WordData */
/** @typedef {{ x: number, y: number, w: number, h: number, v?: number }} SymbolData */
@ -489,10 +491,13 @@ const loadPageElements = (pageId) => {
const dictionary = data.dictionary ?? {};
if (dictionary) {
const wordSymbols = getWordSymbols(pageId, word);
const dictionaryId = getDictionaryId(wordSymbols);
const dictionaryWord = dictionary[dictionaryId];
const suffixLength = Math.max(0, word.suf ?? 0);
const wordId = getDictionaryId(wordSymbols.slice(0, wordSymbols.length - suffixLength));
const suffixId = getDictionaryId(wordSymbols.slice(-suffixLength), true);
const dictionaryWord = dictionary[wordId];
const dictionarySuffix = dictionary[suffixId];
/** @type {HTMLDivElement} */(el.querySelector('.word-meaning')).textContent = dictionaryWord?.tran ?? '';
/** @type {HTMLDivElement} */(el.querySelector('.word-meaning')).textContent = (dictionaryWord?.tran ?? '') + (dictionarySuffix?.tran ?? '');
}
currentPageElements[id] = el;
@ -543,9 +548,27 @@ const loadPageElements = (pageId) => {
}
};
const sortRecursive = (obj) => {
if (typeof obj == 'object') {
const sortedKeys = Object.keys(obj).sort();
const copy = { ...obj };
for (const k in obj)
delete obj[k];
for (const k of sortedKeys)
obj[k] = copy[k];
for (const k of sortedKeys)
sortRecursive();
}
};
const saveUpdatedData = () => {
sortRecursive(data);
localStorage.setItem('tunic_manual_translation.data', JSON.stringify(data));
console.debug("Updated data:", JSON.stringify(data));
console.debug("Updated data:", JSON.stringify(data, null, " "));
};
data = /** @type {Database | null}*/(JSON.parse(localStorage.getItem('tunic_manual_translation.data') || 'null')) ?? data;
@ -609,10 +632,11 @@ const hideProps = () => {
// Words
let lastSelectedWord = '';
/** @type {{ word: WordData, symbols: number[] } | null} */
let lastSelectedWord = null;
/**
* @param {number} pageId
* @param {string} pageId
* @param {SymbolData} word
*/
const getWordSymbols = (pageId, word) => {
@ -640,8 +664,8 @@ const getWordSymbols = (pageId, word) => {
};
/** @param {number[]} wordSymbols */
const getDictionaryId = (wordSymbols) => {
return wordSymbols.map(v => v.toString(36)).join('-');
const getDictionaryId = (wordSymbols, suffix = false) => {
return (suffix ? '-' : '') + wordSymbols.map(v => v.toString(36)).join('-');
};
/** @param {number} symbol */
@ -656,35 +680,56 @@ const getSymbolMaskForCss = (symbol) => {
};
/**
* @param {number} pageId
* @param {string} pageId
* @param {SymbolData} word
*/
const loadWord = (pageId, word) => {
const selectedWordSymbols = getWordSymbols(pageId, word);
lastSelectedWord = getDictionaryId(selectedWordSymbols);
lastSelectedWord = { word, symbols: getWordSymbols(pageId, word) };
refreshWord();
};
const refreshWord = () => {
if (!lastSelectedWord)
return;
const suffixLength = Math.max(0, lastSelectedWord.word.suf ?? 0);
const wordId = getDictionaryId(lastSelectedWord.symbols.slice(0, lastSelectedWord.symbols.length - suffixLength));
const suffixId = getDictionaryId(lastSelectedWord.symbols.slice(-suffixLength), true);
while (wordSymbols.firstChild)
wordSymbols.firstChild.remove();
for (const symbol of selectedWordSymbols) {
for (let i = 0; i < lastSelectedWord.symbols.length; i++) {
const symbol = lastSelectedWord.symbols[i];
const symbolMask = getSymbolMaskForCss(symbol);
const el = /** @type {SVGSVGElement} */(wordSymbolTemplate.cloneNode(true));
el.setAttribute('data-symbol', symbolMask);
el.classList.toggle('suffix', lastSelectedWord.symbols.length - i <= suffixLength);
wordSymbols.appendChild(el);
}
const dictionary = data.dictionary ??= {};
const currentWord = dictionary[lastSelectedWord] ??= {};
const currentWord = dictionary[wordId] ??= {};
const currentSuffix = dictionary[suffixId] ??= {};
wordMeaningInput.value = currentWord.tran ?? '';
wordNotesTextarea.value = currentWord.note ?? '';
wordSuffixMeaningInput.value = suffixLength == 0 ? "-" : (currentSuffix.tran ?? '');
wordSuffixMeaningInput.disabled = suffixLength == 0;
wordSuffixLengthInput.value = String(suffixLength);
};
wordSymbolTemplate.remove();
wordMeaningInput.addEventListener('keyup', ev => {
if (!lastSelectedWord)
return;
const suffixLength = lastSelectedWord.word.suf ?? 0;
const wordId = getDictionaryId(lastSelectedWord.symbols.slice(0, lastSelectedWord.symbols.length - suffixLength));
const dictionary = data.dictionary ??= {};
const currentWord = dictionary[lastSelectedWord] ??= {};
const currentWord = dictionary[wordId] ??= {};
if (currentWord.tran != wordMeaningInput.value) {
currentWord.tran = wordMeaningInput.value;
@ -692,9 +737,42 @@ wordMeaningInput.addEventListener('keyup', ev => {
}
});
wordNotesTextarea.addEventListener('keyup', ev => {
wordSuffixLengthInput.addEventListener('change', ev => {
if (!lastSelectedWord)
return;
const suffixLength = Number(wordSuffixLengthInput.value) || 0;
lastSelectedWord.word.suf = suffixLength;
saveUpdatedData();
refreshWord();
});
wordSuffixMeaningInput.addEventListener('keyup', ev => {
if (!lastSelectedWord)
return;
const suffixLength = lastSelectedWord.word.suf ?? 0;
const suffixId = getDictionaryId(lastSelectedWord.symbols.slice(-suffixLength), true);
const dictionary = data.dictionary ??= {};
const currentWord = dictionary[lastSelectedWord] ??= {};
const currentSuffix = dictionary[suffixId] ??= {};
if (currentSuffix.tran != wordSuffixMeaningInput.value) {
currentSuffix.tran = wordSuffixMeaningInput.value;
saveUpdatedData();
}
});
wordNotesTextarea.addEventListener('keyup', ev => {
if (!lastSelectedWord)
return;
const suffixLength = lastSelectedWord.word.suf ?? 0;
const wordId = getDictionaryId(lastSelectedWord.symbols.slice(0, lastSelectedWord.symbols.length - suffixLength));
const dictionary = data.dictionary ??= {};
const currentWord = dictionary[wordId] ??= {};
if (currentWord.note != wordNotesTextarea.value) {
currentWord.note = wordNotesTextarea.value;

View file

@ -96,6 +96,10 @@ html {
border: 0;
border-radius: .2em;
input[type=number]& {
padding-right: 0;
}
textarea& {
width: 100%;
height: 3rem;
@ -123,6 +127,12 @@ html {
width: 3em;
margin: 0 calc(-3em / 8);
--stroke-color: #fff;
&.suffix g {
--stroke-color: #08f;
}
.word_middle_line,
&[data-symbol*='a'] .word_outer_top_left,
&[data-symbol*='b'] .word_outer_top_right,
@ -136,7 +146,7 @@ html {
&[data-symbol*='j'] .word_inner_bottom_middle,
&[data-symbol*='k'] .word_inner_bottom_right,
&[data-symbol*='l'] .word_circle {
stroke: #fff;
stroke: var(--stroke-color);
}
}
}