index.esm.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import { ElementEvent, MutationEvent, runtime } from '@antv/g-lite';
  2. var MutationRecord = /*#__PURE__*/function () {
  3. MutationRecord.copy = function copy(original) {
  4. var record = new MutationRecord(original.type, original.target);
  5. record.addedNodes = original.addedNodes.slice();
  6. record.removedNodes = original.removedNodes.slice();
  7. record.previousSibling = original.previousSibling;
  8. record.nextSibling = original.nextSibling;
  9. record.attributeName = original.attributeName;
  10. record.attributeNamespace = original.attributeNamespace;
  11. record.oldValue = original.oldValue;
  12. return record;
  13. };
  14. function MutationRecord(type, target) {
  15. this.type = void 0;
  16. this.target = void 0;
  17. this.addedNodes = [];
  18. this.attributeName = null;
  19. this.attributeNamespace = null;
  20. this.nextSibling = null;
  21. this.oldValue = null;
  22. this.previousSibling = null;
  23. this.removedNodes = [];
  24. this.type = type;
  25. this.target = target;
  26. }
  27. return MutationRecord;
  28. }();
  29. var uidCounter = 0;
  30. var registrationsTable = new WeakMap();
  31. var Registration = /*#__PURE__*/function () {
  32. function Registration(observer, target, options) {
  33. this.observer = void 0;
  34. this.target = void 0;
  35. this.options = void 0;
  36. this.transientObservedNodes = [];
  37. this.observer = observer;
  38. this.target = target;
  39. this.options = options;
  40. }
  41. var _proto = Registration.prototype;
  42. _proto.enqueue = function enqueue(record) {
  43. var records = this.observer.records;
  44. var length = records.length;
  45. // There are cases where we replace the last record with the new record.
  46. // For example if the record represents the same mutation we need to use
  47. // the one with the oldValue. If we get same record (this can happen as we
  48. // walk up the tree) we ignore the new record.
  49. if (records.length > 0) {
  50. var lastRecord = records[length - 1];
  51. var recordToReplaceLast = selectRecord(lastRecord, record);
  52. if (recordToReplaceLast) {
  53. records[length - 1] = recordToReplaceLast;
  54. return;
  55. }
  56. } else {
  57. scheduleCallback(this.observer);
  58. }
  59. records[length] = record;
  60. };
  61. _proto.addListeners = function addListeners() {
  62. this.addListeners_(this.target);
  63. };
  64. _proto.addListeners_ = function addListeners_(node) {
  65. var options = this.options;
  66. if (options.attributes) node.addEventListener(ElementEvent.ATTR_MODIFIED, this, true);
  67. // if (options.characterData) node.addEventListener('DOMCharacterDataModified', this, true);
  68. if (options.childList) node.addEventListener(ElementEvent.INSERTED, this, true);
  69. if (options.childList || options.subtree) node.addEventListener(ElementEvent.REMOVED, this, true);
  70. };
  71. _proto.removeListeners = function removeListeners() {
  72. this.removeListeners_(this.target);
  73. };
  74. _proto.removeListeners_ = function removeListeners_(node) {
  75. var options = this.options;
  76. if (options.attributes) node.removeEventListener(ElementEvent.ATTR_MODIFIED, this, true);
  77. // if (options.characterData) node.removeEventListener('DOMCharacterDataModified', this, true);
  78. if (options.childList) node.removeEventListener(ElementEvent.INSERTED, this, true);
  79. if (options.childList || options.subtree) node.removeEventListener(ElementEvent.REMOVED, this, true);
  80. }
  81. /**
  82. * Adds a transient observer on node. The transient observer gets removed
  83. * next time we deliver the change records.
  84. */
  85. // addTransientObserver(node: IElement) {
  86. // // Don't add transient observers on the target itself. We already have all
  87. // // the required listeners set up on the target.
  88. // if (node === this.target) return;
  89. // this.addListeners_(node);
  90. // this.transientObservedNodes.push(node);
  91. // let registrations = registrationsTable.get(node);
  92. // if (!registrations) registrationsTable.set(node, (registrations = []));
  93. // // We know that registrations does not contain this because we already
  94. // // checked if node === this.target.
  95. // registrations.push(this);
  96. // }
  97. ;
  98. _proto.removeTransientObservers = function removeTransientObservers() {
  99. var transientObservedNodes = this.transientObservedNodes;
  100. this.transientObservedNodes = [];
  101. transientObservedNodes.forEach(function (node) {
  102. // Transient observers are never added to the target.
  103. this.removeListeners_(node);
  104. var registrations = registrationsTable.get(node);
  105. for (var i = 0; i < registrations.length; i++) {
  106. if (registrations[i] === this) {
  107. registrations.splice(i, 1);
  108. // Each node can only have one registered observer associated with
  109. // this observer.
  110. break;
  111. }
  112. }
  113. }, this);
  114. };
  115. _proto.handleEvent = function handleEvent(e) {
  116. // Stop propagation since we are managing the propagation manually.
  117. // This means that other mutation events on the page will not work
  118. // correctly but that is by design.
  119. e.stopImmediatePropagation();
  120. var record;
  121. var target;
  122. switch (e.type) {
  123. case ElementEvent.ATTR_MODIFIED:
  124. // http://dom.spec.whatwg.org/#concept-mo-queue-attributes
  125. var name = e.attrName;
  126. // @ts-ignore
  127. var namespace = e.relatedNode.namespaceURI;
  128. target = e.target;
  129. // 1.
  130. record = getRecord('attributes', target);
  131. record.attributeName = name;
  132. record.attributeNamespace = namespace;
  133. // 2.
  134. var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
  135. forEachAncestorAndObserverEnqueueRecord(target, function (options) {
  136. // 3.1, 4.2
  137. if (!options.attributes) return;
  138. // 3.2, 4.3
  139. if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) {
  140. return;
  141. }
  142. // 3.3, 4.4
  143. if (options.attributeOldValue) return getRecordWithOldValue(oldValue);
  144. // 3.4, 4.5
  145. return record;
  146. });
  147. break;
  148. // case 'DOMCharacterDataModified':
  149. // // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata
  150. // var target = e.target;
  151. // // 1.
  152. // var record = getRecord('characterData', target);
  153. // // 2.
  154. // var oldValue = e.prevValue;
  155. // forEachAncestorAndObserverEnqueueRecord(target, function(options) {
  156. // // 3.1, 4.2
  157. // if (!options.characterData)
  158. // return;
  159. // // 3.2, 4.3
  160. // if (options.characterDataOldValue)
  161. // return getRecordWithOldValue(oldValue);
  162. // // 3.3, 4.4
  163. // return record;
  164. // });
  165. // break;
  166. case ElementEvent.REMOVED:
  167. // this.addTransientObserver(e.target as IElement);
  168. // Fall through.
  169. case ElementEvent.INSERTED:
  170. // http://dom.spec.whatwg.org/#concept-mo-queue-childlist
  171. target = e.relatedNode;
  172. var changedNode = e.target;
  173. var addedNodes;
  174. var removedNodes;
  175. if (e.type === ElementEvent.INSERTED) {
  176. addedNodes = [changedNode];
  177. removedNodes = [];
  178. } else {
  179. addedNodes = [];
  180. removedNodes = [changedNode];
  181. }
  182. var previousSibling = changedNode.previousSibling;
  183. var nextSibling = changedNode.nextSibling;
  184. // 1.
  185. record = getRecord('childList', target);
  186. record.addedNodes = addedNodes;
  187. record.removedNodes = removedNodes;
  188. record.previousSibling = previousSibling;
  189. record.nextSibling = nextSibling;
  190. forEachAncestorAndObserverEnqueueRecord(target, function (options) {
  191. // 2.1, 3.2
  192. if (!options.childList) return;
  193. // 2.2, 3.3
  194. return record;
  195. });
  196. }
  197. clearRecords();
  198. };
  199. return Registration;
  200. }();
  201. /**
  202. * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  203. * @see https://github.com/googlearchive/MutationObservers/blob/master/MutationObserver.js
  204. */
  205. var MutationObserver = /*#__PURE__*/function () {
  206. function MutationObserver(callback) {
  207. this.callback = void 0;
  208. this.nodes = [];
  209. this.records = [];
  210. this.uid = uidCounter++;
  211. this.callback = callback;
  212. }
  213. var _proto2 = MutationObserver.prototype;
  214. _proto2.observe = function observe(target, options) {
  215. // 1.1
  216. if (!options.childList && !options.attributes && !options.characterData ||
  217. // 1.2
  218. options.attributeOldValue && !options.attributes ||
  219. // 1.3
  220. options.attributeFilter && options.attributeFilter.length && !options.attributes ||
  221. // 1.4
  222. options.characterDataOldValue && !options.characterData) {
  223. throw new SyntaxError();
  224. }
  225. var registrations = registrationsTable.get(target);
  226. if (!registrations) registrationsTable.set(target, registrations = []);
  227. // 2
  228. // If target's list of registered observers already includes a registered
  229. // observer associated with the context object, replace that registered
  230. // observer's options with options.
  231. var registration;
  232. for (var i = 0; i < registrations.length; i++) {
  233. if (registrations[i].observer === this) {
  234. registration = registrations[i];
  235. registration.removeListeners();
  236. registration.options = options;
  237. break;
  238. }
  239. }
  240. // 3.
  241. // Otherwise, add a new registered observer to target's list of registered
  242. // observers with the context object as the observer and options as the
  243. // options, and add target to context object's list of nodes on which it
  244. // is registered.
  245. if (!registration) {
  246. registration = new Registration(this, target, options);
  247. registrations.push(registration);
  248. this.nodes.push(target);
  249. }
  250. registration.addListeners();
  251. };
  252. _proto2.disconnect = function disconnect() {
  253. var _this = this;
  254. this.nodes.forEach(function (node) {
  255. var registrations = registrationsTable.get(node);
  256. for (var i = 0; i < registrations.length; i++) {
  257. var registration = registrations[i];
  258. if (registration.observer === _this) {
  259. registration.removeListeners();
  260. registrations.splice(i, 1);
  261. // Each node can only have one registered observer associated with
  262. // this observer.
  263. break;
  264. }
  265. }
  266. }, this);
  267. this.records = [];
  268. };
  269. _proto2.takeRecords = function takeRecords() {
  270. var copyOfRecords = this.records;
  271. this.records = [];
  272. return copyOfRecords;
  273. };
  274. return MutationObserver;
  275. }();
  276. // We keep track of the two (possibly one) records used in a single mutation.
  277. var currentRecord;
  278. var recordWithOldValue;
  279. /**
  280. * Creates a record without |oldValue| and caches it as |currentRecord| for
  281. * later use.
  282. */
  283. function getRecord(type, target) {
  284. return currentRecord = new MutationRecord(type, target);
  285. }
  286. /**
  287. * Gets or creates a record with |oldValue| based in the |currentRecord|
  288. */
  289. function getRecordWithOldValue(oldValue) {
  290. if (recordWithOldValue) return recordWithOldValue;
  291. recordWithOldValue = MutationRecord.copy(currentRecord);
  292. recordWithOldValue.oldValue = oldValue;
  293. return recordWithOldValue;
  294. }
  295. function clearRecords() {
  296. currentRecord = recordWithOldValue = undefined;
  297. }
  298. /**
  299. * Whether the record represents a record from the current
  300. * mutation event.
  301. */
  302. function recordRepresentsCurrentMutation(record) {
  303. return record === recordWithOldValue || record === currentRecord;
  304. }
  305. /**
  306. * Selects which record, if any, to replace the last record in the queue.
  307. * This returns |null| if no record should be replaced.
  308. */
  309. function selectRecord(lastRecord, newRecord) {
  310. if (lastRecord === newRecord) return lastRecord;
  311. // Check if the the record we are adding represents the same record. If
  312. // so, we keep the one with the oldValue in it.
  313. if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue;
  314. return null;
  315. }
  316. function removeTransientObserversFor(observer) {
  317. observer.nodes.forEach(function (node) {
  318. var registrations = registrationsTable.get(node);
  319. if (!registrations) return;
  320. registrations.forEach(function (registration) {
  321. if (registration.observer === observer) registration.removeTransientObservers();
  322. });
  323. });
  324. }
  325. /**
  326. * This function is used for the "For each registered observer observer (with
  327. * observer's options as options) in target's list of registered observers,
  328. * run these substeps:" and the "For each ancestor ancestor of target, and for
  329. * each registered observer observer (with options options) in ancestor's list
  330. * of registered observers, run these substeps:" part of the algorithms. The
  331. * |options.subtree| is checked to ensure that the callback is called
  332. * correctly.
  333. *
  334. * @param {Node} target
  335. * @param {function(MutationObserverInit):MutationRecord} callback
  336. */
  337. function forEachAncestorAndObserverEnqueueRecord(target, callback) {
  338. for (var node = target; node; node = node.parentNode) {
  339. var registrations = registrationsTable.get(node);
  340. if (registrations) {
  341. for (var j = 0; j < registrations.length; j++) {
  342. var registration = registrations[j];
  343. var options = registration.options;
  344. // Only target ignores subtree.
  345. if (node !== target && !options.subtree) continue;
  346. var record = callback(options);
  347. if (record) registration.enqueue(record);
  348. }
  349. }
  350. }
  351. }
  352. // This is used to ensure that we never schedule 2 callas to setImmediate
  353. var isScheduled = false;
  354. // Keep track of observers that needs to be notified next time.
  355. var scheduledObservers = [];
  356. /**
  357. * Schedules |dispatchCallback| to be called in the future.
  358. */
  359. function scheduleCallback(observer) {
  360. scheduledObservers.push(observer);
  361. if (!isScheduled) {
  362. isScheduled = true;
  363. // setImmediate(dispatchCallbacks);
  364. if (typeof runtime.globalThis !== 'undefined') {
  365. runtime.globalThis.setTimeout(dispatchCallbacks);
  366. } else {
  367. dispatchCallbacks();
  368. }
  369. }
  370. }
  371. function dispatchCallbacks() {
  372. // http://dom.spec.whatwg.org/#mutation-observers
  373. isScheduled = false; // Used to allow a new setImmediate call above.
  374. var observers = scheduledObservers;
  375. scheduledObservers = [];
  376. // Sort observers based on their creation UID (incremental).
  377. observers.sort(function (o1, o2) {
  378. return o1.uid - o2.uid;
  379. });
  380. var anyNonEmpty = false;
  381. observers.forEach(function (observer) {
  382. // 2.1, 2.2
  383. var queue = observer.takeRecords();
  384. // 2.3. Remove all transient registered observers whose observer is mo.
  385. removeTransientObserversFor(observer);
  386. // 2.4
  387. if (queue.length) {
  388. // @ts-ignore
  389. observer.callback(queue, observer);
  390. anyNonEmpty = true;
  391. }
  392. });
  393. // 3.
  394. if (anyNonEmpty) dispatchCallbacks();
  395. }
  396. export { MutationObserver, MutationRecord, Registration };