index.umd.js 16 KB

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