// ==UserScript==
// @name AJAX plugin - SkIvLib
// @description AJAX plugin by Ivan Skvortsov
// @description:ru AJAX плагин от Ivan Skvortsov
// @include *://*
// @author Ivan Skvortsov
// @version 1.0.0
// @grant none
// ==/UserScript==
(function(){
if( !clog )
var clog = console.log;
var factory = [], queue = [], request_in_progress = false, queue_cleaned = true;
function queue_status()
{
return "queue_status:\n" +
"queue.length = " + queue.length + "\n" +
"in_progress = " + request_in_progress + "\n" +
"cleaned = " + queue_cleaned + "\n" +
"--------------";
}
function request_status( request )
{
return "request_status:\n" +
"method = " + request.method + "\n" +
"url = " + request.url + "\n" +
"async = " + request.async + "\n" +
"data = " + request.data + "\n" +
"onload = " + request.onload + "\n" +
"--------------";
}
function createNewObject( obj )
{
var new_obj = {}, key, val;
for( key in obj )
{
val = obj[key];
if( Object.prototype.hasOwnProperty.call(obj, key) && val !== null )
new_obj[key] = val;
}
return new_obj;
}
function initXHttpFactory()
{
if( factory && factory.length > 0 )
return;
clog( "initXHttpFactory : " + (factory ? factory.length : 0) );
factory = [
function(){ return new XMLHttpRequest();},
function(){ return new ActiveXObject('Msxml3.XMLHTTP');},
function(){ return new ActiveXObject('Msxml2.XMLHTTP.6.0');},
function(){ return new ActiveXObject('Msxml2.XMLHTTP.3.0');},
function(){ return new ActiveXObject('Msxml2.XMLHTTP');},
function(){ return new ActiveXObject('Microsoft.XMLHTTP');},
];
}
function createXHttp()
{
clog("createXHttp");
initXHttpFactory();
for( let i = 0; i < factory.length; ++i )
{
try{
return factory[i]();
}catch(error){}
}
console.error("[createXHttp] can't create xhttp object");
return null;
}
function ObjectToDataString( obj )
{
if( typeof obj === 'object' )
{
var data_str = '', val, key;
for( key in obj )
{
val = obj[key];
if( !Object.prototype.hasOwnProperty.call(obj, key) || !val )
continue;
data_str += key + '=' + val + '&';
}
return data_str.slice(0, -1);
}
else if( typeof obj === 'string' )
return obj;
else
return ( obj ? (obj.toString && obj.toString()) : '' );
}
function getXHttpRequest()
{
clog("getXHttpRequest : queue.length = " + queue.length);
var request = queue[0];
request.method = request.method || 'GET';
if( request.method.toUpperCase() === 'GET' && request.data && request.data !== '' )
{
request.url += '?' + request.data;
request.data = '';
}
request.async = (request.async || true);
clog( request_status(request) );
return request;
}
function handleXHttpEvent( type, xhttp, request, event )
{
if( queue_cleaned )
return;
clog("handleXHttpEvent : url=" + request.url + ", type=" + type + "" +
", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
var context, response;
if( request[type] )
{
response = {
lengthComputable: xhttp.lengthComputable || event.lengthComputable || null,
loaded: xhttp.loaded || event.loaded || 0,
readyState: xhttp.readyState,
responseHeaders: xhttp.responseHeaders ||
(typeof xhttp.getAllResponseHeaders === 'function' ? xhttp.getAllResponseHeaders() : null ) || '',
responseText: xhttp.responseText || xhttp.response,
status: xhttp.status,
statusText: xhttp.statusText,
total: xhttp.total || event.total || 0,
url: xhttp.finalUrl || request.url,
};
context = request.context || response;
request[type].call( context, response );
if( type === 'onerror' || type === 'onload' )
{
request_in_progress = false;
request.delay = request.delay > 20 ? request.delay : 20;
setTimeout( XHttpRequest, request.delay );
}
}
}
function initXHttpEvents( xhttp, request )
{
clog("initXHttpEvents: ", xhttp);
var types = [
'onerror',
'onload',
'onloadend',
'onloadstart',
'onprogress',
'onreadystatechange',
];
function setXHttpEventListener(type){
xhttp[type] = function(event){ handleXHttpEvent(type, xhttp, request, event); };
}
types.forEach( setXHttpEventListener );
}
function initXHttp( xhttp, request )
{
initXHttpEvents( xhttp, request );
for( let key in request.headers )
{
xhttp.setRequestHeader( key, request.headers[key] );
}
}
function XHttpRequest()
{
clog("---> XHttpRequest <---");
var request, xhttp;
request = getXHttpRequest();
if( request && (request_in_progress === false || request.async === true) && queue.length > 0 )
{
queue.shift();
request_in_progress = true;
xhttp = createXHttp();
initXHttp( xhttp, request );
clog("XHttpRequest : url=" + request.url +
", readyState=" + xhttp.readyState + ", status=" + xhttp.status );
xhttp.open( request.method, request.url, request.async );
xhttp.send( request.data || null );
}
}
function addXHttpRequest( ...args )
{
var request, url, settings;
switch( args.length )
{
case 0: return;
case 1:
request = args[0];
if( request.length )
request.forEach( function(req){ queue.push(req);} );
else
queue.push(request);
//queue_cleaned = false;
break;
case 2:
url = args[0];
settings = args[1];
if( url.length )
url.forEach( function(u){queue.push(makeXHttpRequest(u, settings));});
else
queue.push( makeXHttpRequest(url, settings) );
//queue_cleaned = false;
break;
default:
return;
//throw new Error("[addXHttpRequest] invalid arguments length: " + args.length );
}
/*
if( request && request.length )
{
request.forEach( function(req){ queue.push(req);} );
}
else if( request )
{
queue.push(request);
}
else if( url && url.length )
{
url.forEach( function(u){queue.push(makeXHttpRequest(u, settings));});
}
else if( url )
{
queue.push( makeXHttpRequest(url, settings) );
}
else
throw new Error("addXHttpRequest] can't add request, args: " + args);
*/
queue_cleaned = false;
}
function makeXHttpRequest( url, settings )
{
var request = createNewObject(settings);
request.url = url;
return request;
}
function cleanXHttpQueue()
{
queue.length = 0;
request_in_progress = false;
queue_cleaned = true;
}
function queueLength()
{
return queue.length;
}
// AJAX API
SkIvLib.ajaxClean = cleanXHttpQueue;
SkIvLib.ajaxLength = queueLength;
SkIvLib.ajaxStatus = queue_status;
SkIvLib.ajaxAddXHR = addXHttpRequest;
SkIvLib.ajax = function(...args)
{
addXHttpRequest(...args);
XHttpRequest;
}
})();