123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * Adopted from FastDom
  3. * https://github.com/wilsonpage/fastdom
  4. * MIT License
  5. */
  6. import { Injectable } from '@angular/core';
  7. import { Platform } from './platform';
  8. import { removeArrayItem } from '../util/util';
  9. /**
  10. * @hidden
  11. */
  12. export class DomDebouncer {
  13. constructor(dom) {
  14. this.dom = dom;
  15. this.writeTask = null;
  16. this.readTask = null;
  17. }
  18. read(fn) {
  19. if (this.readTask) {
  20. return;
  21. }
  22. return this.readTask = this.dom.read((t) => {
  23. this.readTask = null;
  24. fn(t);
  25. });
  26. }
  27. write(fn) {
  28. if (this.writeTask) {
  29. return;
  30. }
  31. return this.writeTask = this.dom.write((t) => {
  32. this.writeTask = null;
  33. fn(t);
  34. });
  35. }
  36. cancel() {
  37. const writeTask = this.writeTask;
  38. writeTask && this.dom.cancel(writeTask);
  39. const readTask = this.readTask;
  40. readTask && this.dom.cancel(readTask);
  41. this.readTask = this.writeTask = null;
  42. }
  43. }
  44. /**
  45. * @hidden
  46. */
  47. export class DomController {
  48. constructor(plt) {
  49. this.plt = plt;
  50. this.r = [];
  51. this.w = [];
  52. }
  53. debouncer() {
  54. return new DomDebouncer(this);
  55. }
  56. read(fn, timeout) {
  57. if (timeout) {
  58. fn.timeoutId = this.plt.timeout(() => {
  59. this.r.push(fn);
  60. this._queue();
  61. }, timeout);
  62. }
  63. else {
  64. this.r.push(fn);
  65. this._queue();
  66. }
  67. return fn;
  68. }
  69. write(fn, timeout) {
  70. if (timeout) {
  71. fn.timeoutId = this.plt.timeout(() => {
  72. this.w.push(fn);
  73. this._queue();
  74. }, timeout);
  75. }
  76. else {
  77. this.w.push(fn);
  78. this._queue();
  79. }
  80. return fn;
  81. }
  82. cancel(fn) {
  83. if (fn) {
  84. if (fn.timeoutId) {
  85. this.plt.cancelTimeout(fn.timeoutId);
  86. }
  87. removeArrayItem(this.r, fn) || removeArrayItem(this.w, fn);
  88. }
  89. }
  90. _queue() {
  91. const self = this;
  92. if (!self.q) {
  93. self.q = true;
  94. self.plt.raf(function rafCallback(timeStamp) {
  95. self._flush(timeStamp);
  96. });
  97. }
  98. }
  99. _flush(timeStamp) {
  100. let err;
  101. try {
  102. dispatch(timeStamp, this.r, this.w);
  103. }
  104. catch (e) {
  105. err = e;
  106. }
  107. this.q = false;
  108. if (this.r.length || this.w.length) {
  109. this._queue();
  110. }
  111. if (err) {
  112. throw err;
  113. }
  114. }
  115. }
  116. DomController.decorators = [
  117. { type: Injectable },
  118. ];
  119. /** @nocollapse */
  120. DomController.ctorParameters = () => [
  121. { type: Platform, },
  122. ];
  123. function dispatch(timeStamp, r, w) {
  124. let fn;
  125. // ******** DOM READS ****************
  126. while (fn = r.shift()) {
  127. fn(timeStamp);
  128. }
  129. // ******** DOM WRITES ****************
  130. while (fn = w.shift()) {
  131. fn(timeStamp);
  132. }
  133. }
  134. //# sourceMappingURL=dom-controller.js.map