使用上次输入的值自动填写表格

对所有网站生效,支持SPA(比如vue)动态插入的input和select。比如可以自动填写用户名和密码,自动点击同意协议。浏览器需要安装Tampermonkey或者Greasemonkey扩展,安卓手机浏览器推荐Yandex或者Kiwi浏览器。

  1. // ==UserScript==
  2. // @name fill the input and select of form as last time inputed automatically
  3. // @name:zh-CN 使用上次输入的值自动填写表格
  4. // @namespace http://tampermonkey.net/
  5. // @description This script supports SPA like vue。
  6. // @description:zh-CN 对所有网站生效,支持SPA(比如vue)动态插入的input和select。比如可以自动填写用户名和密码,自动点击同意协议。浏览器需要安装Tampermonkey或者Greasemonkey扩展,安卓手机浏览器推荐Yandex或者Kiwi浏览器。
  7. // @include http://*
  8. // @include https://*
  9. // @exclude https://www.baidu.com/*
  10. // @exclude https://www.google.com*
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @author yechenyin
  14. // @license MIT
  15. // @version 1.0.3
  16. // ==/UserScript==
  17. //闭包里的方法的用法和jquery同命名方法一致
  18. (function () {
  19. var jQuery = function (selector) {
  20. return new jQuery.fn.init(selector)
  21. }
  22. jQuery.fn = jQuery.prototype = {
  23. length: 0,
  24. selector: '',
  25. init: function (elementOrSelector) {
  26. var nodes = []
  27. if (typeof (elementOrSelector) == 'string') {
  28. this.selector = elementOrSelector
  29. nodes = document.querySelectorAll(this.selector)
  30. } else if (elementOrSelector instanceof NodeList) {
  31. nodes = elementOrSelector
  32. } else if (elementOrSelector instanceof Element) {
  33. nodes = [elementOrSelector]
  34. }
  35. this.length = nodes.length
  36. for (var i = 0; i < nodes.length; i++) {
  37. this[i] = nodes[i]
  38. }
  39. },
  40. each: function (callback) {
  41. for (var i = 0; i < this.length; i++) {
  42. callback.call(this[i])
  43. }
  44. },
  45. on: function (event, callback) {
  46. this.each(function () {
  47. this.addEventListener(event, callback)
  48. })
  49. },
  50. text: function (string) {
  51. var i = 0
  52. if (string !== undefined) {
  53. for (i = 0; i < this.length; i++) {
  54. this[i].innerText = string
  55. }
  56. } else {
  57. return this[0].innerText
  58. }
  59. },
  60. val: function (value) {
  61. if (value === undefined) {
  62. var ret
  63. if (this[0].type == 'checkbox')
  64. ret = this[0].checked
  65. else if (this[0].type == 'radio' || this[0].type == 'text' || this[0].type == 'password' || this[0].tagName == 'select')
  66. ret = this[0].value
  67. return ret
  68. } else {
  69. for (var i = 0; i < this.length; i++) {
  70. if (this[i].type == 'checkbox' && Boolean(value))
  71. this[i].click()
  72. else if (this[i].type == 'radio')
  73. this[i].checked = this[i].value == value
  74. else if (this[i].type == 'text')
  75. this[i].value = value
  76. else if (this[i].type == 'password')
  77. this[i].value = value
  78. else if (this[i].tagName == 'select')
  79. this[i].value = value
  80. this[i].dispatchEvent(new Event('input', { bubbles: true }))
  81. }
  82. }
  83. },
  84. attr: function (attribute, value) {
  85. if (value === undefined) {
  86. return this[0].getAttribute(attribute)
  87. } else {
  88. this.each(function () {
  89. this.setAttribute(attribute, value)
  90. })
  91. }
  92. },
  93. click: function () {
  94. this[0].click()
  95. },
  96. find: function (selector) {
  97. var j = 0
  98. var result = []
  99. for (var i = 0; i < this.length; i++) {
  100. if (this[i].querySelectorAll(selector).length) {
  101. }
  102. }
  103. },
  104. append: function (html) {
  105. for (var i = 0; i < this.length; i++) {
  106. this[i].innerHTML += html
  107. }
  108. },
  109. }
  110.  
  111. jQuery.fn.init.prototype = jQuery.fn
  112. if (!window.jQuery) window.jQuery = window.$ = jQuery
  113. })()
  114.  
  115. //每当符合选择器规则的元素插入到页面中时,唤起callback方法。如果trigger_once为true,只唤起一次
  116. jQuery.fn.inserted = function (callback, trigger_once = false) {
  117. var selector = this.selector;
  118. if ($(selector).length > 0) {
  119. //log($(selector).length + ' ' + selector + " is loaded at begin");
  120. callback.call($(selector));
  121. }
  122. var finished = false
  123. var recall = function (mutationsList, observer) {
  124. for (var i = 0; i < mutationsList.length; i++) {
  125. //log(mutationsList[i].target)
  126. if (mutationsList[i].addedNodes) {
  127. for (var j = 0; j < mutationsList[i].addedNodes.length; j++) {
  128. var element = mutationsList[i].addedNodes[j]
  129. if (!(trigger_once && finished) && element instanceof Element && element.querySelectorAll(selector).length) {
  130. var container = ''
  131. if (element.id)
  132. container = '#' + element.id
  133. else if (element.className)
  134. container = '.' + element.className
  135. else
  136. container = element.outerHtml
  137. //log(container + ' which contains ' + selector + ' is loaded')
  138. if (trigger_once) {
  139. observer.disconnect()
  140. finished = true
  141. }
  142. callback.call($(element.querySelectorAll(selector)))
  143. }
  144. }
  145. }
  146. }
  147. };
  148. var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
  149. if (MutationObserver) {
  150. var observer = new MutationObserver(recall)
  151. observer.observe(document.body, {
  152. childList: true,
  153. subtree: true
  154. })
  155. }
  156. }
  157.  
  158. //当符合选择器规则的元素插入到页面中时,调用一次callback方法,之后不会再唤起
  159. jQuery.fn.loaded = function (callback) {
  160. if (callback)
  161. this.inserted(callback, true);
  162. }
  163.  
  164. //每当元素类名变化时,唤起callback方法
  165. jQuery.fn.onClassChanged = function (callback) {
  166. var recall = function (mutationsList, observer) {
  167. for (var i = 0; i < mutationsList.length; i++) {
  168. //log(mutationsList[i].target)
  169. if (mutationsList[i].type === 'attributes' && mutationsList[i].attributeName === 'class') {
  170. //callback.call($(mutationsList[i].target))
  171. callback.call(mutationsList[i].target)
  172. }
  173. }
  174. };
  175. var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
  176. if (MutationObserver) {
  177. var observer = new MutationObserver(recall)
  178. var list = document.querySelectorAll(this.selector)
  179. for (var i = 0; i < list.length; i++) {
  180. observer.observe(list[i], { attributes: true })
  181. }
  182. }
  183. }
  184.  
  185. //在元素加载完成后经过delay(单位毫秒)延迟后点击元素
  186. jQuery.fn.clickAfterLoaded = function (delay = 0) {
  187. this.loaded(function () {
  188. setTimeout(function () {
  189. this[0].click()
  190. }.bind(this), delay)
  191. })
  192. }
  193. //在元素加载完成后经过delay(单位毫秒)延迟后设置输入值
  194. jQuery.fn.setAfterLoaded = function (value, delay = 0) {
  195. this.loaded(function () {
  196. setTimeout(function () {
  197. this.val(value)
  198. }.bind(this), delay)
  199. })
  200. }
  201.  
  202. //替代得到http成功回应后的回调
  203. $.replaceResponseCallback = function (callback, continueOriginalCallback = false) {
  204. var open = XMLHttpRequest.prototype.open
  205. XMLHttpRequest.prototype.open = function () {
  206. this.addEventListener(
  207. 'readystatechange',
  208. function () {
  209. if (
  210. this.readyState == 4 &&
  211. this.response
  212. ) {
  213. callback.call(this)
  214. }
  215. },
  216. false
  217. )
  218. if (continueOriginalCallback)
  219. open.apply(this, arguments)
  220. XMLHttpRequest.prototype.open = open
  221. }
  222. }
  223. //url改变后唤起callback,支持监测SPA的#后面的字符串变化
  224. $.onUrlChange = function (callback) {
  225. history.pushState = ((f) =>
  226. function pushState() {
  227. var ret = f.apply(this, arguments)
  228. window.dispatchEvent(new Event('pushstate'))
  229. window.dispatchEvent(new Event('urlchange'))
  230. return ret
  231. })(history.pushState)
  232.  
  233. history.replaceState = ((f) =>
  234. function replaceState() {
  235. var ret = f.apply(this, arguments)
  236. window.dispatchEvent(new Event('replacestate'))
  237. window.dispatchEvent(new Event('urlchange'))
  238. return ret
  239. })(history.replaceState)
  240.  
  241. window.addEventListener('popstate', () => {
  242. window.dispatchEvent(new Event('urlchange'))
  243. })
  244. window.addEventListener('urlchange', function () {
  245. callback()
  246. })
  247. }
  248.  
  249. jQuery.fn.saveChangedValue = function () {
  250. var that = this
  251. that.on('change', function () {
  252. //log(that)
  253. var href = 'inputed_' + location.href.replace(/\?.*/, '')
  254. var inputs = ''
  255. if (typeof GM_getValue === 'undefined')
  256. inputs = localStorage[href]
  257. else if (GM_getValue(href)) {
  258. inputs = GM_getValue(href)
  259. }
  260. if (inputs)
  261. inputs = JSON.parse(inputs)
  262. else
  263. inputs = {}
  264. //log(this.constructor.name)
  265. //log(Object.keys(this))
  266. var name = ''
  267. for (var i = 0; i < that.length; i++) {
  268. if (this == that[i])
  269. name = i
  270. }
  271. inputs[name] = $(this).val()
  272. log(name, inputs[name])
  273. if (typeof GM_setValue === 'undefined')
  274. localStorage[href] = JSON.stringify(inputs)
  275. else
  276. GM_setValue(href, JSON.stringify(inputs))
  277. //log(GM_getValue(href))
  278. })
  279. }
  280. jQuery.fn.recoverSavedValue = function () {
  281. this.inserted(function () {
  282. var that = this
  283. var href = 'inputed_' + location.href.replace(/\?.*/, '')
  284. var inputs = ''
  285. if (typeof GM_getValue === 'undefined')
  286. inputs = localStorage[href]
  287. else if (GM_getValue(href)) {
  288. inputs = GM_getValue(href)
  289. }
  290. if (inputs)
  291. inputs = JSON.parse(inputs)
  292. else
  293. inputs = {}
  294. log(inputs)
  295. if (Object.keys(inputs).length) {
  296. this.each(function () {
  297. var name = ''
  298. for (var i = 0; i < that.length; i++) {
  299. if (this == that[i])
  300. name = i
  301. }
  302. log(name)
  303. if (inputs.hasOwnProperty(name)) {
  304. $(this).val(inputs[name])
  305. }
  306. })
  307. }
  308. })
  309. }
  310.  
  311. function log(info) {
  312. var printInConsole = false;
  313. if (printInConsole) {
  314. console.log(info)
  315. }
  316. }
  317.  
  318. window.onload = function () {
  319. $('input, select').recoverSavedValue()
  320. $('input, select').inserted(function () {
  321. $('input, select').saveChangedValue()
  322. $('.el-select-dropdown__item').onClassChanged(function () {
  323. if (this.classList.contains('selected')) {
  324. log(this.innerText)
  325. }
  326. })
  327. })
  328. }

QingJ © 2025

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