Greasy Fork is available in English.

jQuery-like SPA operation library

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

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