/**
 * jQuery.bdForms
 * Copyright (c) 2011 Brian Dinga
 * License Coming Soon
 * Date: 2/24/2011
 *
 * @projectDescription To apply javascript elements to both server side and client side validation
 * http://depmedia.com
 * @author Brian Dinga
 * @version 0.0.1
 *
 * @id jQuery.fn.bdForms
 * @param {Object} settings 
 * @return {jQuery} Returns object for chaining
 *
 * @example $('ul.links').bdForms();
 *
 * @example $('ul.links').bdForms({ element_class:'className', html_element:'span'});
 *
 * Notes:
 *	- My first jQ plugin ever
 *
 * http://ryanflorence.com/issue-003/
 * http://ryanflorence.com/authoring-jquery-plugins-with-object-oriented-javascript/
 **/
(function( $ ){
	
	var _cmds = {

		init : function( options ) {
			var defaults = {
				target : false,
				hover_delay: 400,
				animate_duration: 500,
				animate_css: {opacity:0},
				js_enabled_class: 'jsEnabled',
				element_class: 'elementErr',
				html_element: 'div'
			}
			return this.each(function(){
				var $this = $(this),
				data = $this.data('bdForms');
				// If the plugin hasn't been initialized yet
				if(!data){
					if(!options){options={target : $this};}
					var the_settings=$.extend( defaults, options );
					this.settings=the_settings;
					$(this).data('bdForms',the_settings);
				}
			});
		},
		attach_error : function(msg,obj){
			var $t=this;
			var data = $($t).data('bdForms');
			if(msg.length>0 && $(obj).length>0){
				var sel_str=data.html_element;
				sel_str=sel_str+(data.element_class.length>0?'.'+data.element_class:'');
				if($(obj).next('.'+data.element_class).filter(':not(animated,.bdFormsRemoving)').length==0){
					$(obj).after('<'+data.html_element+'></'+data.html_element+'>');
					$(obj).next().addClass(data.element_class);
				}
				$(obj).next(sel_str).text(msg);
			}
			return this;
		},
		apply_error : function(){
			this.each(function(){
				var $t=this;
				var data = $($t).data('bdForms');
				$($t).addClass(data.js_enabled_class);
				$($t).find('.'+data.element_class).addClass(data.js_enabled_class);//different CSS if js is Enabled
				$($t).find('.'+data.element_class).dimDiff();
				$($t).find((data.element_class.length>0?'.'+data.element_class:'') + ', textarea, select, input, button').
					hover(
						function(){$($t).bdForms('remove_errors');}, 
						function(){return false;}
				);
			});
			return this;
		},
		remove_errors : function(){
			var $t=this;
			var data = $($t).data('bdForms');
			$($t).find('.'+data.element_class).addClass('bdFormsRemoving').filter(':not(animated)').
				delay(data.hover_delay).
				animate(data.animate_css, data.animate_duration, function(){
					$(this).remove();
			});
			return this;
		}
	};
	$.fn.bdForms = function(doCmd) {
		if(_cmds[doCmd]){
			return _cmds[doCmd].apply(this, Array.prototype.slice.call( arguments, 1 ));
		}else if(typeof doCmd==='object' || !doCmd){
			return _cmds.init.apply(this, arguments);
		}else{
			$.error( 'Method ' +  doCmd + ' does not exist on jQuery.bdForms' );
		}
		//return this;//http://blogs.sitepoint.com/2009/07/22/how-to-develop-a-jquery-plugin/
		return this;
	};



	$.fn.dimDiff = function(mode) {
		var $t=this;
		if(!mode){mode='up';}//move bottom to top
		mode=mode.toLowerCase();
		var is_bad_ie=false;
		var is_ie=false;
		if($.browser.msie && parseInt($.browser.version)<=7){is_bad_ie=true;}
		if($.browser.msie){is_ie=true;}
		if(mode=='up'){
			$($t).each(function(){
				var do_sizer=function(myThis){
					var used_parent=false;
					if($(myThis).prev().length>0){
						var prev_item=$(myThis).prev();
					}else{
						var prev_item=$(myThis).parent();
						used_parent=true;
					}
					var prev_height=0;
					if(intIt($(prev_item).height())==0 && 1==2){//in theory
						var _float=$(prev_item).css('float');
						$(prev_item).css('float','left');
						prev_height+=intIt($(prev_item).height());
						$(prev_item).css('float',_float);
					}else{
						prev_height+=intIt($(prev_item).height());}

					prev_height+=intIt($(prev_item).css('padding-top'));
					prev_height+=intIt($(prev_item).css('padding-bottom'));
					prev_height+=intIt($(prev_item).css('margin-top'));
					prev_height+=intIt($(prev_item).css('margin-bottom'));
					//if(intIt($(myThis).css('border-top-width'))>0 || intIt($(myThis).css('border-bottom-width'))>0){
						if(is_bad_ie===true){
							prev_height+=Math.round(intIt($(prev_item).css('border-top-width'))/1.5);
							prev_height+=Math.round(intIt($(prev_item).css('border-bottom-width'))/1.5);
						}else{
							if(is_ie!=true){//if the element err has border && not IE????
								//prev_height+=Math.round(intIt($(prev_item).css('border-top-width'))/2);
							}
							prev_height+=Math.round(intIt($(prev_item).css('border-bottom-width'))/2);
						}
					//}
					var prev_width=0;
					if(intIt($(prev_item).width())==0 && 1==2){//in theory
						var _float=$(prev_item).css('float');
						$(prev_item).css('float','left');
						prev_width+=intIt($(prev_item).width());
						$(prev_item).css('float',_float);
					}else{
						prev_width+=intIt($(prev_item).width());}
					
					prev_width+=intIt($(prev_item).css('padding-left'));
					prev_width+=intIt($(prev_item).css('padding-right'));
					prev_width+=intIt($(prev_item).css('margin-left'));
					prev_width+=intIt($(prev_item).css('margin-right'));
					//if(intIt($(myThis).css('border-left-width'))>0 || intIt($(myThis).css('border-right-width'))>0){
						if(is_bad_ie===true){
							prev_width+=Math.round(intIt($(prev_item).css('border-left-width'))/1.5);
							prev_width+=Math.round(intIt($(prev_item).css('border-right-width'))/1.5);
						}else{
							prev_width+=Math.round(intIt($(prev_item).css('border-left-width'))/2);
							prev_width+=Math.round(intIt($(prev_item).css('border-right-width'))/2);
						}
					//}
					prev_width=prev_width-(intIt($(myThis).css('padding-left'))+intIt($(myThis).css('padding-right')));
					//do height
					var new_css={'margin-top':'-'+prev_height+'px','width':prev_width+'px'};
					if(is_bad_ie===true){
						new_css['position']='relative';
						new_css['z-index']=999;
						$(myThis).css(new_css);
					}else{
						new_css['position']='absolute';
						new_css['z-index']=999;}
					if(used_parent!=true){
						$(myThis).css(new_css);
					}
				
				}
				if($(this).closest(':animated').length>0){
					var _this=this;
					$(this).css({opacity:0});
					$(this).closest(':animated').queue(function(){
						do_sizer(_this);
						$(_this).animate({opacity:1}, 250, function(){
							$(this).css('opacity','');
						});
					});
				}else{
					do_sizer(this);}
			});
		}
		return this;
	};
})( jQuery );

function intIt(num){
	num=parseInt(num);
	return (isNaN(num)?0:num);
}
