jQuery-like SPA operation library

SPA like vue is supported。offers functions like click element after loaded, call function after url change。

当前为 2022-02-20 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/440334/1020513/jQuery-like%20SPA%20operation%20library.js

  1. // ==UserScript==
  2. // @name jQuery-like SPA operation library
  3. // @description SPA like vue is supported。offers functions like click element after loaded, call function after url change。
  4. // @author yechenyin
  5. // @license MIT
  6. // @version 1.0.2
  7. // ==/UserScript==
  8.  
  9. //闭包里的方法的用法和jquery同命名方法一致
  10. (function () {
  11. let jQuery = function (selector) {
  12. return new jQuery.fn.init(selector)
  13. }
  14. jQuery.fn = jQuery.prototype = {
  15. length: 0,
  16. selector: '',
  17. init: function (elementOrSelector) {
  18. let nodes = []
  19. if (typeof (elementOrSelector) == 'string') {
  20. this.selector = elementOrSelector
  21. nodes = document.querySelectorAll(this.selector)
  22. } else if (elementOrSelector instanceof NodeList) {
  23. nodes = elementOrSelector
  24. } else if (elementOrSelector instanceof Element) {
  25. nodes = [elementOrSelector]
  26. }
  27. this.length = nodes.length
  28. for (let i = 0; i < nodes.length; i++) {
  29. this[i] = nodes[i]
  30. }
  31. },
  32. each: function (callback) {
  33. for (let i = 0; i < this.length; i++) {
  34. callback.call(this[i])
  35. }
  36. },
  37. on: function (event, callback) {
  38. this.each(function () {
  39. this.addEventListener(event, callback)
  40. })
  41. },
  42. text: function (string) {
  43. let i = 0
  44. if (string !== undefined) {
  45. for (i = 0; i < this.length; i++) {
  46. this[i].innerText = string
  47. }
  48. } else {
  49. return this[0].innerText
  50. }
  51. },
  52. val: function (value) {
  53. if (value === undefined) {
  54. let ret
  55. if (this[0].type == 'checkbox')
  56. ret = this[0].checked
  57. else if (this[0].type == 'radio' || this[0].type == 'text' || this[0].type == 'password' || this[0].tagName == 'select')
  58. ret = this[0].value
  59. return ret
  60. } else {
  61. for (let i = 0; i < this.length; i++) {
  62. if (this[i].type == 'checkbox' && Boolean(value))
  63. this[i].click()
  64. else if (this[i].type == 'radio')
  65. this[i].checked = this[i].value == value
  66. else if (this[i].type == 'text')
  67. this[i].value = value
  68. else if (this[i].type == 'password')
  69. this[i].value = value
  70. else if (this[i].tagName == 'select')
  71. this[i].value = value
  72. this[i].dispatchEvent(new Event('input', { bubbles: true }))
  73. }
  74. }
  75. },
  76. attr: function (attribute, value) {
  77. if (value === undefined) {
  78. return this[0].getAttribute(attribute)
  79. } else {
  80. this.each(function () {
  81. this.setAttribute(attribute, value)
  82. })
  83. }
  84. },
  85. click: function () {
  86. this[0].click()
  87. },
  88. find: function (selector) {
  89. let j = 0
  90. let result = []
  91. for (let i = 0; i < this.length; i++) {
  92. if (this[i].querySelectorAll(selector).length) {
  93. }
  94. }
  95. },
  96. append: function (html) {
  97. for (let i = 0; i < this.length; i++) {
  98. this[i].innerHTML += html
  99. }
  100. },
  101. }
  102.  
  103. jQuery.fn.init.prototype = jQuery.fn
  104. if (!window.jQuery) window.jQuery = window.$ = jQuery
  105. })()
  106.  
  107. //每当符合选择器规则的元素插入到页面中时,唤起callback方法。如果trigger_once为true,只唤起一次
  108. jQuery.fn.inserted = function (callback, trigger_once = false) {
  109. let selector = this.selector;
  110. if ($(selector).length > 0) {
  111. //console.log($(selector).length + ' ' + selector + " is loaded at begin");
  112. callback.call($(selector));
  113. }
  114. let finished = false
  115. let recallback = function (mutationsList, observer) {
  116. for (let i = 0; i < mutationsList.length; i++) {
  117. //console.log(mutationsList[i].target)
  118. if (mutationsList[i].addedNodes) {
  119. for (let j = 0; j < mutationsList[i].addedNodes.length; j++) {
  120. let element = mutationsList[i].addedNodes[j]
  121. if (!(trigger_once && finished) && element instanceof Element && element.querySelectorAll(selector).length) {
  122. let container = ''
  123. if (element.id)
  124. container = '#' + element.id
  125. else if (element.className)
  126. container = '.' + element.className
  127. else
  128. container = element.outerHtml
  129. //console.log(container + ' which contains ' + selector + ' is loaded')
  130. if (trigger_once) {
  131. observer.disconnect()
  132. finished = true
  133. }
  134. callback.call($(element.querySelectorAll(selector)))
  135. }
  136. }
  137. }
  138. }
  139. };
  140. let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
  141. if (MutationObserver) {
  142. let observer = new MutationObserver(recallback)
  143. observer.observe(document.body, {
  144. childList: true,
  145. subtree: true
  146. })
  147. }
  148. }
  149.  
  150. //当符合选择器规则的元素插入到页面中时,调用一次callback方法,之后不会在唤起
  151. jQuery.fn.loaded = function (callback) {
  152. if (callback)
  153. this.inserted(callback, true);
  154. }
  155.  
  156. //在元素加载完成后经过delay(单位毫秒)延迟后点击元素
  157. jQuery.fn.clickAfterLoaded = function (delay = 0) {
  158. this.loaded(function () {
  159. setTimeout(function () {
  160. this[0].click()
  161. }.bind(this), delay)
  162. })
  163. }
  164. //在元素加载完成后经过delay(单位毫秒)延迟后设置输入值
  165. jQuery.fn.setAfterLoaded = function (value, delay = 0) {
  166. this.loaded(function () {
  167. setTimeout(function () {
  168. this.val(value)
  169. }.bind(this), delay)
  170. })
  171. }
  172.  
  173. //替代得到http成功回应后的回调
  174. $.replaceResponseCallback = function (callback, continueOriginalCallback = false) {
  175. let open = XMLHttpRequest.prototype.open
  176. XMLHttpRequest.prototype.open = function () {
  177. this.addEventListener(
  178. 'readystatechange',
  179. function () {
  180. if (
  181. this.readyState == 4 &&
  182. this.response
  183. ) {
  184. callback.call(this)
  185. }
  186. },
  187. false
  188. )
  189. if (continueOriginalCallback)
  190. open.apply(this, arguments)
  191. XMLHttpRequest.prototype.open = open
  192. }
  193. }
  194. //url改变后唤起callback,支持监测SPA的#后面的字符串变化
  195. $.onurlchange = function (callback) {
  196. history.pushState = ((f) =>
  197. function pushState() {
  198. let ret = f.apply(this, arguments)
  199. window.dispatchEvent(new Event('pushstate'))
  200. window.dispatchEvent(new Event('urlchange'))
  201. return ret
  202. })(history.pushState)
  203.  
  204. history.replaceState = ((f) =>
  205. function replaceState() {
  206. let ret = f.apply(this, arguments)
  207. window.dispatchEvent(new Event('replacestate'))
  208. window.dispatchEvent(new Event('urlchange'))
  209. return ret
  210. })(history.replaceState)
  211.  
  212. window.addEventListener('popstate', () => {
  213. window.dispatchEvent(new Event('urlchange'))
  214. })
  215. window.addEventListener('urlchange', function () {
  216. callback()
  217. })
  218. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址