CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-element-resize-detector

Optimized cross-browser resize listener for DOM elements with up to 37x better performance

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

Element Resize Detector

Element Resize Detector is a JavaScript library that provides optimized cross-browser resize detection for DOM elements. It offers up to 37x better performance than related approaches through two detection strategies: scroll-based (recommended) and object-based.

Package Information

  • Package Name: element-resize-detector
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install element-resize-detector

Core Imports

Node.js/CommonJS:

var elementResizeDetectorMaker = require("element-resize-detector");

ES modules (if using with a bundler):

import elementResizeDetectorMaker from "element-resize-detector";

Browser (via script tag):

<script src="node_modules/element-resize-detector/dist/element-resize-detector.min.js"></script>

This creates a global function elementResizeDetectorMaker.

Basic Usage

var elementResizeDetectorMaker = require("element-resize-detector");

// Create detector with default options
var erd = elementResizeDetectorMaker();

// Listen to resize events
erd.listenTo(document.getElementById("test"), function(element) {
    var width = element.offsetWidth;
    var height = element.offsetHeight;
    console.log("Size: " + width + "x" + height);
});

// High performance setup
var erdFast = elementResizeDetectorMaker({
    strategy: "scroll"
});

// Listen to multiple elements
var elements = document.querySelectorAll(".resizable");
erdFast.listenTo(elements, function(element) {
    // Handle resize for each element
});

// Cleanup when done
erd.uninstall(document.getElementById("test"));

Architecture

Element Resize Detector is built around several key components:

  • Detection Strategies: Two approaches for detecting size changes - scroll-based (high performance) and object-based (legacy compatibility)
  • State Management: Internal element state tracking during installation, detection setup, and cleanup phases
  • Event System: Listener registration, callback synchronization, and cleanup management
  • Cross-Document Support: Initialization system for elements in iframes and other document contexts
  • Automatic Fallback: Browser detection and automatic strategy selection for optimal compatibility

Capabilities

Factory Function

Creates an element resize detector instance with optional configuration.

/**
 * Creates an element resize detector instance
 * @param {Options} options - Optional configuration object
 * @returns {ElementResizeDetector} Detector instance with public API methods
 */
function elementResizeDetectorMaker(options);

interface ElementResizeDetector {
    listenTo(options: Options, elements: Element | Element[] | NodeList, listener: (element: Element) => void): void;
    listenTo(elements: Element | Element[] | NodeList, listener: (element: Element) => void): void;
    removeListener(element: Element, listener: (element: Element) => void): void;
    removeAllListeners(element: Element): void;
    uninstall(elements: Element | Element[] | NodeList): void;
    initDocument(targetDocument: Document): void;
}

Listen to Elements

Makes elements resize-detectable and starts listening to resize events.

/**
 * Makes elements resize-detectable and starts listening to resize events
 * @param {ListenToOptions} options - Options that override global options for this call (includes onReady callback)
 * @param {Element|Element[]|NodeList} elements - Single element, array of elements, or element collection
 * @param {Function} listener - Callback executed for each resize event, receives element as argument
 */
listenTo(options, elements, listener);

/**
 * Overload without options parameter
 * @param {Element|Element[]|NodeList} elements - Single element, array of elements, or element collection  
 * @param {Function} listener - Callback executed for each resize event, receives element as argument
 */
listenTo(elements, listener);

Usage Example:

// With options
erd.listenTo({ callOnAdd: false }, element, function(el) {
    console.log("Element resized:", el);
});

// Without options
erd.listenTo(element, function(el) {
    console.log("Element resized:", el);
});

// Multiple elements
erd.listenTo([element1, element2], function(el) {
    console.log("Element resized:", el);
});

// With onReady callback
erd.listenTo({
    onReady: function() {
        console.log("All elements are ready for detection");
        // Safe to trigger size changes here
    }
}, elements, function(el) {
    console.log("Element resized:", el);
});

Remove Specific Listener

Removes a specific listener from an element.

/**
 * Removes a specific listener from an element
 * @param {Element} element - DOM element to remove listener from
 * @param {Function} listener - Specific listener function to remove
 */
removeListener(element, listener);

Remove All Listeners

Removes all listeners from an element without completely removing the detector.

/**
 * Removes all listeners from an element without completely removing the detector
 * @param {Element} element - DOM element to remove all listeners from
 */
removeAllListeners(element);

Uninstall Detector

Completely removes the detector and all listeners from elements.

/**
 * Completely removes the detector and all listeners from elements
 * @param {Element|Element[]|NodeList} elements - Elements to uninstall detector from
 */
uninstall(elements);

Initialize Document

Initializes the detector for elements in another document (e.g., iframe).

/**
 * Initializes the detector for elements in another document (e.g., iframe)
 * @param {Document} targetDocument - Document object to initialize for element detection
 */
initDocument(targetDocument);

Usage Example:

// Initialize for iframe content
var iframe = document.getElementById("myFrame");
erd.initDocument(iframe.contentDocument);

// Now you can listen to elements in the iframe
var iframeElement = iframe.contentDocument.getElementById("resizable");
erd.listenTo(iframeElement, function(element) {
    console.log("Iframe element resized");
});

Configuration Options

Global Options

Options passed to elementResizeDetectorMaker(options):

interface Options {
    /** Detection strategy to use. "scroll" is recommended for performance */
    strategy?: "object" | "scroll";
    
    /** Whether listeners should be called when added (guarantees initial call) */
    callOnAdd?: boolean;
    
    /** Enable debug logging for the listenTo method */
    debug?: boolean;
    
    /** Custom ID handler for generating and managing element IDs */
    idHandler?: IdHandler;
    
    /** Custom reporter for logs/warnings/errors. Set to false for quiet mode */
    reporter?: Reporter | false;
    
    /** Custom batch processor for handling resize events */
    batchProcessor?: BatchProcessor;
    
    /** Adds !important to injected CSS rules to avoid conflicts */
    important?: boolean;
}

interface IdHandler {
    /** Gets the resize detector id of the element */
    get(element: Element, readonly?: boolean): string;
    /** Generate and sets the resize detector id of the element */
    set(element: Element): string;
}

interface Reporter {
    log(message: string): void;
    warn(message: string): void;
    error(message: string): void;
}

Default Values:

{
    strategy: "object",
    callOnAdd: true,
    debug: false,
    idHandler: /* internal default */,
    reporter: /* internal default */,
    batchProcessor: /* internal default */,
    important: false
}

listenTo Options

Options that can be passed to individual listenTo calls to override global options:

interface ListenToOptions {
    /** Override global callOnAdd setting for this listener */
    callOnAdd?: boolean;
    
    /** Override global debug setting for this listener */
    debug?: boolean;
    
    /** Callback invoked when all elements are ready for detection */
    onReady?: () => void;
}

Detection Strategies

Scroll Strategy

  • Strategy: "scroll"
  • Performance: Ultra-fast (recommended)
  • Browser Support: Modern browsers only
  • Automatic Fallback: Library automatically detects unsupported browsers and switches to object strategy with warnings:
    • Legacy Opera: "Scroll strategy is not supported on legacy Opera. Changing to object strategy."
    • IE9: "Scroll strategy is not supported on IE9. Changing to object strategy."
var erd = elementResizeDetectorMaker({
    strategy: "scroll" // May automatically fallback to object strategy
});

Object Strategy

  • Strategy: "object"
  • Performance: Standard performance
  • Browser Support: Works on legacy browsers including IE8/9 and Legacy Opera
var erd = elementResizeDetectorMaker({
    strategy: "object"
});

Browser Compatibility

  • Modern Browsers: Full support with scroll strategy
  • Legacy Support: Object strategy supports IE8/9, Opera 12
  • Automatic Fallback: Library automatically selects appropriate strategy based on browser

Error Handling

The library throws specific errors for various conditions:

Factory Function Errors:

  • Invalid strategy: Error: Invalid strategy name: [strategyName] when an unsupported strategy is specified

listenTo Function Errors:

  • Missing elements: Error: At least one element required. when no elements are provided
  • Missing listener: Error: Listener required. when no listener function is provided
  • Invalid element types: Invalid arguments. Must be a DOM element or a collection of DOM elements. (via reporter.error)

Example Error Handling:

try {
    var erd = elementResizeDetectorMaker({
        strategy: "invalid-strategy"
    });
} catch (error) {
    console.error("Strategy error:", error.message);
    // Fallback to default strategy
    erd = elementResizeDetectorMaker();
}

// The library will automatically handle invalid elements via reporter
erd.listenTo("not-an-element", function() {}); // Logs error, doesn't throw

The reporter system handles warnings and errors during operation, and automatic strategy fallback occurs for unsupported browsers.

Performance Characteristics

  • Up to 37x faster than related approaches
  • Scroll strategy provides ultra performance
  • Object strategy for broader compatibility
  • Batched processing of resize events for efficiency

Important Caveats

  1. Position Changes: If the element has position: static it will be changed to position: relative. Any unintentional top/right/bottom/left/z-index styles will therefore be applied and absolute positioned children will be positioned relative to the element.

  2. DOM Injection: A hidden element will be injected as a direct child to the element for detection purposes.

  3. Document Initialization: For elements inside iframes or other documents, you must call initDocument() with the target document before listening to elements in that document.

  4. Element State Management: The library maintains internal state for each element during the installation process:

    • Elements transition through "busy" state during installation to prevent concurrent setup
    • Size changes detected during installation automatically trigger resize events after completion
    • Multiple listenTo calls for the same element are synchronized and share installation completion callbacks

Advanced Usage

Iframe Support

When working with iframes, initialize the iframe's document:

var iframe = document.getElementById("myFrame");

// Initialize when iframe loads
iframe.onload = function() {
    erd.initDocument(iframe.contentDocument);
    
    // Now you can listen to elements inside the iframe
    var iframeElement = iframe.contentDocument.getElementById("resizable");
    erd.listenTo(iframeElement, function(element) {
        console.log("Iframe element resized");
    });
};

CSS Conflicts

If you experience CSS conflicts, use the important option:

var erd = elementResizeDetectorMaker({
    important: true  // Adds !important to injected CSS rules
});

Install with Tessl CLI

npx tessl i tessl/npm-element-resize-detector
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/element-resize-detector@1.2.x
Publish Source
CLI
Badge
tessl/npm-element-resize-detector badge