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 = {};
 | |
| } |