Display scroll refactor (#694)

* Cache navigation header

* Create _focusEntry

* Update scroll restoration

* Require explicit entry focus index
This commit is contained in:
toasted-nutbread 2020-07-26 18:49:38 -04:00 committed by GitHub
parent 104650627d
commit 0512258c8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 36 deletions

View File

@ -250,6 +250,7 @@ class DisplaySearch extends Display {
query query
}, },
state: { state: {
focusEntry: 0,
sentence: {text: query, offset: 0}, sentence: {text: query, offset: 0},
url: window.location.href url: window.location.href
}, },

View File

@ -435,6 +435,7 @@ class Frontend {
wildcards: 'off' wildcards: 'off'
}, },
state: { state: {
focusEntry: 0,
sentence, sentence,
url url
}, },

View File

@ -67,15 +67,16 @@ class Display extends EventDispatcher {
this._history = new DisplayHistory({clearable: true, useBrowserHistory: false}); this._history = new DisplayHistory({clearable: true, useBrowserHistory: false});
this._historyChangeIgnore = false; this._historyChangeIgnore = false;
this._historyHasChanged = false; this._historyHasChanged = false;
this._navigationHeader = document.querySelector('#navigation-header');
this.registerActions([ this.registerActions([
['close', () => { this.onEscape(); }], ['close', () => { this.onEscape(); }],
['next-entry', () => { this._entryScrollIntoView(this._index + 1, null, true); }], ['next-entry', () => { this._focusEntry(this._index + 1, true); }],
['next-entry-x3', () => { this._entryScrollIntoView(this._index + 3, null, true); }], ['next-entry-x3', () => { this._focusEntry(this._index + 3, true); }],
['previous-entry', () => { this._entryScrollIntoView(this._index - 1, null, true); }], ['previous-entry', () => { this._focusEntry(this._index - 1, true); }],
['previous-entry-x3', () => { this._entryScrollIntoView(this._index - 3, null, true); }], ['previous-entry-x3', () => { this._focusEntry(this._index - 3, true); }],
['last-entry', () => { this._entryScrollIntoView(this._definitions.length - 1, null, true); }], ['last-entry', () => { this._focusEntry(this._definitions.length - 1, true); }],
['first-entry', () => { this._entryScrollIntoView(0, null, true); }], ['first-entry', () => { this._focusEntry(0, true); }],
['history-backward', () => { this._sourceTermView(); }], ['history-backward', () => { this._sourceTermView(); }],
['history-forward', () => { this._nextTermView(); }], ['history-forward', () => { this._nextTermView(); }],
['add-note-kanji', () => { this._noteTryAdd('kanji'); }], ['add-note-kanji', () => { this._noteTryAdd('kanji'); }],
@ -454,8 +455,9 @@ class Display extends EventDispatcher {
const link = e.target; const link = e.target;
const {state} = this._history; const {state} = this._history;
state.index = this._entryIndexFind(link); state.focusEntry = this._entryIndexFind(link);
state.scroll = this._windowScroll.y; state.scrollX = this._windowScroll.x;
state.scrollY = this._windowScroll.y;
this._historyStateUpdate(state); this._historyStateUpdate(state);
const query = link.textContent; const query = link.textContent;
@ -469,6 +471,7 @@ class Display extends EventDispatcher {
wildcards: 'off' wildcards: 'off'
}, },
state: { state: {
focusEntry: 0,
sentence: state.sentence, sentence: state.sentence,
url: state.url url: state.url
}, },
@ -512,8 +515,9 @@ class Display extends EventDispatcher {
const layoutAwareScan = this._options.scanning.layoutAwareScan; const layoutAwareScan = this._options.scanning.layoutAwareScan;
const sentence = docSentenceExtract(textSource, sentenceExtent, layoutAwareScan); const sentence = docSentenceExtract(textSource, sentenceExtent, layoutAwareScan);
state.index = this._entryIndexFind(scannedElement); state.focusEntry = this._entryIndexFind(scannedElement);
state.scroll = this._windowScroll.y; state.scrollX = this._windowScroll.x;
state.scrollY = this._windowScroll.y;
this._historyStateUpdate(state); this._historyStateUpdate(state);
this.setContent({ this.setContent({
@ -525,6 +529,7 @@ class Display extends EventDispatcher {
wildcards: 'off' wildcards: 'off'
}, },
state: { state: {
focusEntry: 0,
sentence, sentence,
url: state.url url: state.url
}, },
@ -601,7 +606,7 @@ class Display extends EventDispatcher {
_onWheel(e) { _onWheel(e) {
if (e.altKey) { if (e.altKey) {
if (e.deltaY !== 0) { if (e.deltaY !== 0) {
this._entryScrollIntoView(this._index + (e.deltaY > 0 ? 1 : -1), null, true); this._focusEntry(this._index + (e.deltaY > 0 ? 1 : -1), true);
e.preventDefault(); e.preventDefault();
} }
} else if (e.shiftKey) { } else if (e.shiftKey) {
@ -647,7 +652,6 @@ class Display extends EventDispatcher {
if (interactive) { if (interactive) {
const actionPrevious = document.querySelector('.action-previous'); const actionPrevious = document.querySelector('.action-previous');
const actionNext = document.querySelector('.action-next'); const actionNext = document.querySelector('.action-next');
// const navigationHeader = document.querySelector('.navigation-header');
this._persistentEventListeners.addEventListener(document, 'keydown', this.onKeyDown.bind(this), false); this._persistentEventListeners.addEventListener(document, 'keydown', this.onKeyDown.bind(this), false);
this._persistentEventListeners.addEventListener(document, 'wheel', this._onWheel.bind(this), {passive: false}); this._persistentEventListeners.addEventListener(document, 'wheel', this._onWheel.bind(this), {passive: false});
@ -657,10 +661,6 @@ class Display extends EventDispatcher {
if (actionNext !== null) { if (actionNext !== null) {
this._persistentEventListeners.addEventListener(actionNext, 'click', this._onNextTermView.bind(this)); this._persistentEventListeners.addEventListener(actionNext, 'click', this._onNextTermView.bind(this));
} }
// temporarily disabled
// if (navigationHeader !== null) {
// this.persistentEventListeners.addEventListener(navigationHeader, 'wheel', this.onHistoryWheel.bind(this), {passive: false});
// }
} else { } else {
this._persistentEventListeners.removeAllEventListeners(); this._persistentEventListeners.removeAllEventListeners();
} }
@ -711,7 +711,7 @@ class Display extends EventDispatcher {
} }
} }
async _setContentTermsOrKanji(token, isTerms, definitions, {sentence=null, url=null, index=0, scroll=null}) { async _setContentTermsOrKanji(token, isTerms, definitions, {sentence=null, url=null, focusEntry=null, scrollX=null, scrollY=null}) {
if (typeof url !== 'string') { url = window.location.href; } if (typeof url !== 'string') { url = window.location.href; }
sentence = this._getValidSentenceData(sentence); sentence = this._getValidSentenceData(sentence);
@ -744,7 +744,16 @@ class Display extends EventDispatcher {
container.appendChild(entry); container.appendChild(entry);
} }
this._entryScrollIntoView(index, scroll); if (typeof focusEntry === 'number') {
this._focusEntry(focusEntry, false);
}
if (typeof scrollX === 'number' || typeof scrollY === 'number') {
let {x, y} = this._windowScroll;
if (typeof scrollX === 'number') { x = scrollX; }
if (typeof scrollY === 'number') { y = scrollY; }
this._windowScroll.stop();
this._windowScroll.to(x, y);
}
if ( if (
isTerms && isTerms &&
@ -792,12 +801,10 @@ class Display extends EventDispatcher {
} }
_updateNavigation(previous, next) { _updateNavigation(previous, next) {
const navigation = document.querySelector('#navigation-header'); if (this._navigationHeader === null) { return; }
if (navigation !== null) { this._navigationHeader.hidden = !(previous || next);
navigation.hidden = !(previous || next); this._navigationHeader.dataset.hasPrevious = `${!!previous}`;
navigation.dataset.hasPrevious = `${!!previous}`; this._navigationHeader.dataset.hasNext = `${!!next}`;
navigation.dataset.hasNext = `${!!next}`;
}
} }
_updateAdderButtons(states) { _updateAdderButtons(states) {
@ -840,22 +847,15 @@ class Display extends EventDispatcher {
return entry; return entry;
} }
_entryScrollIntoView(index, scroll, smooth) { _focusEntry(index, smooth) {
this._windowScroll.stop();
const entry = this._entrySetCurrent(index); const entry = this._entrySetCurrent(index);
let target; let target = index === 0 || entry === null ? 0 : this._getElementTop(entry);
if (typeof scroll === 'number') {
target = scroll;
} else {
target = this._index === 0 || entry === null ? 0 : this._getElementTop(entry);
const header = document.querySelector('#navigation-header'); if (this._navigationHeader !== null) {
if (header !== null) { target -= this._navigationHeader.getBoundingClientRect().height;
target -= header.getBoundingClientRect().height;
}
} }
this._windowScroll.stop();
if (smooth) { if (smooth) {
this._windowScroll.animate(this._windowScroll.x, target, 200); this._windowScroll.animate(this._windowScroll.x, target, 200);
} else { } else {