diff --git a/packages/overlayscrollbars/src/observers/domObserver.ts b/packages/overlayscrollbars/src/observers/domObserver.ts index 74b04f5..47e94c4 100644 --- a/packages/overlayscrollbars/src/observers/domObserver.ts +++ b/packages/overlayscrollbars/src/observers/domObserver.ts @@ -1,4 +1,4 @@ -import { each, indexOf, isString, MutationObserverConstructor, isEmptyArray, on, off, attr, is, find, push } from 'support'; +import { each, debounce, indexOf, isString, MutationObserverConstructor, isEmptyArray, on, off, attr, is, find, push } from 'support'; type StringNullUndefined = string | null | undefined; @@ -32,11 +32,11 @@ export const createDOMObserver = ( ): DOMObserver => { let isConnected = false; const { _observeContent, _attributes, _ignoreContentChange, _eventContentChange } = options || {}; - const eventContentChangeCallback = () => { + const eventContentChangeCallback = debounce(() => { if (isConnected) { callback([], false, true); } - }; + }); const refreshEventContentChange = (getElements: (selector: string) => Node[]) => { if (_eventContentChange) { const eventContentChanges = _eventContentChange(); diff --git a/packages/overlayscrollbars/src/support/compatibility/vendors.ts b/packages/overlayscrollbars/src/support/compatibility/vendors.ts index 6ca3b02..d1ec5e4 100644 --- a/packages/overlayscrollbars/src/support/compatibility/vendors.ts +++ b/packages/overlayscrollbars/src/support/compatibility/vendors.ts @@ -1,5 +1,6 @@ -import { each, hasOwnProperty } from 'support/utils'; -import { createDiv } from 'support/dom'; +import { each } from 'support/utils/array'; +import { hasOwnProperty } from 'support/utils/object'; +import { createDiv } from 'support/dom/create'; const firstLetterToUpper = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1); const getDummyStyle = (): CSSStyleDeclaration => createDiv().style; diff --git a/packages/overlayscrollbars/src/support/utils/function.ts b/packages/overlayscrollbars/src/support/utils/function.ts new file mode 100644 index 0000000..fa16180 --- /dev/null +++ b/packages/overlayscrollbars/src/support/utils/function.ts @@ -0,0 +1,34 @@ +import { isNumber } from 'support/utils/types'; +import { cAF, rAF } from 'support/compatibility/apis'; + +/** + * Debounces the given function either with a timeout or a animation frame. + * @param functionToDebounce The function which shall be debounced. + * @param timeout The timeout for debouncing. If 0 or lower animation frame is used for debouncing, a timeout otherwise. + * @param maxWait A maximum amount of ms. before the function will be called even with debounce. + */ +export const debounce = (functionToDebounce: (...args: any) => any, timeout?: number, maxWait?: number) => { + let timeoutId: number | void; + let lastCallTime: number; + const hasTimeout = isNumber(timeout) && timeout > 0; + const hasMaxWait = isNumber(maxWait) && maxWait > 0; + const cancel = hasTimeout ? window.clearTimeout : cAF!; + const set = hasTimeout ? window.setTimeout : rAF!; + const setFn = function (args: IArguments) { + lastCallTime = hasMaxWait ? performance.now() : 0; + timeoutId && cancel(timeoutId); + // eslint-disable-next-line + // @ts-ignore + functionToDebounce.apply(this, args); + }; + + return function () { + // eslint-disable-next-line + // @ts-ignore + const boundSetFn = setFn.bind(this, arguments); // eslint-disable-line + const forceCall = hasMaxWait ? performance.now() - lastCallTime >= maxWait! : false; + + timeoutId && cancel(timeoutId); + timeoutId = forceCall ? boundSetFn() : (set(boundSetFn, timeout!) as number); + }; +}; diff --git a/packages/overlayscrollbars/src/support/utils/index.ts b/packages/overlayscrollbars/src/support/utils/index.ts index 787f33e..e593ce5 100644 --- a/packages/overlayscrollbars/src/support/utils/index.ts +++ b/packages/overlayscrollbars/src/support/utils/index.ts @@ -1,5 +1,6 @@ export * from 'support/utils/array'; export * from 'support/utils/equal'; +export * from 'support/utils/function'; export * from 'support/utils/lexicon'; export * from 'support/utils/object'; export * from 'support/utils/types'; diff --git a/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.browser.ts b/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.browser.ts index c01a966..afb78be 100644 --- a/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.browser.ts +++ b/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.browser.ts @@ -232,9 +232,11 @@ const addRemoveTargetContentBetweenElmsFn = async () => { await addRemoveElementsTest(targetContentBetweenElmsSlot, targetElmContentElmObservations); }; const addImgElmsFn = async () => { + /* const add = async () => { const img = new Image(1, 1); img.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; + const { before, after, compare } = changedThrough(targetElmContentElmObservations); const imgHolder = createDiv('img'); appendChildren(imgHolder, img); @@ -261,6 +263,21 @@ const addImgElmsFn = async () => { await add(); await add(); await add(); +*/ + const add = async () => { + const img = new Image(1, 1); + img.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; + + //const { before, after, compare } = changedThrough(targetElmContentElmObservations); + const imgHolder = createDiv('img'); + appendChildren(imgHolder, img); + + appendChildren(imgElmsSlot, imgHolder); + }; + + add(); + add(); + add(); }; const iterateTargetAttrChange = async () => { await iterateAttrChange(setTargetAttr, targetElmObservations, (observation, selected) => { @@ -340,7 +357,10 @@ createDOMObserver( { _observeContent: true, _eventContentChange: () => { - return [['img', 'load']]; + return [ + ['img', 'load'], + ['iframe', 'load'], + ]; }, _ignoreContentChange: (mutation) => { const { target, attributeName } = mutation; diff --git a/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.scss b/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.scss index b23e69d..7269727 100644 --- a/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.scss +++ b/packages/overlayscrollbars/tests/puppeteer/observers/domObserver/index.scss @@ -77,9 +77,11 @@ body { } .img { + display: inline-block; background: lime; width: 50px; height: 50px; + border-radius: 100%; img { opacity: 0;