var toolTip = null;    //global reference to tool tip box
var hideTimerHnd    //reference to timer for hide/kill
var displayTimerHnd    //reference to timer for display
var autoCloseTimerHnd    //reference to autoclose timer

/* Startup (default) settings*/
var defaultBg = "#DDECFF";    //default background color
var defaultText = "#000";    //default text color

/* Default settings (normally static, but interactive for demo) */
var imagePosition = "left";    //Alignment of image
var textAlign = "right";    //Text Alignment
var displayTime = 100;    //display delay
var hideTime = 0;    //time to auto hide
var autoCloseTime = 0;        //Auto close
var tipOn = false;      // check if over tooltip link
var Xoffset = 0;    //horizontal offset for tip
var Yoffset = 0;    //vertical offset for tip
var useLinkHeight = false; //vertical offset = link height plus Yoffset
var followMouse= false;    //Flag have tip follow mouse
var openAtMouse = false;   //Flag to open at mouse coordinates
var skipCloseTimer = true;    //Flag for auto close to bypass close delay

/* Tips for interactive demo instructions */
var temp = ["...","...","..."];
var positioningText = temp.join("");
temp = [ "...","...","..."];
var mousexyText = temp.join("");
temp = [ "...","...","..."];
var delayText = temp.join("");
temp = [ "...","...","..."];
var imagePosText = temp.join("");
var textPosText = "<dl><dfn>Text Position<\/dfn>";
temp = null;

/*Tool Tip content an array of arrays 
 *    (image, description, optional-bgColor, optional-textcolor)
 */
var messages = new Array();
messages[0] = ['filecab.gif','Here is a ...',"#FFFFFF"];
messages[1] = new Array('mboard.gif','Here is a ...',"#ccf");
messages[2] = new Array('books.gif','Here is a ...','Yellow','red');
messages[3] = new Array('books.gif','Position correction...','black','yellow');
messages[4] = new Array('mboard.gif','Position Correction...','lightgreen','black');

/* Instruction for demo no image */
messages[5] = new Array('',positioningText,'#ccc','black');
messages[6] = new Array('',mousexyText,'#ccc','black');
messages[7] = new Array('',delayText,'#ccc','black');
messages[8] = new Array('',imagePosText,'#ccc','black');
messages[9] = new Array('',textPosText,'#ccc','black');

/* preload images */
if (document.images) {
    var theImgs = [];
    for (var i=0; i < messages.length; i++) {
        if (messages[i][0] != "") {
            theImgs[theImgs.length] = new Image();
            theImgs[theImgs.length -1].src = messages[i][0];
        }
    }
    theImgs = null;
}
/* Onmouseover event handler,
    gets event object, this-object for KHTML,
     and message array index */
function doTooltip(evt, num) {

    if (!toolTip) return;    //If no element to show tip, just let it go.

    evt =  evt || window.event; //capture window.event for IE and KHTML

    /* Clear timers */
    clearTimers();

    /* Check demo option settings, normally not part of toolTip */
    checkOptionSettings(num);

    /* Restore default colors */
    toolTip.style.color = defaultText;
    toolTip.style.backgroundColor = defaultBg;

    /* Set display colorsi,put text, image in toolTip div */
    if (typeof messages[num][2] != "undefined") 
        toolTip.style.backgroundColor = messages[num][2];

    if (typeof messages[num][3] != "undefined") 
        toolTip.style.color = messages[num][3];

    if (typeof toolTip.innerHTML != "undefined") {
        if (messages[num][0]) {
            var pattern = '<img src="%src%" class="%cls%" >%txt%';
            pattern = pattern.replace(/%[a-z]{3}%/g, _makePattern);
            toolTip.innerHTML = pattern;
        } else {
            toolTip.innerHTML = messages[num][1];
        }
    }

    /* internal (nest) function for pattern */
    function _makePattern(a) {
        switch (a) {
        case '%src%':
            return messages[num][0];
        case '%cls%':
            return imagePosition;
        case '%txt%':
            return messages[num][1];
        }
    }

    if (followMouse) {
        //Attach event handler to track mouse position
        document.onmousemove=trackMouse; 
    } else if (openAtMouse) {
        trackMouse(evt); //Get a single instance of mouse X,Y
        showTip(); //Open delay not option for open at mouse
    } else {

        var evtObj = evt.target || evt.srcElement;

        /*  Get reference to element triggering request for tip.
         *  Some browsers register event on the text node 
         *  so there is a loop to the first element.
         */
        while (evtObj.nodeType != 1) {
            evtObj = evtObj.parentNode || evtObj.parentElement;
        }

        /* Set top-left */
        var coordinates = getCoordinates(evtObj);
        toolTip.style.left = coordinates.Xoffset + 'px';
        toolTip.style.top = coordinates.Yoffset + 'px';
    }//endif

    /* Set timer to show toolTip or show immediately */
    if (displayTime > 0) 
        displayTimerHnd = setTimeout(showTip, displayTime);
    else 
        showTip();

}//eof doTooltip
/* Make tip visible, start auto close timer */
function showTip() {
    toolTip.style.visibility='visible';
    
    /* There are 2 options to handle auto close. 
     * The first auto below goes directly to killTip
     * and by-passes the close delay setting. 
     * The second used hideTip and triggers the close delay.
     */
    if (autoCloseTime > 0) {

        if (skipCloseTimer) 
            autoCloseTimerHnd = setTimeout(killTip, autoCloseTime);
        else 
            autoCloseTimerHnd = setTimeout(hideTip, autoCloseTime);

    }//endif

}//eof showTip
/* remove toolTip*/
function killTip() {
    if (toolTip) {
        toolTip.style.visibility = "hidden";
        document.onmousemove=""; //Stop using resourcese

        /* This next code is for demo */
        resetMouseOptionDisplay();
    }
}//eof killTip
/* Mouseout event handler.
 * Clear display timer in case tip not yet displayed
 * and kill tip or set timer to kill
 */
function hideTip() {
    if (toolTip) {

        if (displayTimerHnd) clearTimeout(displayTimerHnd);

        if (hideTime > 0 && toolTip.style.visibility == "visible") {
            hideTimerHnd = setTimeout(killTip, hideTime);
        }
        else {
            killTip();
        }
    }
}//eof hideTip
function clearTimers() {
    if (displayTimerHnd) clearTimeout(displayTimerHnd);
    if (hideTimerHnd) clearTimeout(hideTimerHnd);
    if (autoCloseTimerHnd) clearTimeout(autoCloseTimerHnd);
}
/* onMouseMove event handler. 
 * Positions toolTip to mouse X,Y 
 */
function trackMouse(evt) {

    if (toolTip) {
        /* KHTML (Konqueror/Safari) provides the same 
         * information in window.event and DOM evt.
         * I choose to use evt if available.
         */
        var ie_x = document.body.scrollLeft || 
                document.documentElement.scrollLeft || 0;
        var ie_y = document.body.scrollTop  || 
                document.documentElement.scrollTop  || 0;
        var x, y;

        if (evt) {
            /* evt all Mozilla and IE window.event for open at mouuse. */
            x = (typeof evt.pageX != "undefined")? evt.pageX: (evt.clientX + ie_x);
            y = (typeof evt.pageY != "undefined")? evt.pageY: (evt.clientY + ie_y);
        }
        else {
            /* IE when tracking mouse */
            x = window.event.clientX + ie_x;
            y = window.event.clientY + ie_y;
        }

        /* Code for this demo only */
        document.options.coordinates.value = "X: " + x + ", Y: " + y;

        /* Adjust position for screen right and bottom screen edge */
        x = fitWindowWidth(x + Xoffset);
        y = fitWindowHeight(y + Yoffset);

        /* Move tip into position */
        toolTip.style.left = x + 'px';
        toolTip.style.top = y + 'px';
    }
}//eof trackMouse
/* Get toolTip X,Y when not tracking mouse */
function getCoordinates(obj) {

    if (useLinkHeight) Yoffset += obj.offsetHeight;    //If flag, adjust Yoffset by target height

    var xy = getObjectUpperLeft(obj);

    /* Adjust position for screen right and bottom screen edge */
    var x = fitWindowWidth(xy.x + Xoffset);
    var y = fitWindowHeight(xy.y + Yoffset);

    /* return object with coordinates as properties */
    return {Xoffset: x, Yoffset: y};
}//eof getCoordinates
function getObjectUpperLeft(obj){
    var isIE = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);

    var x = obj.offsetLeft;
    var y = obj.offsetTop;

    /* Calculate page X,Y of upper left corner of element
       where toolTip is to be shown
    */
    obj = obj.offsetParent;
    while (obj) {
        x += obj.offsetLeft;
        y += obj.offsetTop;

        if (typeof obj.clientLeft != "undefined" && obj.tagName != "BODY") {
                /*MS IE doesn't include borders in offset values;
                these are obtained with clientLeft and Top and added in*/
                x += obj.clientLeft;
                y += obj.clientTop;
        }

        if (obj.tagName == "HTML") break; //KHTML KDE has an unidentified object above html
        obj = obj.offsetParent;
    }//endwhile

    return {x:x, y:y};
}//eof getObjectUpperLeft
/* Determine page offset at bottom of screen (it's different than window height)
    Here the pixles the page has been scrolled up is added to window heigth
 */
function getBottomPagePos() {
    var nBottom;

    if (typeof window.scrollY != "undefined" ) {
        //NN6+ FireFox, Mozilla etc.
        nBottom = window.innerHeight + window.scrollY;
    }
    else if (typeof window.pageYOffset != "undefined") {
        //NN4 still in NN6 + but NN6 and Mozilla added scrollY
        nBottom = window.innerHeight + window.pageYOffset;
    }
    else if (document.documentElement && document.documentElement.clientHeight){
        //document.compatMode == "CSS1Compat" that is IE6 standards mode
        nBottom = document.documentElement.clientHeight + document.documentElement.scrollTop;
    }
    else if (document.body && document.body.clientHeight) {
        //document.compatMode != "CSS1Compat" that is quirks mode IE 6 or IE < 6 and Mac IE
        nBottom = document.body.clientHeight + document.body.scrollTop;
    }
    return nBottom;
}//eof getBottomPagePos
/* Determine page offset at right of screen (it's different than window width)
    Here the pixles the page has been scrolled left is added to window width
 */
function getRightPagePos() {
    var nRight;

    if (typeof window.srcollX != "undefined") {
        //"NN6+ FireFox, Mozilla etc."
        nRight = window.innerWidth + window.scrollX;
    }
    else if (typeof window.pageXOffset != "undefined") {
        //NN4 code still in NN6 + but scrollX was added
        nRight = window.innerWidth + window.pageXOffset;
    }
    else if (document.documentElement && document.documentElement.clientWidth){
        //document.compatMode == "CSS1Compat" that is IE6 standards mode"
        nRight = document.documentElement.clientWidth + document.documentElement.scrollLeft;
    }
    else if (document.body && document.body.clientWidth) {
        //document.compatMode != "CSS1Compat" that is quirks mode IE 6 or IE < 6 and Mac IE
        nRight = document.body.clientWidth + document.body.scrollLeft;
    }

    return nRight;
}//eof getRightPagePos
function getTopPagePos() {
    var nTop;

    if (typeof window.scrollY != "undefined" ) {
        //NN6+ FireFox, Mozilla etc.
        nTop= window.scrollY;
    }
    else if (typeof window.pageYOffset != "undefined") {
        //NN4 still in NN6 + but NN6 and Mozilla added scrollY
        nTop = window.pageYOffset;
    }
    else if (document.documentElement && document.documentElement.scrollTop){
        //document.compatMode == "CSS1Compat" that is IE6 standards mode
        nTop = document.documentElement.scrollTop;
    }
    else if (document.body && document.body.scrollTop) {
        //document.compatMode != "CSS1Compat" that is quirks mode IE 6 or IE < 6 and Mac IE
        nTop = document.body.scrollTop;
    }
    return nTop;
}//eof getTopPagePos
function getLeftPagePos() {
    var nLeft;

    if (typeof window.srcollX != "undefined") {
        //"NN6+ FireFox, Mozilla etc."
        nLeft = window.scrollX;
    }
    else if (typeof window.pageXOffset != "undefined") {
        //NN4 code still in NN6 + but scrollX was added
        nLeft = window.pageXOffset;
    }
    else if (document.documentElement && document.documentElement.scrolLeft){
        //document.compatMode == "CSS1Compat" that is IE6 standards mode"
        nLeft = document.documentElement.scrollLeft;
    }
    else if (document.body && document.body.scrollLeft) {
        //document.compatMode != "CSS1Compat" that is quirks mode IE 6 or IE < 6 and Mac IE
        nLeft = document.body.scrollLeft;
    }

    return nLeft;
}//eof getLeftPagePos
/* Determine best page X that keeps object in window. If object
    doesn't fit adjust to left edge ot window.
    Compare object X coordinate to max X not going out
    of window and use left most.
    Then check object X is not past left most visible
    page coordinate.
*/
function fitWindowWidth(tipX) {
    //Don't go past right edge of window

    var rightMaxX = getRightPagePos() - (toolTip.offsetWidth + 16); //16 for scrollbar

    tipX = (rightMaxX < tipX) ? rightMaxX : tipX;

    //But, don't go past left edge of window
    var leftMinX = getLeftPagePos();
    tipX = (tipX < leftMinX) ? leftMinX : tipX;

    return tipX;
}//eof fitWindowWidth
/* Compare max acceptable page offset to toolTip X and return smallest */
function fitWindowHeight(tipY) {
    //Don't go below bottom of window. Put above target if moved.
    var bottomMaxY = getBottomPagePos() - (toolTip.offsetHeight);
    tipY = (bottomMaxY < tipY ) ? tipY - (Yoffset + toolTip.offsetHeight) : tipY;

    //But, don't go past the top of window
    var topMinY = getTopPagePos();
    tipY = (tipY < topMinY) ? topMinY : tipY;

    return tipY
}//eof fitWindowHeight
/* Create a reference to toolTip container */
function initTip() {

    if (document.getElementById){
        toolTip = document.getElementById("tipDiv");
    }
    else if (document.all) {
        toolTip = document.all.tipDiv;
    }
    else if (document.layers) {
        toolTip = document.layers.tipDiv;
    }
    else {
        toolTip = null;
    }
}//eof initTip
/* End of toolTip specific code */
/* Functions specific to this demo and not a normal part of toolTips */
function checkOptionSettings(num) {

    Xoffset = isNaN(parseInt(document.options.xoffset.value))?0:parseInt(document.options.xoffset.value);

    if (num < 5){
        useLinkHeight = document.options.theight.checked;
        toolTip.style.width = "160px";
        toolTip.style.textAlign = textAlign;
    }
    else {
        Xoffset = Math.max(Xoffset, 20);
        useLinkHeight = false;
        toolTip.style.width = "360px";
        toolTip.style.textAlign = "left";
    }

    Yoffset = isNaN(parseInt(document.options.yoffset.value))?0:parseInt(document.options.yoffset.value);
    openAtMouse = document.options.open.checked;
    followMouse = document.options.tracking.checked;
    displayTime = isNaN(document.options.opendelay.value) ? 0 : document.options.opendelay.value ;
    hideTime = isNaN(document.options.closedelay.value) ? 0 : document.options.closedelay.value;
    autoCloseTime = isNaN(document.options.autoclose.value) ? 0 : document.options.autoclose.value;


} //eof checkOptionSettings
function resetMouseOptionDisplay(){
    if (followMouse) {
        document.options.coordinates.value = 'Tracking Suspended';
    }
    else if (openAtMouse) {
        document.options.coordinates.value = 'Open at mouse';
    }
} //eof resetMouseOptionDisplay
/* The check boxes are mutually exclusive and can be all off,
    thus radio buttons where not used.
    Displayed text changes according to which boxes are checked.
*/
function handleCheckBoxes(obj) {

    switch (obj.value){
    case "open":    //open at mouse
        if (obj.checked) {
            obj.form.tracking.checked = false;
            if (obj.form.theight.checked){
                obj.form.theight.checked = false;
                obj.form.yoffset.value = '20';
            }
            obj.form.coordinates.value = 'Open At Mouse';
        }
        else if (!obj.form.tracking.checked) {
            obj.form.coordinates.value = 'Tracking Off';
        }
        break;
    case "tracking":    //track mouse
        if (obj.checked) {
            obj.form.open.checked = false;
            if (obj.form.theight.checked){
                obj.form.theight.checked = false;
                obj.form.yoffset.value = '20';
            }
            obj.form.coordinates.value = 'Tracking On';
        }
        else if (!obj.form.open.checked) {
            obj.form.coordinates.value = 'Tracking Off';
        }
        break;
    case "theight":    //use element offset height
        if (obj.checked) {
            obj.form.open.checked = false;
            obj.form.tracking.checked = false;
            obj.form.coordinates.value = 'Tracking Off';
            obj.form.yoffset.value = "0";
        }
        else {
            obj.form.yoffset.value = '20';
        }
        break;
    }
}//eof handleMouseRadios
window.onload = initTip;
window.onunload = clearTimers;