
//popController.js
//Object to control popup windows from divs
//v1: 23 June 2006
//v2: 25 October 2009 (using OO)
//Author: Tobias Mayer
//===================================================

var DEBUG = 0;  //change to 1, or true to show debug alerts

var popController = function (spec) {

  //pseudo-this: inherits from printable object defined in util.js
  var that = printable(spec);  
  
  spec.lastPop = null;
  spec.scrollIntoView = spec.scrollIntoView || false; 

  var pos = new Array(0, 0);
  var TOP = 0; 
  var LEFT = 1;
  
  //private
  //close the last open popup and set the 'spec.lastPop' value to the value of 'next'
  _closeLast = function (next) {
    if (DEBUG) { alert("_closeLast"); }
    if (spec.lastPop) {
      spec.lastPop.style.display = 'none';
    }
    spec.lastPop = next;
  };

  //private
  //function required by IE to get element position
  //thanks to http://www.quirksmode.org/
  _findPos = function (obj) {
    if (DEBUG) { alert("_findPos"); }
    var curleft = curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while (obj = obj.offsetParent);
    }
    return [curtop,curleft];
  }  
  
  //private, ensure offset has a value
  _offset = function (value) {
    if (DEBUG) { alert("value in = " + value); }
    if (typeof value === "string") {
      value = parseInt(value, 10);  //ensure conversion is to base 10
      if (isNaN(value)) {
        value = 0;
      }
    }
    value = ((!value) || (typeof value !== "number"))? 0 : value;
    if (DEBUG) { alert("value out = " + value); }
    return value;
  }
  
  //show a popup at the point of the mouse click (bottom, left corner aligned with click)
  showAbsolute = function (event, popwin) {  
    if (DEBUG) { alert("showAbsolute"); }
    _closeLast(popwin);
    popwin.style.display = "block";
    //IE uses different variable names for positioning, and needs tiny adjustments (-2, -1)
    if (self.navigator.appName == "Microsoft Internet Explorer") {
      var scrollValue = document.body.scrollTop;
      popwin.style.posTop = event.clientY + scrollValue - popwin.offsetHeight - 2;
      popwin.style.posLeft = event.clientX - 1;
    }
    else {  //not IE (hooray!)
      popwin.style.top = event.pageY - popwin.offsetHeight;
      popwin.style.left = event.pageX;
    }
    if (spec.scrollIntoView) {
      popwin.scrollIntoView(true);
    }
    return popwin;
  };
  that.showAbsolute = showAbsolute;
  
  //show the popup immediately on top of the parent (calling) element, aligned left & top
  showAt = function (caller, popwin) {  
    if (DEBUG) { alert("showAt"); }
    return _showRelative(caller, popwin, 0, 0, 0, 0);
  };
  that.showAt = showAt; 
  
  //show the popup immediately below the parent (calling) element
  showBelow = function (caller, popwin) {  
    if (DEBUG) { alert("showBelow"); }
    return _showRelative(caller, popwin, 0, 0, caller.offsetHeight, 0);
  };
  that.showBelow = showBelow; 
  
  //show the popup immediately above the parent (calling) element
  showAbove = function (caller, popwin) {  
    if (DEBUG) { alert("showAbove"); }
    popwin.style.display = "block"; //need to display before getting height
    //note negative value for offsetTop
    return _showRelative(caller, popwin, -popwin.offsetHeight, 0, 0, 0);
  };
  that.showAbove = showAbove; 
  
  //show the popup immediately to the right of the parent (calling) element
  showRight = function (caller, popwin) {  
    if (DEBUG) { alert("showRight"); }
    return _showRelative(caller, popwin, 0, 0, 0, caller.offsetWidth);
  };
  that.showRight = showRight; 
  
  //show the popup immediately to the left of the parent (calling) element
  showLeft = function (caller, popwin) {  
    if (DEBUG) { alert("showLeft"); }
    popwin.style.display = "block"; //need to display before getting width
    //note negative value for offsetLeft
    return _showRelative(caller, popwin, 0, -popwin.offsetWidth, 0, 0);
  };
  that.showLeft = showLeft; 

  //show the popup at an exact position relative to the caller (needs all 4 offset params)
  //if any param is set to boolean 'true' it defaults to the natural width or height
  //as used in the showAbove|Below|Right|Left set of functions
  showPrecise = function (caller, popwin, offsetTop, offsetLeft, offsetBottom, offsetRight) {  
    if (DEBUG) { alert("showPrecise"); }
    popwin.style.display = "block"; //need to display before getting height/width
    offsetTop = (offsetTop === true)? popwin.offsetHeight : _offset(offsetTop);
    offsetLeft = (offsetLeft === true)? popwin.offsetWidth : _offset(offsetLeft);
    offsetBottom = (offsetBottom === true)? caller.offsetHeight : _offset(offsetBottom);
    offsetRight = (offsetRight === true)? caller.offsetWidth : _offset(offsetRight);
    if (DEBUG) { alert(-offsetTop + "|" + -offsetLeft + "|" + offsetBottom + "|" + offsetRight); }
    //note negative values for offsetTop and offsetLeft
    return _showRelative(caller, popwin, -offsetTop, -offsetLeft, offsetBottom, offsetRight);
  };
  that.showPrecise = showPrecise; 
  
  //private, called by all methods requiring positioning relative to a caller
  _showRelative = function (caller, popwin, offsetTop, offsetLeft, offsetBottom, offsetRight) {  
    if (DEBUG) { alert("_showRelative"); }
    _closeLast(popwin);
    popwin.style.display = "block";
    //IE uses different variable names for positioning
    if (self.navigator.appName == "Microsoft Internet Explorer") {
      pos = _findPos(caller);
      //alert(pos[TOP] + "-" + pos[LEFT]);
      popwin.style.posTop = pos[TOP] + offsetTop + offsetBottom;
      popwin.style.posLeft = pos[LEFT] + offsetLeft + offsetRight;
    }
    else {  //not IE 
      popwin.style.top = caller.offsetTop + offsetTop + offsetBottom;
      popwin.style.left = caller.offsetLeft + offsetLeft + offsetRight;
      //alert(popwin.style.top + ":" + popwin.style.left);
    }
    if (spec.scrollIntoView) {
      popwin.scrollIntoView(true);
    }
    return popwin;
  };
  
  
  hide = function () {
    if (DEBUG) { alert("hide"); }
    _closeLast(null);
  };
  that.hide = hide;

  return that;
};

if (DEBUG) { alert("making popController"); }

//ensure the calling html document loads util.js
document.write("\n<sc"+"ript type='text/javascript' src='../lib/util.js'>");
document.write("</scr"+"ipt>\n");
