// SimplePopup jQuery plugin
// Author: Edward Yang (neo_in_matrix@msn.com)
// History:
//	2009/01/21 1.0 initial version
//  2009/01/22 Added halign option
//
(function($)
{
  // \param domPopup the popup object wrapped in jQuery
  // \param options
  //	*triggerID: which element will trigger the popup, can be the same as buddyID
  //	triggerEvent: what event will trigger the popup - 'click' or 'hover', default is 'click'
  //	buddyID: buddy ID to which popup will be aligned
  //	speed: animation speed - 'slow', 'fast' or milliseconds
  //	effect: animation effect - 'fade, 'slide', default is null
  //	refreshOnPopup: only applicable to popupUrl - refresh content from specified URL on every popup
  //  halign: horizontal aligment to buddy, default is 'left', can be 'right'
  //  noReposition: do not re-position popup object
  function SimplePopup(domPopup, options)
  {
    var _this = this;
    var popup = $(domPopup);
    var opts = $.extend({triggerEvent: 'click', halign: 'left'}, options);
    var buddy = null; if(opts.buddyID) var buddy = $('#' + opts.buddyID);
    var trigger = null; if(opts.triggerID) var trigger = $('#' + opts.triggerID);

    var document_click = function(e)
    {
      if(popup.is(':visible') && !insidePopup(e.pageX, e.pageY) 
        && !insideTrigger(e.pageX, e.pageY))
      {
        _this.hide();
      }
    };

    var insidePopup = function(x, y)
    {
      var offset = popup.offset();
      offset.right = offset.left + popup.outerWidth();
      offset.bottom = offset.top + popup.outerHeight();

      return y < offset.bottom && y > offset.top &&
           x < offset.right && x > offset.left;
    };

    var insideTrigger = function(x, y)
    {
      if(trigger == null) return false;
      var offset = trigger.offset();
      offset.right = offset.left + trigger.outerWidth();
      offset.bottom = offset.top + trigger.outerHeight();

      return y < offset.bottom && y > offset.top &&
           x < offset.right && x > offset.left;
    };

    this.hide = function(e)
    {
      if(opts.effect == 'fade') popup.fadeOut(opts.speed);
      else if(opts.effect == 'slide') popup.slideUp(opts.speed);
      else popup.hide(opts.speed);
    };

    this.show = function(e)
    {
      if(opts.noReposition != true)
      {
        if(buddy == null || opts.triggerEvent == 'hover')
        {
          var x = e.pageX;
          var y = e.pageY;
        }
        else if(buddy)
        {
          var offset = buddy.offset();
          var x = offset.left;
          var y = offset.top + buddy.outerHeight();
          if(opts.halign == 'right')
          {
            x = x + buddy.outerWidth() - popup.outerWidth();
          }
        }
        popup.css('left', x);
        popup.css('top', y);
      }

      if(opts.effect == 'fade') popup.fadeIn(opts.speed);
      else if(opts.effect == 'slide') popup.slideDown(opts.speed);
      else
      {
        popup.show(opts.speed);
      }
      //if(opts.triggerEvent == 'click') e.stopPropagation();
    };

    var popup_mouseout = function(e)
    {
      if(insidePopup(e.pageX, e.pageY)) return;
      if(insideTrigger(e.pageX, e.pageY)) return;
      popup.hide();
    };

    if(opts.triggerEvent == 'click')
    {
      if(trigger)
      {
        trigger.click(this.show);
        popup.click(function(e){e.stopPropagation()});
        $(document).click(document_click);
      }
    }
    else if(opts.triggerEvent == 'hover')
    {
      if(trigger)
      {
        trigger.hover(this.show, popup_mouseout);
        popup.hover(null, popup_mouseout);
      }
    }
    else
    {
      alert('INVALID triggerEvent option value - ' + opts.triggerEvent
        + '\r\nValid values are: click or hover.');
    }
  };

  var L_INSTANCE_NAME = 'SimplePopupInstance';

  $.fn.popupHtml = function(html, options)
  {
    return this.each(function() {
      $(this).append(html);
      if(this.getAttribute(L_INSTANCE_NAME) == null)
        this.setAttribute(L_INSTANCE_NAME, new SimplePopup(this, options));
    });
  };

  $.fn.popupUrl = function(url, options)
  {
    return this.each(function() {
      if(!options.refreshOnPopup)
      {
        var popup = $(this);
        $.get(url, '', function(data, status){popup.append(data);});
      }
      if(this.getAttribute(L_INSTANCE_NAME) == null)
        this.setAttribute(L_INSTANCE_NAME, new SimplePopup(this, options));
    });
  };

  $.fn.popup = function(options)
  {
    return this.each(function() {
      if(this.getAttribute(L_INSTANCE_NAME) == null)
        this.setAttribute(L_INSTANCE_NAME, new SimplePopup(this, options));
    });
  };

})(jQuery);

