135 lines
3.3 KiB
JavaScript
135 lines
3.3 KiB
JavaScript
/*
|
|
---
|
|
|
|
script: Request.JSONP.js
|
|
|
|
name: Request.JSONP
|
|
|
|
description: Defines Request.JSONP, a class for cross domain javascript via script injection.
|
|
|
|
license: MIT-style license
|
|
|
|
authors:
|
|
- Aaron Newton
|
|
- Guillermo Rauch
|
|
|
|
requires:
|
|
- Core/Element
|
|
- Core/Request
|
|
|
|
provides: [Request.JSONP]
|
|
|
|
...
|
|
*/
|
|
|
|
if (!Request.JSONP) {
|
|
Request.JSONP = new Class({
|
|
|
|
Implements: [Chain, Events, Options],
|
|
|
|
options: {/*
|
|
onRetry: $empty(intRetries),
|
|
onRequest: $empty(scriptElement),
|
|
onComplete: $empty(data),
|
|
onSuccess: $empty(data),
|
|
onCancel: $empty(),
|
|
*/
|
|
url: '',
|
|
data: {},
|
|
retries: 0,
|
|
timeout: 0,
|
|
link: 'ignore',
|
|
callbackKey: 'callback',
|
|
injectScript: document.head
|
|
},
|
|
|
|
initialize: function(options){
|
|
this.setOptions(options);
|
|
this.running = false;
|
|
this.requests = 0;
|
|
this.triesRemaining = [];
|
|
},
|
|
|
|
check: function(){
|
|
if (!this.running) return true;
|
|
switch (this.options.link){
|
|
case 'cancel': this.cancel(); return true;
|
|
case 'chain': this.chain(this.caller.bind(this, arguments)); return false;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
send: function(options){
|
|
if (!$chk(arguments[1]) && !this.check(options)) return this;
|
|
|
|
var type = $type(options),
|
|
old = this.options,
|
|
index = $chk(arguments[1]) ? arguments[1] : this.requests++;
|
|
if (type == 'string' || type == 'element') options = {data: options};
|
|
|
|
options = $extend({data: old.data, url: old.url}, options);
|
|
|
|
if (!$chk(this.triesRemaining[index])) this.triesRemaining[index] = this.options.retries;
|
|
var remaining = this.triesRemaining[index];
|
|
|
|
(function(){
|
|
var script = this.getScript(options);
|
|
this.fireEvent('request', script);
|
|
this.running = true;
|
|
|
|
(function(){
|
|
if (remaining){
|
|
this.triesRemaining[index] = remaining - 1;
|
|
if (script){
|
|
script.destroy();
|
|
this.send(options, index).fireEvent('retry', this.triesRemaining[index]);
|
|
}
|
|
} else if(this.running && script && this.options.timeout){
|
|
script.destroy();
|
|
this.cancel().fireEvent('failure');
|
|
}
|
|
}).delay(this.options.timeout, this);
|
|
}).delay(Browser.Engine.trident ? 50 : 0, this);
|
|
return this;
|
|
},
|
|
|
|
cancel: function(){
|
|
if (!this.running) return this;
|
|
this.running = false;
|
|
this.fireEvent('cancel');
|
|
return this;
|
|
},
|
|
|
|
getScript: function(options){
|
|
var index = Request.JSONP.counter,
|
|
data;
|
|
Request.JSONP.counter++;
|
|
|
|
switch ($type(options.data)){
|
|
case 'element': data = document.id(options.data).toQueryString(); break;
|
|
case 'object': case 'hash': data = Hash.toQueryString(options.data);
|
|
}
|
|
|
|
var src = options.url +
|
|
(options.url.test('\\?') ? '&' :'?') +
|
|
(options.callbackKey || this.options.callbackKey) +
|
|
'=Request.JSONP.request_map.request_'+ index +
|
|
(data ? '&' + data : '');
|
|
|
|
var script = new Element('script', {type: 'text/javascript', src: src});
|
|
Request.JSONP.request_map['request_' + index] = function(){ this.success(arguments, script); }.bind(this);
|
|
return script.inject(this.options.injectScript);
|
|
},
|
|
|
|
success: function(args, script){
|
|
if (!this.running) return false;
|
|
if (script) script.destroy();
|
|
this.running = false;
|
|
this.fireEvent('complete', args).fireEvent('success', args).callChain();
|
|
}
|
|
|
|
});
|
|
|
|
Request.JSONP.counter = 0;
|
|
Request.JSONP.request_map = {};
|
|
} |