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;
- }
- }
|