setMutationHandler

MutationObserver wrapper to wait for the specified CSS selector

目前為 2017-02-10 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/12228/174273/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. // the observation target parameter may be omitted so "document" will be used by default:
  15. // setMutationHandler('#some-id', function(nodes) { ....... });
  16. */
  17.  
  18. // ==UserScript==
  19. // @name setMutationHandler
  20. // @description MutationObserver wrapper to wait for the specified CSS selector
  21. // @namespace wOxxOm.scripts
  22. // @author wOxxOm
  23. // @grant none
  24. // @version 2.1.1
  25. // ==/UserScript==
  26.  
  27. function setMutationHandler(baseNode, selector, cb, options) {
  28. if (typeof baseNode == 'string') {
  29. options = cb;
  30. cb = selector;
  31. selector = baseNode;
  32. baseNode = document;
  33. }
  34.  
  35. var ob;
  36.  
  37. if (/^#[\w\d-]+$/.test(selector)) {
  38. selector = selector.substr(1);
  39. ob = new MutationObserver(MOhandlerForId);
  40. } else {
  41. ob = new MutationObserver(MOhandler);
  42. }
  43.  
  44. ob.observe(baseNode || document, options || {subtree:true, childList:true});
  45. return ob;
  46.  
  47. function MOhandler(mutations, observer) {
  48. if (mutations.length > 100 && !document.querySelector(selector))
  49. return;
  50. var found = [];
  51. for (var i=0, m; (m = mutations[i++]); ) {
  52. switch (m.type) {
  53. case 'childList':
  54. var nodes = m.addedNodes, nl = nodes.length;
  55. var textNodesOnly = true;
  56. for (var j=0; j < nl; j++) {
  57. var n = nodes[j];
  58. textNodesOnly &= n.nodeType == 3; // TEXT_NODE
  59. if (n.nodeType != 1) // ELEMENT_NODE
  60. continue;
  61. if (n.matches(selector))
  62. found.push(n);
  63. else if (n.querySelector(selector)) {
  64. n = n.querySelectorAll(selector);
  65. if (n.length < 1000)
  66. found.push.apply(found, n);
  67. else
  68. found = found.concat(found.slice.call(n));
  69. }
  70. }
  71. if (textNodesOnly && m.target.matches(selector))
  72. found.push(m.target);
  73. break;
  74. case 'attributes':
  75. if (m.target.matches(selector))
  76. found.push(m.target);
  77. break;
  78. case 'characterData':
  79. if (m.target.parentNode && m.target.parentNode.matches(selector))
  80. found.push(m.target.parentNode);
  81. break;
  82. }
  83. }
  84. if (!found.length)
  85. return;
  86. if (cb.call(ob, found) === false)
  87. ob.disconnect();
  88. }
  89.  
  90. function MOhandlerForId(mutations, observer) {
  91. var el = document.getElementById(selector);
  92. if (!el || !baseNode.contains(el))
  93. return;
  94. if (cb.call(ob, [el]) === false)
  95. ob.disconnect();
  96. }
  97. }