/*
 * In-Field Label jQuery Plugin
 * http://fuelyourcoding.com/scripts/infield.html
 *
 * Copyright (c) 2009 Doug Neiner
 * Dual licensed under the MIT and GPL licenses.
 * Uses the same license as jQuery, see:
 * http://docs.jquery.com/License
 *
 * @version 0.1
 */
(function($){
	
    $.InFieldLabels = function(label,field, options) {
    
	    // To avoid scope issues, use 'base' instead of 'this'
	    // to reference this class from internal events and functions.
	    var base = this;
	    
	    // Access to jQuery and DOM versions of each element
	    base.$label = $(label);
	    base.label = label;

	 		base.$field = $(field);
			base.field = field;
	        
			base.$label.data("InFieldLabels", base);
			base.showing = true;
	    
			base.$label.click(function() {
				base.$field.focus();
			});
  
	    base.init = function(){
				// Merge supplied options with default options
				base.options = $.extend({},$.InFieldLabels.defaultOptions, options);
	
				// Check if the field is already filled in
				if(base.$field.val() != ""){
					base.$label.hide();
					base.showing = false;
				};
				
				base.$field.focus(function(){
					base.fadeOnFocus();
				}).blur(function(){
					base.checkForEmpty(true);
				}).bind('keydown.infieldlabel',function(e){
					// Use of a namespace (.infieldlabel) allows us to
					// unbind just this method later
					base.hideOnChange(e);
				}).change(function(e){
					base.checkForEmpty();
				}).bind('onPropertyChange', function(){
					base.checkForEmpty();
				});
	    };
	    
			// If the label is currently showing
			// then fade it down to the amount
			// specified in the settings
			base.fadeOnFocus = function(){
				if(base.showing){
					base.setOpacity(base.options.fadeOpacity);
				};
			};
			
			base.setOpacity = function(opacity){
				base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration);
				base.showing = (opacity > 0.0);
			};
			
			// Checks for empty as a fail safe
			// set blur to true when passing from
			// the blur event
			base.checkForEmpty = function(blur){
				if(base.$field.val() == ""){
					base.prepForShow();
					base.setOpacity( blur ? 1.0 : base.options.fadeOpacity );
				} else {
					base.setOpacity(0.0);
				};
			};
			
			base.prepForShow = function(e){
				if(!base.showing) {
					// Prepare for a animate in...
					base.$label.css({opacity: 0.0}).show();
					
					// Reattach the keydown event
					base.$field.bind('keydown.infieldlabel',function(e){
						base.hideOnChange(e);
					});
				};
			};
	
			base.hideOnChange = function(e){
				if(
					(e.keyCode == 16) || // Skip Shift
					(e.keyCode == 9) // Skip Tab
				  ) return; 
				
				if(base.showing){
					base.$label.hide();
					base.showing = false;
				};
				
				// Remove keydown event to save on CPU processing
				base.$field.unbind('keydown.infieldlabel');
			};
	      
			// Run the initialization method
      base.init();
      
    };
	
    $.InFieldLabels.defaultOptions = {
    	fadeOpacity: 0.5, // Once a field has focus, how transparent should the label be
			fadeDuration: 300 // How long should it take to animate from 1.0 opacity to the fadeOpacity
    };
	

    $.fn.inFieldLabels = function(options){
        return this.each(function(){
					// Find input or textarea based on for= attribute
					// The for attribute on the label must contain the ID
					// of the input or textarea element
					var for_attr = $(this).attr('for');
					if( !for_attr ) return; // Nothing to attach, since the for field wasn't used
					
					
					// Find the referenced input or textarea element
					var $field = $(
						"input[title=" + for_attr + "][type='text']," + 
						"input[title=" + for_attr + "][type='password']," + 
						"textarea[title=" + for_attr +"]"
						);
						
					if( $field.length == 0) return; // Again, nothing to attach
					
					// Only create object for input[text], input[password], or textarea
		            (new $.InFieldLabels(this, $field[0], options));
        });
    };
	
})(jQuery);
