jQ EveryWhere

Load jQuery quickly in every site without jQ loaded. Uses CDNJS API and JSCode Storage to make sure we uses the latest version and be also available in limited network. Uses GM storage function to store jQuery code, in order to decrease unneccessary networking and speed up browsing.

  1. // ==UserScript==
  2. // @name jQ EveryWhere
  3. // @namespace jQ EveryWhere
  4. // @version 2020.12.31.5
  5. // @description Load jQuery quickly in every site without jQ loaded. Uses CDNJS API and JSCode Storage to make sure we uses the latest version and be also available in limited network. Uses GM storage function to store jQuery code, in order to decrease unneccessary networking and speed up browsing.
  6. // @description:zh-CN 在没有jQuery库的网页上自动加载jQuery。程序使用来自CDNJS的jQuery库并使用CDNJS的API保证使用的jQuery库是最新版本。由于jQuery加载自CDNJS,所以没有翻墙也可以正常工作。使用了GM方法对jQuery的代码进行本地化存储,减少对同一版本的jQuery进行重复地网络请求,用以提升访问速度。
  7. // @author PY-DNG
  8. // @match http*://*/*
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_xmlhttpRequest
  12. // @connect cdnjs.cloudflare.com
  13. // @connect api.cdnjs.com
  14. // @run-at document-end
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. if (!checkjQ()) {getLatest();};
  21.  
  22. // Function: jQ, are you there?
  23. function checkjQ() {
  24. try {
  25. $();
  26. return true;
  27. } catch(e) {
  28. return false;
  29. }
  30. }
  31.  
  32. // Function: Get latest jQ Library from CDNJS
  33. function getLatest() {
  34. GM_xmlhttpRequest({
  35. method: 'GET',
  36. url: 'https://api.cdnjs.com/libraries/jquery?fields=version,latest',
  37. responseType : 'json',
  38. onload: function(request) {
  39. const reJson = request.response;
  40. const version = reJson['version'];
  41. const latestURL = reJson['latest'];
  42. insertjQ(latestURL, version);
  43. }
  44. })
  45. }
  46.  
  47. // Function: Insert jQuery Library
  48. function insertjQ(jQURL, version) {
  49. // Try to load from local first
  50. let code = GM_getValue('jQ_Code', null);
  51. if (code && versionGreaterOrEaqualThan(GM_getValue('jQ_Version', ''), version)) {
  52. insertJSCode(code);
  53. console.log('jQ inserted from GM_LocalStorage.');
  54. return code;
  55. };
  56.  
  57. // No local jQ stored. Get it from CDNJS.
  58. GM_xmlhttpRequest({
  59. method: 'GET',
  60. url: jQURL,
  61. responseType : 'text',
  62. onload: function(request) {
  63. code = request.responseText;
  64. // Insert jQ
  65. insertJSCode(code);
  66. console.log('jQ inserted from CDNJS.');
  67. // Store jQ code for next time
  68. GM_setValue('jQ_Code', code);
  69. // Store version if updated
  70. if (versionGreaterOrEaqualThan(version, GM_getValue('jQ_Version', ''))) {
  71. console.log('jQ upgraded from ' + GM_getValue('jQ_Version') + ' to ' + version + ' from CDNJS');
  72. GM_setValue('jQ_Version', version);
  73. }
  74. }
  75. })
  76. }
  77.  
  78. // Function: Insert javascript code into this page
  79. function insertJSCode(code) {
  80. const script = document.createElement('script');
  81. script.innerHTML = code;
  82. document.head.appendChild(script);
  83. }
  84.  
  85. // Function: Compare if ver_1 >= ver_2
  86. function versionGreaterOrEaqualThan(ver_1, ver_2) {
  87. // Split
  88. ver_1 = ver_1.split('.');
  89. ver_2 = ver_2.split('.');
  90.  
  91. // Compare number
  92. const len = Math.min(ver_1.length, ver_2.length);
  93. for (let i = 0; i < len; i++) {
  94. if (ver_1[i] > ver_2[i]) {
  95. return true;
  96. } else if (ver_1[i] < ver_2[i]) {
  97. return false;
  98. }
  99. }
  100.  
  101. // Compare length
  102. if (ver_1.length > ver_2.length) {
  103. return true;
  104. } else if (ver_1.length < ver_2.length) {
  105. return false;
  106. }
  107. return true;
  108. }
  109. })();