setMutationHandler

MutationObserver wrapper to wait for the specified CSS selector

Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greasyfork.org/scripts/12228/175122/setMutationHandler.js

  1. // ==UserScript==
  2. // @name setMutationHandler
  3. // @description MutationObserver wrapper to wait for the specified CSS selector
  4. // @namespace wOxxOm.scripts
  5. // @author wOxxOm
  6. // @grant none
  7. // @version 3.0.2
  8. // ==/UserScript==
  9.  
  10. function setMutationHandler(target, selector, handler, options) {
  11. // or setMutationHandler(selector, handler, options) {
  12. // or setMutationHandler(options) {
  13. if (typeof arguments[0] == 'string') {
  14. options = arguments[2] || {};
  15. handler = arguments[1];
  16. selector = arguments[0];
  17. target = document;
  18. } else if (arguments.length == 1 && target && typeof target.handler == 'function') {
  19. options = arguments[0];
  20. handler = options.handler;
  21. selector = options.selector;
  22. target = options.target || document;
  23. } else if (!(target instanceof Node)) {
  24. throw 'Bad params for setMutationHandler.\n' +
  25. 'A: [optional Node] target, [String] selector, [Function] handler, [optional Object] options\n' +
  26. 'B: [Object] options\n' +
  27. 'Options: target, selector, handler, processExisting, childList, attributes, characterData, subtree, attributeOldValue, characterDataOldValue, attributeFilter';
  28. } else
  29. options = options || {};
  30.  
  31. if (options.processExisting && target.querySelector(selector))
  32. handler.call(null, Array.prototype.slice.call(target.querySelectorAll(selector)));
  33. if (!options.attributes && !options.characterData && !options.childList && options.subtree === undefined)
  34. options.childList = options.subtree = true;
  35.  
  36. var cb;
  37. if (/^#[\w\d-]+$/.test(selector)) {
  38. selector = selector.substr(1);
  39. cb = MOhandlerForId;
  40. } else {
  41. cb = MOhandler;
  42. }
  43. var observer = new MutationObserver(cb);
  44. observer.observe(target, options || {subtree:true, childList:true});
  45. return observer;
  46.  
  47. function MOhandler(mutations) {
  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 (handler.call(observer, found) === false)
  87. observer.disconnect();
  88. }
  89.  
  90. function MOhandlerForId(mutations) {
  91. var el = document.getElementById(selector);
  92. if (el && target.contains(el))
  93. if (handler.call(observer, [el]) === false)
  94. observer.disconnect();
  95. }
  96. }