source: imaps-frontend/node_modules/resize-observer-polyfill/dist/ResizeObserver.global.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 30.2 KB
RevLine 
[d565449]1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 typeof define === 'function' && define.amd ? define(factory) :
4 (global.ResizeObserver = factory());
5}(this, (function () { 'use strict';
6
7/**
8 * A collection of shims that provide minimal functionality of the ES6 collections.
9 *
10 * These implementations are not meant to be used outside of the ResizeObserver
11 * modules as they cover only a limited range of use cases.
12 */
13/* eslint-disable require-jsdoc, valid-jsdoc */
14var MapShim = (function () {
15 if (typeof Map !== 'undefined') {
16 return Map;
17 }
18
19 /**
20 * Returns index in provided array that matches the specified key.
21 *
22 * @param {Array<Array>} arr
23 * @param {*} key
24 * @returns {number}
25 */
26 function getIndex(arr, key) {
27 var result = -1;
28
29 arr.some(function (entry, index) {
30 if (entry[0] === key) {
31 result = index;
32
33 return true;
34 }
35
36 return false;
37 });
38
39 return result;
40 }
41
42 return (function () {
43 function anonymous() {
44 this.__entries__ = [];
45 }
46
47 var prototypeAccessors = { size: { configurable: true } };
48
49 /**
50 * @returns {boolean}
51 */
52 prototypeAccessors.size.get = function () {
53 return this.__entries__.length;
54 };
55
56 /**
57 * @param {*} key
58 * @returns {*}
59 */
60 anonymous.prototype.get = function (key) {
61 var index = getIndex(this.__entries__, key);
62 var entry = this.__entries__[index];
63
64 return entry && entry[1];
65 };
66
67 /**
68 * @param {*} key
69 * @param {*} value
70 * @returns {void}
71 */
72 anonymous.prototype.set = function (key, value) {
73 var index = getIndex(this.__entries__, key);
74
75 if (~index) {
76 this.__entries__[index][1] = value;
77 } else {
78 this.__entries__.push([key, value]);
79 }
80 };
81
82 /**
83 * @param {*} key
84 * @returns {void}
85 */
86 anonymous.prototype.delete = function (key) {
87 var entries = this.__entries__;
88 var index = getIndex(entries, key);
89
90 if (~index) {
91 entries.splice(index, 1);
92 }
93 };
94
95 /**
96 * @param {*} key
97 * @returns {void}
98 */
99 anonymous.prototype.has = function (key) {
100 return !!~getIndex(this.__entries__, key);
101 };
102
103 /**
104 * @returns {void}
105 */
106 anonymous.prototype.clear = function () {
107 this.__entries__.splice(0);
108 };
109
110 /**
111 * @param {Function} callback
112 * @param {*} [ctx=null]
113 * @returns {void}
114 */
115 anonymous.prototype.forEach = function (callback, ctx) {
116 var this$1 = this;
117 if ( ctx === void 0 ) ctx = null;
118
119 for (var i = 0, list = this$1.__entries__; i < list.length; i += 1) {
120 var entry = list[i];
121
122 callback.call(ctx, entry[1], entry[0]);
123 }
124 };
125
126 Object.defineProperties( anonymous.prototype, prototypeAccessors );
127
128 return anonymous;
129 }());
130})();
131
132/**
133 * Detects whether window and document objects are available in current environment.
134 */
135var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document;
136
137// Returns global object of a current environment.
138var global$1 = (function () {
139 if (typeof global !== 'undefined' && global.Math === Math) {
140 return global;
141 }
142
143 if (typeof self !== 'undefined' && self.Math === Math) {
144 return self;
145 }
146
147 if (typeof window !== 'undefined' && window.Math === Math) {
148 return window;
149 }
150
151 // eslint-disable-next-line no-new-func
152 return Function('return this')();
153})();
154
155/**
156 * A shim for the requestAnimationFrame which falls back to the setTimeout if
157 * first one is not supported.
158 *
159 * @returns {number} Requests' identifier.
160 */
161var requestAnimationFrame$1 = (function () {
162 if (typeof requestAnimationFrame === 'function') {
163 // It's required to use a bounded function because IE sometimes throws
164 // an "Invalid calling object" error if rAF is invoked without the global
165 // object on the left hand side.
166 return requestAnimationFrame.bind(global$1);
167 }
168
169 return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); };
170})();
171
172// Defines minimum timeout before adding a trailing call.
173var trailingTimeout = 2;
174
175/**
176 * Creates a wrapper function which ensures that provided callback will be
177 * invoked only once during the specified delay period.
178 *
179 * @param {Function} callback - Function to be invoked after the delay period.
180 * @param {number} delay - Delay after which to invoke callback.
181 * @returns {Function}
182 */
183var throttle = function (callback, delay) {
184 var leadingCall = false,
185 trailingCall = false,
186 lastCallTime = 0;
187
188 /**
189 * Invokes the original callback function and schedules new invocation if
190 * the "proxy" was called during current request.
191 *
192 * @returns {void}
193 */
194 function resolvePending() {
195 if (leadingCall) {
196 leadingCall = false;
197
198 callback();
199 }
200
201 if (trailingCall) {
202 proxy();
203 }
204 }
205
206 /**
207 * Callback invoked after the specified delay. It will further postpone
208 * invocation of the original function delegating it to the
209 * requestAnimationFrame.
210 *
211 * @returns {void}
212 */
213 function timeoutCallback() {
214 requestAnimationFrame$1(resolvePending);
215 }
216
217 /**
218 * Schedules invocation of the original function.
219 *
220 * @returns {void}
221 */
222 function proxy() {
223 var timeStamp = Date.now();
224
225 if (leadingCall) {
226 // Reject immediately following calls.
227 if (timeStamp - lastCallTime < trailingTimeout) {
228 return;
229 }
230
231 // Schedule new call to be in invoked when the pending one is resolved.
232 // This is important for "transitions" which never actually start
233 // immediately so there is a chance that we might miss one if change
234 // happens amids the pending invocation.
235 trailingCall = true;
236 } else {
237 leadingCall = true;
238 trailingCall = false;
239
240 setTimeout(timeoutCallback, delay);
241 }
242
243 lastCallTime = timeStamp;
244 }
245
246 return proxy;
247};
248
249// Minimum delay before invoking the update of observers.
250var REFRESH_DELAY = 20;
251
252// A list of substrings of CSS properties used to find transition events that
253// might affect dimensions of observed elements.
254var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight'];
255
256// Check if MutationObserver is available.
257var mutationObserverSupported = typeof MutationObserver !== 'undefined';
258
259/**
260 * Singleton controller class which handles updates of ResizeObserver instances.
261 */
262var ResizeObserverController = function() {
263 this.connected_ = false;
264 this.mutationEventsAdded_ = false;
265 this.mutationsObserver_ = null;
266 this.observers_ = [];
267
268 this.onTransitionEnd_ = this.onTransitionEnd_.bind(this);
269 this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);
270};
271
272/**
273 * Adds observer to observers list.
274 *
275 * @param {ResizeObserverSPI} observer - Observer to be added.
276 * @returns {void}
277 */
278
279
280/**
281 * Holds reference to the controller's instance.
282 *
283 * @private {ResizeObserverController}
284 */
285
286
287/**
288 * Keeps reference to the instance of MutationObserver.
289 *
290 * @private {MutationObserver}
291 */
292
293/**
294 * Indicates whether DOM listeners have been added.
295 *
296 * @private {boolean}
297 */
298ResizeObserverController.prototype.addObserver = function (observer) {
299 if (!~this.observers_.indexOf(observer)) {
300 this.observers_.push(observer);
301 }
302
303 // Add listeners if they haven't been added yet.
304 if (!this.connected_) {
305 this.connect_();
306 }
307};
308
309/**
310 * Removes observer from observers list.
311 *
312 * @param {ResizeObserverSPI} observer - Observer to be removed.
313 * @returns {void}
314 */
315ResizeObserverController.prototype.removeObserver = function (observer) {
316 var observers = this.observers_;
317 var index = observers.indexOf(observer);
318
319 // Remove observer if it's present in registry.
320 if (~index) {
321 observers.splice(index, 1);
322 }
323
324 // Remove listeners if controller has no connected observers.
325 if (!observers.length && this.connected_) {
326 this.disconnect_();
327 }
328};
329
330/**
331 * Invokes the update of observers. It will continue running updates insofar
332 * it detects changes.
333 *
334 * @returns {void}
335 */
336ResizeObserverController.prototype.refresh = function () {
337 var changesDetected = this.updateObservers_();
338
339 // Continue running updates if changes have been detected as there might
340 // be future ones caused by CSS transitions.
341 if (changesDetected) {
342 this.refresh();
343 }
344};
345
346/**
347 * Updates every observer from observers list and notifies them of queued
348 * entries.
349 *
350 * @private
351 * @returns {boolean} Returns "true" if any observer has detected changes in
352 * dimensions of it's elements.
353 */
354ResizeObserverController.prototype.updateObservers_ = function () {
355 // Collect observers that have active observations.
356 var activeObservers = this.observers_.filter(function (observer) {
357 return observer.gatherActive(), observer.hasActive();
358 });
359
360 // Deliver notifications in a separate cycle in order to avoid any
361 // collisions between observers, e.g. when multiple instances of
362 // ResizeObserver are tracking the same element and the callback of one
363 // of them changes content dimensions of the observed target. Sometimes
364 // this may result in notifications being blocked for the rest of observers.
365 activeObservers.forEach(function (observer) { return observer.broadcastActive(); });
366
367 return activeObservers.length > 0;
368};
369
370/**
371 * Initializes DOM listeners.
372 *
373 * @private
374 * @returns {void}
375 */
376ResizeObserverController.prototype.connect_ = function () {
377 // Do nothing if running in a non-browser environment or if listeners
378 // have been already added.
379 if (!isBrowser || this.connected_) {
380 return;
381 }
382
383 // Subscription to the "Transitionend" event is used as a workaround for
384 // delayed transitions. This way it's possible to capture at least the
385 // final state of an element.
386 document.addEventListener('transitionend', this.onTransitionEnd_);
387
388 window.addEventListener('resize', this.refresh);
389
390 if (mutationObserverSupported) {
391 this.mutationsObserver_ = new MutationObserver(this.refresh);
392
393 this.mutationsObserver_.observe(document, {
394 attributes: true,
395 childList: true,
396 characterData: true,
397 subtree: true
398 });
399 } else {
400 document.addEventListener('DOMSubtreeModified', this.refresh);
401
402 this.mutationEventsAdded_ = true;
403 }
404
405 this.connected_ = true;
406};
407
408/**
409 * Removes DOM listeners.
410 *
411 * @private
412 * @returns {void}
413 */
414ResizeObserverController.prototype.disconnect_ = function () {
415 // Do nothing if running in a non-browser environment or if listeners
416 // have been already removed.
417 if (!isBrowser || !this.connected_) {
418 return;
419 }
420
421 document.removeEventListener('transitionend', this.onTransitionEnd_);
422 window.removeEventListener('resize', this.refresh);
423
424 if (this.mutationsObserver_) {
425 this.mutationsObserver_.disconnect();
426 }
427
428 if (this.mutationEventsAdded_) {
429 document.removeEventListener('DOMSubtreeModified', this.refresh);
430 }
431
432 this.mutationsObserver_ = null;
433 this.mutationEventsAdded_ = false;
434 this.connected_ = false;
435};
436
437/**
438 * "Transitionend" event handler.
439 *
440 * @private
441 * @param {TransitionEvent} event
442 * @returns {void}
443 */
444ResizeObserverController.prototype.onTransitionEnd_ = function (ref) {
445 var propertyName = ref.propertyName; if ( propertyName === void 0 ) propertyName = '';
446
447 // Detect whether transition may affect dimensions of an element.
448 var isReflowProperty = transitionKeys.some(function (key) {
449 return !!~propertyName.indexOf(key);
450 });
451
452 if (isReflowProperty) {
453 this.refresh();
454 }
455};
456
457/**
458 * Returns instance of the ResizeObserverController.
459 *
460 * @returns {ResizeObserverController}
461 */
462ResizeObserverController.getInstance = function () {
463 if (!this.instance_) {
464 this.instance_ = new ResizeObserverController();
465 }
466
467 return this.instance_;
468};
469
470ResizeObserverController.instance_ = null;
471
472/**
473 * Defines non-writable/enumerable properties of the provided target object.
474 *
475 * @param {Object} target - Object for which to define properties.
476 * @param {Object} props - Properties to be defined.
477 * @returns {Object} Target object.
478 */
479var defineConfigurable = (function (target, props) {
480 for (var i = 0, list = Object.keys(props); i < list.length; i += 1) {
481 var key = list[i];
482
483 Object.defineProperty(target, key, {
484 value: props[key],
485 enumerable: false,
486 writable: false,
487 configurable: true
488 });
489 }
490
491 return target;
492});
493
494/**
495 * Returns the global object associated with provided element.
496 *
497 * @param {Object} target
498 * @returns {Object}
499 */
500var getWindowOf = (function (target) {
501 // Assume that the element is an instance of Node, which means that it
502 // has the "ownerDocument" property from which we can retrieve a
503 // corresponding global object.
504 var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView;
505
506 // Return the local global object if it's not possible extract one from
507 // provided element.
508 return ownerGlobal || global$1;
509});
510
511// Placeholder of an empty content rectangle.
512var emptyRect = createRectInit(0, 0, 0, 0);
513
514/**
515 * Converts provided string to a number.
516 *
517 * @param {number|string} value
518 * @returns {number}
519 */
520function toFloat(value) {
521 return parseFloat(value) || 0;
522}
523
524/**
525 * Extracts borders size from provided styles.
526 *
527 * @param {CSSStyleDeclaration} styles
528 * @param {...string} positions - Borders positions (top, right, ...)
529 * @returns {number}
530 */
531function getBordersSize(styles) {
532 var positions = [], len = arguments.length - 1;
533 while ( len-- > 0 ) positions[ len ] = arguments[ len + 1 ];
534
535 return positions.reduce(function (size, position) {
536 var value = styles['border-' + position + '-width'];
537
538 return size + toFloat(value);
539 }, 0);
540}
541
542/**
543 * Extracts paddings sizes from provided styles.
544 *
545 * @param {CSSStyleDeclaration} styles
546 * @returns {Object} Paddings box.
547 */
548function getPaddings(styles) {
549 var positions = ['top', 'right', 'bottom', 'left'];
550 var paddings = {};
551
552 for (var i = 0, list = positions; i < list.length; i += 1) {
553 var position = list[i];
554
555 var value = styles['padding-' + position];
556
557 paddings[position] = toFloat(value);
558 }
559
560 return paddings;
561}
562
563/**
564 * Calculates content rectangle of provided SVG element.
565 *
566 * @param {SVGGraphicsElement} target - Element content rectangle of which needs
567 * to be calculated.
568 * @returns {DOMRectInit}
569 */
570function getSVGContentRect(target) {
571 var bbox = target.getBBox();
572
573 return createRectInit(0, 0, bbox.width, bbox.height);
574}
575
576/**
577 * Calculates content rectangle of provided HTMLElement.
578 *
579 * @param {HTMLElement} target - Element for which to calculate the content rectangle.
580 * @returns {DOMRectInit}
581 */
582function getHTMLElementContentRect(target) {
583 // Client width & height properties can't be
584 // used exclusively as they provide rounded values.
585 var clientWidth = target.clientWidth;
586 var clientHeight = target.clientHeight;
587
588 // By this condition we can catch all non-replaced inline, hidden and
589 // detached elements. Though elements with width & height properties less
590 // than 0.5 will be discarded as well.
591 //
592 // Without it we would need to implement separate methods for each of
593 // those cases and it's not possible to perform a precise and performance
594 // effective test for hidden elements. E.g. even jQuery's ':visible' filter
595 // gives wrong results for elements with width & height less than 0.5.
596 if (!clientWidth && !clientHeight) {
597 return emptyRect;
598 }
599
600 var styles = getWindowOf(target).getComputedStyle(target);
601 var paddings = getPaddings(styles);
602 var horizPad = paddings.left + paddings.right;
603 var vertPad = paddings.top + paddings.bottom;
604
605 // Computed styles of width & height are being used because they are the
606 // only dimensions available to JS that contain non-rounded values. It could
607 // be possible to utilize the getBoundingClientRect if only it's data wasn't
608 // affected by CSS transformations let alone paddings, borders and scroll bars.
609 var width = toFloat(styles.width),
610 height = toFloat(styles.height);
611
612 // Width & height include paddings and borders when the 'border-box' box
613 // model is applied (except for IE).
614 if (styles.boxSizing === 'border-box') {
615 // Following conditions are required to handle Internet Explorer which
616 // doesn't include paddings and borders to computed CSS dimensions.
617 //
618 // We can say that if CSS dimensions + paddings are equal to the "client"
619 // properties then it's either IE, and thus we don't need to subtract
620 // anything, or an element merely doesn't have paddings/borders styles.
621 if (Math.round(width + horizPad) !== clientWidth) {
622 width -= getBordersSize(styles, 'left', 'right') + horizPad;
623 }
624
625 if (Math.round(height + vertPad) !== clientHeight) {
626 height -= getBordersSize(styles, 'top', 'bottom') + vertPad;
627 }
628 }
629
630 // Following steps can't be applied to the document's root element as its
631 // client[Width/Height] properties represent viewport area of the window.
632 // Besides, it's as well not necessary as the <html> itself neither has
633 // rendered scroll bars nor it can be clipped.
634 if (!isDocumentElement(target)) {
635 // In some browsers (only in Firefox, actually) CSS width & height
636 // include scroll bars size which can be removed at this step as scroll
637 // bars are the only difference between rounded dimensions + paddings
638 // and "client" properties, though that is not always true in Chrome.
639 var vertScrollbar = Math.round(width + horizPad) - clientWidth;
640 var horizScrollbar = Math.round(height + vertPad) - clientHeight;
641
642 // Chrome has a rather weird rounding of "client" properties.
643 // E.g. for an element with content width of 314.2px it sometimes gives
644 // the client width of 315px and for the width of 314.7px it may give
645 // 314px. And it doesn't happen all the time. So just ignore this delta
646 // as a non-relevant.
647 if (Math.abs(vertScrollbar) !== 1) {
648 width -= vertScrollbar;
649 }
650
651 if (Math.abs(horizScrollbar) !== 1) {
652 height -= horizScrollbar;
653 }
654 }
655
656 return createRectInit(paddings.left, paddings.top, width, height);
657}
658
659/**
660 * Checks whether provided element is an instance of the SVGGraphicsElement.
661 *
662 * @param {Element} target - Element to be checked.
663 * @returns {boolean}
664 */
665var isSVGGraphicsElement = (function () {
666 // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement
667 // interface.
668 if (typeof SVGGraphicsElement !== 'undefined') {
669 return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; };
670 }
671
672 // If it's so, then check that element is at least an instance of the
673 // SVGElement and that it has the "getBBox" method.
674 // eslint-disable-next-line no-extra-parens
675 return function (target) { return target instanceof getWindowOf(target).SVGElement && typeof target.getBBox === 'function'; };
676})();
677
678/**
679 * Checks whether provided element is a document element (<html>).
680 *
681 * @param {Element} target - Element to be checked.
682 * @returns {boolean}
683 */
684function isDocumentElement(target) {
685 return target === getWindowOf(target).document.documentElement;
686}
687
688/**
689 * Calculates an appropriate content rectangle for provided html or svg element.
690 *
691 * @param {Element} target - Element content rectangle of which needs to be calculated.
692 * @returns {DOMRectInit}
693 */
694function getContentRect(target) {
695 if (!isBrowser) {
696 return emptyRect;
697 }
698
699 if (isSVGGraphicsElement(target)) {
700 return getSVGContentRect(target);
701 }
702
703 return getHTMLElementContentRect(target);
704}
705
706/**
707 * Creates rectangle with an interface of the DOMRectReadOnly.
708 * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly
709 *
710 * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions.
711 * @returns {DOMRectReadOnly}
712 */
713function createReadOnlyRect(ref) {
714 var x = ref.x;
715 var y = ref.y;
716 var width = ref.width;
717 var height = ref.height;
718
719 // If DOMRectReadOnly is available use it as a prototype for the rectangle.
720 var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object;
721 var rect = Object.create(Constr.prototype);
722
723 // Rectangle's properties are not writable and non-enumerable.
724 defineConfigurable(rect, {
725 x: x, y: y, width: width, height: height,
726 top: y,
727 right: x + width,
728 bottom: height + y,
729 left: x
730 });
731
732 return rect;
733}
734
735/**
736 * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates.
737 * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit
738 *
739 * @param {number} x - X coordinate.
740 * @param {number} y - Y coordinate.
741 * @param {number} width - Rectangle's width.
742 * @param {number} height - Rectangle's height.
743 * @returns {DOMRectInit}
744 */
745function createRectInit(x, y, width, height) {
746 return { x: x, y: y, width: width, height: height };
747}
748
749/**
750 * Class that is responsible for computations of the content rectangle of
751 * provided DOM element and for keeping track of it's changes.
752 */
753var ResizeObservation = function(target) {
754 this.broadcastWidth = 0;
755 this.broadcastHeight = 0;
756 this.contentRect_ = createRectInit(0, 0, 0, 0);
757
758 this.target = target;
759};
760
761/**
762 * Updates content rectangle and tells whether it's width or height properties
763 * have changed since the last broadcast.
764 *
765 * @returns {boolean}
766 */
767
768
769/**
770 * Reference to the last observed content rectangle.
771 *
772 * @private {DOMRectInit}
773 */
774
775
776/**
777 * Broadcasted width of content rectangle.
778 *
779 * @type {number}
780 */
781ResizeObservation.prototype.isActive = function () {
782 var rect = getContentRect(this.target);
783
784 this.contentRect_ = rect;
785
786 return rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight;
787};
788
789/**
790 * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data
791 * from the corresponding properties of the last observed content rectangle.
792 *
793 * @returns {DOMRectInit} Last observed content rectangle.
794 */
795ResizeObservation.prototype.broadcastRect = function () {
796 var rect = this.contentRect_;
797
798 this.broadcastWidth = rect.width;
799 this.broadcastHeight = rect.height;
800
801 return rect;
802};
803
804var ResizeObserverEntry = function(target, rectInit) {
805 var contentRect = createReadOnlyRect(rectInit);
806
807 // According to the specification following properties are not writable
808 // and are also not enumerable in the native implementation.
809 //
810 // Property accessors are not being used as they'd require to define a
811 // private WeakMap storage which may cause memory leaks in browsers that
812 // don't support this type of collections.
813 defineConfigurable(this, { target: target, contentRect: contentRect });
814};
815
816var ResizeObserverSPI = function(callback, controller, callbackCtx) {
817 this.activeObservations_ = [];
818 this.observations_ = new MapShim();
819
820 if (typeof callback !== 'function') {
821 throw new TypeError('The callback provided as parameter 1 is not a function.');
822 }
823
824 this.callback_ = callback;
825 this.controller_ = controller;
826 this.callbackCtx_ = callbackCtx;
827};
828
829/**
830 * Starts observing provided element.
831 *
832 * @param {Element} target - Element to be observed.
833 * @returns {void}
834 */
835
836
837/**
838 * Registry of the ResizeObservation instances.
839 *
840 * @private {Map<Element, ResizeObservation>}
841 */
842
843
844/**
845 * Public ResizeObserver instance which will be passed to the callback
846 * function and used as a value of it's "this" binding.
847 *
848 * @private {ResizeObserver}
849 */
850
851/**
852 * Collection of resize observations that have detected changes in dimensions
853 * of elements.
854 *
855 * @private {Array<ResizeObservation>}
856 */
857ResizeObserverSPI.prototype.observe = function (target) {
858 if (!arguments.length) {
859 throw new TypeError('1 argument required, but only 0 present.');
860 }
861
862 // Do nothing if current environment doesn't have the Element interface.
863 if (typeof Element === 'undefined' || !(Element instanceof Object)) {
864 return;
865 }
866
867 if (!(target instanceof getWindowOf(target).Element)) {
868 throw new TypeError('parameter 1 is not of type "Element".');
869 }
870
871 var observations = this.observations_;
872
873 // Do nothing if element is already being observed.
874 if (observations.has(target)) {
875 return;
876 }
877
878 observations.set(target, new ResizeObservation(target));
879
880 this.controller_.addObserver(this);
881
882 // Force the update of observations.
883 this.controller_.refresh();
884};
885
886/**
887 * Stops observing provided element.
888 *
889 * @param {Element} target - Element to stop observing.
890 * @returns {void}
891 */
892ResizeObserverSPI.prototype.unobserve = function (target) {
893 if (!arguments.length) {
894 throw new TypeError('1 argument required, but only 0 present.');
895 }
896
897 // Do nothing if current environment doesn't have the Element interface.
898 if (typeof Element === 'undefined' || !(Element instanceof Object)) {
899 return;
900 }
901
902 if (!(target instanceof getWindowOf(target).Element)) {
903 throw new TypeError('parameter 1 is not of type "Element".');
904 }
905
906 var observations = this.observations_;
907
908 // Do nothing if element is not being observed.
909 if (!observations.has(target)) {
910 return;
911 }
912
913 observations.delete(target);
914
915 if (!observations.size) {
916 this.controller_.removeObserver(this);
917 }
918};
919
920/**
921 * Stops observing all elements.
922 *
923 * @returns {void}
924 */
925ResizeObserverSPI.prototype.disconnect = function () {
926 this.clearActive();
927 this.observations_.clear();
928 this.controller_.removeObserver(this);
929};
930
931/**
932 * Collects observation instances the associated element of which has changed
933 * it's content rectangle.
934 *
935 * @returns {void}
936 */
937ResizeObserverSPI.prototype.gatherActive = function () {
938 var this$1 = this;
939
940 this.clearActive();
941
942 this.observations_.forEach(function (observation) {
943 if (observation.isActive()) {
944 this$1.activeObservations_.push(observation);
945 }
946 });
947};
948
949/**
950 * Invokes initial callback function with a list of ResizeObserverEntry
951 * instances collected from active resize observations.
952 *
953 * @returns {void}
954 */
955ResizeObserverSPI.prototype.broadcastActive = function () {
956 // Do nothing if observer doesn't have active observations.
957 if (!this.hasActive()) {
958 return;
959 }
960
961 var ctx = this.callbackCtx_;
962
963 // Create ResizeObserverEntry instance for every active observation.
964 var entries = this.activeObservations_.map(function (observation) {
965 return new ResizeObserverEntry(observation.target, observation.broadcastRect());
966 });
967
968 this.callback_.call(ctx, entries, ctx);
969 this.clearActive();
970};
971
972/**
973 * Clears the collection of active observations.
974 *
975 * @returns {void}
976 */
977ResizeObserverSPI.prototype.clearActive = function () {
978 this.activeObservations_.splice(0);
979};
980
981/**
982 * Tells whether observer has active observations.
983 *
984 * @returns {boolean}
985 */
986ResizeObserverSPI.prototype.hasActive = function () {
987 return this.activeObservations_.length > 0;
988};
989
990// Registry of internal observers. If WeakMap is not available use current shim
991// for the Map collection as it has all required methods and because WeakMap
992// can't be fully polyfilled anyway.
993var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim();
994
995/**
996 * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation
997 * exposing only those methods and properties that are defined in the spec.
998 */
999var ResizeObserver = function(callback) {
1000 if (!(this instanceof ResizeObserver)) {
1001 throw new TypeError('Cannot call a class as a function.');
1002 }
1003 if (!arguments.length) {
1004 throw new TypeError('1 argument required, but only 0 present.');
1005 }
1006
1007 var controller = ResizeObserverController.getInstance();
1008 var observer = new ResizeObserverSPI(callback, controller, this);
1009
1010 observers.set(this, observer);
1011};
1012
1013// Expose public methods of ResizeObserver.
1014['observe', 'unobserve', 'disconnect'].forEach(function (method) {
1015 ResizeObserver.prototype[method] = function () {
1016 return (ref = observers.get(this))[method].apply(ref, arguments);
1017 var ref;
1018 };
1019});
1020
1021var index = (function () {
1022 // Export existing implementation if available.
1023 if (typeof global$1.ResizeObserver !== 'undefined') {
1024 return global$1.ResizeObserver;
1025 }
1026
1027 global$1.ResizeObserver = ResizeObserver;
1028
1029 return ResizeObserver;
1030})();
1031
1032return index;
1033
1034})));
Note: See TracBrowser for help on using the repository browser.