onElementReady

detect when an element is ready

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

  1. // This code from: https://gist.githubusercontent.com/zachhardesty7/ea61364567ce66b94edb81f922efecef/raw/c23ba499828992d632266194384c72ff28dfad6e/onElementReady.js
  2. // ==UserScript==
  3. // @name Library | onElementReady ES6
  4. // @namespace de.sidneys.userscripts
  5. // @homepage https://gist.githubusercontent.com/zachhardesty7/b19c33e4b2cec8861d55df10be0ce162/raw/
  6. // @version 0.6.0
  7. // @description Detect any new DOM Element by its CSS Selector, then trigger a function. Includes Promise- & Callback interface. Based on ES6 MutationObserver. Ships legacy waitForKeyElements interface, too.
  8. // @author sidneys
  9. // @icon https://i.imgur.com/nmbtzlX.png
  10. // @include *://*/*
  11. // ==/UserScript==
  12.  
  13. /**
  14. * ESLint
  15. * @exports
  16. */
  17. /* exported onElementReady */
  18. /* exported waitForKeyElements */
  19.  
  20.  
  21. /**
  22. * @private
  23. *
  24. * Query for new DOM nodes matching a specified selector.
  25. *
  26. * @param {String} selector - CSS Selector
  27. * @param {{ findFirst: boolean, findOnce: boolean }} options - Stop querying after first successful pass, find each el only a single time
  28. * @param {function=} callback - Callback
  29. */
  30. let queryForElements = (selector, options = { findFirst: false, findOnce: true }, callback) => {
  31. // Remember already-found elements via this attribute
  32. const attributeName = 'was-queried'
  33.  
  34. // Search for elements by selector
  35. let elementList = document.querySelectorAll(selector) || []
  36. elementList.forEach((element) => {
  37. if (element.hasAttribute(attributeName)) { return }
  38. element.setAttribute(attributeName, 'true')
  39. callback(element)
  40. // run reset after 2 seconds
  41. if (!options.findOnce) {
  42. setTimeout(() => {
  43. element.removeAttribute(attributeName)
  44. }, 2000)
  45. }
  46. })
  47. }
  48.  
  49. /**
  50. * @public
  51. *
  52. * Wait for Elements with a given CSS selector to enter the DOM.
  53. * Returns a Promise resolving with new Elements, and triggers a callback for every Element.
  54. *
  55. * @param {String} selector - CSS Selector
  56. * @param {{ findFirst: boolean, findOnce: boolean }} options - Stop querying after first successful pass, find each el only a single time
  57. * @param {function=} callback - Callback with Element
  58. * @returns {Promise<Element>} - Resolves with Element
  59. */
  60. let onElementReady = (selector, options = { findFirst: false, findOnce: true }, callback = () => {}) => {
  61. return new Promise((resolve) => {
  62. // Initial Query
  63. queryForElements(selector, options, (element) => {
  64. resolve(element)
  65. callback(element)
  66. })
  67.  
  68. // Continuous Query
  69. const observer = new MutationObserver(() => {
  70. // DOM Changes detected
  71. queryForElements(selector, options, (element) => {
  72. resolve(element)
  73. callback(element)
  74. })
  75.  
  76. if (options.findFirst) { observer.disconnect() }
  77. })
  78.  
  79. // Observe DOM Changes
  80. observer.observe(document.documentElement, {
  81. attributes: false,
  82. childList: true,
  83. subtree: true
  84. })
  85. })
  86. }
  87.  
  88. /**
  89. * @public
  90. * @deprecated
  91. *
  92. * waitForKeyElements Polyfill
  93. *
  94. * @param {String} selector - CSS selector of elements to search / monitor ('.comment')
  95. * @param {function} callback - Callback executed on element detection (called with element as argument)
  96. * @param {{ findFirst: boolean, findOnce: boolean }} options - Stop querying after first successful pass, find each el only a single time
  97. * @returns {Promise<Element>} - Element
  98. */
  99. let waitForKeyElements = (selector, callback, options) => onElementReady(selector, options, callback)