
(function ($) {
    var updaters = [];
    
    function updateFields() {
        for (var i = updaters.length; i--;)
            updaters[i]();
    }
    
    // Regularly update the registered form fields
    // This is required to work correctly with some automatic form fillers
    setInterval(updateFields, 200);
    
    $.fn.compactForm = function (options) {
        // Extend the default options with those provided
        var options = $.extend({}, $.fn.compactForm.defaults, options);
        
        // Search for the wanted elements within the elements as well as among their children
        this.filter(options.select).add(this.find(options.select)).each(function () {
            var input = $(this);
            var label = $('label[for='+input.attr('id')+"]");
            var focus = false; // Tracks if the current input has focus
            
            function updateField(event) {
                var hasValue = (input.val() !== '');
                
                if (event) {
                    focus = (event.type == 'focus');
                }
                if (focus || hasValue) {
                    if (label.is(':visible') && !label.is(':animated')) {
                        if (hasValue || ($.browser.msie && $.browser.version < 7.0)) {
                            label.hide();
                        } else {
                            label.fadeOut('fast');
                        }
                        options.labelHideFn && options.labelHideFn(event, input);
                    }
                } else {
                    if (!label.is(':visible') && !label.is(':animated')) {
                        if ($.browser.msie && $.browser.version < 7.0) {
                            label.show();
                        } else {
                            label.fadeIn('fast');
                        }
                        options.labelShowFn && options.labelShowFn(event, input);
                    }
                }
            };
            
            input.focus(updateField).blur(updateField);
            updaters.push(updateField);
            updateField();
            
            // Clicking on a label gives focus to the input (compatibility for some browsers)
            label.click(function () {
                input.focus();
            });
        });
        
        return this;
    };

    // Publicly accessible default options
    $.fn.compactForm.defaults = {
        // Make these elements compact
        select: 'input[type=text], input[type=password], textarea',
        
        // User functions called when the elements gets or looses focus
        labelShowFn: null,
        labelHideFn: null
    };
})(jQuery);

