setMutationHandler

MutationObserver wrapper to wait for the specified CSS selector

当前为 2017-02-10 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/12228/174269/setMutationHandler.js

  1. /* EXAMPLE:
  2.  
  3. setMutationHandler(document, '.container p.some-child', function(nodes) {
  4. // single node:
  5. nodes[0].remove();
  6.  
  7. // or multiple nodes:
  8. nodes.forEach(node => node.style.display = 'none');
  9.  
  10. // disconnect the observer, this is useful for one-time jobs
  11. return false;
  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.1.0
  22. // ==/UserScript==
  23.  
  24. function setMutationHandler(baseNode, selector, cb, options) {
  25. baseNode = baseNode || document;
  26. var ob;
  27. if (/^#[\w\d-]+$/.test(selector)) {
  28. selector = selector.substr(1);
  29. ob = new MutationObserver(MOhandlerForId);
  30. } else {
  31. ob = new MutationObserver(MOhandler);
  32. }
  33. ob.observe(baseNode, options || {subtree:true, childList:true});
  34. return ob;
  35.  
  36. function MOhandler(mutations, observer) {
  37. if (mutations.length > 100 && !document.querySelector(selector))
  38. return;
  39. var found = [];
  40. for (var i=0, m; (m = mutations[i++]); ) {
  41. switch (m.type) {
  42. case 'childList':
  43. var nodes = m.addedNodes, nl = nodes.length;
  44. var textNodesOnly = true;
  45. for (var j=0; j < nl; j++) {
  46. var n = nodes[j];
  47. textNodesOnly &= n.nodeType == 3; // TEXT_NODE
  48. if (n.nodeType != 1) // ELEMENT_NODE
  49. continue;
  50. if (n.matches(selector))
  51. found.push(n);
  52. else if (n.querySelector(selector)) {
  53. n = n.querySelectorAll(selector);
  54. if (n.length < 1000)
  55. found.push.apply(found, n);
  56. else
  57. found = found.concat(found.slice.call(n));
  58. }
  59. }
  60. if (textNodesOnly && m.target.matches(selector))
  61. found.push(m.target);
  62. break;
  63. case 'attributes':
  64. if (m.target.matches(selector))
  65. found.push(m.target);
  66. break;
  67. case 'characterData':
  68. if (m.target.parentNode && m.target.parentNode.matches(selector))
  69. found.push(m.target.parentNode);
  70. break;
  71. }
  72. }
  73. if (!found.length)
  74. return;
  75. if (cb.call(ob, found) === false)
  76. ob.disconnect();
  77. }
  78.  
  79. function MOhandlerForId(mutations, observer) {
  80. var el = document.getElementById(selector);
  81. if (!el || !baseNode.contains(el))
  82. return;
  83. if (cb.call(ob, [el]) === false)
  84. ob.disconnect();
  85. }
  86. }