// tooltip.js
// ver 1.0.0
// require common.js v1.5.0 or later
// @20090304



var VCOMN;
if (!VCOMN) {
  VCOMN = {};
}

function fncToolTip(opt) {
  new VCOMN.ToolTip(opt);
}

VCOMN.ToolTip = function() {this.initialize.apply(this, arguments)}

VCOMN.ToolTip.prototype = {
  CLASS_NAME: {
    TOOLTIP: 'ttTooltip',
    TOOLTIPBOX: 'ttTooltipBox'
  },
  ID_PREXFIX: {
    TOOLTIP: 'ttTooltip',
    TRIGGER: 'ttTrigger'
  },
  INNER_TAG: {
    NAME: '',
    CLASS: ''
  },
  POSITION: {
    BASE: 'mouse',
    STANDARD: 'top-left',
    X: 5,
    Y: 5
  },
  initialize: function (opt) {
    opt = opt || {};
    this.opt = {};
    this.opt.inner_tag_name = opt.inner_tag_name !== undefined ? opt.inner_tag_name : this.INNER_TAG.NAME;
    this.opt.inner_tag_class = opt.inner_tag_class !== undefined ? opt.inner_tag_class : this.INNER_TAG.CLASS;
    this.opt.class_name_tooltip = opt.class_name_tooltip || this.CLASS_NAME.TOOLTIP;
    this.opt.class_name_tooltipbox = opt.class_name_tooltipbox || this.CLASS_NAME.TOOLTIPBOX;
    this.opt.id_prefix_tooltip = opt.id_prefix_tooltip || this.ID_PREXFIX.TOOLTIP;
    this.opt.id_prefix_trigger = opt.id_prefix_trigger || this.ID_PREXFIX.TRIGGER;
    this.opt.opacity = opt.opacity || 1.0;
    this.opt.position = {};
    this.opt.position.base = opt.position_base || this.POSITION.BASE;
    this.opt.position.standard = opt.position_standard || this.POSITION.STANDARD;
    this.opt.position.x = opt.position_x !== undefined ? opt.position_x : this.POSITION.X;
    this.opt.position.y = opt.position_y !== undefined ? opt.position_y : this.POSITION.Y;
    this.targets = {};
    var tips = VCOMN.getElementsByClassName(this.opt.class_name_tooltip);
    for (var i = 0; i < tips.length; i++) {
      var suffix = tips[i].id.replace(this.opt.id_prefix_tooltip, '');
      var trigger = document.getElementById(this.opt.id_prefix_trigger + suffix);
      if (!trigger) {
        continue;
      }
      VCOMN.EventObserve(trigger, 'mouseover', 
        VCOMN.bindFunc(this.onMouseOver, this, trigger, tips[i]),
        false);
      VCOMN.EventObserve(trigger, 'mouseout', 
        VCOMN.bindFunc(this.onMouseOut, this, trigger, tips[i]),
        false);
      VCOMN.EventObserve(tips[i], 'mouseover', 
        VCOMN.bindFunc(this.onTipMouseOver, this, trigger, tips[i]),
        false);
      VCOMN.EventObserve(tips[i], 'mouseout', 
        VCOMN.bindFunc(this.onTipMouseOut, this, trigger, tips[i]),
        false);
      this.targets[i] = {
        trigger: trigger,
        tooltip: tips[i]
      };
    }
  },
  onTipMouseOver: function (triggerElem, targetElem) {
    targetElem._over = true;
  },
  onTipMouseOut: function (triggerElem, targetElem) {
    targetElem._over = false;
    if (!triggerElem._over) {
      this.onMouseOut(triggerElem, targetElem);
    }
  },
  onMouseOver: function (triggerElem, targetElem, e) {
    triggerElem._over = true;
    this.setTooltip(triggerElem, targetElem, e);
  },
  onMouseMove: function (triggerElem, targetElem, e) {
    if (this.opt.position.base != 'mouse') {
      return;
    }
    var mouse = VCOMN.getMousePosition(e);
    var pos = VCOMN.cumulativeOffset(triggerElem);
    this.setTargetPosition(targetElem, mouse.x + this.opt.position.x, mouse.y + this.opt.position.y);
  },
  onMouseOut: function (triggerElem, targetElem) {
    setTimeout(VCOMN.bindFunc(this.onMouseOutCB, this, triggerElem, targetElem), 0);
    triggerElem._over = false;
  },
  onMouseOutCB: function (triggerElem, targetElem) {
    if (triggerElem._over || targetElem._over) {
      return;
    }
    this.backTooltip(triggerElem, targetElem);
  },
  setTargetPosition: function (targetElem, x, y) {
    var documentElement = document.documentElement;
    var body = document.body;
    if (!this.opt.position.standards) {
      this.opt.position.standards = {};
      var _splits = this.opt.position.standard.split('-');
      for (var i = 0; i < _splits.length; i++) {
        if (_splits[i]) {
          this.opt.position.standards[_splits[i]] = true;
        }
      }
    }
    if (this.opt.position.standards.right) {
      x -= targetElem.clientWidth;
    }
    if (this.opt.position.standards.bottom) {
      y -= targetElem.clientHeight;
    }
    var browser = VCOMN.getBrowserSize();
    var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    if (x + targetElem.clientWidth > browser[0] + scrollLeft) {
      x = browser[0] + scrollLeft - targetElem.clientWidth;
      if (x < scrollLeft && !this.opt.position.standards.right) {
        x = scrollLeft;
      }
    } else if (x < scrollLeft) {
      x = scrollLeft;
    }
    if (y + targetElem.clientHeight > browser[1] + scrollTop) {
      y = browser[1] + scrollTop - targetElem.clientHeight;
      if (y < scrollTop && !this.opt.position.standards.bottom) {
        y = scrollTop;
      }
    } else if (y < scrollTop) {
      y = scrollTop;
    }
    targetElem.style.left = x + 'px';
    targetElem.style.top = y + 'px';
  },
  setTooltip: function (triggerElem, targetElem, e) {
    VCOMN.addClass(targetElem, this.opt.class_name_tooltipbox);
    VCOMN.removeClass(targetElem, this.opt.class_name_tooltip);
    if (this.opt.inner_tag_name && this.opt.inner_tag_class) {
      var test = VCOMN.getElementsByClassName(this.opt.inner_tag_class, targetElem);
      if (!test || !test.length) {
        var inner = document.createElement(this.opt.inner_tag_name);
        inner.className = this.opt.inner_tag_class;
        while (targetElem.firstChild) {
          inner.appendChild(targetElem.firstChild);
        }
        targetElem.appendChild(inner);
      }
    }
    VCOMN.setOpacity(targetElem, this.opt.opacity);
    targetElem.style.position = 'absolute';
    var x, y;
    if (this.opt.position.base == 'mouse') {
      var mouse = VCOMN.getMousePosition(e);
      if (mouse.x) {
        x = mouse.x + this.opt.position.x;
        y = mouse.y + this.opt.position.y;
      }
      triggerElem.onmousemove = VCOMN.bindFunc(this.onMouseMove, this, triggerElem, targetElem);
    } else {
      if (!this.opt.position.bases) {
        this.opt.position.bases = {};
        var _splits = this.opt.position.base.split('-');
        for (var i = 0; i < _splits.length; i++) {
          if (_splits[i]) {
            this.opt.position.bases[_splits[i]] = true;
          }
        }
      }
      var baseElem = triggerElem;
      if (baseElem.tagName.toUpperCase() == 'A') {
        baseElem = triggerElem.firstChild;
        while (baseElem && baseElem.nodeType != 1) {
          baseElem = baseElem.nextSibling;
        }
        if (!baseElem) {
          baseElem = triggerElem;
        }
      }
      var pos = VCOMN.cumulativeOffset(baseElem);
      x = pos[0] + this.opt.position.x;
      y = pos[1] + this.opt.position.y;
      if (this.opt.position.bases.right) {
        x += baseElem.offsetWidth;
      }
      if (this.opt.position.bases.bottom) {
        y += baseElem.offsetHeight;
      }
    }
    this.setTargetPosition(targetElem, x, y);
    if (targetElem.parentNode != document.body) {
      targetElem._parentNode = targetElem.parentNode;
      targetElem._nextSibling = targetElem.nextSibling;
      document.body.insertBefore(targetElem, document.body.firstChild);
    }
  },
  backTooltip: function (triggerElem, targetElem) {
    VCOMN.addClass(targetElem, this.opt.class_name_tooltip);
    VCOMN.removeClass(targetElem, this.opt.class_name_tooltipbox);
    if (this.opt.inner_tag_name && this.opt.inner_tag_class) {
      var test = VCOMN.getElementsByClassName(this.opt.inner_tag_class, targetElem);
      if (test && test.length) {
        var inner = test[0];
        while (inner.firstChild) {
          targetElem.appendChild(inner.firstChild);
        }
        targetElem.removeChild(inner);
      }
    }
    if (targetElem._parentNode && targetElem.parentNode != targetElem._parentNode) {
      targetElem._parentNode.insertBefore(targetElem, targetElem._nextSibling);
      targetElem._parentNode = undefined;
      targetElem._nextSibling = undefined;
    }
    triggerElem.onmousemove = '';
  }
};


