/**
* jquery.simpletip 1.3.1. A simple tooltip plugin
* 
* Copyright (c) 2009 Craig Thompson
* http://craigsworks.com
*
* Licensed under GPLv3
* http://www.opensource.org/licenses/gpl-3.0.html
*
* Launch  : February 2009
* Version : 1.3.1
* Released: February 5, 2009 - 11:04am
*/
(function($) {

    function Simpletip(elem, conf) {
        var self = this;
        elem = jQuery(elem);

        var tooltip = jQuery(document.createElement('div'))
                     .addClass(conf.baseClass)
                     .addClass((conf.fixed) ? conf.fixedClass : '')
                     .addClass((conf.persistent) ? conf.persistentClass : '')
                     .html(conf.content)
                     .appendTo(document.body);

        if (!conf.hidden) tooltip.show();
        else tooltip.hide();

        tooltip.mouseenter(function() {
            if (self.hideTimer != null) {
                clearTimeout(self.hideTimer);
                self.hideTimer = null;
            }
        });

        tooltip.mouseleave(function() {
            self.hide();
        });

        if (!conf.persistent) {
            elem.hover(
            function(event) {
                if (self.hideTimer != null) {
                    clearTimeout(self.hideTimer);
                    self.hideTimer = null;
                }

                self.showTimer = setTimeout(function() { 
                    self.show(event);
                }, 500);
            },
            function() {
                if (self.showTimer != null) {
                    clearTimeout(self.showTimer);
                    self.showTimer = null;
                }
                self.hideTimer = setTimeout(function() {
                    self.hide(); 
                }, 200);
            }
         );

            if (!conf.fixed) {
                elem.mousemove(function(event) {
                    if (tooltip.css('display') !== 'none') self.updatePos(event);
                });
            };
        }
        else {
            elem.click(function(event) {
                if (event.target === elem.get(0)) {
                    if (tooltip.css('display') !== 'none')
                        self.hide();
                    else
                        self.show();
                };
            });

            jQuery(window).mousedown(function(event) {
                if (tooltip.css('display') !== 'none') {
                    var check = (conf.focus) ? jQuery(event.target).parents('.tooltip').andSelf().filter(function() { return this === tooltip.get(0) }).length : 0;
                    if (check === 0) self.hide();
                };
            });
        };


        jQuery.extend(self,
      {
          getVersion: function() {
              return [1, 2, 0];
          },

          getParent: function() {
              return elem;
          },

          getTooltip: function() {
              return tooltip;
          },

          getPos: function() {
              return tooltip.offset();
          },

          setPos: function(posX, posY) {
              var elemPos = elem.offset();

              if (typeof posX == 'string') posX = parseInt(posX) + elemPos.left;
              if (typeof posY == 'string') posY = parseInt(posY) + elemPos.top;

              tooltip.css({ left: posX, top: posY });

              return self;
          },

          show: function(event) {
              conf.onBeforeShow.call(self);

              self.updatePos((conf.fixed) ? null : event);

              switch (conf.showEffect) {
                  case 'fade':
                      tooltip.fadeIn(conf.showTime); break;
                  case 'slide':
                      tooltip.slideDown(conf.showTime, self.updatePos); break;
                  case 'custom':
                      conf.showCustom.call(tooltip, conf.showTime); break;
                  default:
                  case 'none':
                      tooltip.show(); break;
              };

              tooltip.addClass(conf.activeClass);

              conf.onShow.call(self);

              return self;
          },

          hide: function() {
              conf.onBeforeHide.call(self);

              switch (conf.hideEffect) {
                  case 'fade':
                      tooltip.fadeOut(conf.hideTime); break;
                  case 'slide':
                      tooltip.slideUp(conf.hideTime); break;
                  case 'custom':
                      conf.hideCustom.call(tooltip, conf.hideTime); break;
                  default:
                  case 'none':
                      tooltip.hide(); break;
              };

              tooltip.removeClass(conf.activeClass);

              conf.onHide.call(self);

              return self;
          },

          update: function(content) {
              tooltip.html(content);
              conf.content = content;

              return self;
          },

          load: function(uri, data) {
              conf.beforeContentLoad.call(self);

              tooltip.load(uri, data, function() { conf.onContentLoad.call(self); });

              return self;
          },

          boundryCheck: function(posX, posY) {
              var newX = posX + tooltip.outerWidth();
              var newY = posY + tooltip.outerHeight();

              var windowWidth = jQuery(window).width() + jQuery(window).scrollLeft();
              var windowHeight = jQuery(window).height() + jQuery(window).scrollTop();

              return [(newX >= windowWidth), (newY >= windowHeight)];
          },

          updatePos: function(event) {
              var tooltipWidth = tooltip.outerWidth();
              var tooltipHeight = tooltip.outerHeight();

              if (!event && conf.fixed) {
                  if (conf.position.constructor == Array) {
                      posX = parseInt(conf.position[0]);
                      posY = parseInt(conf.position[1]);
                  }
                  else if (jQuery(conf.position).attr('nodeType') === 1) {
                      var offset = jQuery(conf.position).offset();
                      posX = offset.left;
                      posY = offset.top;
                  }
                  else {
                      var elemPos = elem.offset();
                      var elemWidth = elem.outerWidth();
                      var elemHeight = elem.outerHeight();

                      switch (conf.position) {
                          case 'top':
                              var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
                              var posY = elemPos.top - tooltipHeight;
                              break;

                          case 'bottom':
                              var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
                              var posY = elemPos.top + elemHeight;
                              break;

                          case 'left':
                              var posX = elemPos.left - tooltipWidth;
                              var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
                              break;

                          case 'right':
                              var posX = elemPos.left + elemWidth;
                              var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
                              break;

                          default:
                          case 'default':
                              var posX = (elemWidth / 2) + elemPos.left + 20;
                              var posY = elemPos.top;
                              break;
                      };
                  };
              }
              else {
                  var posX = event.pageX;
                  var posY = event.pageY;
              };

              if (typeof conf.position != 'object') {
                  posX = posX + conf.offset[0];
                  posY = posY + conf.offset[1];

                  if (conf.boundryCheck) {
                      var overflow = self.boundryCheck(posX, posY);

                      if (overflow[0]) posX = posX - (tooltipWidth / 2) - (2 * conf.offset[0]);
                      if (overflow[1]) posY = posY - (tooltipHeight / 2) - (2 * conf.offset[1]);
                  }
              }
              else {
                  if (typeof conf.position[0] == "string") posX = String(posX);
                  if (typeof conf.position[1] == "string") posY = String(posY);
              };

              self.setPos(posX, posY);

              return self;
          }
      });
    };

    jQuery.fn.simpletip = function(conf) {
        // Check if a simpletip is already present
        var api = jQuery(this).eq(typeof conf == 'number' ? conf : 0).data("simpletip");
        if (api) return api;

        // Default configuration
        var defaultConf = {
            // Basics
            content: 'A simple tooltip',
            persistent: false,
            focus: false,
            hidden: true,

            // Positioning
            position: 'default',
            offset: [0, 0],
            boundryCheck: true,
            fixed: true,

            // Effects
            showEffect: 'fade',
            showTime: 150,
            showCustom: null,
            hideEffect: 'fade',
            hideTime: 150,
            hideCustom: null,

            hideTimer: null,
            showTimer: null,

            // Selectors and classes
            baseClass: 'tooltip',
            activeClass: 'active',
            fixedClass: 'fixed',
            persistentClass: 'persistent',
            focusClass: 'focus',

            // Callbacks
            onBeforeShow: function() { },
            onShow: function() { },
            onBeforeHide: function() { },
            onHide: function() { },
            beforeContentLoad: function() { },
            onContentLoad: function() { }
        };
        jQuery.extend(defaultConf, conf);

        this.each(function() {
            var el = new Simpletip(jQuery(this), defaultConf);
            jQuery(this).data("simpletip", el);
        });

        return this;
    };
})();