UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

524 lines (315 loc) โ€ข 12.3 kB
# ๐Ÿ“ฆ `TinySmartScroller` Class A utility class for managing smart scroll behavior in DOM containers or the window. Ideal for dynamic content like chat UIs or live feeds. --- ## ๐Ÿงฉ Typedefs ### ๐Ÿงฑ `NodeSizes` ```js type NodeSizes = { height: number, width: number }; ``` Represents the **dimensions of a DOM element** in pixels. ### ๐Ÿ” `NodeSizesEvent` ```js type NodeSizesEvent = (elem, sizes, elemAmount) => NodeSizes | undefined; ``` A **callback function** used to compare previous and current element sizes, optionally returning custom size adjustments. * `elem`: the DOM element. * `sizes.old`: previous size. * `sizes.now`: current size. * `elemAmount.old` / `elemAmount.now`: number of matching elements before/after. ### ๐Ÿ“ก `ScrollListenersFunc` ```js type ScrollListenersFunc = (payload: any) => void; ``` A generic **scroll event callback function**. --- ## ๐Ÿ—๏ธ Constructor ### โœ… `new TinySmartScroller(target, options?)` Initializes a new smart scroller instance. ```js const scroller = new TinySmartScroller(document.querySelector('.chatbox'), { autoScrollBottom: true, observeMutations: true, preserveScrollOnLayoutShift: true, debounceTime: 100, querySelector: '.message', }); ``` ### ๐Ÿ”ง Options: | Option | Type | Default | Description | | | ----------------------------- | --------------------- | ----------- | -------------------------------------------------------------------- | ----------------------------------------- | | `extraScrollBoundary` | `number` | `0` | Adds extra margin for scroll edge detection | | | `autoScrollBottom` | `boolean` | `true` | Auto-scroll to bottom on updates | | | `observeMutations` | `boolean` | `true` | Uses MutationObserver to detect DOM changes | | | `preserveScrollOnLayoutShift` | `boolean` | `true` | Prevents jumps in scroll position due to layout shifts | | | `debounceTime` | `number` | `100` | Debounce time (ms) for scroll processing | | | `querySelector` | \`string | null\` | `null` | Filters which children should be observed | | `attributeFilter` | `string[]\|Set\|null` | Default set | Which attributes to track for mutations (e.g., `src`, `style`, etc.) | | --- ## ๐Ÿ“ Size Helpers ### ๐Ÿ” `getSimpleOnHeight(filter = [])` Returns a size filter function that only compares height difference for allowed tags. ```js const filter = scroller.getSimpleOnHeight(['IMG', 'VIDEO']); ``` #### โœ… Use when: * You want to track layout shifts that affect only **vertical space**. * You want to limit updates by tag name (like images or videos only). ### โž• `addSimpleOnHeight(filter)` Same as `getSimpleOnHeight()`, but **registers the filter** into the scroll system. ```js scroller.addSimpleOnHeight(['IFRAME']); ``` --- ## ๐Ÿ–ผ๏ธ Load Tags Management These are used to determine **which tags can trigger scroll corrections** when they load (e.g., images expanding). ### ๐Ÿ“„ `getLoadTags()` Returns a list of currently tracked **load-sensitive tag names**. ```js const tags = scroller.getLoadTags(); // ['IMG', 'IFRAME', 'VIDEO'] ``` ### โž• `addLoadTag(tag)` Adds a tag to the **load tracking set**. ```js scroller.addLoadTag('AUDIO'); ``` ### โž– `removeLoadTag(tag)` Removes a tag from the load tracking set. ```js scroller.removeLoadTag('IFRAME'); ``` ### โ“ `hasLoadTag(tag)` Checks if a tag is being tracked. ```js scroller.hasLoadTag('IMG'); // true ``` ### โ™ป๏ธ `resetLoadTags(addDefault = false)` Clears the load tags. If `addDefault` is true, resets to: `'IMG'`, `'IFRAME'`, `'VIDEO'`. ```js scroller.resetLoadTags(true); ``` --- ## ๐Ÿงฌ Attribute Filters Management Used by the MutationObserver to watch **specific attribute changes**. ### ๐Ÿ“‹ `getAttributeFilters()` Returns the current list of tracked attributes. ```js scroller.getAttributeFilters(); // ['class', 'style', 'src', ...] ``` ### โž• `addAttributeFilter(attr)` Adds an attribute to the filter set. ```js scroller.addAttributeFilter('data-src'); ``` ### โž– `removeAttributeFilter(attr)` Removes an attribute from the filter set. ```js scroller.removeAttributeFilter('style'); ``` ### โ“ `hasAttributeFilter(attr)` Checks if an attribute is being watched. ```js scroller.hasAttributeFilter('src'); // true ``` ### โ™ป๏ธ `resetAttributeFilters(addDefault = false)` Clears attribute filters. If `addDefault` is true, resets to: ```js ['class', 'style', 'src', 'data-*', 'height', 'width'] ``` --- ## ๐Ÿง  Size Filter Handlers ### ๐Ÿช `onSize(handler)` Registers a custom handler to observe changes in element size. ```js scroller.onSize((elem, sizes) => { if (sizes.now.height > sizes.old.height) { return { height: sizes.now.height - sizes.old.height, width: 0 }; } }); ``` * ๐Ÿ“Œ **Throws** if `handler` is not a function. * ๐Ÿšซ Does nothing if the instance is destroyed. --- ### โŒ `offSize(handler)` Removes a previously registered size change handler. ```js scroller.offSize(mySizeHandler); ``` * ๐Ÿ“Œ **Throws** if `handler` is not a function. * ๐Ÿšซ Does nothing if the instance is destroyed. --- ## ๐Ÿ—ฃ๏ธ Scroll Event Listeners ### ๐Ÿงท `on(event, handler)` Registers a scroll-related listener. ```js scroller.on('onAutoScroll', (payload) => { console.log('Auto-scrolling triggered!', payload); }); ``` * ๐Ÿ“Œ **Valid events**: `onScrollBoundary`, `onAutoScroll`, `onScrollPause`, `onExtraScrollBoundary` * ๐Ÿ“Œ **Throws** if `event` is not a string or `handler` is not a function. --- ### โŒ `off(event, handler)` Removes a scroll event listener. ```js scroller.off('onAutoScroll', myListener); ``` * ๐Ÿ“Œ **Throws** if `event` is not a string or `handler` is not a function. --- ## ๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ Visibility Map Updater ### ๐Ÿ” `_scrollDataUpdater()` Scans visible elements and tracks visibility changes internally. ```js const result = scroller._scrollDataUpdater(); // Map<Element, { oldIsVisible: boolean, isVisible: boolean }> ``` * โœ… Returns a `Map` of visibility states for each target element. --- ## ๐Ÿš€ Internal Event Emission ### ๐Ÿ“ฃ `_emit(event, payload?)` Calls all registered handlers for the specified scroll event. ```js scroller._emit('onAutoScroll', { debug: true }); ``` * ๐Ÿ“Œ **Throws** if `event` is not a string. * ๐Ÿšซ Does nothing if the instance is destroyed. --- ## ๐Ÿ“œ Scroll Position Evaluation ### ๐ŸŽข `_onScroll()` Handles scroll updates, boundary detection, and emits relevant events: ```js // Emits: 'onScrollBoundary' 'onExtraScrollBoundary' 'onAutoScroll' 'onScrollPause' ``` * ๐Ÿ”„ Updates scroll direction states like `isAtBottom`, `isAtTop`. * ๐Ÿง  Determines whether to pause or continue auto-scroll. --- ## ๐Ÿ”ง Scroll Correction on Layout Shifts ### ๐Ÿช„ `_fixScroll(targets = [])` Attempts to correct scroll position after layout changes (like image loading or content insertion). ```js scroller._fixScroll([imgElement]); ``` * ๐Ÿ” Measures height & width delta using `ResizeObserver` entries. * ๐Ÿ”„ Preserves scroll position intelligently unless scrolled to bottom. * ๐Ÿ“Œ Throws if invalid return types are found in size handlers. --- ## ๐Ÿงฌ Mutation Observer Setup ### ๐Ÿ‘€ `_observeMutations()` Initializes a `MutationObserver` to watch child mutations and trigger scroll adjustments. * ๐ŸŽฏ Watches: * Element insertion/removal * Attribute changes (filtered) * ๐Ÿ“Œ Automatically sets up `ResizeObserver` and load listeners on new elements. --- ## ๐Ÿ“ Resize Observer Setup ### ๐Ÿงฟ `_observeResizes(elements)` Applies a `ResizeObserver` to elements for layout shift tracking. ```js scroller._observeResizes(document.querySelectorAll('.message')); ``` * ๐ŸŽฏ Updates size maps (`#oldSizes`, `#newSizes`) * ๐Ÿ“Œ Throws if `ResizeObserver` is missing or invalid. --- ## ๐Ÿ“ก Load Event Listener for Media ### ๐ŸŽฌ `_listenLoadEvents(elements)` Tracks loading of elements like `IMG`, `IFRAME`, and `VIDEO`. ```js scroller._listenLoadEvents(imgElement); ``` * โณ Listens for the `load` event. * โœ… Triggers scroll updates and auto-scroll when media finishes loading. * โœ… Honors load tags set by `addLoadTag()`. --- ## ๐Ÿงฑ DOM and Element Accessors ### ๐ŸŽฏ `target` Returns the internal scroll container element being monitored. ```js const container = scroller.target; ``` * ๐Ÿ”™ Returns the target DOM element (or `window` if in window mode). ### ๐Ÿ•ต๏ธโ€โ™€๏ธ `getOldSize(el)` Gets the previous recorded size of an element. ```js scroller.getOldSize(myDiv); // โ†’ { height: 120, width: 300 } ``` * โ“ Returns `null` if the element wasn't tracked. ### ๐Ÿ“ `getNewSize(el)` Gets the most recent measured size of an element. ```js scroller.getNewSize(myDiv); // โ†’ { height: 150, width: 300 } ``` * โ“ Returns `null` if the element wasn't tracked. --- ## ๐Ÿ‘๏ธ Visibility Status Checkers ### ๐Ÿ‘€ `wasVisible(el)` Returns `true` if the element was visible during the last scroll update. ### ๐Ÿ”Ž `isVisible(el)` Returns `true` if the element is currently visible in the scroll view. ### โฑ๏ธ `wasTimedVisible(el)` Returns visibility based on the previous **timed** visibility update. ### โŒš `isTimedVisible(el)` Returns visibility based on the current **timed** visibility update. --- ## ๐Ÿ“ Scroll Configuration and Info ### โž• `setExtraScrollBoundary(pixels)` Defines a custom pixel margin for top/bottom boundary detection. ```js scroller.setExtraScrollBoundary(50); ``` * ๐Ÿ”’ Throws if not a valid number. ### ๐Ÿ“Š `getExtraScrollBoundary()` Returns the currently defined extra scroll boundary in pixels. ### ๐Ÿ“‰ `getLastKnownScrollBottomOffset()` Gets the last recorded scroll distance from the bottom (in pixels). ### โฌ‡๏ธ `scrollToBottom()` Scrolls the target all the way to the bottom immediately. ### โฌ†๏ธ `scrollToTop()` Scrolls the target all the way to the top immediately. --- ## ๐Ÿงญ Scroll Position Status ### ๐Ÿ”š `isAtCustomBottom()` Returns `true` if the user is within the custom boundary of the bottom. ### ๐Ÿ” `isAtCustomTop()` Returns `true` if the user is within the custom boundary of the top. ### ๐Ÿงจ `isAtBottom()` Returns `true` if user is currently scrolled to the actual bottom. ### ๐Ÿงท `isAtTop()` Returns `true` if user is currently scrolled to the actual top. ### โธ๏ธ `isScrollPaused()` Returns `true` if auto-scroll is currently paused. --- ## ๐Ÿ’ป Internal Engine Status ### ๐ŸŒ `isWindow()` Returns `true` if the scroll target is the `window` object. ### ๐Ÿ’€ `isDestroyed()` Returns `true` if the instance has already been destroyed. ### ๐Ÿ” `getAutoScrollBottom()` Returns whether auto-scroll-to-bottom is active. ### ๐Ÿงฌ `getObserveMutations()` Returns whether `MutationObserver` is currently enabled. ### ๐Ÿงท `getPreserveScrollOnLayoutShift()` Returns whether scroll preservation is enabled when layout shifts. ### โŒ› `getDebounceTime()` Returns the debounce delay (ms) for scroll-based events. --- ## ๐Ÿงฎ Tracked Element Info ### ๐Ÿ“ `getElemAmount()` Returns the current number of matching observed elements. ### ๐Ÿงพ `getPrevElemAmount()` Returns the previous number of matching elements. ### ๐Ÿงต `getQuerySelector()` Returns the CSS selector used to filter tracked elements. --- ## ๐Ÿ’ฃ Cleanup and Destruction ### โ˜ ๏ธ `destroy()` Disconnects all internal listeners and observers and clears memory. ```js scroller.destroy(); ``` * ๐Ÿงน Removes `scroll`, `resize`, and `load` listeners. * ๐Ÿงผ Clears WeakMaps and listener registries. * โŒ Once destroyed, the instance should not be reused.