[BUG] UI shifting in mobile browser #2488
| @@ -155,6 +155,7 @@ import { | |||
| 155 | ensureImageFormatSupported, | 155 | ensureImageFormatSupported, |
| 156 | flashHighlight, | 156 | flashHighlight, |
| 157 | isTrueBoolean, | 157 | isTrueBoolean, |
| 158 | debouncedThrottle, | ||
| 158 | } from './scripts/utils.js'; | 159 | } from './scripts/utils.js'; |
| 159 | import { debounce_timeout } from './scripts/constants.js'; | 160 | import { debounce_timeout } from './scripts/constants.js'; |
| 160 | 161 | ||
| @@ -9236,7 +9237,7 @@ jQuery(async function () { | |||
| 9236 | e.style.height = `${e.scrollHeight + 4}px`; | 9237 | e.style.height = `${e.scrollHeight + 4}px`; |
| 9237 | is_use_scroll_holder = true; | 9238 | is_use_scroll_holder = true; |
| 9238 | } | 9239 | } |
| 9239 | const autoFitEditTextAreaDebounced = debounce(autoFitEditTextArea, debounce_timeout.short); | 9240 | const autoFitEditTextAreaDebounced = debouncedThrottle(autoFitEditTextArea, debounce_timeout.standard); |
| 9240 | document.addEventListener('input', e => { | 9241 | document.addEventListener('input', e => { |
| 9241 | if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { | 9242 | if (e.target instanceof HTMLTextAreaElement && e.target.classList.contains('edit_textarea')) { |
| 9242 | const immediately = e.target.scrollHeight > e.target.offsetHeight || e.target.value === ''; | 9243 | const immediately = e.target.scrollHeight > e.target.offsetHeight || e.target.value === ''; |
| @@ -302,6 +302,32 @@ export function throttle(func, limit = 300) { | |||
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | /** | 304 | /** |
| 305 | * Creates a debounced throttle function that only invokes func at most once per every limit milliseconds. | ||
| 306 | * @param {function} func The function to throttle. | ||
| 307 | * @param {number} [limit=300] The limit in milliseconds. | ||
| 308 | * @returns {function} The throttled function. | ||
| 309 | */ | ||
| 310 | export function debouncedThrottle(func, limit = 300) { | ||
| 311 | let last, deferTimer; | ||
| 312 | let db = debounce(func); | ||
| 313 | |||
| 314 | return function() { | ||
| 315 | let now = +new Date, args = arguments; | ||
| 316 | if(!last || (last && now < last + limit)) { | ||
| 317 | clearTimeout(deferTimer); | ||
| 318 | db.apply(this, args); | ||
| 319 | deferTimer = setTimeout(function() { | ||
| 320 | last = now; | ||
| 321 | func.apply(this, args); | ||
| 322 | }, limit); | ||
| 323 | } else { | ||
| 324 | last = now; | ||
| 325 | func.apply(this, args); | ||
| 326 | } | ||
| 327 | }; | ||
| 328 | } | ||
| 329 | |||
| 330 | /** | ||
| 305 | * Checks if an element is in the viewport. | 331 | * Checks if an element is in the viewport. |
| 306 | * @param {Element} el The element to check. | 332 | * @param {Element} el The element to check. |
| 307 | * @returns {boolean} True if the element is in the viewport, false otherwise. | 333 | * @returns {boolean} True if the element is in the viewport, false otherwise. |