diff --git a/public/script.js b/public/script.js index 104025887..8dac03389 100644 --- a/public/script.js +++ b/public/script.js @@ -155,6 +155,7 @@ import { ensureImageFormatSupported, flashHighlight, isTrueBoolean, + debouncedThrottle, } from './scripts/utils.js'; import { debounce_timeout } from './scripts/constants.js'; @@ -9236,7 +9237,7 @@ jQuery(async function () { e.style.height = `${e.scrollHeight + 4}px`; is_use_scroll_holder = true; } - const autoFitEditTextAreaDebounced = debounce(autoFitEditTextArea, debounce_timeout.short); + const autoFitEditTextAreaDebounced = debouncedThrottle(autoFitEditTextArea, debounce_timeout.standard); document.addEventListener('input', e => { if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { const immediately = e.target.scrollHeight > e.target.offsetHeight || e.target.value === ''; diff --git a/public/scripts/utils.js b/public/scripts/utils.js index 9e437d30a..83207891e 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -301,6 +301,32 @@ export function throttle(func, limit = 300) { }; } +/** + * Creates a debounced throttle function that only invokes func at most once per every limit milliseconds. + * @param {function} func The function to throttle. + * @param {number} [limit=300] The limit in milliseconds. + * @returns {function} The throttled function. + */ +export function debouncedThrottle(func, limit = 300) { + let last, deferTimer; + let db = debounce(func); + + return function() { + let now = +new Date, args = arguments; + if(!last || (last && now < last + limit)) { + clearTimeout(deferTimer); + db.apply(this, args); + deferTimer = setTimeout(function() { + last = now; + func.apply(this, args); + }, limit); + } else { + last = now; + func.apply(this, args); + } + }; +} + /** * Checks if an element is in the viewport. * @param {Element} el The element to check.