Skip to content

Instantly share code, notes, and snippets.

@swvitaliy
Created May 4, 2012 06:34
Show Gist options
  • Save swvitaliy/2592618 to your computer and use it in GitHub Desktop.
Save swvitaliy/2592618 to your computer and use it in GitHub Desktop.
js cross domain request (script src)
/*
cross domain request ( script src)
todo:
- Исправить вызов события complete
- Не создавать объект запроса сразу, а искать в пуле и инициализировать
найденный актуальными значениями полей объекта xdr и входными параметрами
( или создавать новый, если не был найден )
- Исправить удаление переменной результата ( сейчас удаляется весь объект,
с которого начинается путь к ней )
@created: 4.05.12
@author: swvitaliy ([email protected])
*/
var xdr = xdr || {}
;(function(xdr)
{
function XdrRequest(config)
{
var defaults =
{
container:'head',
scriptClass:'xdr',
timeout: 30, // seconds
waitDelay: 50 // milliseconds
};
var now = (new Date()).getTime();
this.scriptClass = config.scriptClass || defaults.scriptClass;
this.proxyUrl = config.proxyUrl;
this.requestUri = config.uri;
this.requestData = config.data;
this.timeout = config.timeout || defaults.timeout;
this.container = config.container || defaults.container;
this.responseVarName = config.responseVarName.replace('.', '_');
this.waitDelay = config.waitDelay || defaults.waitDelay;
this.events =
{
success:config.success || null,
complete:config.complete || null,
error:config.error || null,
continue:config.continue || null
};
this.context = config.context || null;
this.init();
if (config.start)
{
this.open();
}
}
XdrRequest.prototype =
{
init: function()
{
this.request = { script:null };
this.response = { body:null };
},
opened:function()
{
return this.request.script !== null;
},
open: function()
{
if ( this.opened() )
{
return false;
}
this._makeRequest();
this._startWaiting();
},
_makeRequest: function()
{
var container = this.container,
proxy = this.proxyUrl,
responseVarName = this.responseVarName;
function queryArray(name, params)
{
var i, r = {};
for ( i in params)
{
if (params.hasOwnProperty(i))
{
r[name + '[' + i + ']'] = params[i];
}
}
return r;
}
function extendObj(properties)
{
var i;
for ( i in properties)
{
if ( properties.hasOwnProperty(i) )
{
this[i] = properties[i];
}
}
}
function httpBuildQuery(params)
{
var i, r = [];
for ( i in params)
{
if ( params.hasOwnProperty(i) )
{
r.push(i + '=' + encodeURIComponent(params[i]));
}
}
return r.join('&');
}
function appendScriptToContainer(uri, params, attributes)
{
if (typeof container === 'string')
{
container = $(container);
}
if (container instanceof jQuery)
{
container = container.get(0);
}
params = queryArray('query', params);
params = httpBuildQuery(params);
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= proxy + '?responseVarName=' + responseVarName + '&uri=' + uri + '&' + params;
if (attributes)
{
extendObj.apply(script, [attributes]);
}
container.appendChild(script);
return script;
}
this.request.script =
appendScriptToContainer(encodeURIComponent(this.requestUri), this.requestData,
{
class:this.scriptClass,
id:this.scriptClass + '_' + (new Date()).getTime()
});
},
_startWaiting: function()
{
var thisObj = this,
startTime = (new Date()).getTime(),
timeout = this.timeout,
responseVar = this.responseVarName,
response = this.response,
events = this.events,
context = this.context;
if ( eval( 'window.' + responseVar ) !== undefined )
{
throw "xdr.Request.open variable \"" + 'window.' + responseVar + "\" already exists";
}
function sendEvent(ev)
{
if ( !events.hasOwnProperty(ev) )
{
throw 'xdr.XdrRequest - send undefined event ({ev})'.replace('{ev}', ev)
}
if ( !events[ev] )
{
return false;
}
var evArgs = [].slice.apply(arguments, [1]);
events[ev].apply(context, [thisObj].concat(evArgs));
return true;
}
function waitForResponse()
{
var val = eval( 'window.' + responseVar );
if ( val !== undefined )
{
response.body = val;
sendEvent('complete');
thisObj.close();
sendEvent('success', val);
return true;
}
var now = (new Date()).getTime();
if ( (now - startTime) / 1000 >= timeout )
{
sendEvent('complete');
thisObj.close();
sendEvent('error', { errorType: 'timeout' });
}
else
{
sendEvent('continue');
setTimeout(waitForResponse, this.waitDelay);
}
return false;
}
waitForResponse();
},
close: function()
{
if ( !this.opened() )
{
return false;
}
this._removeResponseVar();
var $scriptRequest = $(this.request.script);
if ( !$scriptRequest.length )
{
return false;
}
$scriptRequest.remove();
this.request.script = null;
return true;
},
_removeResponseVar: function()
{
var name, str = this.responseVarName,
a = str.indexOf('.'),
b = str.indexOf('['),
pos = [];
if ( a >= 0 ) pos.push(a);
if ( b >= 0 ) pos.push(b);
name = ( pos.length === 0 ) ? str :
str.slice(0, Math.max.apply(null, pos));
delete window[name];
return true;
}
};
/* api functions & properties */
xdr.timeout = 30;
xdr.scriptClass = 'xdr_' + (new Date()).getTime();
xdr.container = 'head';
xdr.proxyUrl = 'http://your_domain.com/proxy/url/';
xdr.responseVarName = 'replaceThisLineInTheNameOfTheVariableResponse';
xdr.waitDelay = 50;
xdr.Request = XdrRequest;
xdr.requests = [];
xdr.makeRequest = function(uri, data, success, error)
{
var request = new XdrRequest({
timeout:this.timeout,
scriptClass:this.scriptClass,
container:this.container,
proxyUrl:this.proxyUrl,
responseVarName:this.responseVarName + (new Date).getTime() + Math.round(9999999999999 * Math.random()),
waitDelay:this.waitDelay,
uri:uri,
data:data,
success:success,
error:error,
start:true
});
this.requests.push(request);
return request;
};
})(xdr);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment