/**
 * Usage: $('form').hintable();
 */
;(function($) {
  $.fn.hintable = function(options) {
    var opts = $.extend($.fn.hintable.defaults, options || {}), _fields = [], _interval = null;
    
    $(this).filter('input[type=text], input[type=password], textarea').each(function() {
      var f = $(this);
      _fields.push(f);
      
      // create the hint label
      createHintLabel(f);
      f.focus(function() {
        onFocus(f);
      }).blur(function() {
        checkEmpty(f, true);
      }).change(function() {
        checkEmpty(f);
      }).bind('keydown.hintable', function(e) {
        onKeyDown(f, e);
      });
    });
    
    $(self).blur(function() {
      clearInterval(_interval);
      _interval = null;
    }).focus(function() {
      if(_interval) return;
      setInterval(function() {
        check();
      }, 200);
    }).focus();
    
    function createHintLabel(f) {
      f.parent('.divformfield').addClass(opts.containerClass);
      var l = document.createElement('label');
      l.className = opts.hintClass;
      l.innerHTML = f.attr('title');
      l.htmlFor = f.attr('id');
      f.before(l);
    };
    
    function isEmpty(f) {
      return $.trim(f.val()).length === 0;
    };
    
    function onFocus(f) {
      if(isEmpty(f)) showHint(f, true);
      f.bind('keydown.hintable', function(e) {
        onKeyDown(f, e);
      });
    };
    
    function checkEmpty(f, blur) {
      if(isEmpty(f)) {
        showHint(f, !blur);
      }
    };
    
    function onKeyDown(f, e) {
      // ignore shift & tab
      if(e.keyCode == 16 || e.keyCode == 9) return;
      hideHint(f);
      f.unbind('keydown.hintable');
    };
    
    function hideHint(f) {
      f.prev('label.' + opts.hintClass).removeClass(opts.partialClass).addClass(opts.hiddenClass);
    };
    
    function showHint(f, partial) {
      if(partial)
        f.prev('label.' + opts.hintClass).addClass(opts.partialClass).removeClass(opts.hiddenClass);
      else
        f.prev('label.' + opts.hintClass).removeClass(opts.partialClass).removeClass(opts.hiddenClass);
    };
    
    function check() {
      var l = _fields.length;
      for(var i = 0; i < l; i++) {
        if(_fields[i] && _fields[i].val() != '') hideHint(_fields[i]); 
      }
    };
    
    return this;
  };
  
  $.fn.hintable.defaults = {
    hintClass: 'hintable',
    hiddenClass: 'hint-hidden',
    partialClass: 'hint-partial',
    containerClass: 'hint-container'
  };
})(jQuery);

