From 5deccb2e97dc97c4a6c58c14825378ff20eadb2c Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 18 Oct 2016 18:48:21 +0200 Subject: [PATCH] Improve keyboard navigation (move) performance --- lib/modules/selectedEntry.js | 37 +++++++++++++++++++++++++++++------- lib/modules/showImages.js | 2 +- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/modules/selectedEntry.js b/lib/modules/selectedEntry.js index 79bb5d28fa..a69911339d 100644 --- a/lib/modules/selectedEntry.js +++ b/lib/modules/selectedEntry.js @@ -117,8 +117,8 @@ module.go = () => { addFocusBorder(); } - addListener((selected, unselected) => unselected && Hover.infocard('showParent').close(false)); - addListener(updateActiveElement); + addListener((selected, unselected) => unselected && Hover.infocard('showParent').close(false), 'beforePaint'); + addListener(updateActiveElement, 'beforePaint'); addListener(updateLastSelectedCache); }; @@ -167,12 +167,36 @@ function _selectedThing() { return selectedThing; } -const listeners = new $.Callbacks(); +const listeners = { 'beforeScroll': [], 'beforePaint': [], 'idle': [] }; -export function addListener(callback) { - listeners.add(callback); +export function addListener(callback, when = 'idle') { + listeners[when].push(callback); } +const runCallbacks = (() => { + function runListeners(listeners, newSelected, oldSelected, options) { + for (const listener of listeners) listener(newSelected, oldSelected, options); + } + + let idleCallback; + const requestIdle = window.requestIdleCallback ? + window.requestIdleCallback : + fn => requestAnimationFrame(() => requestAnimationFrame(fn)); + const runIdle = callback => { + idleCallback = callback; + requestIdle(() => { + if (idleCallback) idleCallback(); + idleCallback = null; + }) + } + + return (...args) => { + runListeners(listeners.beforeScroll, ...args); + requestAnimationFrame(() => runListeners(listeners.beforePaint, ...args)); + runIdle(() => runListeners(listeners.idle, ...args)); + }; +})(); + function _select(thingOrEntry, options = {}) { const newThing = new Thing(thingOrEntry); if (!newThing.thing || newThing.is(selectedThing)) return; @@ -184,9 +208,8 @@ function _select(thingOrEntry, options = {}) { (newThing.entry.getBoundingClientRect().top > oldSelected.entry.getBoundingClientRect().top ? 'down' : 'up') : null; - listeners.fire(newSelected, oldSelected, options); + runCallbacks(newSelected, oldSelected, options); - // options.scrollStyle may be changed by listeners, so have this run last scrollToElement(newThing.entry, options); selectedThing = newSelected; diff --git a/lib/modules/showImages.js b/lib/modules/showImages.js index 02667a0c51..96606ac506 100644 --- a/lib/modules/showImages.js +++ b/lib/modules/showImages.js @@ -364,7 +364,7 @@ module.go = () => { findAllImages(document.body); document.addEventListener('dragstart', () => false); - SelectedEntry.addListener(mediaBrowse); + SelectedEntry.addListener(mediaBrowse, 'beforeScroll'); // Handle spotlight next/prev hiding open expando's const spotlight = document.querySelector('#siteTable_organic');