Add hotkeys
This commit is contained in:
parent
ad3141ef6e
commit
15bba03e1d
|
@ -168,8 +168,7 @@
|
||||||
<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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,126 @@
|
||||||
|
import { confirmEditWord, submitWordForm } from "./wordManagement";
|
||||||
|
import { showSection, getIsDetailsPanelDisplayed, hideDetailsPanel } from "./displayToggles";
|
||||||
|
import { renderInfoModal, renderMaximizedTextbox } from "./render";
|
||||||
|
import { showSearchModal, clearSearchText } from "./search";
|
||||||
|
import { saveAndCloseSettingsModal, openSettingsModal } from "./settings";
|
||||||
|
import { saveAndCloseEditModal, openEditModal } from "./dictionaryManagement";
|
||||||
|
|
||||||
|
export function enableHotKeys() {
|
||||||
|
document.addEventListener('keydown', hotKeyActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function disableHotKeys() {
|
||||||
|
document.removeEventListener('keydown', hotKeyActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hotKeyActions(event) {
|
||||||
|
console.log(event);
|
||||||
|
|
||||||
|
if (typeof event.key === 'undefined' || typeof event.ctrlKey === 'undefined' || typeof event.altKey === 'undefined') {
|
||||||
|
console.warn('Browser does not have required event properties for hotkeys.');
|
||||||
|
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(); openEditModal()} break;
|
||||||
|
case 'h': if (event.ctrlKey) {event.preventDefault(); 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -277,7 +277,7 @@ 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(/(Field Help|IPA Chart)/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 => {
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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 { getNextId } from './utilities';
|
|
||||||
import { openEditModal, saveEditModal, saveAndCloseEditModal } from './dictionaryManagement';
|
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);
|
||||||
|
@ -96,15 +99,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 +141,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(),
|
|
||||||
definition: removeTags(definition).trim(),
|
|
||||||
details: removeTags(details).trim(),
|
|
||||||
wordId: getNextId(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (validateWord(word)) {
|
|
||||||
addWord(word);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setupIPAFields();
|
setupIPAFields();
|
||||||
setupMaximizeButtons();
|
setupMaximizeButtons();
|
||||||
|
|
|
@ -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";
|
||||||
|
@ -46,6 +46,27 @@ export function sortWords(render) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function addWord(word, render = true) {
|
export function addWord(word, render = true) {
|
||||||
window.currentDictionary.words.push(word);
|
window.currentDictionary.words.push(word);
|
||||||
addMessage('Word Created Successfully');
|
addMessage('Word Created Successfully');
|
||||||
|
@ -75,8 +96,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,
|
||||||
|
|
Loading…
Reference in New Issue