jQuery-like SPA operation library

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

Acest script nu ar trebui instalat direct. Aceasta este o bibliotecă pentru alte scripturi care este inclusă prin directiva meta a // @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. }