/*
Datagraf jQuery field-hint plugin
Author: Lars Danielsen

Adds a hint text for a form field, that disappears when the field has focus,
or has been filled out. Works for input types text and password, textarea
and file

Required: jQuery

Synopsis:

jQuery(elem).fieldhint({
	text: 'This is a hint',
	autoPosition: false,
    callBack:
        function (show, obj) {
            if (show) {
                obj.css('background-color', 'gold');
	        } else {
                obj.css('background-color', 'silver');
            }
        }
   });

or just: jQuery(elem).fieldhint('This is a hint');
or even: jQuery(elem).fieldhint();

In the last example, the text will be taken from the element's alt tag. 

text:               Hint to use
autoPosition:       Attemt to position the hint correctly, basic
autoStyle:          Attemt to style the text of the hint like the input field, basic
doHandleOtherHints: Attemt to handle hints on other handled fields, to make it work when the browser
                    fills i.e. login-fields automatically
callBack            A function to call whenever the hint is handled. Receives two arguments; a boolean
                    indicating if the hint is being showed, and a jQuery wrapped set containing
                    the input field
remove              when set to a true value, the plugin will remove an existing hint from the elements

Resulting html example:
<div class="fieldhint-fieldwrapper" style="position: relative; margin: 0pt; padding: 0pt; display: inline;">
    <input class="hasFieldHint" />
    <label class="hint" style="position: absolute; cursor: text; top: -2px; left: 0px;">This is a hint</label>
</div>

You have to do further positioning and styling yourself. The browsers render
form fields very differently, so I gave up on attempting cross-browser positioning
Use margin on the label.hint to do positioning

*/

var fieldHintIntervals = new Array();

jQuery.fn.fieldhint = function(init) {
    var defaults = {
        autoStyle: true,
        autoPosition: true,
        intervals: new Array(),
        doHandleOtherHints: true,
        remove: false,
        debug: false,
        callBack: null
    };
    
    return this.each(function() {
        //var o = jQuery(this);
        if (typeof init != 'object') {
            init = {text: init};
        }
        var options = jQuery.extend(defaults, init);
        if (!options.text) {
            options.text = jQuery(this).attr('alt');
        }
        if (options.debug) {
            if (!jQuery('#fieldhint_debug').size()) {
                jQuery('body').append('<div id="fieldhint_debug"></div>');
            }
        }
        options.name = jQuery(this).attr('id');
        //o.options = options;
        removeHint(jQuery(this));
        if (!options.remove) {
            addHint(jQuery(this), options);
        }
        
    });
    
    function addHint (o, options) {
        var fieldwrapper    = jQuery('<div class="fieldhint-fieldwrapper"></div>');
        var hint            = jQuery('<label class="hint">' + options.text + '</label>');
        fieldwrapper.css('position', 'relative')
            .css('margin', '0')
            .css('padding', '0')
            .css('display', 'inline')
            .css('float', o.css('float'));
        hint.css('position', 'absolute');
        
        o.wrap(fieldwrapper)
            .after(hint)
            .addClass('hasFieldHint');
        
        if (options.autoPosition) {
            hint.css('top', o.position().top)
               .css('left', o.position().left)
               .css('float', o.css('float'));
        }
        
        if (options.autoStyle) {
            hint.css('fontFamily', o.css('fontFamily'))
               .css('fontSize', o.css('fontSize'))
               .css('color', o.css('color'))
               .css('cursor', 'text');
        }
        
        hint.click(function(event) {
            o.trigger('focus');
        });
        
        o.bind('blur.fieldhint', function(event) {
            if (o.hasClass('fieldhintBeingHandled')) {
                o.removeClass('fieldhintBeingHandled');
                handleHint(o, options);
            }
            if (options.doHandleOtherHints) {
                for (var i = 0; i < fieldHintIntervals.length; i++) {
                    window.clearInterval(fieldHintIntervals[i]);
                }
            }
            if (options.debug) {
                $('#fieldhint_debug').text('stopped');
            }
        });
        
        o.bind('focus.fieldhint', function(event) {
            hint.hide();
            o.addClass('fieldhintBeingHandled');
            if (options.doHandleOtherHints) {
                fieldHintIntervals.push(window.setInterval(function () {handleOtherHints(o, options);}, 50));
            }
            if (options && options.callBack) {
                options.callBack(false, o);
            }
        });
        
        handleHint(o, options);
        window.setTimeout(function () {handleHint(o, options);}, 30);
        if (options.debug) {
            $('#fieldhint_debug').text('stopped');
        }
    }
    
    function handleHint (o, options) {
        var hint = o.parent().find('.hint');
        var show = !o.val();
        if (!show) {
            hint.hide();
        } else if (!o.hasClass('fieldhintBeingHandled')) {
            hint.show();
        }
        if (options && options.callBack) {
            options.callBack(show, o);
        }
    }
    
    function handleOtherHints(o, options) {
        jQuery(".hasFieldHint").each(function() {
            if (this !== o.get(0)) {
                handleHint(jQuery(this));
            }
        });
        
        if (options.debug) {
            $('#fieldhint_debug').text('running');
        }
    }
    
    function removeHint (o) {
        var wrapper = o.parent('.fieldhint-fieldwrapper');
        if (wrapper.size()) {
            wrapper.before(o);
            wrapper.remove();
            o.removeClass('hasFieldHint')
                .removeClass('fieldhintBeingHandled')
                .unbind('focus.fieldhint')
                .unbind('blur.fieldhint');
        }
    }
    
};

