( function( $ ) {
  // plugin definition
  $.fn.overlabel = function( options ) {
    // build main options before element iteration
    var opts = $.extend( {}, $.fn.overlabel.defaults, options );
    var selection = this.filter( 'label[for]' ).map( function() {
      var label = $( this );
      var id = label.attr( 'for' );
      var field = document.getElementById( id );

      if ( !field ) return;

      // build element specific options
      var o = $.meta ? $.extend( {}, opts, label.data() ) : opts;

      label.addClass( o.label_class );

      var hide_label = function() { label.css( o.hide_css ) };
      var show_label = function() { this.value || label.css( o.show_css ) };

      $( field )
           .parent().addClass( o.wrapper_class ).end()
           .focus( hide_label ).blur( show_label ).each( hide_label ).each( show_label );

      return this;
    } );

    return opts.filter ? selection : selection.end();
  };

  // publicly accessible defaults
  $.fn.overlabel.defaults = {
    label_class:   'overlabel-apply',
    wrapper_class: 'overlabel-wrapper',
    hide_css:      { 'text-indent': '-10000px' },
    show_css:      { 'text-indent': '0px', 'cursor': 'text', 'display': 'block' },
    filter:        false
  };

} )( jQuery );
