AJAX plugin - SkIvLib

AJAX plugin by Ivan Skvortsov

当前为 2017-08-02 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/31953/209386/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.0.1
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. var SkIvLib = {};
  12. (function(){
  13. if( !clog )
  14. var clog = console.log;
  15. var factory = [], queue = [], request_in_progress = false, queue_cleaned = true;
  16. function queue_status()
  17. {
  18. return "queue_status:\n" +
  19. "queue.length = " + queue.length + "\n" +
  20. "in_progress = " + request_in_progress + "\n" +
  21. "cleaned = " + queue_cleaned + "\n" +
  22. "--------------";
  23. }
  24. function request_status( request )
  25. {
  26. return "request_status:\n" +
  27. "method = " + request.method + "\n" +
  28. "url = " + request.url + "\n" +
  29. "async = " + request.async + "\n" +
  30. "data = " + request.data + "\n" +
  31. "onload = " + request.onload + "\n" +
  32. "--------------";
  33. }
  34. function createNewObject( obj )
  35. {
  36. var new_obj = {}, key, val;
  37. for( key in obj )
  38. {
  39. val = obj[key];
  40. if( Object.prototype.hasOwnProperty.call(obj, key) && val !== null )
  41. new_obj[key] = val;
  42. }
  43. return new_obj;
  44. }
  45. function initXHttpFactory()
  46. {
  47. if( factory && factory.length > 0 )
  48. return;
  49. clog( "initXHttpFactory : " + (factory ? factory.length : 0) );
  50. factory = [
  51. function(){ return new XMLHttpRequest();},
  52. function(){ return new ActiveXObject('Msxml3.XMLHTTP');},
  53. function(){ return new ActiveXObject('Msxml2.XMLHTTP.6.0');},
  54. function(){ return new ActiveXObject('Msxml2.XMLHTTP.3.0');},
  55. function(){ return new ActiveXObject('Msxml2.XMLHTTP');},
  56. function(){ return new ActiveXObject('Microsoft.XMLHTTP');},
  57. ];
  58. }
  59. function createXHttp()
  60. {
  61. clog("createXHttp");
  62. initXHttpFactory();
  63. for( let i = 0; i < factory.length; ++i )
  64. {
  65. try{
  66. return factory[i]();
  67. }catch(error){}
  68. }
  69. console.error("[createXHttp] can't create xhttp object");
  70. return null;
  71. }
  72. function ObjectToDataString( obj )
  73. {
  74. if( typeof obj === 'object' )
  75. {
  76. var data_str = '', val, key;
  77. for( key in obj )
  78. {
  79. val = obj[key];
  80. if( !Object.prototype.hasOwnProperty.call(obj, key) || !val )
  81. continue;
  82. data_str += key + '=' + val + '&';
  83. }
  84. return data_str.slice(0, -1);
  85. }
  86. else if( typeof obj === 'string' )
  87. return obj;
  88. else
  89. return ( obj ? (obj.toString && obj.toString()) : '' );
  90. }
  91. function getXHttpRequest()
  92. {
  93. clog("getXHttpRequest : queue.length = " + queue.length);
  94. var request = queue[0];
  95. request.method = request.method || 'GET';
  96. if( request.method.toUpperCase() === 'GET' && request.data && request.data !== '' )
  97. {
  98. request.url += '?' + request.data;
  99. request.data = '';
  100. }
  101. request.async = (request.async || true);
  102. clog( request_status(request) );
  103. return request;
  104. }
  105. function handleXHttpEvent( type, xhttp, request, event )
  106. {
  107. if( queue_cleaned )
  108. return;
  109. clog("handleXHttpEvent : url=" + request.url + ", type=" + type + "" +
  110. ", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
  111. var context, response;
  112. if( request[type] )
  113. {
  114. response = {
  115. lengthComputable: xhttp.lengthComputable || event.lengthComputable || null,
  116. loaded: xhttp.loaded || event.loaded || 0,
  117. readyState: xhttp.readyState,
  118. responseHeaders: xhttp.responseHeaders ||
  119. (typeof xhttp.getAllResponseHeaders === 'function' ? xhttp.getAllResponseHeaders() : null ) || '',
  120. responseText: xhttp.responseText || xhttp.response,
  121. status: xhttp.status,
  122. statusText: xhttp.statusText,
  123. total: xhttp.total || event.total || 0,
  124. url: xhttp.finalUrl || request.url,
  125. };
  126. context = request.context || response;
  127. request[type].call( context, response );
  128. if( type === 'onerror' || type === 'onload' )
  129. {
  130. request_in_progress = false;
  131. request.delay = request.delay > 20 ? request.delay : 20;
  132. setTimeout( XHttpRequest, request.delay );
  133. }
  134. }
  135. }
  136. function initXHttpEvents( xhttp, request )
  137. {
  138. clog("initXHttpEvents: ", xhttp);
  139. var types = [
  140. 'onerror',
  141. 'onload',
  142. 'onloadend',
  143. 'onloadstart',
  144. 'onprogress',
  145. 'onreadystatechange',
  146. ];
  147. function setXHttpEventListener(type){
  148. xhttp[type] = function(event){ handleXHttpEvent(type, xhttp, request, event); };
  149. }
  150. types.forEach( setXHttpEventListener );
  151. }
  152. function initXHttp( xhttp, request )
  153. {
  154. initXHttpEvents( xhttp, request );
  155. for( let key in request.headers )
  156. {
  157. xhttp.setRequestHeader( key, request.headers[key] );
  158. }
  159. }
  160. function XHttpRequest()
  161. {
  162. clog("---> XHttpRequest <---");
  163. var request, xhttp;
  164. request = getXHttpRequest();
  165. if( request && (request_in_progress === false || request.async === true) && queue.length > 0 )
  166. {
  167. queue.shift();
  168. request_in_progress = true;
  169. xhttp = createXHttp();
  170. initXHttp( xhttp, request );
  171. clog("XHttpRequest : url=" + request.url +
  172. ", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
  173. xhttp.open( request.method, request.url, request.async );
  174. xhttp.send( request.data || null );
  175. }
  176. }
  177. function addXHttpRequest( ...args )
  178. {
  179. var request, url, settings;
  180. switch( args.length )
  181. {
  182. case 0: return;
  183. case 1:
  184. request = args[0];
  185. clog('request: ', request);
  186. if( request.length )
  187. request.forEach( function(req){ queue.push(req);} );
  188. else
  189. queue.push(request);
  190. //queue_cleaned = false;
  191. break;
  192. case 2:
  193. url = args[0];
  194. settings = args[1];
  195. clog('request: url=' + url + ', settings: ', settings);
  196. if( url.length )
  197. url.forEach( function(u){queue.push(makeXHttpRequest(u, settings));});
  198. else
  199. queue.push( makeXHttpRequest(url, settings) );
  200. //queue_cleaned = false;
  201. break;
  202. default:
  203. return;
  204. //throw new Error("[addXHttpRequest] invalid arguments length: " + args.length );
  205. }
  206. /*
  207. if( request && request.length )
  208. {
  209. request.forEach( function(req){ queue.push(req);} );
  210. }
  211. else if( request )
  212. {
  213. queue.push(request);
  214. }
  215. else if( url && url.length )
  216. {
  217. url.forEach( function(u){queue.push(makeXHttpRequest(u, settings));});
  218. }
  219. else if( url )
  220. {
  221. queue.push( makeXHttpRequest(url, settings) );
  222. }
  223. else
  224. throw new Error("addXHttpRequest] can't add request, args: " + args);
  225. */
  226. queue_cleaned = false;
  227. }
  228. function makeXHttpRequest( url, settings )
  229. {
  230. var request = createNewObject(settings);
  231. request.url = url;
  232. return request;
  233. }
  234. function cleanXHttpQueue()
  235. {
  236. queue.length = 0;
  237. request_in_progress = false;
  238. queue_cleaned = true;
  239. }
  240. function queueLength()
  241. {
  242. return queue.length;
  243. }
  244. // AJAX API
  245. SkIvLib.ajaxClean = cleanXHttpQueue;
  246. SkIvLib.ajaxLength = queueLength;
  247. SkIvLib.ajaxStatus = queue_status;
  248. SkIvLib.ajaxAddXHR = addXHttpRequest;
  249. SkIvLib.ajax = function(...args)
  250. {
  251. clog('SkIvLib.ajax');
  252. addXHttpRequest(...args);
  253. XHttpRequest;
  254. }
  255. })();