| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 | import {Map} from './shims/es6-collections.js';import ResizeObservation from './ResizeObservation.js';import ResizeObserverEntry from './ResizeObserverEntry.js';import getWindowOf from './utils/getWindowOf.js';export default class ResizeObserverSPI {    /**     * Collection of resize observations that have detected changes in dimensions     * of elements.     *     * @private {Array<ResizeObservation>}     */    activeObservations_ = [];    /**     * Reference to the callback function.     *     * @private {ResizeObserverCallback}     */    callback_;    /**     * Public ResizeObserver instance which will be passed to the callback     * function and used as a value of it's "this" binding.     *     * @private {ResizeObserver}     */    callbackCtx_;    /**     * Reference to the associated ResizeObserverController.     *     * @private {ResizeObserverController}     */    controller_;    /**     * Registry of the ResizeObservation instances.     *     * @private {Map<Element, ResizeObservation>}     */    observations_ = new Map();    /**     * Creates a new instance of ResizeObserver.     *     * @param {ResizeObserverCallback} callback - Callback function that is invoked     *      when one of the observed elements changes it's content dimensions.     * @param {ResizeObserverController} controller - Controller instance which     *      is responsible for the updates of observer.     * @param {ResizeObserver} callbackCtx - Reference to the public     *      ResizeObserver instance which will be passed to callback function.     */    constructor(callback, controller, callbackCtx) {        if (typeof callback !== 'function') {            throw new TypeError('The callback provided as parameter 1 is not a function.');        }        this.callback_ = callback;        this.controller_ = controller;        this.callbackCtx_ = callbackCtx;    }    /**     * Starts observing provided element.     *     * @param {Element} target - Element to be observed.     * @returns {void}     */    observe(target) {        if (!arguments.length) {            throw new TypeError('1 argument required, but only 0 present.');        }        // Do nothing if current environment doesn't have the Element interface.        if (typeof Element === 'undefined' || !(Element instanceof Object)) {            return;        }        if (!(target instanceof getWindowOf(target).Element)) {            throw new TypeError('parameter 1 is not of type "Element".');        }        const observations = this.observations_;        // Do nothing if element is already being observed.        if (observations.has(target)) {            return;        }        observations.set(target, new ResizeObservation(target));        this.controller_.addObserver(this);        // Force the update of observations.        this.controller_.refresh();    }    /**     * Stops observing provided element.     *     * @param {Element} target - Element to stop observing.     * @returns {void}     */    unobserve(target) {        if (!arguments.length) {            throw new TypeError('1 argument required, but only 0 present.');        }        // Do nothing if current environment doesn't have the Element interface.        if (typeof Element === 'undefined' || !(Element instanceof Object)) {            return;        }        if (!(target instanceof getWindowOf(target).Element)) {            throw new TypeError('parameter 1 is not of type "Element".');        }        const observations = this.observations_;        // Do nothing if element is not being observed.        if (!observations.has(target)) {            return;        }        observations.delete(target);        if (!observations.size) {            this.controller_.removeObserver(this);        }    }    /**     * Stops observing all elements.     *     * @returns {void}     */    disconnect() {        this.clearActive();        this.observations_.clear();        this.controller_.removeObserver(this);    }    /**     * Collects observation instances the associated element of which has changed     * it's content rectangle.     *     * @returns {void}     */    gatherActive() {        this.clearActive();        this.observations_.forEach(observation => {            if (observation.isActive()) {                this.activeObservations_.push(observation);            }        });    }    /**     * Invokes initial callback function with a list of ResizeObserverEntry     * instances collected from active resize observations.     *     * @returns {void}     */    broadcastActive() {        // Do nothing if observer doesn't have active observations.        if (!this.hasActive()) {            return;        }        const ctx = this.callbackCtx_;        // Create ResizeObserverEntry instance for every active observation.        const entries = this.activeObservations_.map(observation => {            return new ResizeObserverEntry(                observation.target,                observation.broadcastRect()            );        });        this.callback_.call(ctx, entries, ctx);        this.clearActive();    }    /**     * Clears the collection of active observations.     *     * @returns {void}     */    clearActive() {        this.activeObservations_.splice(0);    }    /**     * Tells whether observer has active observations.     *     * @returns {boolean}     */    hasActive() {        return this.activeObservations_.length > 0;    }}
 |