Compare commits
10 Commits
b8702a6716
...
a321ae1582
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | a321ae1582 | |
Robbie Antenesse | c644593994 | |
Robbie Antenesse | 335b3dbb3e | |
Robbie Antenesse | 3f17a19c50 | |
Robbie Antenesse | 048c964405 | |
Robbie Antenesse | 5d38aa4e17 | |
Robbie Antenesse | 15bba03e1d | |
Robbie Antenesse | ad3141ef6e | |
Robbie Antenesse | d682b0060e | |
Robbie Antenesse | ac8d88f082 |
69
index.html
69
index.html
|
@ -143,30 +143,37 @@
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<a class="close-button" onclick="this.parentElement.parentElement.style.display='none';">×︎</a>
|
<a class="close-button" onclick="this.parentElement.parentElement.style.display='none';">×︎</a>
|
||||||
<section>
|
<section>
|
||||||
<form>
|
<form class="split two">
|
||||||
<label>Use IPA Auto-Fill
|
<div>
|
||||||
<input id="settingsUseIPA" type="checkbox" checked><br />
|
<label>Use IPA Auto-Fill
|
||||||
<small>Check this to use character combinations to input International Phonetic Alphabet characters into
|
<input id="settingsUseIPA" type="checkbox" checked><br />
|
||||||
Pronunciation fields.</small>
|
<small>Check this to use character combinations to input International Phonetic Alphabet characters into
|
||||||
</label>
|
Pronunciation fields.</small>
|
||||||
|
</label>
|
||||||
<label>Theme
|
|
||||||
<select disabled>
|
<label>Use Hotkeys
|
||||||
<option selected value="default">Default</option>
|
<input id="settingsUseHotkeys" type="checkbox" checked><br />
|
||||||
<option value="dark">Dark</option>
|
<small>Check this to enable keyboard combinations to perform different helpful actions.</small>
|
||||||
<option value="light">Light</option>
|
</label>
|
||||||
<option value="blue">Blue</option>
|
|
||||||
<option value="green">Green</option>
|
<label>Theme
|
||||||
<option value="royal">Royal</option>
|
<select disabled>
|
||||||
</select>
|
<option selected value="default">Default</option>
|
||||||
</label>
|
<option value="dark">Dark</option>
|
||||||
|
<option value="light">Light</option>
|
||||||
|
<option value="blue">Blue</option>
|
||||||
|
<option value="green">Green</option>
|
||||||
|
<option value="royal">Royal</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="accountSettings"></div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<a class="button" id="settingsSave">Save</a>
|
<a class="button" id="settingsSave">Save</a>
|
||||||
<a class="button" id="settingsSaveAndClose">Save & Close</a>
|
<a class="button" id="settingsSaveAndClose">Save & Close</a>
|
||||||
<a class="red button" onclick="this.parentElement.parentElement.parentElement.style.display='none';">Close Without
|
<a class="red button" onclick="this.parentElement.parentElement.parentElement.style.display='none';">Close Without Saving</a>
|
||||||
Saving</a>
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -203,21 +210,24 @@
|
||||||
<div class="split three">
|
<div class="split three">
|
||||||
<div>
|
<div>
|
||||||
<label>Consonants<br>
|
<label>Consonants<br>
|
||||||
<input id="editConsonants" class="ipa-field"><br>
|
<small>(Space separated list)</small><br>
|
||||||
|
<input id="editConsonants" class="ipa-field" placeholder="p b m n t ..."><br>
|
||||||
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
||||||
<a class="label-button ipa-table-button">IPA Chart</a>
|
<a class="label-button ipa-table-button">IPA Chart</a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Vowels<br>
|
<label>Vowels<br>
|
||||||
<input id="editVowels" class="ipa-field"><br>
|
<small>(Space separated list)</small><br>
|
||||||
|
<input id="editVowels" class="ipa-field" placeholder="æ u e ɪ ..."><br>
|
||||||
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
||||||
<a class="label-button ipa-table-button">IPA Chart</a>
|
<a class="label-button ipa-table-button">IPA Chart</a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Polyphthongs / Blends<br>
|
<label>Polyphthongs / Blends<br>
|
||||||
<input id="editBlends" class="ipa-field"><br>
|
<small>(Space separated list)</small><br>
|
||||||
|
<input id="editBlends" class="ipa-field" placeholder="ai ou ue ..."><br>
|
||||||
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
<a class="label-help-button ipa-field-help-button">Field Help</a>
|
||||||
<a class="label-button ipa-table-button">IPA Chart</a>
|
<a class="label-button ipa-table-button">IPA Chart</a>
|
||||||
</label>
|
</label>
|
||||||
|
@ -282,21 +292,24 @@
|
||||||
<div class="split two">
|
<div class="split two">
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<a class="button">Import JSON</a><br>
|
<label class="button">Import JSON <input type="file" id="importDictionaryFile" accept="application/json, .dict"><br>
|
||||||
<small>Import a previously-exported <code>JSON</code> file.</small>
|
<small>Import a previously-exported <code>JSON</code> file.</small>
|
||||||
|
</label>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="button">Import Words</a><br>
|
<label class="button">Import Words <input type="file" id="importWordsCSV" accept="text/csv, .csv"><br>
|
||||||
<small>Import a CSV file of words. (Download an <a>example file with the correct formatting</a>.)</small>
|
<small>Import a CSV file of words.</small>
|
||||||
|
</label>
|
||||||
|
<a class="small button" download="Lexiconga_import-template.csv" href="data:text/csv;charset=utf-8,%22word%22,%22pronunciation%22,%22part of speech%22,%22definition%22,%22explanation%22%0A">Download an example file with the correct formatting</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<a class="button">Export JSON</a><br>
|
<a class="button" id="exportDictionaryButton">Export JSON</a><br>
|
||||||
<small>Export your work as a <code>JSON</code> file to re-import later.</small>
|
<small>Export your work as a <code>JSON</code> file to re-import later.</small>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a class="button">Export Words</a><br>
|
<a class="button" id="exportWordsButton">Export Words</a><br>
|
||||||
<small>Export a CSV file of your words.</small>
|
<small>Export a CSV file of your words.</small>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"marked": "^0.6.2",
|
"marked": "^0.6.2",
|
||||||
"normalize.css": "^8.0.1"
|
"normalize.css": "^8.0.1",
|
||||||
|
"papaparse": "^4.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,8 @@ export const DEFAULT_DICTIONARY = {
|
||||||
name: '',
|
name: '',
|
||||||
pronunciation: '',
|
pronunciation: '',
|
||||||
partOfSpeech: '',
|
partOfSpeech: '',
|
||||||
simpleDefinition: '',
|
definition: '',
|
||||||
longDefinition: '',
|
details: '',
|
||||||
wordId: 0
|
wordId: 0
|
||||||
}, */
|
}, */
|
||||||
],
|
],
|
||||||
|
@ -56,6 +56,7 @@ export const DEFAULT_DICTIONARY = {
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS = {
|
export const DEFAULT_SETTINGS = {
|
||||||
useIPAPronunciationField: true,
|
useIPAPronunciationField: true,
|
||||||
|
useHotkeys: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_PAGE_SIZE = 50;
|
export const DEFAULT_PAGE_SIZE = 50;
|
||||||
|
|
|
@ -4,6 +4,24 @@ export function cloneObject(object) {
|
||||||
return JSON.parse(JSON.stringify(object));
|
return JSON.parse(JSON.stringify(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function download(data, filename, type) {
|
||||||
|
var file = new Blob([data], { type });
|
||||||
|
if (window.navigator.msSaveOrOpenBlob) // IE10+
|
||||||
|
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||||
|
else { // Others
|
||||||
|
var a = document.createElement("a"),
|
||||||
|
url = URL.createObjectURL(file);
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
setTimeout(function () {
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getIndicesOf(searchStr, findIn, caseSensitive) {
|
export function getIndicesOf(searchStr, findIn, caseSensitive) {
|
||||||
// https://stackoverflow.com/a/3410557
|
// https://stackoverflow.com/a/3410557
|
||||||
const searchStrLen = searchStr.length;
|
const searchStrLen = searchStr.length;
|
||||||
|
@ -52,5 +70,5 @@ export function removeTags(html) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function slugify(string) {
|
export function slugify(string) {
|
||||||
return removeDiacritics(string).replace(/[!a-zA-Z0-9-_]/g, '-');
|
return removeDiacritics(string).replace(/[^a-zA-Z0-9-_]/g, '-');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { renderDictionaryDetails, renderPartsOfSpeech } from "./render";
|
import { renderDictionaryDetails, renderPartsOfSpeech, renderAll } from "./render";
|
||||||
import { removeTags, cloneObject, getTimestampInSeconds } from "../helpers";
|
import { removeTags, cloneObject, getTimestampInSeconds, download, slugify } from "../helpers";
|
||||||
import { LOCAL_STORAGE_KEY, DEFAULT_DICTIONARY, MIGRATE_VERSION } from "../constants";
|
import { LOCAL_STORAGE_KEY, DEFAULT_DICTIONARY, MIGRATE_VERSION } from "../constants";
|
||||||
import { addMessage } from "./utilities";
|
import { addMessage, getNextId } from "./utilities";
|
||||||
|
import { addWord } from "./wordManagement";
|
||||||
|
|
||||||
export function updateDictionary () {
|
export function updateDictionary () {
|
||||||
|
|
||||||
|
@ -19,9 +20,9 @@ export function openEditModal() {
|
||||||
document.getElementById('editDescription').value = description;
|
document.getElementById('editDescription').value = description;
|
||||||
document.getElementById('editPartsOfSpeech').value = partsOfSpeech.join(',');
|
document.getElementById('editPartsOfSpeech').value = partsOfSpeech.join(',');
|
||||||
|
|
||||||
document.getElementById('editConsonants').value = consonants.join(',');
|
document.getElementById('editConsonants').value = consonants.join(' ');
|
||||||
document.getElementById('editVowels').value = vowels.join(',');
|
document.getElementById('editVowels').value = vowels.join(' ');
|
||||||
document.getElementById('editBlends').value = blends.join(',');
|
document.getElementById('editBlends').value = blends.join(' ');
|
||||||
document.getElementById('editOnset').value = phonotactics.onset.join(',');
|
document.getElementById('editOnset').value = phonotactics.onset.join(',');
|
||||||
document.getElementById('editNucleus').value = phonotactics.nucleus.join(',');
|
document.getElementById('editNucleus').value = phonotactics.nucleus.join(',');
|
||||||
document.getElementById('editCoda').value = phonotactics.coda.join(',');
|
document.getElementById('editCoda').value = phonotactics.coda.join(',');
|
||||||
|
@ -46,9 +47,9 @@ export function saveEditModal() {
|
||||||
window.currentDictionary.description = removeTags(document.getElementById('editDescription').value.trim());
|
window.currentDictionary.description = removeTags(document.getElementById('editDescription').value.trim());
|
||||||
window.currentDictionary.partsOfSpeech = document.getElementById('editPartsOfSpeech').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.partsOfSpeech = document.getElementById('editPartsOfSpeech').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
||||||
|
|
||||||
window.currentDictionary.details.phonology.consonants = document.getElementById('editConsonants').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.consonants = document.getElementById('editConsonants').value.split(' ').map(val => val.trim()).filter(val => val !== '');
|
||||||
window.currentDictionary.details.phonology.vowels = document.getElementById('editVowels').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.vowels = document.getElementById('editVowels').value.split(' ').map(val => val.trim()).filter(val => val !== '');
|
||||||
window.currentDictionary.details.phonology.blends = document.getElementById('editBlends').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.blends = document.getElementById('editBlends').value.split(' ').map(val => val.trim()).filter(val => val !== '');
|
||||||
window.currentDictionary.details.phonology.phonotactics.onset = document.getElementById('editOnset').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.phonotactics.onset = document.getElementById('editOnset').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
||||||
window.currentDictionary.details.phonology.phonotactics.nucleus = document.getElementById('editNucleus').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.phonotactics.nucleus = document.getElementById('editNucleus').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
||||||
window.currentDictionary.details.phonology.phonotactics.coda = document.getElementById('editCoda').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
window.currentDictionary.details.phonology.phonotactics.coda = document.getElementById('editCoda').value.split(',').map(val => val.trim()).filter(val => val !== '');
|
||||||
|
@ -93,13 +94,128 @@ export function clearDictionary() {
|
||||||
window.currentDictionary = cloneObject(DEFAULT_DICTIONARY);
|
window.currentDictionary = cloneObject(DEFAULT_DICTIONARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function importDictionary() {
|
||||||
|
const importDictionaryField = document.getElementById('importDictionaryFile');
|
||||||
|
|
||||||
|
if (importDictionaryField.files.length === 1) {
|
||||||
|
if (confirm('Importing a dicitonary file will overwrite and replace your current dictionary!\nDo you want to continue?')) {
|
||||||
|
addMessage('Importing Dictionary...');
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.onload = function (fileLoadedEvent) {
|
||||||
|
const textFromFileLoaded = fileLoadedEvent.target.result;
|
||||||
|
const importedDictionary = JSON.parse(textFromFileLoaded);
|
||||||
|
if (importedDictionary && importedDictionary.hasOwnProperty('words')) {
|
||||||
|
window.currentDictionary = importedDictionary;
|
||||||
|
saveDictionary();
|
||||||
|
renderAll();
|
||||||
|
importDictionaryField.value = '';
|
||||||
|
document.getElementById('editModal').style.display = 'none';
|
||||||
|
addMessage('Dictionary Imported Successfully');
|
||||||
|
} else {
|
||||||
|
addMessage('Dictionary could not be imported', 10000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fileReader.readAsText(importDictionaryField.files[0], "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importWords() {
|
||||||
|
const importWordsField = document.getElementById('importWordsCSV');
|
||||||
|
|
||||||
|
if (importWordsField.files.length === 1) {
|
||||||
|
if (confirm('Importing a CSV file with words will add all of the words in the file to your dictionary regardless of duplication!\nDo you want to continue?')) {
|
||||||
|
addMessage('Importing words...');
|
||||||
|
import('papaparse').then(papa => {
|
||||||
|
let wordsImported = 0;
|
||||||
|
papa.parse(importWordsField.files[0], {
|
||||||
|
header: true,
|
||||||
|
encoding: "utf-8",
|
||||||
|
step: results => {
|
||||||
|
if (results.errors.length > 0) {
|
||||||
|
results.errors.forEach(err => {
|
||||||
|
addMessage('Error Importing Word: ' + err);
|
||||||
|
console.error('Error Importing Word: ', err)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const row = results.data[0];
|
||||||
|
addWord({
|
||||||
|
name: removeTags(row.word).trim(),
|
||||||
|
pronunciation: removeTags(row.pronunciation).trim(),
|
||||||
|
partOfSpeech: removeTags(row['part of speech']).trim(),
|
||||||
|
definition: removeTags(row.definition).trim(),
|
||||||
|
details: removeTags(row.explanation).trim(),
|
||||||
|
wordId: getNextId(),
|
||||||
|
}, false, false);
|
||||||
|
wordsImported++;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
saveDictionary();
|
||||||
|
renderAll();
|
||||||
|
importWordsField.value = '';
|
||||||
|
document.getElementById('editModal').style.display = 'none';
|
||||||
|
addMessage(`Done Importing ${wordsImported} Words`);
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
addMessage('Error Importing Words: ' + err);
|
||||||
|
console.error('Error Importing Words: ', err);
|
||||||
|
},
|
||||||
|
skipEmptyLines: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportDictionary() {
|
||||||
|
addMessage('Exporting JSON...');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const file = JSON.stringify(window.currentDictionary),
|
||||||
|
{ name, specification } = window.currentDictionary;
|
||||||
|
|
||||||
|
const fileName = slugify(name + '_' + specification) + '.json';
|
||||||
|
|
||||||
|
download(file, fileName, 'application/json;charset=utf-8');
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportWords() {
|
||||||
|
addMessage('Exporting Words...');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
import('papaparse').then(papa => {
|
||||||
|
const { name, specification } = window.currentDictionary;
|
||||||
|
|
||||||
|
const fileName = slugify(name + '_' + specification) + '_words.csv';
|
||||||
|
|
||||||
|
const words = window.currentDictionary.words.map(word => {
|
||||||
|
return {
|
||||||
|
word: word.name,
|
||||||
|
pronunciation: word.pronunciation,
|
||||||
|
'part of speech': word.partOfSpeech,
|
||||||
|
definition: word.definition,
|
||||||
|
explanation: word.details,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const csv = papa.unparse(words, { quotes: true });
|
||||||
|
download(csv, fileName, 'text/csv;charset=utf-8');
|
||||||
|
});
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
export function migrateDictionary() {
|
export function migrateDictionary() {
|
||||||
let migrated = false;
|
let migrated = false;
|
||||||
if (!window.currentDictionary.hasOwnProperty('version')) {
|
if (!window.currentDictionary.hasOwnProperty('version')) {
|
||||||
const fixStupidOldNonsense = string => string.replace(/"/g, '"').replace(/'/g, "'").replace(/\/g, '\\').replace(/<br>/g, '\n');
|
const fixStupidOldNonsense = string => string.replace(/"/g, '"').replace(/'/g, "'").replace(/\/g, '\\').replace(/<br>/g, '\n');
|
||||||
window.currentDictionary.description = fixStupidOldNonsense(window.currentDictionary.description);
|
window.currentDictionary.description = fixStupidOldNonsense(window.currentDictionary.description);
|
||||||
window.currentDictionary.words = window.currentDictionary.words.map(word => {
|
window.currentDictionary.words = window.currentDictionary.words.map(word => {
|
||||||
word.longDefinition = fixStupidOldNonsense(word.longDefinition);
|
word.definition = word.simpleDefinition;
|
||||||
|
delete word.simpleDefinition;
|
||||||
|
word.details = fixStupidOldNonsense(word.longDefinition);
|
||||||
|
delete word.longDefinition;
|
||||||
return word;
|
return word;
|
||||||
});
|
});
|
||||||
window.currentDictionary = Object.assign({}, DEFAULT_DICTIONARY, window.currentDictionary);
|
window.currentDictionary = Object.assign({}, DEFAULT_DICTIONARY, window.currentDictionary);
|
||||||
|
|
|
@ -8,6 +8,14 @@ export function showSection(sectionName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hideDetailsPanel() {
|
||||||
|
document.getElementById('detailsPanel').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIsDetailsPanelDisplayed() {
|
||||||
|
return document.getElementById('detailsPanel').style.display !== 'none';
|
||||||
|
}
|
||||||
|
|
||||||
function showDescription() {
|
function showDescription() {
|
||||||
const detailsPanel = document.getElementById('detailsPanel');
|
const detailsPanel = document.getElementById('detailsPanel');
|
||||||
detailsPanel.style.display = 'block';
|
detailsPanel.style.display = 'block';
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
import { confirmEditWord, submitWordForm } from "./wordManagement";
|
||||||
|
import { showSection, getIsDetailsPanelDisplayed, hideDetailsPanel } from "./displayToggles";
|
||||||
|
import { renderInfoModal, renderMaximizedTextbox } from "./render";
|
||||||
|
import { showSearchModal, clearSearchText } from "./search";
|
||||||
|
import { saveAndCloseSettingsModal, openSettingsModal, saveSettings } from "./settings";
|
||||||
|
import { saveAndCloseEditModal, openEditModal } from "./dictionaryManagement";
|
||||||
|
import { addMessage } from "./utilities";
|
||||||
|
|
||||||
|
export function enableHotKeys() {
|
||||||
|
document.addEventListener('keydown', hotKeyActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function disableHotKeys() {
|
||||||
|
document.removeEventListener('keydown', hotKeyActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hotKeyActions(event) {
|
||||||
|
if (typeof event.key === 'undefined' || typeof event.ctrlKey === 'undefined' || typeof event.altKey === 'undefined') {
|
||||||
|
addMessage('Hotkeys disabled');
|
||||||
|
console.warn('Browser does not have required event properties for hotkeys.');
|
||||||
|
window.settings.useHotkeys = false;
|
||||||
|
saveSettings();
|
||||||
|
disableHotKeys();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.key) {
|
||||||
|
case 'Escape': hideAllModals(); break;
|
||||||
|
case 'Return':
|
||||||
|
case 'Enter': {
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
if (document.getElementById('settingsModal').style.display !== 'none') {
|
||||||
|
saveAndCloseSettingsModal();
|
||||||
|
} else if (document.getElementById('editModal').style.display !== 'none') {
|
||||||
|
saveAndCloseEditModal();
|
||||||
|
} else {
|
||||||
|
submitWord();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
case 'd': if (event.ctrlKey) {event.preventDefault(); toggleDetailsDisplay();} break;
|
||||||
|
case 'e': if (event.ctrlKey) {event.preventDefault(); hideAllModals(); openEditModal();} break;
|
||||||
|
case 'h': if (event.ctrlKey) {event.preventDefault(); hideAllModals(); showHelpModal();} break;
|
||||||
|
case 'm': if (event.ctrlKey) {event.preventDefault(); maximizeTextarea();} break;
|
||||||
|
case 's': {
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
event.preventDefault();
|
||||||
|
hideAllModals();
|
||||||
|
if (event.shiftKey) { // This is a failsafe in case the 'S' case below doesn't work for certain browsers
|
||||||
|
openSettingsModal();
|
||||||
|
} else {
|
||||||
|
showSearchModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'S': if (event.ctrlKey) {event.preventDefault(); hideAllModals(); openSettingsModal();} break;
|
||||||
|
case 'x': if (event.ctrlKey) {event.preventDefault(); clearSearchText();} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideAllModals() {
|
||||||
|
const permanentModals = ['#searchModal', '#settingsModal', '#editModal'];
|
||||||
|
const hideModals = document.querySelectorAll(permanentModals.join(',')),
|
||||||
|
removeModals = document.querySelectorAll('.modal:not(' + permanentModals.join('):not(') + ')');
|
||||||
|
Array.from(hideModals).forEach(modal => modal.style.display = 'none');
|
||||||
|
Array.from(removeModals).forEach(modal => modal.parentElement.removeChild(modal));
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleDetailsDisplay() {
|
||||||
|
const activeTab = document.querySelector('#detailsSection nav li.active');
|
||||||
|
console.log(activeTab);
|
||||||
|
Array.from(document.querySelectorAll('#detailsSection nav li')).forEach(li => li.classList.remove('active'));
|
||||||
|
if (activeTab) {
|
||||||
|
switch(activeTab.innerText.trim().toLowerCase()) {
|
||||||
|
case 'description': {
|
||||||
|
document.querySelector('#detailsSection nav li:nth-child(2)').classList.add('active');
|
||||||
|
showSection('details');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'details': {
|
||||||
|
document.querySelector('#detailsSection nav li:nth-child(3)').classList.add('active');
|
||||||
|
showSection('stats');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'stats': {
|
||||||
|
hideDetailsPanel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
document.querySelector('#detailsSection nav li:nth-child(1)').classList.add('active');
|
||||||
|
showSection('description');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitWord() {
|
||||||
|
const focused = document.activeElement;
|
||||||
|
if (focused && focused.id) {
|
||||||
|
const isSubmittableField = focused.id.includes('wordName') || focused.id.includes('wordDefinition') || focused.id.includes('wordDetails');
|
||||||
|
if (isSubmittableField) {
|
||||||
|
if (focused.parentElement.parentElement.classList.contains('edit-form')) {
|
||||||
|
const wordId = parseInt(focused.parentElement.parentElement.id.replace('editForm_', ''));
|
||||||
|
confirmEditWord(wordId);
|
||||||
|
} else {
|
||||||
|
submitWordForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHelpModal() {
|
||||||
|
import('../markdown/help.md').then(html => {
|
||||||
|
renderInfoModal(html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function maximizeTextarea() {
|
||||||
|
const focused = document.activeElement;
|
||||||
|
if (focused) {
|
||||||
|
const maximizeButton = focused.parentElement.querySelector('.maximize-button');
|
||||||
|
console.log(maximizeButton);
|
||||||
|
console.log(maximizeButton.parentElement);
|
||||||
|
if (maximizeButton) {
|
||||||
|
renderMaximizedTextbox(maximizeButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -154,7 +154,7 @@ export function renderWords() {
|
||||||
|
|
||||||
// words.slice(pageStart, pageEnd).forEach(originalWord => {
|
// words.slice(pageStart, pageEnd).forEach(originalWord => {
|
||||||
words.forEach(originalWord => {
|
words.forEach(originalWord => {
|
||||||
let detailsMarkdown = removeTags(originalWord.longDefinition);
|
let detailsMarkdown = removeTags(originalWord.details);
|
||||||
const references = detailsMarkdown.match(/\{\{.+?\}\}/g);
|
const references = detailsMarkdown.match(/\{\{.+?\}\}/g);
|
||||||
if (references && Array.isArray(references)) {
|
if (references && Array.isArray(references)) {
|
||||||
new Set(references).forEach(reference => {
|
new Set(references).forEach(reference => {
|
||||||
|
@ -170,8 +170,8 @@ export function renderWords() {
|
||||||
name: removeTags(originalWord.name),
|
name: removeTags(originalWord.name),
|
||||||
pronunciation: removeTags(originalWord.pronunciation),
|
pronunciation: removeTags(originalWord.pronunciation),
|
||||||
partOfSpeech: removeTags(originalWord.partOfSpeech),
|
partOfSpeech: removeTags(originalWord.partOfSpeech),
|
||||||
simpleDefinition: removeTags(originalWord.simpleDefinition),
|
definition: removeTags(originalWord.definition),
|
||||||
longDefinition: detailsMarkdown,
|
details: detailsMarkdown,
|
||||||
wordId: originalWord.wordId,
|
wordId: originalWord.wordId,
|
||||||
});
|
});
|
||||||
wordsHTML += `<article class="entry" id="${word.wordId}">
|
wordsHTML += `<article class="entry" id="${word.wordId}">
|
||||||
|
@ -186,9 +186,9 @@ export function renderWords() {
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<dl>
|
<dl>
|
||||||
<dt class="definition">${word.simpleDefinition}</dt>
|
<dt class="definition">${word.definition}</dt>
|
||||||
<dd class="details">
|
<dd class="details">
|
||||||
${md(word.longDefinition)}
|
${md(word.details)}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</article>`;
|
</article>`;
|
||||||
|
@ -261,10 +261,10 @@ export function renderEditForm(wordId = false) {
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label>Definition<span class="red">*</span><br>
|
<label>Definition<span class="red">*</span><br>
|
||||||
<input id="wordDefinition_${wordId}" value="${word.simpleDefinition}" placeholder="Equivalent words">
|
<input id="wordDefinition_${wordId}" value="${word.definition}" placeholder="Equivalent words">
|
||||||
</label>
|
</label>
|
||||||
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
|
<label>Details<span class="red">*</span><a class="label-button maximize-button">Maximize</a><br>
|
||||||
<textarea id="wordDetails_${wordId}" placeholder="Markdown formatting allowed">${word.longDefinition}</textarea>
|
<textarea id="wordDetails_${wordId}" placeholder="Markdown formatting allowed">${word.details}</textarea>
|
||||||
</label>
|
</label>
|
||||||
<div id="wordErrorMessage_${wordId}"></div>
|
<div id="wordErrorMessage_${wordId}"></div>
|
||||||
<a class="button edit-save-changes" id="editWordButton_${wordId}">Save Changes</a>
|
<a class="button edit-save-changes" id="editWordButton_${wordId}">Save Changes</a>
|
||||||
|
@ -277,8 +277,8 @@ export function renderEditForm(wordId = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderIPATable(ipaTableButton) {
|
export function renderIPATable(ipaTableButton) {
|
||||||
ipaTableButton = typeof ipaTableButton.target === 'undefined' ? ipaTableButton : ipaTableButton.target;
|
ipaTableButton = typeof ipaTableButton.target === 'undefined' || ipaTableButton.target === '' ? ipaTableButton : ipaTableButton.target;
|
||||||
// const label = ipaTableButton.parentElement.innerText.replace(/(\*|Maximize)/g, '').trim();
|
const label = ipaTableButton.parentElement.innerText.replace(/(Field Help|IPA Chart)/g, '').trim();
|
||||||
const textBox = ipaTableButton.parentElement.querySelector('input');
|
const textBox = ipaTableButton.parentElement.querySelector('input');
|
||||||
import('./KeyboardFire/phondue/ipa-table.html').then(html => {
|
import('./KeyboardFire/phondue/ipa-table.html').then(html => {
|
||||||
const modalElement = document.createElement('section');
|
const modalElement = document.createElement('section');
|
||||||
|
@ -286,7 +286,7 @@ export function renderIPATable(ipaTableButton) {
|
||||||
modalElement.innerHTML = `<div class="modal-background"></div>
|
modalElement.innerHTML = `<div class="modal-background"></div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<a class="close-button">×︎</a>
|
<a class="close-button">×︎</a>
|
||||||
<header><label>Pronunciation <input value="${textBox.value}" class="ipa-field"></label></header>
|
<header><label>${label} <input value="${textBox.value}" class="ipa-field"></label></header>
|
||||||
<section>
|
<section>
|
||||||
${html}
|
${html}
|
||||||
</section>
|
</section>
|
||||||
|
@ -301,7 +301,8 @@ export function renderIPATable(ipaTableButton) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMaximizedTextbox(maximizeButton) {
|
export function renderMaximizedTextbox(maximizeButton) {
|
||||||
maximizeButton = typeof maximizeButton.target === 'undefined' ? maximizeButton : maximizeButton.target;
|
maximizeButton = typeof maximizeButton.target === 'undefined' || maximizeButton.target === '' ? maximizeButton : maximizeButton.target;
|
||||||
|
console.log(maximizeButton.parentElement);
|
||||||
const label = maximizeButton.parentElement.innerText.replace(/(\*|Maximize)/g, '').trim();
|
const label = maximizeButton.parentElement.innerText.replace(/(\*|Maximize)/g, '').trim();
|
||||||
const textBox = maximizeButton.parentElement.querySelector('textarea');
|
const textBox = maximizeButton.parentElement.querySelector('textarea');
|
||||||
const modalElement = document.createElement('section');
|
const modalElement = document.createElement('section');
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
import { cloneObject, getIndicesOf } from "../helpers";
|
import { cloneObject, getIndicesOf } from "../helpers";
|
||||||
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
||||||
|
import { renderWords } from "./render";
|
||||||
|
|
||||||
|
export function showSearchModal() {
|
||||||
|
document.getElementById('searchModal').style.display = 'block';
|
||||||
|
document.getElementById('searchBox').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearSearchText() {
|
||||||
|
document.getElementById('searchBox').value = '';
|
||||||
|
document.getElementById('openSearchModal').value = '';
|
||||||
|
renderWords();
|
||||||
|
}
|
||||||
|
|
||||||
export function getSearchTerm() {
|
export function getSearchTerm() {
|
||||||
return document.getElementById('searchBox').value;
|
return document.getElementById('searchBox').value;
|
||||||
|
@ -44,18 +56,18 @@ export function getMatchingSearchWords() {
|
||||||
searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase();
|
searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase();
|
||||||
let name = filters.ignoreDiacritics ? removeDiacritics(word.name) : word.name;
|
let name = filters.ignoreDiacritics ? removeDiacritics(word.name) : word.name;
|
||||||
name = filters.caseSensitive ? name : name.toLowerCase();
|
name = filters.caseSensitive ? name : name.toLowerCase();
|
||||||
let simpleDefinition = filters.ignoreDiacritics ? removeDiacritics(word.simpleDefinition) : word.simpleDefinition;
|
let definition = filters.ignoreDiacritics ? removeDiacritics(word.definition) : word.definition;
|
||||||
simpleDefinition = filters.caseSensitive ? simpleDefinition : simpleDefinition.toLowerCase();
|
definition = filters.caseSensitive ? definition : definition.toLowerCase();
|
||||||
let longDefinition = filters.ignoreDiacritics ? removeDiacritics(word.longDefinition) : word.longDefinition;
|
let details = filters.ignoreDiacritics ? removeDiacritics(word.details) : word.details;
|
||||||
longDefinition = filters.caseSensitive ? longDefinition : longDefinition.toLowerCase();
|
details = filters.caseSensitive ? details : details.toLowerCase();
|
||||||
|
|
||||||
const isInName = filters.name && (filters.exact
|
const isInName = filters.name && (filters.exact
|
||||||
? searchTerm == name
|
? searchTerm == name
|
||||||
: new RegExp(searchTerm, 'g').test(name));
|
: new RegExp(searchTerm, 'g').test(name));
|
||||||
const isInDefinition = filters.definition && (filters.exact
|
const isInDefinition = filters.definition && (filters.exact
|
||||||
? searchTerm == simpleDefinition
|
? searchTerm == definition
|
||||||
: new RegExp(searchTerm, 'g').test(simpleDefinition));
|
: new RegExp(searchTerm, 'g').test(definition));
|
||||||
const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(longDefinition);
|
const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(details);
|
||||||
return searchTerm === '' || isInName || isInDefinition || isInDetails;
|
return searchTerm === '' || isInName || isInDefinition || isInDetails;
|
||||||
});
|
});
|
||||||
return matchingWords;
|
return matchingWords;
|
||||||
|
@ -82,21 +94,21 @@ export function highlightSearchTerm(word) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (filters.definition) {
|
if (filters.definition) {
|
||||||
const simpleDefinitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.simpleDefinition), filters.caseSensitive);
|
const definitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.definition), filters.caseSensitive);
|
||||||
simpleDefinitionMatches.forEach((wordIndex, i) => {
|
definitionMatches.forEach((wordIndex, i) => {
|
||||||
wordIndex += '<mark></mark>'.length * i;
|
wordIndex += '<mark></mark>'.length * i;
|
||||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.substring(0, wordIndex)
|
markedUpWord.definition = markedUpWord.definition.substring(0, wordIndex)
|
||||||
+ '<mark>' + markedUpWord.simpleDefinition.substr(wordIndex, searchTermLength) + '</mark>'
|
+ '<mark>' + markedUpWord.definition.substr(wordIndex, searchTermLength) + '</mark>'
|
||||||
+ markedUpWord.simpleDefinition.substr(wordIndex + searchTermLength);
|
+ markedUpWord.definition.substr(wordIndex + searchTermLength);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (filters.details) {
|
if (filters.details) {
|
||||||
const longDefinitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.longDefinition), filters.caseSensitive);
|
const detailsMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.details), filters.caseSensitive);
|
||||||
longDefinitionMatches.forEach((wordIndex, i) => {
|
detailsMatches.forEach((wordIndex, i) => {
|
||||||
wordIndex += '<mark></mark>'.length * i;
|
wordIndex += '<mark></mark>'.length * i;
|
||||||
markedUpWord.longDefinition = markedUpWord.longDefinition.substring(0, wordIndex)
|
markedUpWord.details = markedUpWord.details.substring(0, wordIndex)
|
||||||
+ '<mark>' + markedUpWord.longDefinition.substr(wordIndex, searchTermLength) + '</mark>'
|
+ '<mark>' + markedUpWord.details.substr(wordIndex, searchTermLength) + '</mark>'
|
||||||
+ markedUpWord.longDefinition.substr(wordIndex + searchTermLength);
|
+ markedUpWord.details.substr(wordIndex + searchTermLength);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,10 +117,10 @@ export function highlightSearchTerm(word) {
|
||||||
markedUpWord.name = markedUpWord.name.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
markedUpWord.name = markedUpWord.name.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||||
}
|
}
|
||||||
if (filters.definition) {
|
if (filters.definition) {
|
||||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
markedUpWord.definition = markedUpWord.definition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||||
}
|
}
|
||||||
if (filters.details) {
|
if (filters.details) {
|
||||||
markedUpWord.longDefinition = markedUpWord.longDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
markedUpWord.details = markedUpWord.details.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return markedUpWord;
|
return markedUpWord;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { cloneObject } from "../helpers";
|
||||||
import { usePhondueDigraphs } from "./KeyboardFire/phondue/ipaField";
|
import { usePhondueDigraphs } from "./KeyboardFire/phondue/ipaField";
|
||||||
import { renderWords } from "./render";
|
import { renderWords } from "./render";
|
||||||
import { addMessage } from "./utilities";
|
import { addMessage } from "./utilities";
|
||||||
|
import { enableHotKeys, disableHotKeys } from "./hotkeys";
|
||||||
|
|
||||||
export function loadSettings() {
|
export function loadSettings() {
|
||||||
const storedSettings = window.localStorage.getItem(SETTINGS_KEY);
|
const storedSettings = window.localStorage.getItem(SETTINGS_KEY);
|
||||||
|
@ -16,17 +17,20 @@ export function saveSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openSettingsModal() {
|
export function openSettingsModal() {
|
||||||
const { useIPAPronunciationField } = window.settings;
|
const { useIPAPronunciationField, useHotkeys } = window.settings;
|
||||||
|
|
||||||
document.getElementById('settingsUseIPA').checked = useIPAPronunciationField;
|
document.getElementById('settingsUseIPA').checked = useIPAPronunciationField;
|
||||||
|
document.getElementById('settingsUseHotkeys').checked = useHotkeys;
|
||||||
|
|
||||||
document.getElementById('settingsModal').style.display = '';
|
document.getElementById('settingsModal').style.display = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveSettingsModal() {
|
export function saveSettingsModal() {
|
||||||
window.settings.useIPAPronunciationField = document.getElementById('settingsUseIPA').checked;
|
window.settings.useIPAPronunciationField = document.getElementById('settingsUseIPA').checked;
|
||||||
|
window.settings.useHotkeys = document.getElementById('settingsUseHotkeys').checked;
|
||||||
|
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
toggleHotkeysEnabled();
|
||||||
toggleIPAPronunciationFields();
|
toggleIPAPronunciationFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +39,13 @@ export function saveAndCloseSettingsModal() {
|
||||||
document.getElementById('settingsModal').style.display = 'none';
|
document.getElementById('settingsModal').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toggleHotkeysEnabled() {
|
||||||
|
disableHotKeys();
|
||||||
|
if (window.settings.useHotkeys) {
|
||||||
|
enableHotKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function toggleIPAPronunciationFields() {
|
export function toggleIPAPronunciationFields() {
|
||||||
const ipaButtons = document.querySelectorAll('.ipa-table-button, .ipa-field-help-button'),
|
const ipaButtons = document.querySelectorAll('.ipa-table-button, .ipa-field-help-button'),
|
||||||
ipaFields = document.querySelectorAll('.ipa-field');
|
ipaFields = document.querySelectorAll('.ipa-field');
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {showSection} from './displayToggles';
|
import {showSection, hideDetailsPanel} from './displayToggles';
|
||||||
import { renderWords, renderEditForm, renderMaximizedTextbox, renderInfoModal, renderIPATable } from './render';
|
import { renderWords, renderEditForm, renderMaximizedTextbox, renderInfoModal, renderIPATable } from './render';
|
||||||
import { validateWord, addWord, confirmEditWord, cancelEditWord, confirmDeleteWord } from './wordManagement';
|
import { confirmEditWord, cancelEditWord, confirmDeleteWord, submitWordForm } from './wordManagement';
|
||||||
import { removeTags } from '../helpers';
|
import { openEditModal, saveEditModal, saveAndCloseEditModal, exportDictionary, exportWords, importDictionary, importWords } from './dictionaryManagement';
|
||||||
import { getNextId } from './utilities';
|
|
||||||
import { openEditModal, saveEditModal, saveAndCloseEditModal } from './dictionaryManagement';
|
|
||||||
import { goToNextPage, goToPreviousPage, goToPage } from './pagination';
|
import { goToNextPage, goToPreviousPage, goToPage } from './pagination';
|
||||||
import { insertAtCursor, getInputSelection, setSelectionRange } from './StackOverflow/inputCursorManagement';
|
import { insertAtCursor, getInputSelection, setSelectionRange } from './StackOverflow/inputCursorManagement';
|
||||||
import { usePhondueDigraphs } from './KeyboardFire/phondue/ipaField';
|
import { usePhondueDigraphs } from './KeyboardFire/phondue/ipaField';
|
||||||
import { openSettingsModal, saveSettingsModal, saveAndCloseSettingsModal } from './settings';
|
import { openSettingsModal, saveSettingsModal, saveAndCloseSettingsModal } from './settings';
|
||||||
|
import { enableHotKeys } from './hotkeys';
|
||||||
|
import { showSearchModal, clearSearchText } from './search';
|
||||||
|
|
||||||
export default function setupListeners() {
|
export default function setupListeners() {
|
||||||
setupDetailsTabs();
|
setupDetailsTabs();
|
||||||
|
@ -16,6 +16,9 @@ export default function setupListeners() {
|
||||||
setupWordForm();
|
setupWordForm();
|
||||||
setupMobileWordFormButton();
|
setupMobileWordFormButton();
|
||||||
setupInfoButtons();
|
setupInfoButtons();
|
||||||
|
if (window.settings.useHotkeys) {
|
||||||
|
enableHotKeys();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDetailsTabs() {
|
function setupDetailsTabs() {
|
||||||
|
@ -33,7 +36,7 @@ function setupDetailsTabs() {
|
||||||
const isActive = tab.classList.contains('active');
|
const isActive = tab.classList.contains('active');
|
||||||
tabs.forEach(t => t.classList.remove('active'));
|
tabs.forEach(t => t.classList.remove('active'));
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
document.getElementById('detailsPanel').style.display = 'none';
|
hideDetailsPanel();
|
||||||
} else {
|
} else {
|
||||||
tab.classList.add('active');
|
tab.classList.add('active');
|
||||||
showSection(section);
|
showSection(section);
|
||||||
|
@ -79,6 +82,10 @@ function setupEditFormInteractions() {
|
||||||
function setupEditFormButtons() {
|
function setupEditFormButtons() {
|
||||||
document.getElementById('editSave').addEventListener('click', () => saveEditModal());
|
document.getElementById('editSave').addEventListener('click', () => saveEditModal());
|
||||||
document.getElementById('editSaveAndClose').addEventListener('click', () => saveAndCloseEditModal());
|
document.getElementById('editSaveAndClose').addEventListener('click', () => saveAndCloseEditModal());
|
||||||
|
document.getElementById('importDictionaryFile').addEventListener('change', importDictionary);
|
||||||
|
document.getElementById('importWordsCSV').addEventListener('change', importWords);
|
||||||
|
document.getElementById('exportDictionaryButton').addEventListener('click', exportDictionary);
|
||||||
|
document.getElementById('exportWordsButton').addEventListener('click', exportWords);
|
||||||
|
|
||||||
setupMaximizeButtons();
|
setupMaximizeButtons();
|
||||||
}
|
}
|
||||||
|
@ -96,15 +103,8 @@ function setupSearchBar() {
|
||||||
searchBox.addEventListener('input', event => {
|
searchBox.addEventListener('input', event => {
|
||||||
openSearchModal.value = event.target.value;
|
openSearchModal.value = event.target.value;
|
||||||
});
|
});
|
||||||
clearSearchButton.addEventListener('click', event => {
|
clearSearchButton.addEventListener('click', clearSearchText);
|
||||||
searchBox.value = '';
|
openSearchModal.addEventListener('click', showSearchModal);
|
||||||
openSearchModal.value = '';
|
|
||||||
renderWords();
|
|
||||||
});
|
|
||||||
openSearchModal.addEventListener('click', () => {
|
|
||||||
document.getElementById('searchModal').style.display = 'block';
|
|
||||||
searchBox.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
const toggleDetailsCheck = function() {
|
const toggleDetailsCheck = function() {
|
||||||
if (searchExactWords.checked) {
|
if (searchExactWords.checked) {
|
||||||
|
@ -145,26 +145,7 @@ function setupWordForm() {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
addWordButton.addEventListener('click', () => {
|
addWordButton.addEventListener('click', submitWordForm);
|
||||||
const name = document.getElementById('wordName').value,
|
|
||||||
pronunciation = document.getElementById('wordPronunciation').value,
|
|
||||||
partOfSpeech = document.getElementById('wordPartOfSpeech').value,
|
|
||||||
definition = document.getElementById('wordDefinition').value,
|
|
||||||
details = document.getElementById('wordDetails').value;
|
|
||||||
|
|
||||||
const word = {
|
|
||||||
name: removeTags(name).trim(),
|
|
||||||
pronunciation: removeTags(pronunciation).trim(),
|
|
||||||
partOfSpeech: removeTags(partOfSpeech).trim(),
|
|
||||||
simpleDefinition: removeTags(definition).trim(),
|
|
||||||
longDefinition: removeTags(details).trim(),
|
|
||||||
wordId: getNextId(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (validateWord(word)) {
|
|
||||||
addWord(word);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setupIPAFields();
|
setupIPAFields();
|
||||||
setupMaximizeButtons();
|
setupMaximizeButtons();
|
||||||
|
@ -219,8 +200,8 @@ export function setupSettingsModal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupWordEditFormButtons() {
|
export function setupWordEditFormButtons() {
|
||||||
const saveChangesButtons = document.getElementsByClassName('edit-save-changes');
|
const saveChangesButtons = document.getElementsByClassName('edit-save-changes'),
|
||||||
const cancelChangesButtons = document.getElementsByClassName('edit-cancel');
|
cancelChangesButtons = document.getElementsByClassName('edit-cancel');
|
||||||
Array.from(saveChangesButtons).forEach(button => {
|
Array.from(saveChangesButtons).forEach(button => {
|
||||||
button.removeEventListener('click', confirmEditWord);
|
button.removeEventListener('click', confirmEditWord);
|
||||||
button.addEventListener('click', confirmEditWord);
|
button.addEventListener('click', confirmEditWord);
|
||||||
|
|
|
@ -123,8 +123,8 @@ export function generateRandomWords(numberOfWords) {
|
||||||
name: word,
|
name: word,
|
||||||
pronunciation: '/' + word + '/',
|
pronunciation: '/' + word + '/',
|
||||||
partOfSpeech: Math.random() > 0.5 ? 'Noun' : 'Verb',
|
partOfSpeech: Math.random() > 0.5 ? 'Noun' : 'Verb',
|
||||||
simpleDefinition: word,
|
definition: word,
|
||||||
longDefinition: word + (index > 0 ? '\n\nRef: {{' + words[index - 1] + '}}' : ''),
|
details: word + (index > 0 ? '\n\nRef: {{' + words[index - 1] + '}}' : ''),
|
||||||
wordId: getNextId(),
|
wordId: getNextId(),
|
||||||
}, false);
|
}, false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { renderWords } from "./render";
|
import { renderWords } from "./render";
|
||||||
import { wordExists, addMessage } from "./utilities";
|
import { wordExists, addMessage, getNextId } from "./utilities";
|
||||||
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
||||||
import { removeTags } from "../helpers";
|
import { removeTags } from "../helpers";
|
||||||
import { saveDictionary } from "./dictionaryManagement";
|
import { saveDictionary } from "./dictionaryManagement";
|
||||||
|
@ -12,7 +12,7 @@ export function validateWord(word, wordId = false) {
|
||||||
if (word.name === '') {
|
if (word.name === '') {
|
||||||
errorMessage += '<p class="bold red">Word field must not be blank.</p>';
|
errorMessage += '<p class="bold red">Word field must not be blank.</p>';
|
||||||
}
|
}
|
||||||
if (word.simpleDefinition === '' && word.longDefinition === '') {
|
if (word.definition === '' && word.details === '') {
|
||||||
errorMessage += '<p class="bold red">You must enter Definition or Details.</p>';
|
errorMessage += '<p class="bold red">You must enter Definition or Details.</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ export function validateWord(word, wordId = false) {
|
||||||
|
|
||||||
export function sortWords(render) {
|
export function sortWords(render) {
|
||||||
const { sortByDefinition } = window.currentDictionary.settings;
|
const { sortByDefinition } = window.currentDictionary.settings;
|
||||||
const sortBy = sortByDefinition ? 'simpleDefinition' : 'name';
|
const sortBy = sortByDefinition ? 'definition' : 'name';
|
||||||
|
|
||||||
window.currentDictionary.words.sort((wordA, wordB) => {
|
window.currentDictionary.words.sort((wordA, wordB) => {
|
||||||
if (removeDiacritics(wordA[sortBy]).toLowerCase() === removeDiacritics(wordB[sortBy]).toLowerCase()) return 0;
|
if (removeDiacritics(wordA[sortBy]).toLowerCase() === removeDiacritics(wordB[sortBy]).toLowerCase()) return 0;
|
||||||
|
@ -46,9 +46,43 @@ export function sortWords(render) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addWord(word, render = true) {
|
export function submitWordForm() {
|
||||||
|
const name = document.getElementById('wordName').value,
|
||||||
|
pronunciation = document.getElementById('wordPronunciation').value,
|
||||||
|
partOfSpeech = document.getElementById('wordPartOfSpeech').value,
|
||||||
|
definition = document.getElementById('wordDefinition').value,
|
||||||
|
details = document.getElementById('wordDetails').value;
|
||||||
|
|
||||||
|
const word = {
|
||||||
|
name: removeTags(name).trim(),
|
||||||
|
pronunciation: removeTags(pronunciation).trim(),
|
||||||
|
partOfSpeech: removeTags(partOfSpeech).trim(),
|
||||||
|
definition: removeTags(definition).trim(),
|
||||||
|
details: removeTags(details).trim(),
|
||||||
|
wordId: getNextId(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (validateWord(word)) {
|
||||||
|
addWord(word);
|
||||||
|
clearWordForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearWordForm() {
|
||||||
|
document.getElementById('wordName').value = '';
|
||||||
|
document.getElementById('wordPronunciation').value = '';
|
||||||
|
document.getElementById('wordPartOfSpeech').value = '';
|
||||||
|
document.getElementById('wordDefinition').value = '';
|
||||||
|
document.getElementById('wordDetails').value = '';
|
||||||
|
|
||||||
|
document.getElementById('wordName').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addWord(word, render = true, message = true) {
|
||||||
window.currentDictionary.words.push(word);
|
window.currentDictionary.words.push(word);
|
||||||
addMessage('Word Created Successfully');
|
if (message) {
|
||||||
|
addMessage(`<a href="#${word.wordId}">${word.name}</a> Created Successfully`, 10000);
|
||||||
|
}
|
||||||
sortWords(render);
|
sortWords(render);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +109,9 @@ export function updateWord(word, wordId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function confirmEditWord() {
|
export function confirmEditWord(id) {
|
||||||
const wordId = parseInt(this.id.replace('editWordButton_', ''));
|
const wordId = typeof id.target !== 'undefined' ? parseInt(this.id.replace('editWordButton_', '')) : id;
|
||||||
|
console.log(wordId);
|
||||||
const name = document.getElementById('wordName_' + wordId).value,
|
const name = document.getElementById('wordName_' + wordId).value,
|
||||||
pronunciation = document.getElementById('wordPronunciation_' + wordId).value,
|
pronunciation = document.getElementById('wordPronunciation_' + wordId).value,
|
||||||
partOfSpeech = document.getElementById('wordPartOfSpeech_' + wordId).value,
|
partOfSpeech = document.getElementById('wordPartOfSpeech_' + wordId).value,
|
||||||
|
@ -87,8 +122,8 @@ export function confirmEditWord() {
|
||||||
name: removeTags(name).trim(),
|
name: removeTags(name).trim(),
|
||||||
pronunciation: removeTags(pronunciation).trim(),
|
pronunciation: removeTags(pronunciation).trim(),
|
||||||
partOfSpeech: removeTags(partOfSpeech).trim(),
|
partOfSpeech: removeTags(partOfSpeech).trim(),
|
||||||
simpleDefinition: removeTags(definition).trim(),
|
definition: removeTags(definition).trim(),
|
||||||
longDefinition: removeTags(details).trim(),
|
details: removeTags(details).trim(),
|
||||||
wordId,
|
wordId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#settingsModal {
|
||||||
|
.modal-content section {
|
||||||
|
padding: ($general-padding * 2) $general-padding $general-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#mobileWordFormShow {
|
#mobileWordFormShow {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3524,6 +3524,11 @@ pako@~1.0.5:
|
||||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
|
||||||
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
|
||||||
|
|
||||||
|
papaparse@^4.6.3:
|
||||||
|
version "4.6.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-4.6.3.tgz#742e5eaaa97fa6c7e1358d2934d8f18f44aee781"
|
||||||
|
integrity sha512-LRq7BrHC2kHPBYSD50aKuw/B/dGcg29omyJbKWY3KsYUZU69RKwaBHu13jGmCYBtOc4odsLCrFyk6imfyNubJQ==
|
||||||
|
|
||||||
parcel-bundler@^1.12.3:
|
parcel-bundler@^1.12.3:
|
||||||
version "1.12.3"
|
version "1.12.3"
|
||||||
resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.12.3.tgz#2bbf70bfa2d06097f071653285040bd125684d09"
|
resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.12.3.tgz#2bbf70bfa2d06097f071653285040bd125684d09"
|
||||||
|
|
Loading…
Reference in New Issue