AJAX plugin - SkIvLib

AJAX plugin by Ivan Skvortsov

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/31953/209659/AJAX%20plugin%20-%20SkIvLib.js

  1. // ==UserScript==
  2. // @name AJAX plugin - SkIvLib
  3. // @description AJAX plugin by Ivan Skvortsov
  4. // @description:ru AJAX плагин от Ivan Skvortsov
  5. // @include *://*
  6. // @author Ivan Skvortsov
  7. // @version 1.1.3
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function(){
  12. var clog = function(){};
  13. if( !clog )
  14. clog = console.log;
  15. var factory = [], queue = [], request_in_progress = false, queue_cleaned = true;
  16. var xhttpResponse = [];
  17. function addXHttpResponse( responseText )
  18. {
  19. if( typeof responseText !== 'string' )
  20. return xhttpResponse.push({invalid: true});
  21. xhttpResponse.push({
  22. invalid: false,
  23. text: responseText,
  24. get bytes(){ return this.text.length; },
  25. get Kb(){ return this.bytes/1024; },
  26. get Mb(){ return this.bytes/(1024 * 1024); },
  27. });
  28. }
  29. function queueStatus()
  30. {
  31. return "queueStatus:\n" +
  32. "queue.length = " + queue.length + "\n" +
  33. "in_progress = " + request_in_progress + "\n" +
  34. "cleaned = " + queue_cleaned + "\n" +
  35. "--------------";
  36. }
  37. function requestStatus( request )
  38. {
  39. return "requestStatus:\n" +
  40. "method = " + request.method + "\n" +
  41. "url = " + request.url + "\n" +
  42. "async = " + request.async + "\n" +
  43. "data = " + request.data + "\n" +
  44. //"onload = " + request.onload + "\n" +
  45. "--------------";
  46. }
  47. function createNewObject( obj )
  48. {
  49. if( !obj )
  50. return {};
  51. var new_obj = {}, key, val;
  52. for( key in obj )
  53. {
  54. val = obj[key];
  55. if( Object.prototype.hasOwnProperty.call(obj, key) && val )
  56. new_obj[key] = val;
  57. }
  58. return new_obj;
  59. }
  60. function initXHttpFactory()
  61. {
  62. if( factory && factory.length > 0 )
  63. return;
  64. clog( "initXHttpFactory");
  65. factory = [
  66. function(){ return new XMLHttpRequest();},
  67. function(){ return new ActiveXObject('Msxml3.XMLHTTP');},
  68. function(){ return new ActiveXObject('Msxml2.XMLHTTP.6.0');},
  69. function(){ return new ActiveXObject('Msxml2.XMLHTTP.3.0');},
  70. function(){ return new ActiveXObject('Msxml2.XMLHTTP');},
  71. function(){ return new ActiveXObject('Microsoft.XMLHTTP');},
  72. ];
  73. }
  74. function createXHttp()
  75. {
  76. clog("createXHttp");
  77. initXHttpFactory();
  78. for( let i = 0; i < factory.length; ++i )
  79. {
  80. try{
  81. return factory[i]();
  82. }catch(error){}
  83. }
  84. console.error("[createXHttp] can't create xhttp object");
  85. return null;
  86. }
  87. function getXHttpRequest()
  88. {
  89. clog("getXHttpRequest : queue.length = " + queue.length);
  90. if( !(queue.length > 0) )
  91. return null;
  92. var request = queue[0];
  93. request.method = request.method || 'GET';
  94. if( request.method.toUpperCase() === 'GET' && request.data && request.data !== '' )
  95. {
  96. request.url += '?' + request.data;
  97. request.data = '';
  98. }
  99. request.async = (typeof request.async !== 'boolean' ? true : request.async );
  100. request.store = (typeof request.store !== 'boolean' ? false: request.store );
  101. clog( requestStatus(request) );
  102. return request;
  103. }
  104. function handleXHttpEvent( type, xhttp, request, event )
  105. {
  106. clog("handleXHttpEvent : url=" + request.url + ", type=" + type + ", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
  107. var context, response;
  108. if( request[type] )
  109. {
  110. response = xhttp;
  111. response.lengthComputable = xhttp.lengthComputable || event.lengthComputable || false;
  112. response.loaded = xhttp.loaded || event.loaded || 0;
  113. response.total = xhttp.total || event.total || 0;
  114. response.url = xhttp.responseURL || request.url;
  115. context = request.context || response;
  116. request[type].call( context, response.responseText );
  117. if( type === 'onerror' || type === 'onload' ||
  118. (type === 'onreadystatechange' && response.readyState == 4 && response.status == 200 && !request.onload ) )
  119. {
  120. addXHttpResponse( (request.store ? response.responseText : undefined) );
  121. request_in_progress = false;
  122. request.delay = request.delay > 20 ? request.delay : 20;
  123. setTimeout( XHttpRequest, request.delay );
  124. }
  125. }
  126. }
  127. function initXHttpEvents( xhttp, request )
  128. {
  129. var types = [
  130. 'onabort',
  131. 'onerror',
  132. 'onload',
  133. 'onloadend',
  134. 'onloadstart',
  135. 'onprogress',
  136. 'onreadystatechange',
  137. 'ontimeout',
  138. ];
  139. function addXHttpEventListener(type){
  140. if( request[type] )
  141. xhttp[type] = function XHttpEvents(event){handleXHttpEvent(type, xhttp, request, event);};
  142. }
  143. types.forEach( addXHttpEventListener );
  144. clog("initXHttpEvents: ", xhttp);
  145. }
  146. function initXHttp( xhttp, request )
  147. {
  148. initXHttpEvents( xhttp, request );
  149. for( let key in request.headers )
  150. {
  151. xhttp.setRequestHeader( key, request.headers[key] );
  152. }
  153. }
  154. function XHttpRequest()
  155. {
  156. var request, xhttp;
  157. request = getXHttpRequest();
  158. if( request && (request_in_progress === false || request.async === true) && queue.length > 0 )
  159. {
  160. clog("XHttpRequest");
  161. queue.shift();
  162. request_in_progress = true;
  163. xhttp = createXHttp();
  164. initXHttp( xhttp, request );
  165. clog("XHttpRequest : url=" + request.url + ", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
  166. xhttp.open( request.method, request.url, request.async );
  167. xhttp.send( request.data || null );
  168. }
  169. }
  170. function addXHttpRequest( ...args )
  171. {
  172. var request, url, settings;
  173. switch( args.length )
  174. {
  175. case 0:
  176. return;
  177. case 1:
  178. request = args[0];
  179. clog("request: ", request);
  180. if( request.length )
  181. request.forEach( function(req){ queue.push(req);} );
  182. else
  183. queue.push(request);
  184. break;
  185. case 2:
  186. url = args[0];
  187. settings = args[1];
  188. clog("request: url=" + url + ", settings: ", settings);
  189. if( url.length )
  190. url.forEach( function(u){queue.push(constructXHttpRequest(u, settings));});
  191. else
  192. queue.push( constructXHttpRequest(url, settings) );
  193. break;
  194. default:
  195. return;
  196. }
  197. queue_cleaned = false;
  198. }
  199. function constructXHttpRequest( url, settings )
  200. {
  201. var request = createNewObject(settings);
  202. request.url = url;
  203. return request;
  204. }
  205. function cleanXHttpQueue()
  206. {
  207. xhttpResponse.length = 0;
  208. queue.length = 0;
  209. request_in_progress = false;
  210. queue_cleaned = true;
  211. }
  212. function queueLength()
  213. {
  214. return queue.length;
  215. }
  216. function getXHttpResponse(index)
  217. {
  218. if( !index || index < 0 )
  219. return xhttpResponse;
  220. else if( xhttpResponse.length > 0 )
  221. return xhttpResponse[index];
  222. else
  223. return {text: '', invalid: true, bytes:0, Kb: 0, Mb: 0};
  224. }
  225. window.SkIvLib = window.SkIvLib || {};
  226. // AJAX API
  227. SkIvLib.ajaxResponse = getXHttpResponse;
  228. SkIvLib.ajaxClean = cleanXHttpQueue;
  229. SkIvLib.ajaxLength = queueLength;
  230. SkIvLib.ajaxStatus = queueStatus;
  231. SkIvLib.ajaxAddXHR = addXHttpRequest;
  232. SkIvLib.ajax = function(...args)
  233. {
  234. xhttpResponse.length = 0;
  235. addXHttpRequest(...args);
  236. console.log("SkIvLib.ajax(): length = " + this.ajaxLength());
  237. XHttpRequest();
  238. };
  239. })();