Merge pull request #233 from toasted-nutbread/static-handlers
Static handlers
This commit is contained in:
commit
46ab36180f
@ -126,35 +126,35 @@ async function apiTemplateRender(template, data, dynamic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function apiCommandExec(command) {
|
async function apiCommandExec(command) {
|
||||||
const handlers = {
|
const handlers = apiCommandExec.handlers;
|
||||||
search: () => {
|
if (handlers.hasOwnProperty(command)) {
|
||||||
chrome.tabs.create({url: chrome.extension.getURL('/bg/search.html')});
|
const handler = handlers[command];
|
||||||
},
|
|
||||||
|
|
||||||
help: () => {
|
|
||||||
chrome.tabs.create({url: 'https://foosoft.net/projects/yomichan/'});
|
|
||||||
},
|
|
||||||
|
|
||||||
options: () => {
|
|
||||||
chrome.runtime.openOptionsPage();
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: async () => {
|
|
||||||
const optionsContext = {
|
|
||||||
depth: 0,
|
|
||||||
url: window.location.href
|
|
||||||
};
|
|
||||||
const options = await apiOptionsGet(optionsContext);
|
|
||||||
options.general.enable = !options.general.enable;
|
|
||||||
await apiOptionsSave('popup');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[command];
|
|
||||||
if (handler) {
|
|
||||||
handler();
|
handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
apiCommandExec.handlers = {
|
||||||
|
search: () => {
|
||||||
|
chrome.tabs.create({url: chrome.extension.getURL('/bg/search.html')});
|
||||||
|
},
|
||||||
|
|
||||||
|
help: () => {
|
||||||
|
chrome.tabs.create({url: 'https://foosoft.net/projects/yomichan/'});
|
||||||
|
},
|
||||||
|
|
||||||
|
options: () => {
|
||||||
|
chrome.runtime.openOptionsPage();
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle: async () => {
|
||||||
|
const optionsContext = {
|
||||||
|
depth: 0,
|
||||||
|
url: window.location.href
|
||||||
|
};
|
||||||
|
const options = await apiOptionsGet(optionsContext);
|
||||||
|
options.general.enable = !options.general.enable;
|
||||||
|
await apiOptionsSave('popup');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async function apiAudioGetUrl(definition, source) {
|
async function apiAudioGetUrl(definition, source) {
|
||||||
return audioBuildUrl(definition, source);
|
return audioBuildUrl(definition, source);
|
||||||
|
@ -69,68 +69,13 @@ class Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMessage({action, params}, sender, callback) {
|
onMessage({action, params}, sender, callback) {
|
||||||
const forward = (promise, callback) => {
|
const handlers = Backend.messageHandlers;
|
||||||
return promise.then(result => {
|
if (handlers.hasOwnProperty(action)) {
|
||||||
callback({result});
|
const handler = handlers[action];
|
||||||
}).catch(error => {
|
const promise = handler(params, sender);
|
||||||
callback({error: error.toString ? error.toString() : error});
|
promise
|
||||||
});
|
.then(result => callback({result}))
|
||||||
};
|
.catch(error => callback({error: typeof error.toString === 'function' ? error.toString() : error}));
|
||||||
|
|
||||||
const handlers = {
|
|
||||||
optionsGet: ({optionsContext, callback}) => {
|
|
||||||
forward(apiOptionsGet(optionsContext), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
kanjiFind: ({text, optionsContext, callback}) => {
|
|
||||||
forward(apiKanjiFind(text, optionsContext), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
termsFind: ({text, optionsContext, callback}) => {
|
|
||||||
forward(apiTermsFind(text, optionsContext), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
definitionAdd: ({definition, mode, context, optionsContext, callback}) => {
|
|
||||||
forward(apiDefinitionAdd(definition, mode, context, optionsContext), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
definitionsAddable: ({definitions, modes, optionsContext, callback}) => {
|
|
||||||
forward(apiDefinitionsAddable(definitions, modes, optionsContext), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
noteView: ({noteId}) => {
|
|
||||||
forward(apiNoteView(noteId), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
templateRender: ({template, data, dynamic, callback}) => {
|
|
||||||
forward(apiTemplateRender(template, data, dynamic), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
commandExec: ({command, callback}) => {
|
|
||||||
forward(apiCommandExec(command), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
audioGetUrl: ({definition, source, callback}) => {
|
|
||||||
forward(apiAudioGetUrl(definition, source), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
screenshotGet: ({options}) => {
|
|
||||||
forward(apiScreenshotGet(options, sender), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
forward: ({action, params}) => {
|
|
||||||
forward(apiForward(action, params, sender), callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
frameInformationGet: () => {
|
|
||||||
forward(apiFrameInformationGet(sender), callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[action];
|
|
||||||
if (handler) {
|
|
||||||
params.callback = callback;
|
|
||||||
handler(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -227,5 +172,20 @@ class Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Backend.messageHandlers = {
|
||||||
|
optionsGet: ({optionsContext}) => apiOptionsGet(optionsContext),
|
||||||
|
kanjiFind: ({text, optionsContext}) => apiKanjiFind(text, optionsContext),
|
||||||
|
termsFind: ({text, optionsContext}) => apiTermsFind(text, optionsContext),
|
||||||
|
definitionAdd: ({definition, mode, context, optionsContext}) => apiDefinitionAdd(definition, mode, context, optionsContext),
|
||||||
|
definitionsAddable: ({definitions, modes, optionsContext}) => apiDefinitionsAddable(definitions, modes, optionsContext),
|
||||||
|
noteView: ({noteId}) => apiNoteView(noteId),
|
||||||
|
templateRender: ({template, data, dynamic}) => apiTemplateRender(template, data, dynamic),
|
||||||
|
commandExec: ({command}) => apiCommandExec(command),
|
||||||
|
audioGetUrl: ({definition, source}) => apiAudioGetUrl(definition, source),
|
||||||
|
screenshotGet: ({options}, sender) => apiScreenshotGet(options, sender),
|
||||||
|
forward: ({action, params}, sender) => apiForward(action, params, sender),
|
||||||
|
frameInformationGet: (params, sender) => apiFrameInformationGet(sender),
|
||||||
|
};
|
||||||
|
|
||||||
window.yomichan_backend = new Backend();
|
window.yomichan_backend = new Backend();
|
||||||
window.yomichan_backend.prepare();
|
window.yomichan_backend.prepare();
|
||||||
|
@ -63,60 +63,25 @@ class DisplayFloat extends Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMessage(e) {
|
onMessage(e) {
|
||||||
const handlers = {
|
|
||||||
termsShow: ({definitions, options, context}) => {
|
|
||||||
this.termsShow(definitions, options, context);
|
|
||||||
},
|
|
||||||
|
|
||||||
kanjiShow: ({definitions, options, context}) => {
|
|
||||||
this.kanjiShow(definitions, options, context);
|
|
||||||
},
|
|
||||||
|
|
||||||
clearAutoPlayTimer: () => {
|
|
||||||
this.clearAutoPlayTimer();
|
|
||||||
},
|
|
||||||
|
|
||||||
orphaned: () => {
|
|
||||||
this.onOrphaned();
|
|
||||||
},
|
|
||||||
|
|
||||||
setOptions: (options) => {
|
|
||||||
const css = options.general.customPopupCss;
|
|
||||||
if (css) {
|
|
||||||
this.setStyle(css);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
popupNestedInitialize: ({id, depth, parentFrameId, url}) => {
|
|
||||||
this.optionsContext.depth = depth;
|
|
||||||
this.optionsContext.url = url;
|
|
||||||
popupNestedInitialize(id, depth, parentFrameId, url);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const {action, params} = e.data;
|
const {action, params} = e.data;
|
||||||
const handler = handlers[action];
|
const handlers = DisplayFloat.messageHandlers;
|
||||||
if (handler) {
|
if (handlers.hasOwnProperty(action)) {
|
||||||
handler(params);
|
const handler = handlers[action];
|
||||||
|
handler(this, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
const handlers = {
|
const key = Display.getKeyFromEvent(e);
|
||||||
67: /* c */ () => {
|
const handlers = DisplayFloat.onKeyDownHandlers;
|
||||||
if (e.ctrlKey && !window.getSelection().toString()) {
|
if (handlers.hasOwnProperty(key)) {
|
||||||
this.onSelectionCopy();
|
const handler = handlers[key];
|
||||||
return true;
|
if (handler(this, e)) {
|
||||||
}
|
e.preventDefault();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[e.keyCode];
|
|
||||||
if (handler && handler()) {
|
|
||||||
e.preventDefault();
|
|
||||||
} else {
|
|
||||||
super.onKeyDown(e);
|
|
||||||
}
|
}
|
||||||
|
super.onKeyDown(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
autoPlayAudio() {
|
autoPlayAudio() {
|
||||||
@ -131,6 +96,18 @@ class DisplayFloat extends Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialize(options, popupInfo, url) {
|
||||||
|
const css = options.general.customPopupCss;
|
||||||
|
if (css) {
|
||||||
|
this.setStyle(css);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {id, depth, parentFrameId} = popupInfo;
|
||||||
|
this.optionsContext.depth = depth;
|
||||||
|
this.optionsContext.url = url;
|
||||||
|
popupNestedInitialize(id, depth, parentFrameId, url);
|
||||||
|
}
|
||||||
|
|
||||||
setStyle(css) {
|
setStyle(css) {
|
||||||
const parent = document.head;
|
const parent = document.head;
|
||||||
|
|
||||||
@ -146,4 +123,22 @@ class DisplayFloat extends Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisplayFloat.onKeyDownHandlers = {
|
||||||
|
'C': (self, e) => {
|
||||||
|
if (e.ctrlKey && !window.getSelection().toString()) {
|
||||||
|
self.onSelectionCopy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DisplayFloat.messageHandlers = {
|
||||||
|
termsShow: (self, {definitions, options, context}) => self.termsShow(definitions, options, context),
|
||||||
|
kanjiShow: (self, {definitions, options, context}) => self.kanjiShow(definitions, options, context),
|
||||||
|
clearAutoPlayTimer: (self) => self.clearAutoPlayTimer(),
|
||||||
|
orphaned: (self) => self.onOrphaned(),
|
||||||
|
initialize: (self, {options, popupInfo, url}) => self.initialize(options, popupInfo, url)
|
||||||
|
};
|
||||||
|
|
||||||
window.yomichan_display = new DisplayFloat();
|
window.yomichan_display = new DisplayFloat();
|
||||||
|
@ -55,7 +55,7 @@ class Frontend {
|
|||||||
try {
|
try {
|
||||||
this.options = await apiOptionsGet(this.getOptionsContext());
|
this.options = await apiOptionsGet(this.getOptionsContext());
|
||||||
|
|
||||||
window.addEventListener('message', this.onFrameMessage.bind(this));
|
window.addEventListener('message', this.onWindowMessage.bind(this));
|
||||||
window.addEventListener('mousedown', this.onMouseDown.bind(this));
|
window.addEventListener('mousedown', this.onMouseDown.bind(this));
|
||||||
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
window.addEventListener('mousemove', this.onMouseMove.bind(this));
|
||||||
window.addEventListener('mouseover', this.onMouseOver.bind(this));
|
window.addEventListener('mouseover', this.onMouseOver.bind(this));
|
||||||
@ -71,7 +71,7 @@ class Frontend {
|
|||||||
window.addEventListener('contextmenu', this.onContextMenu.bind(this));
|
window.addEventListener('contextmenu', this.onContextMenu.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(this.onBgMessage.bind(this));
|
chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
@ -135,20 +135,12 @@ class Frontend {
|
|||||||
this.popupTimerClear();
|
this.popupTimerClear();
|
||||||
}
|
}
|
||||||
|
|
||||||
onFrameMessage(e) {
|
onWindowMessage(e) {
|
||||||
const handlers = {
|
const action = e.data;
|
||||||
popupClose: () => {
|
const handlers = Frontend.windowMessageHandlers;
|
||||||
this.searchClear(true);
|
if (handlers.hasOwnProperty(action)) {
|
||||||
},
|
const handler = handlers[action];
|
||||||
|
handler(this);
|
||||||
selectionCopy: () => {
|
|
||||||
document.execCommand('copy');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[e.data];
|
|
||||||
if (handler) {
|
|
||||||
handler();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,20 +232,11 @@ class Frontend {
|
|||||||
this.contextMenuChecking = false;
|
this.contextMenuChecking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBgMessage({action, params}, sender, callback) {
|
onRuntimeMessage({action, params}, sender, callback) {
|
||||||
const handlers = {
|
const handlers = Frontend.runtimeMessageHandlers;
|
||||||
optionsUpdate: () => {
|
if (handlers.hasOwnProperty(action)) {
|
||||||
this.updateOptions();
|
const handler = handlers[action];
|
||||||
},
|
handler(this, params);
|
||||||
|
|
||||||
popupSetVisible: ({visible}) => {
|
|
||||||
this.popup.setVisible(visible);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[action];
|
|
||||||
if (handler) {
|
|
||||||
handler(params);
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,4 +512,25 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frontend.windowMessageHandlers = {
|
||||||
|
popupClose: (self) => {
|
||||||
|
self.searchClear(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectionCopy: () => {
|
||||||
|
document.execCommand('copy');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Frontend.runtimeMessageHandlers = {
|
||||||
|
optionsUpdate: (self) => {
|
||||||
|
self.updateOptions();
|
||||||
|
},
|
||||||
|
|
||||||
|
popupSetVisible: (self, {visible}) => {
|
||||||
|
self.popup.setVisible(visible);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
window.yomichan_frontend = Frontend.create();
|
window.yomichan_frontend = Frontend.create();
|
||||||
|
@ -56,17 +56,19 @@ class Popup {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const parentFrameId = (typeof this.frameId === 'number' ? this.frameId : null);
|
const parentFrameId = (typeof this.frameId === 'number' ? this.frameId : null);
|
||||||
this.container.addEventListener('load', () => {
|
this.container.addEventListener('load', () => {
|
||||||
this.invokeApi('popupNestedInitialize', {
|
this.invokeApi('initialize', {
|
||||||
id: this.id,
|
options: {
|
||||||
depth: this.depth,
|
general: {
|
||||||
parentFrameId,
|
customPopupCss: options.general.customPopupCss
|
||||||
|
}
|
||||||
|
},
|
||||||
|
popupInfo: {
|
||||||
|
id: this.id,
|
||||||
|
depth: this.depth,
|
||||||
|
parentFrameId
|
||||||
|
},
|
||||||
url: this.url
|
url: this.url
|
||||||
});
|
});
|
||||||
this.invokeApi('setOptions', {
|
|
||||||
general: {
|
|
||||||
customPopupCss: options.general.customPopupCss
|
|
||||||
}
|
|
||||||
});
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
this.observeFullscreen();
|
this.observeFullscreen();
|
||||||
|
@ -150,135 +150,23 @@ class Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(e) {
|
onKeyDown(e) {
|
||||||
const noteTryAdd = mode => {
|
const key = Display.getKeyFromEvent(e);
|
||||||
const button = this.adderButtonFind(this.index, mode);
|
const handlers = Display.onKeyDownHandlers;
|
||||||
if (button !== null && !button.classList.contains('disabled')) {
|
if (handlers.hasOwnProperty(key)) {
|
||||||
this.noteAdd(this.definitions[this.index], mode);
|
const handler = handlers[key];
|
||||||
|
if (handler(this, e)) {
|
||||||
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const noteTryView = mode => {
|
|
||||||
const button = this.viewerButtonFind(this.index);
|
|
||||||
if (button !== null && !button.classList.contains('disabled')) {
|
|
||||||
apiNoteView(button.dataset.noteId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlers = {
|
|
||||||
27: /* escape */ () => {
|
|
||||||
this.onSearchClear();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
33: /* page up */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(this.index - 3, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
34: /* page down */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(this.index + 3, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
35: /* end */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(this.definitions.length - 1, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
36: /* home */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(0, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
38: /* up */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(this.index - 1, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
40: /* down */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.entryScrollIntoView(this.index + 1, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
66: /* b */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
this.sourceTermView();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
69: /* e */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
noteTryAdd('term-kanji');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
75: /* k */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
noteTryAdd('kanji');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
82: /* r */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
noteTryAdd('term-kana');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
80: /* p */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
const entry = this.getEntry(this.index);
|
|
||||||
if (entry !== null && entry.dataset.type === 'term') {
|
|
||||||
this.audioPlay(this.definitions[this.index], this.firstExpressionIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
86: /* v */ () => {
|
|
||||||
if (e.altKey) {
|
|
||||||
noteTryView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handler = handlers[e.keyCode];
|
|
||||||
if (handler && handler()) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onWheel(e) {
|
onWheel(e) {
|
||||||
const handler = () => {
|
if (e.altKey) {
|
||||||
if (e.altKey) {
|
const delta = e.deltaY;
|
||||||
if (e.deltaY < 0) { // scroll up
|
if (delta !== 0) {
|
||||||
this.entryScrollIntoView(this.index - 1, null, true);
|
this.entryScrollIntoView(this.index + (delta > 0 ? 1 : -1), null, true);
|
||||||
return true;
|
e.preventDefault();
|
||||||
} else if (e.deltaY > 0) { // scroll down
|
|
||||||
this.entryScrollIntoView(this.index + 1, null, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if (handler()) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,6 +347,20 @@ class Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noteTryAdd(mode) {
|
||||||
|
const button = this.adderButtonFind(this.index, mode);
|
||||||
|
if (button !== null && !button.classList.contains('disabled')) {
|
||||||
|
this.noteAdd(this.definitions[this.index], mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
noteTryView() {
|
||||||
|
const button = this.viewerButtonFind(this.index);
|
||||||
|
if (button !== null && !button.classList.contains('disabled')) {
|
||||||
|
apiNoteView(button.dataset.noteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async noteAdd(definition, mode) {
|
async noteAdd(definition, mode) {
|
||||||
try {
|
try {
|
||||||
this.setSpinnerVisible(true);
|
this.setSpinnerVisible(true);
|
||||||
@ -634,4 +536,115 @@ class Display {
|
|||||||
const documentRect = document.documentElement.getBoundingClientRect();
|
const documentRect = document.documentElement.getBoundingClientRect();
|
||||||
return elementRect.top - documentRect.top;
|
return elementRect.top - documentRect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getKeyFromEvent(event) {
|
||||||
|
const key = event.key;
|
||||||
|
return key.length === 1 ? key.toUpperCase() : key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Display.onKeyDownHandlers = {
|
||||||
|
'Escape': (self) => {
|
||||||
|
self.onSearchClear();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
'PageUp': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(self.index - 3, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'PageDown': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(self.index + 3, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'End': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(self.definitions.length - 1, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'Home': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(0, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'ArrowUp': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(self.index - 1, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'ArrowDown': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.entryScrollIntoView(self.index + 1, null, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'B': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.sourceTermView();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'E': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.noteTryAdd('term-kanji');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'K': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.noteTryAdd('kanji');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'R': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.noteTryAdd('term-kana');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'P': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
const entry = self.getEntry(self.index);
|
||||||
|
if (entry !== null && entry.dataset.type === 'term') {
|
||||||
|
self.audioPlay(self.definitions[self.index], self.firstExpressionIndex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
'V': (self, e) => {
|
||||||
|
if (e.altKey) {
|
||||||
|
self.noteTryView();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user