﻿ 
var Widget_Tooltip_ShowTimeoutMilSecs = 100;
var Widget_Tooltip_HideTimeoutMilSecs = 500;

;(function($) {
 
  // the tooltip element
 var helper = {},
  // the current tooltipped element
  currentId,
  // timeout id for delayed tooltips
  showTimer,
  // timeout id for delayed tooltips
  hideTimer;
 
 $.tooltip = {
  blocked: false,
  defaults: {
   extraClass: "",
   top: 15,
   left: 15,
   id: "tooltip"
  },
  block: function() {
   $.tooltip.blocked = !$.tooltip.blocked;
  }
 };
 
 $.fn.extend({
  tooltip: function(settings) {
   settings = $.extend({}, $.tooltip.defaults, settings);
   createHelper(settings);
   helper.parent.hover(function(){clearTimeout(hideTimer)}, hideAfterDelay);  
   
   return this.each(function() {
     $.data(this, "tooltip", settings);
     this.tOpacity = helper.parent.css("opacity");
     $(this).removeAttr("title");
     // also remove alt attribute to prevent default tooltip in IE
     this.alt = "";
    })
    .hover(showAfterDelay, hideAfterDelay);
  },
  hideWhenEmpty: function() {
   return this.each(function() {
    $(this)[ $(this).html() ? "show" : "hide" ]();
   });
  },
  url: function() {
   return this.attr('href') || this.attr('src');
  }
 });

 function hideOnClickOutside(evt) {
  var target = $(evt.target);
  if (target.is('#tooltip') || target.parents('#tooltip').length>0 || '#' + target[0].id==currentId ||(currentId!=null && target.parents(currentId).length>0))
   return;
  if (currentId != '')
   hide.apply($(currentId)[0], arguments); 
  $("body").unbind('click', hideOnClickOutside);
 }
    
 function createHelper(settings) {
  // there can be only one tooltip helper
  if( helper.parent )
   return;
  // create the helper
  helper.parent = $('<div id="' + settings.id + '"><div class="body"></div></div>')
   // add to document
   .appendTo(document.body)
   // hide it at first
   .hide();
   
  // apply bgiframe if available
  if ( $.fn.bgiframe )
   helper.parent.bgiframe();

  helper.body = $('div.body', helper.parent);
 }
 
 function settings(element) {
  return $.data(element, "tooltip");
 }
 

 function hideAfterDelay() {
  clearTimeout(hideTimer);
  clearTimeout(showTimer);
  if (!currentId)
   return;
  var obj=$(currentId)[0];
  hideTimer = setTimeout(function() {hide.apply(obj, arguments)}, Widget_Tooltip_HideTimeoutMilSecs);
 }

 function showAfterDelay(evt) {
  clearTimeout(hideTimer);
  clearTimeout(showTimer);
  var obj = this;
  var ev = evt;
  showTimer = setTimeout(function() {setTooltipContents.apply(obj, [ev])}, Widget_Tooltip_ShowTimeoutMilSecs);

 }

 function show() {
  helper.parent.show();
  $("body").click(hideOnClickOutside);
  updatePosition();
 }
  
 function setTooltipContents(evt) {
  if (helper.parent.is(":visible"))
   hide.apply(this, arguments);

  // if this is the current source, or it has no title (occurs with click event), stop
  if ( $.tooltip.blocked || this.id == currentId)
   return;

  // save current
  currentId = "#" + this.id;


  var bodyContent = settings(this).bodyHandler.call(this);
  if (bodyContent.nodeType || bodyContent.jquery) {
   helper.body.empty().append(bodyContent)
  } else {
   helper.body.html( bodyContent );
  }
  helper.body.show();
  
  
  // add an optional class for this tip
  helper.parent.addClass(settings(this).extraClass);

  
  show.apply(this, arguments);
  // updatePosition at least once
  updatePosition(evt);
 }


 

 function updatePosition(evt) {
  if($.tooltip.blocked)
   return;
  
  if (evt && evt.target.tagName == "OPTION") {
   return;
  }
  
  
  // if no current element is available, remove this listener
  if( currentId == null ) {
   return; 
  }

  
  // remove position helper classes
  helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
  
  
  var left = helper.parent[0].offsetLeft;
  var top = helper.parent[0].offsetTop;
  if (evt) {
   // position the helper 15 pixel to bottom right, starting from mouse position
   left = evt.pageX + settings($(currentId)[0]).left;
   top = evt.pageY + settings($(currentId)[0]).top;
   var right='auto';
   if (($(window).width() - 450) < (left  - $(window).scrollLeft())) {
    right = $(window).width() - left;
    left = 'auto';
   }
   helper.parent.css({
    left: left,
    right: right,
    top: top
   });
  }
  
  var v = viewport(),
   h = helper.parent[0];
  // check horizontal position
  if (v.x + v.cx < h.offsetLeft + h.offsetWidth && left != "auto") {
   left -= h.offsetWidth + 20 + settings($(currentId)[0]).left;
   helper.parent.css({left: left + 'px'}).addClass("viewport-right");
  }
  // check vertical position
  if ((v.y + v.cy < h.offsetTop + h.offsetHeight) && (h.offsetTop > h.offsetHeight)) {
   top -= h.offsetHeight + 20 + settings($(currentId)[0]).top;
   helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
  }
  if (helper.parent.is(":visible"))
   helper.parent.queue( function() {$(this).removeShadow().dropShadow({left:2, top:2});$(this).dequeue();})
 }
 
 function viewport() {
  return {
   x: $(window).scrollLeft(),
   y: $(window).scrollTop(),
   cx: $(window).width(),
   cy: $(window).height()
  };
 }
 
 // hide helper and restore added classes
 function hide(evt) {
  if($.tooltip.blocked)
   return;

  // no more current element
  currentId = null;
  
  var tsettings = settings(this);
  helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
  
  helper.parent.removeShadow();
  $("body").unbind('click',hideOnClickOutside);
 }
 
})(osjs);



function RichWidgets_Widget_Tooltip(widgetId, HTMLTooltipText){
 osjs(function($){
  HTMLTooltipText = HTMLTooltipText.match(/<[^<>]+>/)? HTMLTooltipText: HTMLTooltipText.replace(/\n/g,"<br>\n");
  $('#' + widgetId).tooltip(
   { bodyHandler: function() { return HTMLTooltipText;  }
   , extraClass:'Widget_Tooltip'});
 });
}
