/*
 * Usage: 
 *   <div id='tooltip' style="display:none; margin: 5px; background-color: red;">
 *     Detail infos on product 1....<br />
 *   </div>
 *
 *   <div id='product_1'>
 *     This is product 1
 *   </div>
 *
 *   <script type="text/javascript">
 *     var my_tooltip = new Dropdown('product_1', 'tooltip')
 *   </script>
 */

var all_dropdowns = [];

var Dropdown = Class.create();
Dropdown.prototype = {
   initialize: function(element, flyout, opts) {
    var options = Object.extend({
       default_css: false,
       margin: "0px",
       padding: "5px",
       backgroundColor: "#d6d6fc",
       delta_x: 5,
       delta_y: 5,
       zindex: 1000,
       elementPadding: 0
    }, arguments[2] || {});

    this.element = $(element);
    this.flyout  = $(flyout);

    this.options = options;
      this.shown = false;
    this.flyout.hide();

     // The effective area denotes the x1,y1,x2,y2 coordinates that the open menu covers
     // all mouseout events will look at this before deciding to continue
     this.effectiveArea = [];

    this.eventMouseOver = this.showDropdown.bindAsEventListener(this);
    this.eventMouseOut  = this.hideDropdown.bindAsEventListener(this);
    this.eventMouseOutTimer  = this.hideDropdownTimer.bindAsEventListener(this);

    this.registerEvents();
	this.timer;
  },
   
  registerEvents: function() {
    Event.observe(this.element, "mouseover", this.eventMouseOver);

    Event.observe(this.element, "mouseout", this.eventMouseOut);
    Event.observe(this.flyout, "mouseout", this.eventMouseOut);
    Event.observe(document, "mousemove", this.eventMouseOutTimer);
  },

   isInsideElement: function(ele,x,y)
   {
      coords = [this.findPos(ele), this.getBottomRight(ele)].flatten();
      if(((x > coords[0]) && (x < coords[2])) &&
	 ((y > coords[1]) && (y < coords[3]))) return true;
      return false;
   },

   hideDropdown: function(event)
   {
      mouse_x = Event.pointerX(event);
      mouse_y = Event.pointerY(event);

      if(this._isInsideMenu(mouse_x, mouse_y)) {
		return;
	}
	this._hideDropdown();
   },
	
	
	_isInsideMenu : function(mouse_x, mouse_y){
		return (this.isInsideElement(this.flyout, mouse_x, mouse_y) || this.isInsideElement(this.element, mouse_x, mouse_y));
	},
	
	_hideDropdown : function(){
      this.element.removeClassName('rolled-over');
      this.flyout.hide();
      this.shown = false;
	},

	hideDropdownTimer : function(event){
		var _this = this;
     	mouse_x = Event.pointerX(event);
      	mouse_y = Event.pointerY(event);
		var hideDropdown = function(){
	     	if(_this._isInsideMenu(mouse_x, mouse_y)) return;
			_this._hideDropdown();
		}
		clearTimeout(this.timer);
		this.timer = setTimeout(hideDropdown, 100, event);
	},

  showDropdown: function(event)
   {
	if(this.shown) return;
      ele = $(Event.findElement(event, 'a'));
      Event.stop(event);
      bottomLeft = this.getBottomLeft(ele);
      this.element.addClassName('rolled-over');
      this.setStyleAndPosition(bottomLeft[0], bottomLeft[1]);
      this.flyout.show();
      this.shown = true;
      ie_apply_zindex(this.element.id, this.options.zindex + 1);
   },
  
  setStyleAndPosition: function(x, y)
   {
      // set the right styles to position the tool tip
      Element.setStyle(this.flyout, { position:'absolute',
	 			      top:y + "px",
	 			      left:x + "px",
				      zIndex:(this.options.zindex)
	 			    });
	
      // apply default theme if wanted
      if (this.options.default_css)
      {
	 Element.setStyle(this.flyout, { margin:this.options.margin,
		 			 padding:this.options.padding,
		                         backgroundColor:this.options.backgroundColor,
					 zIndex:this.options.zindex
		 		       });	
      }	
  },

   setEffectiveArea: function()
   {
      this.effectiveArea = [this.findPos(this.element), this.getBottomRight(this.flyout)].flatten();
   },

   findPos: function(obj)
   {
      var curleft = curtop = 0;
      if (obj.offsetParent)
      {
	 do
	 {
	    curleft += obj.offsetLeft;
	    curtop += obj.offsetTop;
	 }
	 while (obj = obj.offsetParent);
      }
      return [curleft,curtop];
   },

   getBottomRight: function(ele)
   {
      pos = this.getBottomLeft(ele);
      return [pos[0] + ele.getWidth(), pos[1]];
   },

   getBottomLeft: function(ele)
   {
      id = $(ele).id;
      if(id) ele = $(id);
      
      topleft = this.findPos(ele);
      height = $(ele).getHeight();
      if(height == 0) height = ele.getElementsByTagName('li').length * 25; // hack for list items
      bottomleft = [topleft[0], topleft[1] + height];
      return bottomleft;
   }
}

var iaz_preserved_elements = [];
var iaz_preserved_zindexes = [];

function ie_apply_zindex(element_id, zindex, context_id) {
   // default values
   if (undefined == zindex) { zindex = 1; }
   var context = (undefined == context_id ? $(context_id) : $(document.body));
   var element = $(element_id);

   // undo past ie_apply_zindex()
   for (i = iaz_preserved_elements.length-1; i >= 0; i--) {
      iaz_preserved_elements[i].setStyle({'z-index': iaz_preserved_zindexes[i]});
   }
   iaz_preserved_elements = [];
   iaz_preserved_zindexes = [];

   // find relative-positioned ancestors of element within context
   element.ancestors().each(
      function(ancestor) {
         if ('relative' == ancestor.getStyle('position')) {
            // preserve ancestor's current z-index
            iaz_preserved_elements.push(ancestor);
            iaz_preserved_zindexes.push( ancestor.getStyle('z-index') );

            // apply z-index to ancestor
            ancestor.setStyle({'z-index': zindex});
         }
         if (ancestor == context) { throw $break; }
      }
   );
}