More display updates (#1050)
* Use grid for layout * Add data-count attribute * Fix scroll issues during focus * Add index to entries * Simplify audio playback
This commit is contained in:
parent
af33fff6fb
commit
7b6a4c4e36
@ -44,7 +44,7 @@ class DisplaySearch extends Display {
|
||||
});
|
||||
this._onKeyDownIgnoreKeys = new Map([
|
||||
['ANY_MOD', new Set([
|
||||
'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End', 'Enter',
|
||||
'Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageDown', 'PageUp', 'Home', 'End', 'Enter', 'Escape',
|
||||
'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10',
|
||||
'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20',
|
||||
'F21', 'F22', 'F23', 'F24'
|
||||
@ -157,7 +157,7 @@ class DisplaySearch extends Display {
|
||||
case 'kanji':
|
||||
animate = content.animate;
|
||||
valid = content.definitions.length > 0;
|
||||
this._queryInput.blur();
|
||||
this.blurElement(this._queryInput);
|
||||
break;
|
||||
case 'clear':
|
||||
valid = false;
|
||||
@ -183,7 +183,7 @@ class DisplaySearch extends Display {
|
||||
// Search
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.currentTarget.blur();
|
||||
this.blurElement(e.currentTarget);
|
||||
this._search();
|
||||
}
|
||||
|
||||
|
@ -240,15 +240,16 @@ a {
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-areas: "main";
|
||||
justify-items: stretch;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.content-scroll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
grid-area: main;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
overflow-x: hidden;
|
||||
|
@ -473,11 +473,15 @@ class DisplayGenerator {
|
||||
|
||||
_appendMultiple(container, createItem, detailsArray, ...args) {
|
||||
let count = 0;
|
||||
const {ELEMENT_NODE} = Node;
|
||||
if (Array.isArray(detailsArray)) {
|
||||
for (const details of detailsArray) {
|
||||
const item = createItem(details, ...args);
|
||||
if (item === null) { continue; }
|
||||
container.appendChild(item);
|
||||
if (item.nodeType === ELEMENT_NODE) {
|
||||
item.dataset.index = `${count}`;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
@ -183,8 +183,6 @@ class Display extends EventDispatcher {
|
||||
['popupMessage', {async: 'dynamic', handler: this._onDirectMessage.bind(this)}]
|
||||
]);
|
||||
window.addEventListener('focus', this._onWindowFocus.bind(this), false);
|
||||
document.documentElement.addEventListener('focusin', this._onDocumentFocusIn.bind(this), false);
|
||||
document.documentElement.addEventListener('focusout', this._onDocumentFocusOut.bind(this), false);
|
||||
this._updateFocusedElement();
|
||||
this._progressIndicatorVisible.on('change', this._onProgressIndicatorVisibleChanged.bind(this));
|
||||
}
|
||||
@ -283,11 +281,7 @@ class Display extends EventDispatcher {
|
||||
|
||||
if (this._definitions.length === 0) { return; }
|
||||
|
||||
const definition = this._definitions[0];
|
||||
const expressionIndex = this._getFirstExpressionIndex();
|
||||
const callback = () => {
|
||||
this._audioPlay(definition, expressionIndex, 0);
|
||||
};
|
||||
const callback = () => this._playAudio(0, 0);
|
||||
|
||||
if (this._autoPlayAudioDelay > 0) {
|
||||
this._autoPlayAudioTimer = setTimeout(callback, this._autoPlayAudioDelay);
|
||||
@ -413,6 +407,11 @@ class Display extends EventDispatcher {
|
||||
// NOP
|
||||
}
|
||||
|
||||
blurElement(element) {
|
||||
element.blur();
|
||||
this._updateFocusedElement();
|
||||
}
|
||||
|
||||
// Message handlers
|
||||
|
||||
_onMessage({action, params}, sender, callback) {
|
||||
@ -588,14 +587,6 @@ class Display extends EventDispatcher {
|
||||
this._updateFocusedElement();
|
||||
}
|
||||
|
||||
_onDocumentFocusIn() {
|
||||
this._updateFocusedElement();
|
||||
}
|
||||
|
||||
_onDocumentFocusOut() {
|
||||
this._updateFocusedElement();
|
||||
}
|
||||
|
||||
async _onKanjiLookup(e) {
|
||||
try {
|
||||
e.preventDefault();
|
||||
@ -604,7 +595,7 @@ class Display extends EventDispatcher {
|
||||
const link = e.target;
|
||||
const {state} = this._history;
|
||||
|
||||
state.focusEntry = this._entryIndexFind(link);
|
||||
state.focusEntry = this._getClosestDefinitionIndex(link);
|
||||
state.scrollX = this._windowScroll.x;
|
||||
state.scrollY = this._windowScroll.y;
|
||||
this._historyStateUpdate(state);
|
||||
@ -664,7 +655,7 @@ class Display extends EventDispatcher {
|
||||
const layoutAwareScan = this._options.scanning.layoutAwareScan;
|
||||
const sentence = this._documentUtil.extractSentence(textSource, sentenceExtent, layoutAwareScan);
|
||||
|
||||
state.focusEntry = this._entryIndexFind(scannedElement);
|
||||
state.focusEntry = this._getClosestDefinitionIndex(scannedElement);
|
||||
state.scrollX = this._windowScroll.x;
|
||||
state.scrollY = this._windowScroll.y;
|
||||
this._historyStateUpdate(state);
|
||||
@ -715,23 +706,16 @@ class Display extends EventDispatcher {
|
||||
_onAudioPlay(e) {
|
||||
e.preventDefault();
|
||||
const link = e.currentTarget;
|
||||
const entry = link.closest('.entry');
|
||||
const index = this._entryIndexFind(entry);
|
||||
if (index < 0 || index >= this._definitions.length) { return; }
|
||||
|
||||
const expressionIndex = this._indexOf(entry.querySelectorAll('.term-expression .action-play-audio'), link);
|
||||
this._audioPlay(
|
||||
this._definitions[index],
|
||||
// expressionIndex is used in audioPlay to detect result output mode
|
||||
Math.max(expressionIndex, this._options.general.resultOutputMode === 'merge' ? 0 : -1),
|
||||
index
|
||||
);
|
||||
const definitionIndex = this._getClosestDefinitionIndex(link);
|
||||
if (definitionIndex < 0) { return; }
|
||||
const expressionIndex = Math.max(0, this._getClosestExpressionIndex(link));
|
||||
this._playAudio(definitionIndex, expressionIndex);
|
||||
}
|
||||
|
||||
_onNoteAdd(e) {
|
||||
e.preventDefault();
|
||||
const link = e.currentTarget;
|
||||
const index = this._entryIndexFind(link);
|
||||
const index = this._getClosestDefinitionIndex(link);
|
||||
if (index < 0 || index >= this._definitions.length) { return; }
|
||||
|
||||
this._noteAdd(this._definitions[index], link.dataset.mode);
|
||||
@ -770,7 +754,7 @@ class Display extends EventDispatcher {
|
||||
|
||||
_onDebugLogClick(e) {
|
||||
const link = e.currentTarget;
|
||||
const index = this._entryIndexFind(link);
|
||||
const index = this._getClosestDefinitionIndex(link);
|
||||
if (index < 0 || index >= this._definitions.length) { return; }
|
||||
const definition = this._definitions[index];
|
||||
console.log(definition);
|
||||
@ -937,6 +921,7 @@ class Display extends EventDispatcher {
|
||||
this._displayGenerator.createTermEntry(definitions[i]) :
|
||||
this._displayGenerator.createKanjiEntry(definitions[i])
|
||||
);
|
||||
entry.dataset.index = `${i}`;
|
||||
container.appendChild(entry);
|
||||
}
|
||||
|
||||
@ -1187,11 +1172,19 @@ class Display extends EventDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
async _audioPlay(definition, expressionIndex, entryIndex) {
|
||||
async _playAudio(definitionIndex, expressionIndex) {
|
||||
if (definitionIndex < 0 || definitionIndex >= this._definitions.length) { return; }
|
||||
|
||||
const definition = this._definitions[definitionIndex];
|
||||
if (definition.type === 'kanji') { return; }
|
||||
|
||||
const {expressions} = definition;
|
||||
if (expressionIndex < 0 || expressionIndex >= expressions.length) { return; }
|
||||
|
||||
const {expression, reading} = expressions[expressionIndex];
|
||||
|
||||
const overrideToken = this._progressIndicatorVisible.setOverride(true);
|
||||
try {
|
||||
const {expression, reading} = expressionIndex === -1 ? definition : definition.expressions[expressionIndex];
|
||||
|
||||
this._stopPlayingAudio();
|
||||
|
||||
let audio, info;
|
||||
@ -1208,7 +1201,7 @@ class Display extends EventDispatcher {
|
||||
info = 'Could not find audio';
|
||||
}
|
||||
|
||||
const button = this._audioButtonFindImage(entryIndex, expressionIndex);
|
||||
const button = this._audioButtonFindImage(definitionIndex, expressionIndex);
|
||||
if (button !== null) {
|
||||
let titleDefault = button.dataset.titleDefault;
|
||||
if (!titleDefault) {
|
||||
@ -1239,6 +1232,10 @@ class Display extends EventDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
async _playAudioCurrent() {
|
||||
return await this._playAudio(this._index, 0);
|
||||
}
|
||||
|
||||
_stopPlayingAudio() {
|
||||
if (this._audioPlaying !== null) {
|
||||
this._audioPlaying.pause();
|
||||
@ -1246,10 +1243,6 @@ class Display extends EventDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
_getFirstExpressionIndex() {
|
||||
return this._options.general.resultOutputMode === 'merge' ? 0 : -1;
|
||||
}
|
||||
|
||||
_getEntry(index) {
|
||||
const entries = this._container.querySelectorAll('.entry');
|
||||
return index >= 0 && index < entries.length ? entries[index] : null;
|
||||
@ -1271,9 +1264,19 @@ class Display extends EventDispatcher {
|
||||
};
|
||||
}
|
||||
|
||||
_entryIndexFind(element) {
|
||||
const entry = element.closest('.entry');
|
||||
return entry !== null ? this._indexOf(this._container.querySelectorAll('.entry'), entry) : -1;
|
||||
_getClosestDefinitionIndex(element) {
|
||||
return this._getClosestIndex(element, '.entry');
|
||||
}
|
||||
|
||||
_getClosestExpressionIndex(element) {
|
||||
return this._getClosestIndex(element, '.term-expression');
|
||||
}
|
||||
|
||||
_getClosestIndex(element, selector) {
|
||||
const node = element.closest(selector);
|
||||
if (node === null) { return -1; }
|
||||
const index = parseInt(node.dataset.index, 10);
|
||||
return Number.isFinite(index) ? index : -1;
|
||||
}
|
||||
|
||||
_adderButtonFind(index, mode) {
|
||||
@ -1307,15 +1310,6 @@ class Display extends EventDispatcher {
|
||||
return container !== null ? container.querySelector('.action-play-audio>img') : null;
|
||||
}
|
||||
|
||||
_indexOf(nodeList, node) {
|
||||
for (let i = 0, ii = nodeList.length; i < ii; ++i) {
|
||||
if (nodeList[i] === node) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
_getElementTop(element) {
|
||||
const elementRect = element.getBoundingClientRect();
|
||||
const documentRect = this._contentScrollBodyElement.getBoundingClientRect();
|
||||
@ -1331,16 +1325,6 @@ class Display extends EventDispatcher {
|
||||
};
|
||||
}
|
||||
|
||||
_playAudioCurrent() {
|
||||
const index = this._index;
|
||||
if (index < 0 || index >= this._definitions.length) { return; }
|
||||
|
||||
const entry = this._getEntry(index);
|
||||
if (entry !== null && entry.dataset.type === 'term') {
|
||||
this._audioPlay(this._definitions[index], this._getFirstExpressionIndex(), index);
|
||||
}
|
||||
}
|
||||
|
||||
_historyHasState() {
|
||||
return isObject(this._history.state);
|
||||
}
|
||||
@ -1581,7 +1565,7 @@ class Display extends EventDispatcher {
|
||||
activeElement === document.documentElement ||
|
||||
activeElement === document.body
|
||||
) {
|
||||
target.focus();
|
||||
target.focus({preventScroll: true});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user