

(function($) {

	$.fn.attrs = function(){
		var elem = this[0]; //get first element in set
		var attrs = {}
		if (! elem) return attrs;
		
		for (attr in elem.attributes){ 
			if(elem.attributes[attr].value){
			  attrs[elem.attributes[attr].name] = elem.attributes[attr].value;
			}
		}
		return attrs;
	};

	$.fn.ajaxForm = function(options){
		var opts = $.extend({}, $.fn.ajaxForm.defaults, options);
		return this.each(
			function(i){
				var $this = $(this);
				var attrs = $this.attrs();
				var opt_attrs = $.extend(
					{}, 
					{'dest' : attrs.action, 'method' : attrs.method}, 
					{'dest' : attrs['ajax-action']}
				);
				var o = $this.metadata ? $.extend({}, opts, opt_attrs, $this.metadata()) : $.extend({}, opts, opt_attrs);
				o.dest = o.dest.replace(/^https/,'http');
				$this.submit($this.ajaxForm.submitFunc(o));
			}
		);
	};
	
	$.fn.ajaxForm.defaults = {
		method : 'post',
		dest : '',
		selector : '.ajax-form',
		validator : null,
		load_img : '',
		load_text : 'LOADING...',
		loader : function(){
			return this.load_img ? 
				"<img src='"+this.load_img+"' title='Loading...' />" : 
				"<span class='loading'>"+this.load_text+"</span>";
		},
		before_submit : function($form){
			var loader = this.loader();
			$form.hide('fast', function(){$form.before(loader)});
		},
		extra_values : {},
		ajax_success : function($form, response){
			var $response = $(response)
			$form.siblings('.loading').remove();
			$form.siblings('.form-errors').hide('fast', function(){$(this).remove()});
			$form.replaceWith($response);
			$response.find(this.selector).ajaxForm(this);
		},
		ajax_error : function(request, status, error){
			alert(status); 
		},
		ajax_complete : function(){},
		ajax : {},
		finish : function($form){}
	};
	
	$.fn.ajaxForm.set = function(name, value){
		this.defaults[name] = value;
	}
	$.fn.ajaxForm.setDefaults = function(o){
		$.extend(this.defaults, o);
	}
	
	$.fn.ajaxForm.submitFunc = function(o){
		var f = function(){
			var $form = $(this);
			var values = $form.serialize();
			values += (values ? '&' : '') + $.param(o.extra_values);
			
			if(o.validator){
				if (! o.validator(values)){
					return false;
				}
			}
			
			o.before_submit($form);
			
			$form.siblings('.form-errors').hide('fast', function(){$(this).remove()});
			var ajaxOptions = {
				url : o.dest,
				data : values,
				type : o.method,
				success : function(response){
					o.ajax_success($form, response);
				},
				error: o.ajax_error,
				complete : function(request, status, error){
					o.ajax_complete(request, status, error);
					o.finish($form);
				}
			}
			
			$.extend(ajaxOptions, o.ajax);
			$.ajax(ajaxOptions);
			return false;	
		};
		return f;
	}

})(jQuery);

$.extend({'ajaxForm' : function(form, options) {
	var $form = this(form);
	var method = $form.attr('method');
	
	var dest = $form.attr('ajax-action');
	if (! dest)	dest = $form.attr('action');
	dest = dest.replace(/^https/,'http');
	
	var loader = $form.attr('loader');
	if (loader)	var loadImg = "<img class='loading' src="+loader+" alt='Loading...' title='Loading...' />";
	
	var values = $form.serialize();
	$form.hide('fast', function(){$form.before(loadImg)});
	$form.siblings('.form-errors').hide('fast', function(){$(this).remove()});
	
	var ajaxOptions = {
		url : dest,
		data : values,
		type : 'post',
		success : function(response){
			$form.siblings('.loading').remove();
			$form.replaceWith(response);
			$.bindAjaxForms('.ajax-form');
		}
	}
	
	this.ajax(ajaxOptions);
	return false;	
}});

$.extend({'bindAjaxForms' : function(selector){
	this(selector).each(function(index) {
		$(this).unbind('submit');
		$(this).submit(function(){
			$.ajaxForm(this);
			return false;
		});
	});	
}});

