/*!
 * jQuery MouseTip plugin v0.1
 * 2010-11-20
 *
 * Copyright (c) 2010 Pavel Tzonkov <pavelc@users.sourceforge.net>
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 */

(function($) {
    $.fn.mousetip = function(settings) {
        var version = '0.1';

        var c = {
            cssClass: 'mousetip',
            position: {
                left: 15,
                top: 20,
                vertical: 'bottom',
                horizontal: 'right'
            },
            align: 'default',
            snap: true,
            content: false,
            eventOpen: 'mouseenter',
            eventClose: 'mouseleave',
            fade: 'fast'
        };

        var testTip = 'jQuery mousetip plugin v' + version + '<br />Undefined Tip!';

        var nopx = function(px) {
            return parseInt(px.substr(0, px.length - 2));
        };

        var _width = function(el) {
            return el.outerWidth() + nopx(el.css('marginLeft')) + nopx(el.css('marginRight'));
        };

        var _height = function(el) {
            return el.outerHeight() + nopx(el.css('marginTop')) + nopx(el.css('marginBottom'));
        };

        var close = function(el) {
            var tip = el.data('tip');
            if (tip) {
                el.data('tip', false);
                tip.fadeOut(c.fade, function() {
                    tip.detach();
                });
            }
            return false;
		};

        var snap = function(el, left, top) {
            var x = $(window).scrollLeft();
            var y = $(window).scrollTop();
            var width = _width(el);
            var height = _height(el);

            if ((width <= $(window).width()) && (height <= $(window).height())) {
                if (left < x)
                    left = x;
                else if ((left + width) > (x + $(window).width()))
                    left = $(window).width() - width;

                if (top < y)
                    top = y;
                else if ((top + height) > (y + $(window).height()))
                    top = $(window).height() - height;
            }

            el.css({
                left: left + 'px',
                top: top + 'px'
            });
        };

        var checkCSS = function(selector, property) {
            var rules = document.all ? 'rules' : 'cssRules';

            for (var sheet = 0; sheet < document.styleSheets.length; sheet++)
                if (document.styleSheets[sheet][rules] != null)
                    for (var rule = 0; rule < document.styleSheets[sheet][rules].length; rule++)
                        if ((document.styleSheets[sheet][rules][rule].selectorText == selector)) {
                            if (typeof property == 'undefined')
                                return true;
                            if (typeof document.styleSheets[sheet][rules][rule].style[property] !== 'undefined')
                                return document.styleSheets[sheet][rules][rule].style[property];
                        }

            return false;
        };

		if ((typeof settings != 'undefined') && settings.substr)
            c.content = settings;
		else
            $.extend(c, settings);

		this.each(function() {
		    e = $(this).first();
		    e.unbind(c.eventOpen);
		    e.unbind(c.eventClose);
		    var content;
            if (e.data('content') && e.data('content').length)
                content = e.data('content');
            else if (c.content !== false)
                content = c.content
            else if (e.attr('title').length)
                content = e.attr('title');
            else
                content = testTip;

            if (e.attr('title')) e.attr('title', '');
            e.data('content', content);

			e.bind(c.eventOpen, function() {
			    if ((c.eventOpen == c.eventClose) && $(this).data('tip'))
			        return close($(this));

                $('body').append('<div class="' + c.cssClass + '">' + content + '</div>');
                var tip = $('div.' + c.cssClass).last();

                tip.css({
                    position: 'absolute',
                    display: 'none'
                });

                if (!checkCSS('.' + c.cssClass) && !checkCSS('div.' + c.cssClass)) {
                    tip.css({
                        background: '#ffb',
                        border: '1px solid #885',
                        padding: '2px 3px',
                        margin: '2px',
                        width: tip.innerWidth() + 'px',
                        borderRadius: '3px',
                        color: '#555'
                    });
                    tip.css('-moz-border-radius', '3px');
                    tip.css('-webkit-border-radius', '3px');

                } else if (
                    !checkCSS('.' + c.cssClass, 'width') &&
                    !checkCSS('div.' + c.cssClass, 'width')
                )
                    tip.css('width', tip.innerWidth());

                if (c.position.substr) {
                    var top, left;

                    if (/^top|bottom$/.test(c.position) &&
                        !/^left|right|center$/.test(c.align)
                    )
                        c.align = 'left';

                    if (/^left|right$/.test(c.position) &&
                        !/^top|bottom|center$/.test(c.align)
                    )
                        c.align = 'top';

                    if (/^top|bottom$/.test(c.position)) {
                        if (c.align == 'left')
                            left = $(this).offset().left;
                        else if (c.align == 'right')
                            left = $(this).offset().left + _width($(this)) - _width(tip);
                        else if (c.align == 'center')
                            left = $(this).offset().left - parseInt((_width(tip) - _width($(this))) / 2);
                    }

                    if (/^left|right$/.test(c.position)) {
                        if (c.align == 'top')
                            top = $(this).offset().top;
                        else if (c.align == 'bottom')
                            top = $(this).offset().top + _height($(this)) - _height(tip);
                        else if (c.align == 'center')
                            top = $(this).offset().top - parseInt((_height(tip) - _height($(this))) / 2);
                    }

                    if (/^top(Left|Right)?$/.test(c.position))
                        top = $(this).offset().top - _height(tip);
                    if (/^bottom(Left|Right)?$/.test(c.position))
                        top = $(this).offset().top + _height($(this));
                    if (/^(topL|bottomL|l)eft$/.test(c.position))
                        left = $(this).offset().left - _width(tip);
                    if (/^(topR|bottomR|r)ight$/.test(c.position))
                        left = $(this).offset().left + _width($(this));

                    tip.css({
                        left: $(window).scrollLeft() + 'px',
                        top: $(window).scrollTop() + 'px'
                    });

                    if (c.snap) snap(tip, left, top);
                    tip.fadeIn(c.fade);

                } else if (typeof c.position == 'object') {
                    if (!c.position.left) c.position.left = 0;
                    if (!c.position.top) c.position.top = 0;
                    $(this).unbind('mousemove');
                    $(this).bind('mousemove', function(ev) {
                        var left = ev.pageX + c.position.left;
                        var top = ev.pageY + c.position.top;
                        if (/^top|center$/.test(c.position.vertical)) {
                            var height = _height(tip);
                            if (c.position.vertical == "top")
                                top -= height;
                            else if (c.position.vertical == "center")
                                top -= parseInt(height / 2);
                        }
                        if (/^left|center$/.test(c.position.horizontal)) {
                            var width = _width(tip);
                            if (c.position.horizontal == "left")
                                left -= width;
                            else if (c.position.horizontal == "center")
                                left -= parseInt(width / 2);
                        }
                        tip.css({
                            left: $(window).scrollLeft() + 'px',
                            top: $(window).scrollTop() + 'px'
                        });
                        tip.fadeIn(c.fade);
                        if (c.snap) snap(tip, left, top);
                    });
                }

                $(this).data('tip', tip);
			});

			if (c.eventOpen != c.eventClose) {
			    e.bind(c.eventClose, function() {
                    return close($(this));
			    });
			}
		});
	};
})(jQuery);
