/*
 * jQuery clueTip plugin
 * Version 0.2  (05/16/2007)
 * @requires jQuery v1.1.1
 * @requires Dimensions plugin 
 *
 * 
 * Copyright (c) 2007 Karl Swedberg
 * Inspired by Cody Lindley's jTip (http://www.codylindley.com)
 * Thanks to Shelane Enos for the feature ideas 
 * Thanks to Jonathan Chaffer, as always, for the help.
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */

(function($) { 
    
  var $cluetip, $cluetipInner, $cluetipOuter;

  $.fn.cluetip = function(options) {
    
    // set up default options
    var defaults = {
      width: 275,
      local: false,
      attribute: 'rel',
      titleAttribute: 'title',
      hoverClass: '',
      sticky: false,
      closePosition: 'top',
      closeText: 'Close',
      truncate: '',
      dataType: 'html',
      pngFix: false,
      ajaxProcess: function(data) {return data;}
    };
    
    return this.each(function() {
      
      $.extend(defaults, options);

      // create the cluetip divs
      if (!$cluetip) {
        $cluetipInner = $('<div id="cluetip-inner"></div>');
        $cluetipOuter = $('<div id="cluetip-outer"></div>')
        .append($cluetipInner);
        
        $cluetip = $('<div></div>')
          .attr({'id': 'cluetip'})
          .css({position: 'absolute'})
        .append($cluetipOuter)
        .appendTo('body')
        .hide();
      }
      if (defaults.pngFix) {
        $('#cluetip').pngfix();
      }
      var $this = $(this);      
      var tipAttribute = $this.attr(defaults.attribute);
      if (!tipAttribute) return true;
      
      // vertical measurements
      var tipHeight, wHeight;
      var sTop, offTop, posY;

      // horizontal measurements
      var tipWidth = parseInt(defaults.width, 10);
      var offWidth = this.offsetWidth;
      var offLeft, posX, docWidth;
      
      var tipTitle = (defaults.attribute != 'title') ? $this.attr(defaults.titleAttribute) : '';
      var localContent;
      
      // close cluetip and reset title attribute if one exists
      var cluetipClose = function() {      
        $cluetipInner.empty().parent().parent().hide();
        if (tipTitle) {
          $this.attr('title', tipTitle);
        }
      };

      var cluetipShow = function(bpY) {
         tipHeight = $cluetip.outerHeight();

         if ($this.css('display') == 'block') {
            $cluetip.css({top: (bpY - 10) + 'px'});

         }
         else {
           $cluetip.css({top: posY + 'px'});
         }
         if ( posY + tipHeight > sTop + wHeight ) {
           $cluetip.css({top: (sTop + wHeight - tipHeight - 10) + 'px'});
         } 

         if (defaults.truncate) {

           var $truncloaded = $cluetipInner.html();//.slice(0,defaults.truncate) + '...';
           $cluetipInner.html($truncloaded);
         }

         if (defaults.sticky) {
           var $closeLink = $('<a href="#" id="cluetip-close">' + defaults.closeText + '</a>');
           (defaults.closePosition == 'bottom') ? $cluetipInner.append($closeLink) : $cluetipInner.prepend($closeLink);
           $closeLink.click(function() {
             cluetipClose();
             return false;
           });
         }
         if (tipTitle) { 
           $cluetipInner.prepend('<h3 id="cluetip-title">' + tipTitle + '</h3>');
         }
         $cluetip.show();

      };

      
      // on click
      $this.click(function() {
        if (tipAttribute == $this.attr('href')) {
          return false;
        }
      })
// ON MOUSE OVER ...
      .hover(function(event) {
        
        if (tipAttribute == $this.attr('href')) {
          //$this.css('cursor', 'crosshair');
        }
        if (tipTitle) {
          $this.removeAttr('title');          
        }
        if (defaults.hoverClass) {
          $this.addClass(defaults.hoverClass)
        }
        
        sTop = $(document).scrollTop();
        offTop = $this.offset().top;
        offLeft = $this.offset().left;
        docWidth = $(document).width();
        posX = (offWidth > offLeft && offLeft > tipWidth)
          || offLeft + offWidth + tipWidth > docWidth 
          ? offLeft - tipWidth - 15 
          : offWidth + offLeft + 15;
        posY = offTop - 10;

        $cluetip.css({width: defaults.width});
        if ($this.css('display') != 'block' && posX >=0) {
          $cluetip.css({left: posX + 'px'});
        } else {
          if (event.pageX + tipWidth > docWidth) {
            $cluetip.css({left: (event.pageX - tipWidth - 30) + 'px'})
          } else {
            $cluetip.css({left: (event.pageX + 30) + 'px'});
          }
          var pY = event.pageY;
        }
        wHeight = $(window).height();

        
// load external file via ajax
        if (!defaults.local && tipAttribute.indexOf('#') != 0) {

          $.ajax({
            url: tipAttribute,
            success: function(data) {
              $cluetipInner.html(defaults.ajaxProcess(data));
              
              cluetipShow(pY);
            }
          });

// load an element from the same page
        } else if (defaults.local && tipAttribute.indexOf('#') == 0){
          var localContent = $(tipAttribute).html();
          $cluetipInner.html(localContent);
          cluetipShow(pY);
        }
 // on mouseout...    
      }, function() {
        if (defaults.sticky == false) {
          cluetipClose();
        };
        if (defaults.hoverClass) {
          $this.removeClass(defaults.hoverClass);
        }
      });
      
    });
  };  
  
})(jQuery);