watch.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import {ElementRef} from '@angular/core';
  2. import extend from 'lodash-es/extend';
  3. import {IncrementalStackManager} from '@ex-helpers/stack';
  4. import {bounds} from './bounds';
  5. import './element';
  6. interface SizeCollectionItem {
  7. triggerCheck: () => void;
  8. startCountdown: () => void;
  9. callback: (height: number, width: number) => void;
  10. observer?: MutationObserver;
  11. id?: number;
  12. legacy?: boolean;
  13. }
  14. const DEFAULT_OPTIONS = {
  15. attributes: true,
  16. childList: true,
  17. characterData: true
  18. };
  19. ElementRef.prototype.watchSize = function
  20. (callback: (height: number, width: number) => void,
  21. options?: { attributes?: boolean, childList?: boolean, characterData?: boolean },
  22. params: { timeout?: number, legacy: boolean } = {legacy: false}) {
  23. if (!this._watchSizeCollection) {
  24. Object.defineProperty(this, '_watchSizeCollection', {
  25. enumerable: false,
  26. configurable: true,
  27. writable: false,
  28. value: new IncrementalStackManager<SizeCollectionItem>('id')
  29. });
  30. }
  31. options = extend(DEFAULT_OPTIONS, options);
  32. let timeout: any;
  33. let lastHeight: number;
  34. let lastWidth: number;
  35. const triggerCheck = () => {
  36. const sizes = bounds(this.nativeElement).size;
  37. if (lastWidth === sizes.width && lastHeight === sizes.height) {
  38. return;
  39. }
  40. lastHeight = sizes.height;
  41. lastWidth = sizes.width;
  42. callback(sizes.height, sizes.width);
  43. };
  44. const startCountdown = () => {
  45. clearTimeout(timeout);
  46. timeout = setTimeout(() => {
  47. triggerCheck();
  48. }, params.timeout || 100);
  49. };
  50. const item = this._watchSizeCollection.add({
  51. callback,
  52. startCountdown,
  53. triggerCheck
  54. });
  55. if (MutationObserver && params.legacy === false) {
  56. const observer = new MutationObserver(mutations => {
  57. startCountdown();
  58. });
  59. item.observer = observer;
  60. item.legacy = false;
  61. startCountdown();
  62. observer.observe(this.nativeElement, options);
  63. return () => observer.disconnect();
  64. } else {
  65. item.legacy = true;
  66. const checkInterval = setInterval(() => {
  67. triggerCheck();
  68. }, 200);
  69. startCountdown();
  70. return () => clearInterval(checkInterval);
  71. }
  72. };
  73. ElementRef.prototype.triggerSizeCheck = function () {
  74. if (this._watchSizeCollection) {
  75. this._watchSizeCollection.execute('triggerCheck');
  76. }
  77. };
  78. ElementRef.prototype.watchChanges = function (callback: MutationCallback, options: MutationObserverInit) {
  79. if (MutationObserver) {
  80. const observer = new MutationObserver(callback);
  81. observer.observe(this.nativeElement, options);
  82. return () => observer.disconnect();
  83. }
  84. return () => {
  85. };
  86. };