/**
* @file 	Moo.Form.js
* @author 	Mark Fabrizio Jr.
* @date		February 2006
* @description	This extends the Element object with an ajaxSubmit method. 
* @required	Moo,Element,Array,String,Event,Ajax,XHR,Common,Dom
*/
Moo = window.Moo || {};
Moo.Form = new Class(
	{
		
		getOptions: function(){
			return {
				bind: true
			};
		},
		initialize: function( el, options ){
			this.valid = true;
			this.element = $(el);
			if( !this.element || this.element.getTag() != 'form' ){
				this.valid = false;
				return;
			}
			this.setOptions( this.getOptions(), options );
			if( this.options.bind ){
				this.element.addEvent('submit', function(evt){
					evt.preventDefault();
					this.submit();
					return false;
				}.bindWithEvent(this) );
			}
		},
		submit: function( ){
			if( !this.valid ){ return false; }
			this.fireEvent('submit');
			var action = this.options.action || this.element.action;
			if( !action ){
				return false;
			}
			var createFrame = function(form){
			
				var frameId = 'ajaxSubmit' + (form.name || form.id);
				var io = null;
				if(window.ActiveXObject){
					io = $(document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'));
					io.src='javascript:false';
				}
				else{
					io = new Element('iframe').setProperties({
						id: frameId,
						name: frameId
					});
				}
				io.setStyles({
					position: 'absolute',
					top: '-1000px',
					left: '-1000px'
				});
				document.body.appendChild(io);
				return io;
			}
			
			
			var uploadCallback = function(){
				var obj={};
				var success = true;
				try{
					obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
					obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
				}
				catch(e){ success = false; }
				if( success ){
					this.fireEvent('onSuccess', obj );
				}else{
					this.fireEvent('onFailure', obj );
				}
				this.fireEvent('onComplete', obj );
				io.removeEvent('load', uploadCallback );
				io.remove.delay(100, io);
			}.bind(this);
			
			var parameters = this.element.toQueryString();
			var appendData = '';
			if( this.options.appendData ){
				switch( $type( this.options.appendData ) ){
					case 'element': appendData = $(this.options.appendData).toQueryString(); break;
					case 'object':  appendData = Object.toQueryString(this.options.appendData);
				}
			}
			
			// handle simple form submission
			if( this.element.getElements('input[type=file]').length == 0 ){
				
				var method = (this.method || "get");
				parameters = ( parameters.length == 0 ) ? appendData : ( ( appendData.length > 0 ) ? parameters+'&'+appendData : parameters );
				var options = $merge( { method: method }, this.options );
				if( method == 'get' && parameters.length > 0 ){
					if( action.test(/\?/ ) ){
						action += ( action.test(/\?$/) ? '':'&' ) + parameters;
					}else{
						action += '?'+parameters;
					}
				}
				var req = new Ajax(
					action,
					options
				);
				req.events = this.events;
				req.request( parameters );
				return;
				
			}
			// ok - we have upload case
			if(this.element.encoding){
				this.element.encoding = 'multipart/form-data';
			}
			else{
				this.element.enctype = 'multipart/form-data';
			}
			var formElements = $A();
			if( appendData.length > 0 ){
				var pairs = appendData.split( "&" );
				for(i=0;i<pairs.length;i++){
					var delimitPos = pairs[i].indexOf('=');
					if(delimitPos != -1){ 
						formElements[i] = new Element('input');
						formElements[i].type = 'hidden';
						formElements[i].name = pairs[i].substring(0,delimitPos);
						formElements[i].value = pairs[i].substring(delimitPos+1);
						formElements[i].injectInside(this.element);
					}
				}
			}
			var io = createFrame( this.element );
			var old_method = this.method || "post";
			var old_target = this.target || '';
			this.element.method = "post";
			this.element.target = io.id;
			io.addEvent( 'load', uploadCallback );
			this.element.submit();
			for(i=0;i<formElements.length;i++){
				formElements.remove();
			}
			this.element.method = old_method;
			this.element.target = old_target;
		}
	}
);
Moo.Form.implement( new Options );
Moo.Form.implement( new Events );

Element.extend({
	ajaxSubmit: function( options ){
		return new Moo.Form( this, $merge({ bind: false }, options) ).submit();
	}
});
