From cc8287964b4d52b203f56efc87181dbbab42979e Mon Sep 17 00:00:00 2001 From: amazingrise <8315221+AmazingRise@users.noreply.github.com> Date: Fri, 14 May 2021 14:17:46 +0800 Subject: Change throttle to debounce. --- layouts/partials/journal.html | 165 +++++++++++++++++++++++++++++++++++++++--- static/js/toc-collapse.js | 152 -------------------------------------- 2 files changed, 153 insertions(+), 164 deletions(-) diff --git a/layouts/partials/journal.html b/layouts/partials/journal.html index ea7ee66..83b8041 100644 --- a/layouts/partials/journal.html +++ b/layouts/partials/journal.html @@ -60,18 +60,159 @@ app = new Vue({ document.body.classList.remove("night"); } }, - throttle(callback, limit) { - var wait = false; - return function (...args) { - if (!wait) { - callback(...args); - wait = true; - setTimeout(function () { - wait = false; - }, limit); + debounce(func, wait, options) { + let lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime + + let lastInvokeTime = 0 + let leading = false + let maxing = false + let trailing = true + + // Bypass `requestAnimationFrame` by explicitly setting `wait=0`. + const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function') + + if (typeof func !== 'function') { + throw new TypeError('Expected a function') + } + function isObject(value) { + const type = typeof value + return value != null && (type === 'object' || type === 'function') + } + + wait = +wait || 0 + if (isObject(options)) { + leading = !!options.leading + maxing = 'maxWait' in options + maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait + trailing = 'trailing' in options ? !!options.trailing : trailing + } + + function invokeFunc(time) { + const args = lastArgs + const thisArg = lastThis + + lastArgs = lastThis = undefined + lastInvokeTime = time + result = func.apply(thisArg, args) + return result + } + + function startTimer(pendingFunc, wait) { + if (useRAF) { + root.cancelAnimationFrame(timerId) + return root.requestAnimationFrame(pendingFunc) } + return setTimeout(pendingFunc, wait) } - } + + function cancelTimer(id) { + if (useRAF) { + return root.cancelAnimationFrame(id) + } + clearTimeout(id) + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time + // Start the timer for the trailing edge. + timerId = startTimer(timerExpired, wait) + // Invoke the leading edge. + return leading ? invokeFunc(time) : result + } + + function remainingWait(time) { + const timeSinceLastCall = time - lastCallTime + const timeSinceLastInvoke = time - lastInvokeTime + const timeWaiting = wait - timeSinceLastCall + + return maxing + ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting + } + + function shouldInvoke(time) { + const timeSinceLastCall = time - lastCallTime + const timeSinceLastInvoke = time - lastInvokeTime + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) + } + + function timerExpired() { + const time = Date.now() + if (shouldInvoke(time)) { + return trailingEdge(time) + } + // Restart the timer. + timerId = startTimer(timerExpired, remainingWait(time)) + } + + function trailingEdge(time) { + timerId = undefined + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time) + } + lastArgs = lastThis = undefined + return result + } + + function cancel() { + if (timerId !== undefined) { + cancelTimer(timerId) + } + lastInvokeTime = 0 + lastArgs = lastCallTime = lastThis = timerId = undefined + } + + function flush() { + return timerId === undefined ? result : trailingEdge(Date.now()) + } + + function pending() { + return timerId !== undefined + } + + function debounced(...args) { + const time = Date.now() + const isInvoking = shouldInvoke(time) + + lastArgs = args + lastThis = this + lastCallTime = time + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime) + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = startTimer(timerExpired, wait) + return invokeFunc(lastCallTime) + } + } + if (timerId === undefined) { + timerId = startTimer(timerExpired, wait) + } + return result + } + debounced.cancel = cancel + debounced.flush = flush + debounced.pending = pending + return debounced + } + }, created() { window.addEventListener('scroll', this.handleScroll); @@ -138,7 +279,7 @@ app = new Vue({ {{ if and (not (.Params.disableToC) ) (.IsPage) }} spy(); - window.addEventListener('wheel', this.throttle(spy,200), false); + window.addEventListener('wheel', this.debounce(spy, 250, { 'maxWait': 1000 }), false); {{ end }} }, @@ -148,6 +289,6 @@ app = new Vue({ } }); -new SmoothScroll('a#globalBackToTop'); +//new SmoothScroll('a#globalBackToTop'); \ No newline at end of file diff --git a/static/js/toc-collapse.js b/static/js/toc-collapse.js index b106ee2..427b2e5 100644 --- a/static/js/toc-collapse.js +++ b/static/js/toc-collapse.js @@ -60,155 +60,3 @@ $().ready(function () { //From https://github.com/lodash/lodash/blob/master/debounce.js // and https://github.com/lodash/lodash/blob/master/isObject.js -function debounce(func, wait, options) { - let lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime - - let lastInvokeTime = 0 - let leading = false - let maxing = false - let trailing = true - - // Bypass `requestAnimationFrame` by explicitly setting `wait=0`. - const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function') - - if (typeof func !== 'function') { - throw new TypeError('Expected a function') - } - function isObject(value) { - const type = typeof value - return value != null && (type === 'object' || type === 'function') - } - - wait = +wait || 0 - if (isObject(options)) { - leading = !!options.leading - maxing = 'maxWait' in options - maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait - trailing = 'trailing' in options ? !!options.trailing : trailing - } - - function invokeFunc(time) { - const args = lastArgs - const thisArg = lastThis - - lastArgs = lastThis = undefined - lastInvokeTime = time - result = func.apply(thisArg, args) - return result - } - - function startTimer(pendingFunc, wait) { - if (useRAF) { - root.cancelAnimationFrame(timerId) - return root.requestAnimationFrame(pendingFunc) - } - return setTimeout(pendingFunc, wait) - } - - function cancelTimer(id) { - if (useRAF) { - return root.cancelAnimationFrame(id) - } - clearTimeout(id) - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time - // Start the timer for the trailing edge. - timerId = startTimer(timerExpired, wait) - // Invoke the leading edge. - return leading ? invokeFunc(time) : result - } - - function remainingWait(time) { - const timeSinceLastCall = time - lastCallTime - const timeSinceLastInvoke = time - lastInvokeTime - const timeWaiting = wait - timeSinceLastCall - - return maxing - ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting - } - - function shouldInvoke(time) { - const timeSinceLastCall = time - lastCallTime - const timeSinceLastInvoke = time - lastInvokeTime - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) - } - - function timerExpired() { - const time = Date.now() - if (shouldInvoke(time)) { - return trailingEdge(time) - } - // Restart the timer. - timerId = startTimer(timerExpired, remainingWait(time)) - } - - function trailingEdge(time) { - timerId = undefined - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time) - } - lastArgs = lastThis = undefined - return result - } - - function cancel() { - if (timerId !== undefined) { - cancelTimer(timerId) - } - lastInvokeTime = 0 - lastArgs = lastCallTime = lastThis = timerId = undefined - } - - function flush() { - return timerId === undefined ? result : trailingEdge(Date.now()) - } - - function pending() { - return timerId !== undefined - } - - function debounced(...args) { - const time = Date.now() - const isInvoking = shouldInvoke(time) - - lastArgs = args - lastThis = this - lastCallTime = time - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime) - } - if (maxing) { - // Handle invocations in a tight loop. - timerId = startTimer(timerExpired, wait) - return invokeFunc(lastCallTime) - } - } - if (timerId === undefined) { - timerId = startTimer(timerExpired, wait) - } - return result - } - debounced.cancel = cancel - debounced.flush = flush - debounced.pending = pending - return debounced -} -- cgit v1.2.3