
	jQuery( document ).ready( function( ){
		
		// For all the inputs that are text inputs
		jQuery( 'input:text, input:password').each( function( ){
			var $this = jQuery( this );
			
			// get the label
			var label = jQuery( 'label[for='+this.id+']' );
			
			// If no label, then return to avoid errors
			if( label.size( ) == 0 ){
				return;
			}
			
			// create wrapper element
			var wrapper = jQuery( '<div class="compactlabel-wrapper"></div>' );
			$this.wrap( wrapper );
			
			// move the label to before the the input
			$this.before( label );
			
			// create label backing
			var backing = jQuery( '<div class="compactlabel-label-backing"></div>' )
				.insertBefore( $this )
				.height( label.height( ) )
				.width( label.width( ) );
			
			// basic style information
			var labelOffset = label.position( ), inputOffset = $this.position( ), labelHeight = label.outerHeight( );
			
			// flag for if on or off
			var isHover = false, isFocus = false;
			
			// a jQuery object of the backing and label to animate both together
			var animatedElements = jQuery( backing.get( ) ).add( label.get( ) );
			
			
			// common functionality for hover on and focus on
			var on = function( event ){
				$this.parent( ).addClass( 'compactlabel-wrapper-on' );
				animatedElements.stop( ).animate( { "top": '-'+(labelHeight - inputOffset.top)+'px' } );				
			};
			
			// common functionality for hover off and focus off
			var off = function( event ){
				if( isHover || isFocus ){
					return;
				}
				if( inputEmpty ){
					label.removeClass( 'compactlabel-hide' );
				} else {
					label.addClass( 'compactlabel-hide' );
				}
				
				if( !inputEmptyChange ){
					animatedElements.stop( );
				}
				
				animatedElements.animate( 
					{ "top": labelOffset.top + 'px' }, 
					function( ){ 
						$this.parent( ).removeClass( 'compactlabel-wrapper-on' ) 
					} );
			};
			
			var onHover = function( event ){
				isHover = true;
				on( event );
			};
			
			var offHover = function( event ){
				isHover = false;
				off( event );
			};
			
			var onFocus = function( event ){
				isFocus = true;
				on( event );
			};
			
			var offFocus = function( event ){
				isFocus = false;
				off( event );
			};
			
			// The pieces for keeping track if the value of the input is empty
			var inputEmpty = false, inputEmptyStart = false, inputEmptyChange = false;
			var checkInputEmpty = function( ){
				inputEmpty = $this.val( ) == '';
			};
			checkInputEmpty( );
			// ID for setTimeout for checkInputEmpty
			var checkInputEmptyFnID = null;
			
			
			
			if( !inputEmpty ){
				label.addClass( 'compactlabel-hide' );
			}
			
			// add the events
			// events to track if the value changed empty state	
			$this.focus( function( ){				
				inputEmptyStart = inputEmpty;
				inputEmptyChange = false;
				checkInputEmptyFnID = setInterval( checkInputEmpty, 50 );
			} );
			
			$this.blur( function( ){
				clearInterval( checkInputEmptyFnID );
				checkInputEmpty( );
				inputEmptyChange = inputEmptyStart != inputEmpty;
			} );
			
			// animation events
			$this.focus( onFocus );
			$this.blur( offFocus );
			$this.hover( onHover, offHover );
			label.hover( onHover, offHover );
			
			
		} );
	} );
