resize-observer.umd.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ResizeObserver = {}));
  5. })(this, (function (exports) { 'use strict';
  6. var resizeObservers = [];
  7. var hasActiveObservations = function () {
  8. return resizeObservers.some(function (ro) { return ro.activeTargets.length > 0; });
  9. };
  10. var hasSkippedObservations = function () {
  11. return resizeObservers.some(function (ro) { return ro.skippedTargets.length > 0; });
  12. };
  13. var msg = 'ResizeObserver loop completed with undelivered notifications.';
  14. var deliverResizeLoopError = function () {
  15. var event;
  16. if (typeof ErrorEvent === 'function') {
  17. event = new ErrorEvent('error', {
  18. message: msg
  19. });
  20. }
  21. else {
  22. event = document.createEvent('Event');
  23. event.initEvent('error', false, false);
  24. event.message = msg;
  25. }
  26. window.dispatchEvent(event);
  27. };
  28. var ResizeObserverBoxOptions;
  29. (function (ResizeObserverBoxOptions) {
  30. ResizeObserverBoxOptions["BORDER_BOX"] = "border-box";
  31. ResizeObserverBoxOptions["CONTENT_BOX"] = "content-box";
  32. ResizeObserverBoxOptions["DEVICE_PIXEL_CONTENT_BOX"] = "device-pixel-content-box";
  33. })(ResizeObserverBoxOptions || (ResizeObserverBoxOptions = {}));
  34. var freeze = function (obj) { return Object.freeze(obj); };
  35. var ResizeObserverSize = (function () {
  36. function ResizeObserverSize(inlineSize, blockSize) {
  37. this.inlineSize = inlineSize;
  38. this.blockSize = blockSize;
  39. freeze(this);
  40. }
  41. return ResizeObserverSize;
  42. }());
  43. var DOMRectReadOnly = (function () {
  44. function DOMRectReadOnly(x, y, width, height) {
  45. this.x = x;
  46. this.y = y;
  47. this.width = width;
  48. this.height = height;
  49. this.top = this.y;
  50. this.left = this.x;
  51. this.bottom = this.top + this.height;
  52. this.right = this.left + this.width;
  53. return freeze(this);
  54. }
  55. DOMRectReadOnly.prototype.toJSON = function () {
  56. var _a = this, x = _a.x, y = _a.y, top = _a.top, right = _a.right, bottom = _a.bottom, left = _a.left, width = _a.width, height = _a.height;
  57. return { x: x, y: y, top: top, right: right, bottom: bottom, left: left, width: width, height: height };
  58. };
  59. DOMRectReadOnly.fromRect = function (rectangle) {
  60. return new DOMRectReadOnly(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  61. };
  62. return DOMRectReadOnly;
  63. }());
  64. var isSVG = function (target) { return target instanceof SVGElement && 'getBBox' in target; };
  65. var isHidden = function (target) {
  66. if (isSVG(target)) {
  67. var _a = target.getBBox(), width = _a.width, height = _a.height;
  68. return !width && !height;
  69. }
  70. var _b = target, offsetWidth = _b.offsetWidth, offsetHeight = _b.offsetHeight;
  71. return !(offsetWidth || offsetHeight || target.getClientRects().length);
  72. };
  73. var isElement = function (obj) {
  74. var _a;
  75. if (obj instanceof Element) {
  76. return true;
  77. }
  78. var scope = (_a = obj === null || obj === void 0 ? void 0 : obj.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
  79. return !!(scope && obj instanceof scope.Element);
  80. };
  81. var isReplacedElement = function (target) {
  82. switch (target.tagName) {
  83. case 'INPUT':
  84. if (target.type !== 'image') {
  85. break;
  86. }
  87. case 'VIDEO':
  88. case 'AUDIO':
  89. case 'EMBED':
  90. case 'OBJECT':
  91. case 'CANVAS':
  92. case 'IFRAME':
  93. case 'IMG':
  94. return true;
  95. }
  96. return false;
  97. };
  98. var global = typeof window !== 'undefined' ? window : {};
  99. var cache = new WeakMap();
  100. var scrollRegexp = /auto|scroll/;
  101. var verticalRegexp = /^tb|vertical/;
  102. var IE = (/msie|trident/i).test(global.navigator && global.navigator.userAgent);
  103. var parseDimension = function (pixel) { return parseFloat(pixel || '0'); };
  104. var size = function (inlineSize, blockSize, switchSizes) {
  105. if (inlineSize === void 0) { inlineSize = 0; }
  106. if (blockSize === void 0) { blockSize = 0; }
  107. if (switchSizes === void 0) { switchSizes = false; }
  108. return new ResizeObserverSize((switchSizes ? blockSize : inlineSize) || 0, (switchSizes ? inlineSize : blockSize) || 0);
  109. };
  110. var zeroBoxes = freeze({
  111. devicePixelContentBoxSize: size(),
  112. borderBoxSize: size(),
  113. contentBoxSize: size(),
  114. contentRect: new DOMRectReadOnly(0, 0, 0, 0)
  115. });
  116. var calculateBoxSizes = function (target, forceRecalculation) {
  117. if (forceRecalculation === void 0) { forceRecalculation = false; }
  118. if (cache.has(target) && !forceRecalculation) {
  119. return cache.get(target);
  120. }
  121. if (isHidden(target)) {
  122. cache.set(target, zeroBoxes);
  123. return zeroBoxes;
  124. }
  125. var cs = getComputedStyle(target);
  126. var svg = isSVG(target) && target.ownerSVGElement && target.getBBox();
  127. var removePadding = !IE && cs.boxSizing === 'border-box';
  128. var switchSizes = verticalRegexp.test(cs.writingMode || '');
  129. var canScrollVertically = !svg && scrollRegexp.test(cs.overflowY || '');
  130. var canScrollHorizontally = !svg && scrollRegexp.test(cs.overflowX || '');
  131. var paddingTop = svg ? 0 : parseDimension(cs.paddingTop);
  132. var paddingRight = svg ? 0 : parseDimension(cs.paddingRight);
  133. var paddingBottom = svg ? 0 : parseDimension(cs.paddingBottom);
  134. var paddingLeft = svg ? 0 : parseDimension(cs.paddingLeft);
  135. var borderTop = svg ? 0 : parseDimension(cs.borderTopWidth);
  136. var borderRight = svg ? 0 : parseDimension(cs.borderRightWidth);
  137. var borderBottom = svg ? 0 : parseDimension(cs.borderBottomWidth);
  138. var borderLeft = svg ? 0 : parseDimension(cs.borderLeftWidth);
  139. var horizontalPadding = paddingLeft + paddingRight;
  140. var verticalPadding = paddingTop + paddingBottom;
  141. var horizontalBorderArea = borderLeft + borderRight;
  142. var verticalBorderArea = borderTop + borderBottom;
  143. var horizontalScrollbarThickness = !canScrollHorizontally ? 0 : target.offsetHeight - verticalBorderArea - target.clientHeight;
  144. var verticalScrollbarThickness = !canScrollVertically ? 0 : target.offsetWidth - horizontalBorderArea - target.clientWidth;
  145. var widthReduction = removePadding ? horizontalPadding + horizontalBorderArea : 0;
  146. var heightReduction = removePadding ? verticalPadding + verticalBorderArea : 0;
  147. var contentWidth = svg ? svg.width : parseDimension(cs.width) - widthReduction - verticalScrollbarThickness;
  148. var contentHeight = svg ? svg.height : parseDimension(cs.height) - heightReduction - horizontalScrollbarThickness;
  149. var borderBoxWidth = contentWidth + horizontalPadding + verticalScrollbarThickness + horizontalBorderArea;
  150. var borderBoxHeight = contentHeight + verticalPadding + horizontalScrollbarThickness + verticalBorderArea;
  151. var boxes = freeze({
  152. devicePixelContentBoxSize: size(Math.round(contentWidth * devicePixelRatio), Math.round(contentHeight * devicePixelRatio), switchSizes),
  153. borderBoxSize: size(borderBoxWidth, borderBoxHeight, switchSizes),
  154. contentBoxSize: size(contentWidth, contentHeight, switchSizes),
  155. contentRect: new DOMRectReadOnly(paddingLeft, paddingTop, contentWidth, contentHeight)
  156. });
  157. cache.set(target, boxes);
  158. return boxes;
  159. };
  160. var calculateBoxSize = function (target, observedBox, forceRecalculation) {
  161. var _a = calculateBoxSizes(target, forceRecalculation), borderBoxSize = _a.borderBoxSize, contentBoxSize = _a.contentBoxSize, devicePixelContentBoxSize = _a.devicePixelContentBoxSize;
  162. switch (observedBox) {
  163. case ResizeObserverBoxOptions.DEVICE_PIXEL_CONTENT_BOX:
  164. return devicePixelContentBoxSize;
  165. case ResizeObserverBoxOptions.BORDER_BOX:
  166. return borderBoxSize;
  167. default:
  168. return contentBoxSize;
  169. }
  170. };
  171. var ResizeObserverEntry = (function () {
  172. function ResizeObserverEntry(target) {
  173. var boxes = calculateBoxSizes(target);
  174. this.target = target;
  175. this.contentRect = boxes.contentRect;
  176. this.borderBoxSize = freeze([boxes.borderBoxSize]);
  177. this.contentBoxSize = freeze([boxes.contentBoxSize]);
  178. this.devicePixelContentBoxSize = freeze([boxes.devicePixelContentBoxSize]);
  179. }
  180. return ResizeObserverEntry;
  181. }());
  182. var calculateDepthForNode = function (node) {
  183. if (isHidden(node)) {
  184. return Infinity;
  185. }
  186. var depth = 0;
  187. var parent = node.parentNode;
  188. while (parent) {
  189. depth += 1;
  190. parent = parent.parentNode;
  191. }
  192. return depth;
  193. };
  194. var broadcastActiveObservations = function () {
  195. var shallowestDepth = Infinity;
  196. var callbacks = [];
  197. resizeObservers.forEach(function processObserver(ro) {
  198. if (ro.activeTargets.length === 0) {
  199. return;
  200. }
  201. var entries = [];
  202. ro.activeTargets.forEach(function processTarget(ot) {
  203. var entry = new ResizeObserverEntry(ot.target);
  204. var targetDepth = calculateDepthForNode(ot.target);
  205. entries.push(entry);
  206. ot.lastReportedSize = calculateBoxSize(ot.target, ot.observedBox);
  207. if (targetDepth < shallowestDepth) {
  208. shallowestDepth = targetDepth;
  209. }
  210. });
  211. callbacks.push(function resizeObserverCallback() {
  212. ro.callback.call(ro.observer, entries, ro.observer);
  213. });
  214. ro.activeTargets.splice(0, ro.activeTargets.length);
  215. });
  216. for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) {
  217. var callback = callbacks_1[_i];
  218. callback();
  219. }
  220. return shallowestDepth;
  221. };
  222. var gatherActiveObservationsAtDepth = function (depth) {
  223. resizeObservers.forEach(function processObserver(ro) {
  224. ro.activeTargets.splice(0, ro.activeTargets.length);
  225. ro.skippedTargets.splice(0, ro.skippedTargets.length);
  226. ro.observationTargets.forEach(function processTarget(ot) {
  227. if (ot.isActive()) {
  228. if (calculateDepthForNode(ot.target) > depth) {
  229. ro.activeTargets.push(ot);
  230. }
  231. else {
  232. ro.skippedTargets.push(ot);
  233. }
  234. }
  235. });
  236. });
  237. };
  238. var process = function () {
  239. var depth = 0;
  240. gatherActiveObservationsAtDepth(depth);
  241. while (hasActiveObservations()) {
  242. depth = broadcastActiveObservations();
  243. gatherActiveObservationsAtDepth(depth);
  244. }
  245. if (hasSkippedObservations()) {
  246. deliverResizeLoopError();
  247. }
  248. return depth > 0;
  249. };
  250. var trigger;
  251. var callbacks = [];
  252. var notify = function () { return callbacks.splice(0).forEach(function (cb) { return cb(); }); };
  253. var queueMicroTask = function (callback) {
  254. if (!trigger) {
  255. var toggle_1 = 0;
  256. var el_1 = document.createTextNode('');
  257. var config = { characterData: true };
  258. new MutationObserver(function () { return notify(); }).observe(el_1, config);
  259. trigger = function () { el_1.textContent = "".concat(toggle_1 ? toggle_1-- : toggle_1++); };
  260. }
  261. callbacks.push(callback);
  262. trigger();
  263. };
  264. var queueResizeObserver = function (cb) {
  265. queueMicroTask(function ResizeObserver() {
  266. requestAnimationFrame(cb);
  267. });
  268. };
  269. var watching = 0;
  270. var isWatching = function () { return !!watching; };
  271. var CATCH_PERIOD = 250;
  272. var observerConfig = { attributes: true, characterData: true, childList: true, subtree: true };
  273. var events = [
  274. 'resize',
  275. 'load',
  276. 'transitionend',
  277. 'animationend',
  278. 'animationstart',
  279. 'animationiteration',
  280. 'keyup',
  281. 'keydown',
  282. 'mouseup',
  283. 'mousedown',
  284. 'mouseover',
  285. 'mouseout',
  286. 'blur',
  287. 'focus'
  288. ];
  289. var time = function (timeout) {
  290. if (timeout === void 0) { timeout = 0; }
  291. return Date.now() + timeout;
  292. };
  293. var scheduled = false;
  294. var Scheduler = (function () {
  295. function Scheduler() {
  296. var _this = this;
  297. this.stopped = true;
  298. this.listener = function () { return _this.schedule(); };
  299. }
  300. Scheduler.prototype.run = function (timeout) {
  301. var _this = this;
  302. if (timeout === void 0) { timeout = CATCH_PERIOD; }
  303. if (scheduled) {
  304. return;
  305. }
  306. scheduled = true;
  307. var until = time(timeout);
  308. queueResizeObserver(function () {
  309. var elementsHaveResized = false;
  310. try {
  311. elementsHaveResized = process();
  312. }
  313. finally {
  314. scheduled = false;
  315. timeout = until - time();
  316. if (!isWatching()) {
  317. return;
  318. }
  319. if (elementsHaveResized) {
  320. _this.run(1000);
  321. }
  322. else if (timeout > 0) {
  323. _this.run(timeout);
  324. }
  325. else {
  326. _this.start();
  327. }
  328. }
  329. });
  330. };
  331. Scheduler.prototype.schedule = function () {
  332. this.stop();
  333. this.run();
  334. };
  335. Scheduler.prototype.observe = function () {
  336. var _this = this;
  337. var cb = function () { return _this.observer && _this.observer.observe(document.body, observerConfig); };
  338. document.body ? cb() : global.addEventListener('DOMContentLoaded', cb);
  339. };
  340. Scheduler.prototype.start = function () {
  341. var _this = this;
  342. if (this.stopped) {
  343. this.stopped = false;
  344. this.observer = new MutationObserver(this.listener);
  345. this.observe();
  346. events.forEach(function (name) { return global.addEventListener(name, _this.listener, true); });
  347. }
  348. };
  349. Scheduler.prototype.stop = function () {
  350. var _this = this;
  351. if (!this.stopped) {
  352. this.observer && this.observer.disconnect();
  353. events.forEach(function (name) { return global.removeEventListener(name, _this.listener, true); });
  354. this.stopped = true;
  355. }
  356. };
  357. return Scheduler;
  358. }());
  359. var scheduler = new Scheduler();
  360. var updateCount = function (n) {
  361. !watching && n > 0 && scheduler.start();
  362. watching += n;
  363. !watching && scheduler.stop();
  364. };
  365. var skipNotifyOnElement = function (target) {
  366. return !isSVG(target)
  367. && !isReplacedElement(target)
  368. && getComputedStyle(target).display === 'inline';
  369. };
  370. var ResizeObservation = (function () {
  371. function ResizeObservation(target, observedBox) {
  372. this.target = target;
  373. this.observedBox = observedBox || ResizeObserverBoxOptions.CONTENT_BOX;
  374. this.lastReportedSize = {
  375. inlineSize: 0,
  376. blockSize: 0
  377. };
  378. }
  379. ResizeObservation.prototype.isActive = function () {
  380. var size = calculateBoxSize(this.target, this.observedBox, true);
  381. if (skipNotifyOnElement(this.target)) {
  382. this.lastReportedSize = size;
  383. }
  384. if (this.lastReportedSize.inlineSize !== size.inlineSize
  385. || this.lastReportedSize.blockSize !== size.blockSize) {
  386. return true;
  387. }
  388. return false;
  389. };
  390. return ResizeObservation;
  391. }());
  392. var ResizeObserverDetail = (function () {
  393. function ResizeObserverDetail(resizeObserver, callback) {
  394. this.activeTargets = [];
  395. this.skippedTargets = [];
  396. this.observationTargets = [];
  397. this.observer = resizeObserver;
  398. this.callback = callback;
  399. }
  400. return ResizeObserverDetail;
  401. }());
  402. var observerMap = new WeakMap();
  403. var getObservationIndex = function (observationTargets, target) {
  404. for (var i = 0; i < observationTargets.length; i += 1) {
  405. if (observationTargets[i].target === target) {
  406. return i;
  407. }
  408. }
  409. return -1;
  410. };
  411. var ResizeObserverController = (function () {
  412. function ResizeObserverController() {
  413. }
  414. ResizeObserverController.connect = function (resizeObserver, callback) {
  415. var detail = new ResizeObserverDetail(resizeObserver, callback);
  416. observerMap.set(resizeObserver, detail);
  417. };
  418. ResizeObserverController.observe = function (resizeObserver, target, options) {
  419. var detail = observerMap.get(resizeObserver);
  420. var firstObservation = detail.observationTargets.length === 0;
  421. if (getObservationIndex(detail.observationTargets, target) < 0) {
  422. firstObservation && resizeObservers.push(detail);
  423. detail.observationTargets.push(new ResizeObservation(target, options && options.box));
  424. updateCount(1);
  425. scheduler.schedule();
  426. }
  427. };
  428. ResizeObserverController.unobserve = function (resizeObserver, target) {
  429. var detail = observerMap.get(resizeObserver);
  430. var index = getObservationIndex(detail.observationTargets, target);
  431. var lastObservation = detail.observationTargets.length === 1;
  432. if (index >= 0) {
  433. lastObservation && resizeObservers.splice(resizeObservers.indexOf(detail), 1);
  434. detail.observationTargets.splice(index, 1);
  435. updateCount(-1);
  436. }
  437. };
  438. ResizeObserverController.disconnect = function (resizeObserver) {
  439. var _this = this;
  440. var detail = observerMap.get(resizeObserver);
  441. detail.observationTargets.slice().forEach(function (ot) { return _this.unobserve(resizeObserver, ot.target); });
  442. detail.activeTargets.splice(0, detail.activeTargets.length);
  443. };
  444. return ResizeObserverController;
  445. }());
  446. var ResizeObserver = (function () {
  447. function ResizeObserver(callback) {
  448. if (arguments.length === 0) {
  449. throw new TypeError("Failed to construct 'ResizeObserver': 1 argument required, but only 0 present.");
  450. }
  451. if (typeof callback !== 'function') {
  452. throw new TypeError("Failed to construct 'ResizeObserver': The callback provided as parameter 1 is not a function.");
  453. }
  454. ResizeObserverController.connect(this, callback);
  455. }
  456. ResizeObserver.prototype.observe = function (target, options) {
  457. if (arguments.length === 0) {
  458. throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': 1 argument required, but only 0 present.");
  459. }
  460. if (!isElement(target)) {
  461. throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element");
  462. }
  463. ResizeObserverController.observe(this, target, options);
  464. };
  465. ResizeObserver.prototype.unobserve = function (target) {
  466. if (arguments.length === 0) {
  467. throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': 1 argument required, but only 0 present.");
  468. }
  469. if (!isElement(target)) {
  470. throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': parameter 1 is not of type 'Element");
  471. }
  472. ResizeObserverController.unobserve(this, target);
  473. };
  474. ResizeObserver.prototype.disconnect = function () {
  475. ResizeObserverController.disconnect(this);
  476. };
  477. ResizeObserver.toString = function () {
  478. return 'function ResizeObserver () { [polyfill code] }';
  479. };
  480. return ResizeObserver;
  481. }());
  482. exports.ResizeObserver = ResizeObserver;
  483. exports.ResizeObserverEntry = ResizeObserverEntry;
  484. exports.ResizeObserverSize = ResizeObserverSize;
  485. Object.defineProperty(exports, '__esModule', { value: true });
  486. }));