setMutationHandler

MutationObserver wrapper to wait for the specified CSS selector

As of 2016-07-20. See the latest version.

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/12228/137072/setMutationHandler.js

  1. /* EXAMPLE:
  2. setMutationHandler(document, '.container p.some-child', function(nodes) {
  3. // single node:
  4. nodes[0].remove();
  5. // or multiple nodes:
  6. nodes.forEach(function(node) {
  7. node.style.display = 'none';
  8. });
  9.  
  10. //this.disconnect(); // disconnect the observer, this is useful for one-time jobs
  11. return true; // continue enumerating current batch of mutations
  12. });
  13. */
  14.  
  15. // ==UserScript==
  16. // @name setMutationHandler
  17. // @description MutationObserver wrapper to wait for the specified CSS selector
  18. // @namespace wOxxOm.scripts
  19. // @author wOxxOm
  20. // @grant none
  21. // @version 2.0.6
  22. // ==/UserScript==
  23.  
  24. function setMutationHandler(baseNode, selector, cb, options) {
  25. var queue = [];
  26. var ob = new MutationObserver(function handler(mutations) {
  27. if (mutations && mutations.length > 100) {
  28. if (!queue.length)
  29. setTimeout(handler, 0);
  30. queue.push(mutations);
  31. return;
  32. }
  33. do {
  34. if (!mutations) {
  35. mutations = queue.shift();
  36. if (!mutations)
  37. return;
  38. }
  39.  
  40. for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++) {
  41. switch (m.type) {
  42. case 'childList':
  43. if (m.addedNodes[0] && m.addedNodes[0].nodeType == 3) { // TEXT_NODE
  44. if (m.target.matches(selector) && !cb.call(ob, [m.target], m))
  45. return;
  46. continue;
  47. }
  48. for (var j=0, nodes=m.addedNodes, nl=nodes.length, n; (j<nl) && (n=nodes[j]); j++)
  49. if (n.nodeType == 1) { // ELEMENT_NODE
  50. if (n.matches(selector))
  51. n = [n];
  52. else if (n.querySelector(selector))
  53. n = Array.prototype.slice.call(n.querySelectorAll(selector));
  54. else
  55. continue;
  56. if (!cb.call(ob, n, m))
  57. return;
  58. }
  59. break;
  60. case 'attributes':
  61. if (m.target.matches(selector) && !cb.call(ob, [m.target], m))
  62. return;
  63. break;
  64. case 'characterData':
  65. if (m.target.parentNode && m.target.parentNode.matches(selector) && !cb.call(ob, [m.target.parentNode], m))
  66. return;
  67. break;
  68. }
  69. }
  70. mutations = null;
  71. } while (queue.length);
  72. });
  73. ob.observe(baseNode, options || {subtree:true, childList:true});
  74. return ob;
  75. }