(function ($) {
    // @todo Document this.
    $.extend($, {
        placeholder: {
            browser_supported: function () {
                return this._supported !== undefined ?
                  this._supported :
                  (this._supported = !!('placeholder' in $('<input type="text">')[0]));
            },
            shim: function (opts) {
                var config = {
                    color: '#bbb',
                    cls: 'placeholder',
                    selector: 'input[placeholder], textarea[placeholder]'
                };
                $.extend(config, opts);
                return !this.browser_supported() && $(config.selector)._placeholder_shim(config);
            }
        }
    });

    $.extend($.fn, {
        _placeholder_shim: function (config) {
            function calcPositionCss(target) {
                var op = $(target).offsetParent().offset();
                var ot = $(target).offset();

                return {
                    top: ot.top - op.top,
                    left: ot.left - op.left,
                    width: $(target).width()
                };
            }
            function adjustToResizing(label) {
                var $target = label.data('target');
                if (typeof $target !== "undefined") {
                    label.css(calcPositionCss($target));
                    $(window).one("resize", function () { adjustToResizing(label); });
                }
            }
            return this.each(function () {
                var $this = $(this);

                if ($this.is(':visible')) {

                    if ($this.data('placeholder')) {
                        var $ol = $this.data('placeholder');
                        $ol.css(calcPositionCss($this));
                        return true;
                    }

                    var possible_line_height = {};
                    if (!$this.is('textarea') && $this.css('height') != 'auto') {
                        possible_line_height = { lineHeight: $this.css('height'), whiteSpace: 'nowrap' };
                    }

                    var isBorderBox = ($this.css('box-sizing') === 'border-box');
                    var isTextarea = $this.is('textarea');

                    var ol = $('<label />')
                      .text($this.attr('placeholder'))
                      .addClass(config.cls)
                      .css($.extend({
                          position: 'absolute',
                          display: 'inline',
                          'float': 'none',
                          overflow: 'hidden',
                          textAlign: 'left',
                          color: config.color,
                          cursor: 'text',
                          paddingTop: !isTextarea && isBorderBox ? '0' : $this.css('padding-top'),
                          paddingRight: $this.css('padding-right'),
                          paddingBottom: !isTextarea && isBorderBox ? '0' : $this.css('padding-bottom'),
                          paddingLeft: $this.css('padding-left'),
                          fontSize: $this.css('font-size'),
                          fontFamily: $this.css('font-family'),
                          fontStyle: $this.css('font-style'),
                          fontWeight: $this.css('font-weight'),
                          textTransform: $this.css('text-transform'),
                          backgroundColor: 'transparent',
                          zIndex: 99
                      }, possible_line_height))
                      .css(calcPositionCss(this))
                      .attr('for', this.id)
                      .data('target', $this)
                      .click(function () {
                          if (!$(this).data('target').is(':disabled')) {
                              $(this).data('target').focus();
                          }
                      })
                      .insertBefore(this);
                    $this
                        .data('placeholder', ol)
                        .on('keydown', function () {
                            ol.hide();
                        })
                        .on('blur change', function () {
                            ol[$this.val().length ? 'hide' : 'show']();
                        })
                        .triggerHandler('blur');
                    $(window).one("resize", function () { adjustToResizing(ol); });
                }
            });
        }
    });
})(jQuery);

jQuery(document).add(window).bind('ready load', function () {
    if (jQuery.placeholder) {
        jQuery.placeholder.shim();
    }
});