var evance = evance || {};
/*
	evance.eventDispatcher
	-----------------
	This is applied to an Object to install event dispatch capabilities.
	Obviously the Object you apply it to shouldn't already have such
	capabilities.
	
	Example:
	
	var myObj = {
		myMethod: function(){
			this.trigger('event', {//event object});
		}
	};
	evance.eventDispatcher(myObj);
	myObj.bind('event', function(e){//do something});
*/
	evance.eventDispatcher = function(obj){
			
			// Apply an addListener() method to the Object.
			obj.bind = function(type, fn){
				if(this._listeners === undefined) this._listeners = [];
				this._listeners.push({'type':type, 'listener': fn});
			};
			
			// Apply a removeListener() method to the Object
			obj.unbind = function(type, fn){
				if(this._isDispatching === undefined) this._isDispatching = false;
				if(this._listeners !== undefined){
					/*
						if an event is already dispatching we don't want to cause errors 
						as a result of removing the listener immediately. Better to add it
						to a queue and wait till the event has fully dispatched before 
						removing the listener from the list.
					*/
					if(this._isDispatching){
						if(this._removeListenerQueue === undefined) this._removeListenerQueue = [];
						this._removeListenerQueue.push({'type':type, 'listener':fn});
					} else {
						for(var i=0; i<this._listeners.length; i++){
							if((type == this._listeners[i].type) &&
							   (fn == this._listeners[i].listener)) var index = i;
						}
						if(index !== undefined) this._listeners.splice(index, 1);
					}
				}
			};
			
			// Apply a dispatchEvent() method to the Object
			obj.trigger = function(type, e){
				if(this._isDispatching === undefined) this._isDispatching = true;
				if(this._listeners !== undefined){
					for(var i=0; i<this._listeners.length; i++){
						if(this._listeners[i].type == type) {
							this._listeners[i].listener(e);
						}
					}
				}
				this._isDispatching = false;
				if(this._removeListenerQueue !== undefined){
					for(var i=0; i<this._removeListenerQueue.length; i++){
						this.removeListener(this._removeListenerQueue[i].type, this._removeListenerQueue[i].listener);
					}
					delete this._removeListenerQueue;
				}
			};
	};

(function($) {
	$.fn.disable = function(){
		$(this).each(function(){
			var self = $(this);
			if(!self.attr('disabled')){
				var button = self;
				if(self.is('select') && self.hasClass('evSelect')){
					button = self.siblings(':first');
				} else if(self.is('input') && self.hasClass('label')){
					button = self.parent();
				} else if(self.is('a')){
					// unbind all current events on this item
					// then bind a new one to prevent default actions
					self.unbind('click');
					self.bind('click', function(e){return false});
				}
				if(button){ button.addClass('disabled'); }
				self.trigger('disable', {type: 'ondisable'});
				self.attr('disabled', 'disabled');
			}
		});
		return this;
	};
	
	$.fn.enable = function(){
		$(this).each(function(){
			var self = $(this);
			if(self.attr('disabled')){
				var button = self;
				if(self.is('select') && self.hasClass('evSelect')){
					button = self.siblings(':first');
				} else if(self.is('input') && self.hasClass('label')){
					button = self.parent();
				} else if(self.is('a')){
					// unbind the prevent default function
					self.unbind('click');
				}
				if(button){ button.removeClass('disabled'); }
				self.trigger('enable', {type: 'onenable'});
				self.removeAttr('disabled');
			}
		});
		return this;
	};
	
/*
	evFormButton
	-------------
	This takes care of the focus and blur button highlights
*/
	$.fn.evFormButton = function(){
		$(this).each(function(){
			var button = null;
			if($(this).hasClass('evButton')){
				button = $('input:first', this);
			} else if($(this).is('input') && $(this).parent().hasClass('evButton')){
				button = $(this);
			}
			
			if(button != null){
				button.bind('focus', function(e){
					$(this).parent().addClass('focus');
				});
				button.bind('blur', function(e){
					$(this).parent().removeClass('focus');
				});
			}
		});
	};
	
/*
	evSelectButton
	---------
	Styles a standard select input into a pretty evButton
*/
	$.fn.evSelectButton = function(){
		$(this).each(function(){

			var evSelect = $(this);
			var evWrap = $('<span class="evSelectButton"></span>');
			evSelect.wrap(evWrap);
			var selectWidth = evSelect.width();
			evWrap.width(selectWidth);
			
			var label = this.options[this.selectedIndex].text;
			
			if(evSelect.attr('data-title')){
				label = '<span class="title">' + evSelect.attr('data-title') + ':</span> ' + label;
			}
			
			var evButton = $('<span class="evButton"></span>');
			var evLabel = $('<span class="label">'+label+'</span>');
			var evIcon = $('<span class="icon iconSelect"></span>');
			var evCap = $('<span class="cap"></span>');
			evButton.append(evLabel);
			evButton.append(evIcon);
			evButton.append(evCap);
			
			evButton.css({
				'position': 'absolute', 
				'z-index': 5
			});
			evSelect.css({
				'position': 'relative',
				'opacity': 0, 
				'filter': 'alpha(opacity=0)',
				'z-index': 6
			});
			
			$(this).before(evButton);
			
			var labelPadding = evLabel.outerWidth() - evLabel.width(); // 10
			var buttonPadding = evButton.outerWidth() - evButton.width();
			var buttonWidth = selectWidth-evCap.width()-buttonPadding;

			var labelWidth = selectWidth - evCap.width() - evIcon.width() - labelPadding -3;
			evLabel.width(labelWidth);
			evLabel.css({
				'overflow': 'hidden'
			});
			
			evSelect.bind('change', function(e){
				var label = this.options[this.selectedIndex].text;
				if(evSelect.attr('data-title')){
					label = '<span class="title">' + evSelect.attr('data-title') + ':</span> ' + label;
				}
				evLabel.html(label);
			});
			
			evSelect.bind('keyup', function(e){
				var label = this.options[this.selectedIndex].text;
				if(evSelect.attr('data-title')){
					label = '<span class="title">' + evSelect.attr('data-title') + ':</span> ' + label;
				}
				evLabel.html(label);
			});
			
			evSelect.bind('mouseover', function(e){
				evButton.addClass('active');
			});
			
			evSelect.bind('mouseout', function(e){
				evButton.removeClass('active');
			});
			
			evSelect.bind('focus', function(e){
				evButton.addClass('focus');
			});
			
			evSelect.bind('blur', function(e){
				evButton.removeClass('focus');
			});
			
			return this;
		});
		return this;
	};
	
/*
	evTextField
	---------
	Styles a standard input field
*/
	$.fn.evTextField = function(){
		$(this).each(function(){
			var span = $(this);
			var input = $('input:first', span);
			var autohide = false;
			var autoselect = false;
			var cancelButton = $('.iconClose', span);
			
			if(cancelButton){
				cancelButton.bind('click', function(e){
					input.val('');
					$(this).css('visibility', 'hidden');
					input.focus();
					return false;
				});
			}
			
			input.bind('keyup', function(e){
				if(cancelButton){
					if($(this).val() != ''){
						cancelButton.css('visibility', 'visible');
					} else {
						cancelButton.css('visibility', 'hidden');
					}
				}
				return true;
			});
			
			input.bind('focus', function(e){
				span.addClass('focus');
				if(autohide != false && $(this).val() == autohide){
					$(this).val('');
				} else if(autoselect){
					$(this).select();
				}
				
				if(cancelButton && $(this).val() != ''){
					cancelButton.css('visibility', 'visible');
				}
				
				$(this).keypress(function(e){
					if($(this).hasClass('error')){
						$(this).removeClass('error');
						$(this).parent().removeClass('error');
					}
				});
			});
			
			input.bind('blur', function(e){
				span.removeClass('focus');
				if($(this).val() == '' && autohide != false){
					$(this).val(autohide);
				}
				if(cancelButton && $(this).val() == ''){
					cancelButton.css('visibility', 'hidden');
				}
			});
			
			if(input.attr('data-autogrow') && input.attr('data-autogrow').toLowerCase() == 'true'){
				input.autoGrowInput();
			}
			if(input.attr('data-autohide') && input.attr('data-autohide').toLowerCase() == 'true'){
				autohide = input.val();
			}
			if(input.attr('data-autoselect') && input.attr('data-autoselect').toLowerCase() == 'true'){
				autoselect = true;
			}
			
			return this;
		});
		
		return this;
	};
	
/*
	evTextArea
*/
	$.fn.evTextArea = function(){
		$(this).each(function(){
			var span = $(this);
			var textarea = $('textarea', span);
			textarea.bind('focus', function(e){
				span.addClass('focus');
				
				$(this).keypress(function(e){
					if($(this).hasClass('error')){
						$(this).removeClass('error');
						$(this).parent().removeClass('error');
					}
				});

			});
			textarea.bind('blur', function(e){
				span.removeClass('focus');
			});
			return this;
		});
		return this;
	}
	
/*
	evCheckbox
	-----------
*/
	$.fn.evCheckbox = function(){
		$(this).each(function(){
			if(this.type == 'checkbox'){
				var span = $('<a href="#" class="evCheckbox"></a>');
				var field = this;
				$(this).before(span);
				if(this.disabled == true){
					span.css('background-position', ((this.checked)?'0 -160px':'0 -128px'));
				} else if(this.checked == true){
					span.css('background-position', '0 -64px');
				}
				
				$(this).bind('change', function(event){
					if(!this.disabled){
						span.css('background-position', (this.checked)?'0 -64px':'0 0');
					} else {
						span.css('background-position', (this.checked)?'0 -160px':'0 -128px');
					}
				});
				
				span.bind('mouseover focus', function(event){
					if(!field.disabled){
						span.css('background-position', (field.checked)?'0 -96px':'0 -32px');
					}						 
				});
				
				span.bind('mouseout blur', function(event){
					if(!field.disabled){
						span.css('background-position', (field.checked)?'0 -64px':'0 0');
					}						 
				});
				
				span.bind('click', function(event){
					if(!field.disabled){
						field.checked = !field.checked;
						$(field).trigger('change');
					}
					return false;
				});
				span.bind('keyup', function(event){
					if(!field.disabled && (event.keyCode == 32)){
						field.checked = !field.checked;
						$(field).trigger('change');
					}
					event.preventDefault();
					return false;
				});
				
				$(field).css('display', 'none');
			}
		});
	}

/*
	evTextArea
*/
	$.fn.evSelectField = function(){
		$(this).each(function(){
			var span = $(this);
			var cover = $('.selectCover', span);
			var select = $('select', span);
			
			select.bind('click', function(e){
				span.addClass('focus');
			});
			
			select.bind('change', function(e){
				if($(this).hasClass('error')){
					$(this).removeClass('error');
					$(this).parent().removeClass('error');
				}
			});
			
			select.bind('blur', function(e){
				span.removeClass('focus');
			});
			
			if(cover.length > 1){
				span.removeClass('error');	
			}
			
			return this;
		});
		return this;
	}
	

})(jQuery);


/*
	Load UI components Automagically
*/
$(document).ready(function(){
	$('.evSelect').evSelectButton();
	$('input').evFormButton();
	$('.evTextField').evTextField();
	$('.evTextArea').evTextArea();
	$('.evCheckbox').evCheckbox();
	$('.selectField').evSelectField();
});
		  
