// 
// These javascript functions get loaded into ALL datacom web pages.
// Add and modify functions with care!
//

var ua = navigator.userAgent.toLowerCase();
var msIE = ((ua.indexOf('msie') != -1) && (ua.indexOf('opera') == -1) && (ua.indexOf('webtv') == -1)); 

// Add a "trim" function to Javascript's string object type
String.prototype.trim = function() {
    // Strip leading and trailing white-space
    return this.replace(/^\s*|\s*$/g, "");
}


//
// Hide or display an object
//
function toggleBox(id) {
    if(document.layers) {    //NN4+
        if (document.layers[id].visibility == "show") {
            document.layers[id].visibility = "hide";
        } else {
            document.layers[id].visibility = "show";
        }
    }
    else if(document.getElementById) {     //gecko(NN6) + IE 5+
        var obj = document.getElementById(id);
        if (obj.style.visibility == "visible" || obj.style.display == "block") {
            obj.style.visibility = "hidden";
            obj.style.display = "none";
        } else {
            obj.style.visibility = "visible";
            obj.style.display = "block";
        }
    }
    else if(document.all) {  // IE 4
        if (document.all[id].style.visibility == "visible" || document.all[id].style.display == "block") {
            document.all[id].style.visibility = "hidden";
            document.all[id].style.display = "none";
        } else {
            document.all[id].style.visibility = "visible";
            document.all[id].style.display = "block";
        }
    }
}


// Remove an element
function removeElement(name) {
    var remove = document.getElementById(name);
    if (remove) {
        var parent = remove.parentNode;
        parent.removeChild(remove);
    }
}



// Taken from mail.google.com and modified
function el(id) {
    if(document.layers) {    //NN4+
       return document.layers[id];
    }
    else if (document.getElementById) {  // Gecko (NN6, Firefox, IE 5+)
        return document.getElementById(id);
    }
    else if(document.all) {  // IE 4
        return document.all[id];
    }
    else if (window[id]) {
        return window[id];
    }
    return null;
}



// Read a cookie's value
function getcookie(cookiename) {
    var cookiestring=""+document.cookie;
    var index1=cookiestring.indexOf(cookiename);
    if (index1==-1 || cookiename=="") return ""; 
    var index2=cookiestring.indexOf(';',index1);
    if (index2==-1) index2=cookiestring.length; 
    return unescape(cookiestring.substring(index1+cookiename.length+1,index2));
}

// Internal function for setcookie
function getexpirydate(nodays){
    var UTCstring;
    var Today = new Date();
    var nomilli=Date.parse(Today);
    Today.setTime(nomilli+nodays*24*60*60*1000);
    return Today.toUTCString();
}

// Set a cookie
function setcookie(name,value,duration_days) {
    var cookiestring=name+"="+escape(value)+";EXPIRES="+getexpirydate(duration_days);
    document.cookie=cookiestring;
}



///////////////////////////////////////////////////////////////////////////////
// Do not remove this notice.
// 
// Copyright 2001 by Mike Hall.
// See http://www.brainjar.com for terms of use.
// 
// Version:      v1.3
// Last Update:  2006-04-11
// 
// Large portions rewritten by Brandon Zehm <caspian@dotconf.net>
//   * Added support for the Konqueror web browser
//   * Save window position in global object (hash) window_position['el_name' + ('_x'|'_y')]
//   * Added several options documented below to dragStart()
//   
// DOCUMENTATION
//   Options for dragStart():
//       savePosition 0 | 1
//           Enable or disable saving the "window" position via xajax.
//           Default: 1 (enabled)
//       drag = both | vertical | horizontal
//           Permit movement on only the horizontal, vertical, or both axis.
//           Default: both
//       detectEdge = 0 | 1
//           Detect screen edges and don't allow elements to be "dropped" if
//           it's top-left corner is not currently viewable.
//           Default: 1 (enabled)
//       opacity = 0.0 - 1.0
//           Define the opacity of the element being dragged.  0 is totally 
//           transparent, 1 is full opacity.
//           Default: 0.7
// 
//*****************************************************************************
// 
// To make an element "draggable" just add a tag like this into it:
//   onmousedown="dragStart(event, 'id_name')
// For advanced options after the element_id pass a comma separated list
// of options and values like this:
//   onmousedown="dragStart(event, 'id_name', 'savePosition', 0, 'drag', 'vertical')
// 
///////////////////////////////////////////////////////////////////////////////



// Determine browser and version.
function Browser() {

  var ua, s, i;

  this.isIE    = false;
  this.isNS    = false;
  this.isKONQ  = false;
  this.version = null;

  ua = navigator.userAgent;

  s = "MSIE";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isIE = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }

  s = "Netscape6/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }
  
  // Check to see if it's konqueror .. KHTML
  s = "KHTML/";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isKONQ = true;
    this.version = parseFloat(ua.substr(i + s.length));
    return;
  }
  
  // Treat any other "Gecko" browser as NS 6.1.
  s = "Gecko";
  if ((i = ua.indexOf(s)) >= 0) {
    this.isNS = true;
    this.version = 6.1;
    return;
  }
  
}

// Global browser object
var browser = new Browser();

// Global object to hold drag information.
// We only really need one since you can't drag more than one window at a time
var dragObj = new Object();
dragObj.zIndex = 0;




function dragStart(event, id) {
    var el;
    var x, y;
    
    // Define default options
    dragObj.options = new Object;
    dragObj.options['drag']            = 'both';
    dragObj.options['savePosition']    = 1;
    dragObj.options['opacity']         = 0.7;
    dragObj.options['detectEdge']      = 1;
    
    // Load in the options from the function call
    for (var i = 2; i < arguments.length; i += 2) {
        dragObj.options[arguments[i]] = arguments[i + 1];
    }
    
    // If an element id was given, find it. Otherwise use the element being clicked on.
    if (id)
        dragObj.elNode = document.getElementById(id);
    else {
        if (browser.isIE)
            dragObj.elNode = window.event.srcElement;
        if (browser.isNS || browser.isKONQ)
            dragObj.elNode = event.target;
        
        // If this is a text node, use its parent element.
        if (dragObj.elNode.nodeType == 3)
            dragObj.elNode = dragObj.elNode.parentNode;
    }
    
    // Get cursor position with respect to the page.
    if (browser.isNS) {
        x = event.clientX + window.scrollX;
        y = event.clientY + window.scrollY;
    }
    else if (browser.isIE || browser.isKONQ) {
        x = window.event.clientX + document.documentElement.scrollLeft
            + document.body.scrollLeft;
        y = window.event.clientY + document.documentElement.scrollTop
            + document.body.scrollTop;
    }
    
    // Make sure the element is positioned absolutly
    // (if it wasn't positioned absolutely before, it will move to the top left
    //  of the screen if we don't set it's position, so we do that too)
    dragObj.elNode.style.position = "absolute";
    
    // Find the element's current position .. calculate it if it's not already set.
    dragObj.elStartTop  = calcOffset(dragObj.elNode, 'offsetTop');
    dragObj.elStartLeft = calcOffset(dragObj.elNode, 'offsetLeft');
    
    // Save starting positions of cursor and element.
    dragObj.cursorStartX = x;
    dragObj.cursorStartY = y;
    if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
    if (isNaN(dragObj.elStartTop))  dragObj.elStartTop  = 0;
    
    // Update element's z-index & opacity
    dragObj.zIndex = dragObj.elNode.style.zIndex;
    dragObj.elNode.style.zIndex = (dragObj.zIndex + 2);
    
    // Update the opacity .. at the end we do the CSS3 standard way, eventually browser detection shouldn't be needed.
    if (dragObj.options.opacity > 0 && dragObj.options.opacity < 1) {
        if (browser.isNS)
            dragObj.elNode.style.MozOpacity = dragObj.options.opacity;
        else if (browser.isKONQ)
            dragObj.elNode.style.KHTMLOpacity = dragObj.options.opacity;
        else if (browser.isIE)
            dragObj.elNode.style.filter = 'Alpha(opacity=' + (dragObj.options.opacity * 100) + ')';
        dragObj.elNode.style.opacity = dragObj.options.opacity;
    }
    
    // Capture mousemove and mouseup events on the page.
    if (browser.isNS || browser.isKONQ) {
        document.addEventListener("mousemove", dragGo,   true);
        document.addEventListener("mouseup",   dragStop, true);
        event.preventDefault();
    }
    else if (browser.isIE) {
        document.attachEvent("onmousemove", dragGo);
        document.attachEvent("onmouseup",   dragStop);
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    }
}


function dragGo(event) {
    var x, y;
    
    // Get cursor position with respect to the page.
    if (browser.isIE || browser.isKONQ) {
        x = window.event.clientX + document.documentElement.scrollLeft
            + document.body.scrollLeft;
        y = window.event.clientY + document.documentElement.scrollTop
            + document.body.scrollTop;
    }
    if (browser.isNS) {
        x = event.clientX + window.scrollX;
        y = event.clientY + window.scrollY;
    }
    
    // Move drag element by the same amount the cursor has moved.
    if (dragObj.options.drag == 'both' || dragObj.options.drag == 'horizontal')
        dragObj.elNode.style.left = (dragObj.elStartLeft + x - dragObj.cursorStartX) + "px";
    if (dragObj.options.drag == 'both' || dragObj.options.drag == 'vertical')
        dragObj.elNode.style.top  = (dragObj.elStartTop  + y - dragObj.cursorStartY) + "px";
    
    if (browser.isIE) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    }
    if (browser.isNS || browser.isKONQ)
        event.preventDefault();
}


function dragStop(event) {
    
    // Update element's z-index
    dragObj.elNode.style.zIndex = dragObj.zIndex;
    
    // Update element's opacity if we need to
    if (dragObj.options.opacity > 0 && dragObj.options.opacity < 1) {
        if (browser.isNS)
            dragObj.elNode.style.MozOpacity = '1.0';
        else if (browser.isKONQ)
            dragObj.elNode.style.KhtmlOpacity = '1.0';
        else if (browser.isIE)
            dragObj.elNode.style.filter = "Alpha(opacity=100)";
        dragObj.elNode.style.opacity = '1.0';
    }
    
    // Global object/hash to save current window positions in (for use outside of this library)
    if (typeof(window_position) == 'undefined')
        window_position = new Object();
    
    // Get the element's currnet coordinates
    var currentX = parseInt(dragObj.elNode.style.left);
    var currentY = parseInt(dragObj.elNode.style.top);
    
    // If the top-left corner is off the screen, get it's original position if we need to.
    if (dragObj.options.detectEdge == 1) {
        if (dragObj.options.drag == 'both' || dragObj.options.drag == 'horizontal') {
            if (currentX < 0 || currentX > parseInt(document.body.clientWidth)) {
                currentX = parseInt(dragObj.elStartLeft);
                dragObj.elNode.style.left = currentX + 'px';
            }
        }
        if (dragObj.options.drag == 'both' || dragObj.options.drag == 'vertical') {
            if (currentY < 0 || currentY > parseInt(document.body.clientHeight)) {
                currentY = parseInt(dragObj.elStartTop);
                dragObj.elNode.style.top  = currentY + 'px';
            }
        }
    }
    
    // Save it's position in a global variable for use outside this script
    window_position[dragObj.elNode.id + '_x'] = currentX;
    window_position[dragObj.elNode.id + '_y'] = currentY;
    
    // Stop capturing mousemove and mouseup events.
    if (browser.isIE) {
        document.detachEvent("onmousemove", dragGo);
        document.detachEvent("onmouseup",   dragStop);
    }
    if (browser.isNS || browser.isKONQ) {
        document.removeEventListener("mousemove", dragGo,   true);
        document.removeEventListener("mouseup",   dragStop, true);
    }
    
    // Brandon: Modification for IPDB: We want to save the window's position in the PHP session
    // after it's been moved, so here we do an xajax call if it's available.
    if (dragObj.options.savePosition == 1)
        xajax_window_save_position(dragObj.elNode.id, window_position[dragObj.elNode.id + '_x'], window_position[dragObj.elNode.id + '_y']);
    
}



//////////////////////////////////////////////////////////////////////////////
// 
// Generic Auto-Suggest Javascript/Xajax Library
// Based loosly off of code from http://www.mininova.org/
// Author: Brandon Zehm <caspian@dotconf.net>
// 
// Version: 1.3
// Last Update: 2006-04-11
// 
// LICENSE:
// This script is licenced under the GNU LGPL, which basically means you
// can use it for any purpose whatsoever.
// 
// ABOUT:
// This script is intended to be used in conjunction with Xajax 
// (http://www.xajaxproject.org/) to provide a simple method for building
// "Google Suggest" style auto-suggest drop down boxes for text input fields.
// 
// USAGE:
// 
// 
// CHANGELOG:
//   v1.3
//     Updated calcOffset() to handle relative positioned objects.
// 
//////////////////////////////////////////////////////////////////////////////


// A few global variables
var suggestions = Array();
var storedSearchString = '';
var hoveredSuggestion = -1; 
var inter_exec = null;




//////////////////////////////////////////////////////////////////////////////
//  Function: suggest_setup (input_element_name, suggest_div_name)
//  Setup search suggest for the specified element-name.
//////////////////////////////////////////////////////////////////////////////
function suggest_setup(el_input, el_suggest) {
    
    // Find the input and suggest elemements
    var _input   = document.getElementById(el_input);
    var _suggest = document.getElementById(el_suggest);
    
    _input.setAttribute('autocomplete', 'off');
    
    // Setup some event handlers for the specified elements
    // We have to "hard code" el_input and el_suggest into these
    // anonymous functions or you can't have more than one suggest
    // form per web page.
    var code_keydown = "function(ev) { " +
                       "    try { searchKeyDown(event.keyCode, document.getElementById('"+el_input+"'), document.getElementById('"+el_suggest+"')); } " +
                       "    catch(e) { searchKeyDown(ev.keyCode, document.getElementById('"+el_input+"'), document.getElementById('"+el_suggest+"')); } " +
                       "};";
    var code_keyup   = "function(ev) { " +
                       "    try { searchKeyUp(event.keyCode, document.getElementById('"+el_input+"'), document.getElementById('"+el_suggest+"')); } " +
                       "    catch(e) { searchKeyUp(ev.keyCode, document.getElementById('"+el_input+"'), document.getElementById('"+el_suggest+"')); } " +
                       "};";
    var code_onblur  = "function() { " +
                       "    setTimeout(\"hoveredSuggestion = -1; _el = document.getElementById('"+el_suggest+"'); if (_el) _el.style.display = 'none';\", 200); " +
                       "};";
    
    eval("_input.onkeydown = " + code_keydown);
    eval("_input.onkeyup = " + code_keyup);
    eval("_input.onblur = " + code_onblur);
}




///////////////////////////////////////////////////////////////////////
//  Function: suggest_init (_input, _suggest)
//  Setup the suggest div.
///////////////////////////////////////////////////////////////////////
function suggest_init(_input, _suggest) {
    _suggest.style.top   = calcOffset(_input, 'offsetTop') + _input.offsetHeight - 1 + 'px';
    _suggest.style.left  = calcOffset(_input, 'offsetLeft') + 'px';
    _suggest.style.width = (_input.offsetWidth - 2) + 'px';
}



///////////////////////////////////////////////////////////////////////
//  Function: calcOffset(element, OffsetType)
//  Calculates the current offset, or position, in pixels of the 
//  specified element on the page.  OffsetType will usually be either
//  "offsetTop" or "offsetLeft".
///////////////////////////////////////////////////////////////////////
function calcOffset(_el, offsetType) {
    var calculatedOffset = 0;
    var start_id = _el.id;
    while (_el) {
        // Stop if we've reached an absolutly or relativly positioned element
        if (_el.id != start_id && (_el.style.position == 'absolute' || _el.style.position == 'relative') ) { break; }
        // Otherwise add the offset of the current element and go to our parent.
        calculatedOffset += _el[offsetType];
        _el = _el.offsetParent;
    }
    return calculatedOffset;
}




// Common Key Codes
//    8 = backspace
//    9 = tab (shouldn't ever get that right?)
//   13 = enter
//   17 = ctrl
//   18 = alt
//   27 = esc
//   38 = up arrow
//   40 = down arrow
//   46 = delete

///////////////////////////////////////////////////////////////////////
//  Function:    searchKeyDown (eventKeyCode, _input, _suggest)
//  Description: onKeyDown() handler for input fields
///////////////////////////////////////////////////////////////////////
function searchKeyDown(evKeyCode, _input, _suggest) {
    if(_suggest.style.display == 'block') {
        
        // If they pushed the up arrow key
        if (evKeyCode == 38 && hoveredSuggestion != -1) {
            hoveredSuggestion--;
            hoverSuggestion(hoveredSuggestion, hoveredSuggestion+1, _suggest);
            _input.value = suggestions[hoveredSuggestion];
            
            // If the last "up" key put the hoveredSuggestion at -1, they're at
            // the top of of the suggestion list, display their original query string.
            if(hoveredSuggestion == -1)
                _input.value = storedSearchString;
            
        }
        
        // If they pushed the down arrow key
        else if (evKeyCode == 40 && hoveredSuggestion < suggestions.length -1) {
            hoveredSuggestion++; 
            hoverSuggestion(hoveredSuggestion, hoveredSuggestion-1, _suggest);
            _input.value = suggestions[hoveredSuggestion];
        }
        
        // If they push <tab> or <enter> set the value to the current selection
        // and hide the suggestion box.
        else if (evKeyCode == 9 || evKeyCode == 13) {
            // If it was <tab> and there isn't a selected suggestion, use the first one
            if (hoveredSuggestion == -1 && evKeyCode == 9)
                hoveredSuggestion = 0;
            if (hoveredSuggestion != -1 && suggestions[hoveredSuggestion] != 'No suggestions...' && suggestions[hoveredSuggestion] != 'Searching...')
                _input.value = storedSearchString = suggestions[hoveredSuggestion];
            _suggest.style.display = 'none';
            _input.focus();
        }
        
        // If they push any other key, put them back in the input form but leave the suggestions up
        else if(evKeyCode != 38 && evKeyCode != 40 && evKeyCode != 13)
            hoveredSuggestion = -1;
        
    }
    
}



///////////////////////////////////////////////////////////////////////
//  Function:    searchKeyUp (eventKeyCode, _input, _suggest)
//  Description: onKeyUp() handler for input fields
///////////////////////////////////////////////////////////////////////
function searchKeyUp(evKeyCode, _input, _suggest) {
    
    // If the input value has changed and they're typing (i.e. they didn't just push enter, up or down, etc...)
    if(_input.value != storedSearchString && hoveredSuggestion == -1 && evKeyCode != 13 && evKeyCode != 38 && evKeyCode != 40) {
        
        storedSearchString = _input.value;
        
        // If the suggestion box is visible, hide it until we have results.
        if (_suggest.style.display == 'block') {
            _suggest.style.display = 'none';
        }
        
        // Make an xajax call to get suggestions (if there are still at least 3 input characters)
        // (if there were results, the php script will send back a command to display them)
        script = "if (document.getElementById('"+_input.id+"').value.length > 0) { " + 
                 "    suggestions = Array('Searching...'); " + 
                 "    suggest_display('"+_input.id+"', '"+_suggest.id+"'); " + 
                 "    xajax_suggest('" + _input.id + "', '"+escape(_input.value)+"', '"+_input.id+"', '"+_suggest.id+"'); " + 
                 "}";
        
        // Wait a while after the last keystroke until we actually make the xajax call
        if (inter_exec) clearInterval(inter_exec);
        inter_exec = setInterval(script + "clearInterval(inter_exec);", 300);
    }
    
    // If they push "esc", "backspace", or they've erased all input, hide the suggestion menu
    else if ((_input.value == '' || evKeyCode == 27 || evKeyCode == 8) && _suggest.style.display == 'block') {
        _suggest.style.display = 'none';
        hoveredSuggestion = -1;
    }
    
    // Anytime they press enter make sure that we cancel any pending suggest calls
    if (evKeyCode == 13) {
        clearInterval(inter_exec);
        _suggest.style.display = 'none';
        hoveredSuggestion = -1;
    }
    
}




///////////////////////////////////////////////////////////////////////
// Function:
//     suggest_display (el_input, el_suggest)
// 
// Description:
//     Display the list of suggestions in the "suggestions" array 
//     in the suggest element just below the input element.
//     
///////////////////////////////////////////////////////////////////////
function suggest_display(el_input, el_suggest) {
    // Find the input and suggest elemements
    _input   = document.getElementById(el_input);
    _suggest = document.getElementById(el_suggest);
    
    // If the elements don't exist, just exit
    if ((!_input) || (!_suggest)) { return; }
    
    _suggest.style.display = 'block';
    _suggest.innerHTML = '';
    hoveredSuggestion = -1;
    var j = 0;
    
    suggest_init(_input, _suggest);
    suggestion_width = _input.offsetWidth - 6;
    
    // HACK for our website?:
    if (msIE) { suggestion_width = _input.offsetWidth - 2; }
    
    // If there aren't any suggestions display "No suggestions..."
    if(suggestions.length == 0) {
        // _suggest.style.display = 'none';
        // FIXME: we may want a global variable to display "No results..." instead.
        suggestions = Array('No suggestions...');
    }
    
    // Display the suggestions!
    for (var i=0; i<suggestions.length; i++) {
        // FIXME: after a click we need to refocus the input element we just selected a value for
        _suggest.innerHTML += '<div style="width:' + suggestion_width + 'px;" ' +
                              'onMouseOver="hoverSuggestion(' + i + ', hoveredSuggestion, document.getElementById(\'' + _suggest.id + '\'))" ' + 
                              'onClick="document.getElementById(\'' + _input.id + '\').value = this.innerHTML;' +
                                       'hoveredSuggestion = -1;' + 
                                       'document.getElementById(\'' + _suggest.id + '\').style.display = \'none\'">' + 
                              suggestions[i] + '</div>';
    }
}



// Colors the div that has the mouse over it a different color
function hoverSuggestion(newHover, oldHover, _suggest) {
    if(oldHover != -1) {
        _suggest.getElementsByTagName('div').item(oldHover).className = '';
    }
    if(newHover != -1) { 
        _suggest.getElementsByTagName('div').item(newHover).className = 'hovered'; 
        hoveredSuggestion = newHover;
    }
}




//////////////////////////////////////////////////////////////////////////////
//
// Author: Brandon Zehm <caspian@dotconf.net>
//
// WebWin Javascript Library
//
// Version: 1.4
// Last Update: 2006-08-22
//
// LICENSE:
// This script is licenced under the GNU LGPL, which basically means you
// can use it for any purpose whatsoever.  Full details at:
//   http://www.gnu.org/copyleft/lesser.html
//
// ABOUT:
//
// USAGE:
//
// CHANGELOG:
//   v1.4 - 2006-08-22 - Brandon Zehm
//     * Initial public release
//////////////////////////////////////////////////////////////////////////////

// This should match the setting in the .css and .php file!
var window_default_zindex = 2;

// Function to hide/show a moveable ipdb "window"
// Uses toggleBox() and el() from global.js
// Shows/hides the window if it exits, otherwise
// makes an xajax call to load/create the window.
function toggle_window(el_name) {
    var _el = el(el_name);
    
    // If the element doesn't exist, we need to make an xajax
    // call to create the "window".
    if (!_el) {
        xajax_window_open(el_name);
        return;
    }
    
    // Initialize window position
    initialize_window(el_name);
    
    // Display/hide the box
    toggleBox(el_name);
    
    // If the window is visible, focus it.
    if (_el.style.display == 'block')
        focus_window(_el.id);
}



// Function to set initial position of various elements
// Uses calcOffset() from suggest.js
// 
// NOTE: This function will have site-specific definitions in it!
// 
function initialize_window(el_name) {
    var _el = el(el_name);
    
    // Global object/hash to save current window positions in (for use outside of this library)
    if (typeof(window_position) == 'undefined')
        window_position = new Object();
    
    // If there is no position defined for this "window", let's set something.
    if (typeof(window_position[el_name+'_x']) == 'undefined') {
        window_position[el_name+'_x'] = 0;
        window_position[el_name+'_y'] = 0;
        
        switch (el_name) {
            
            // Just choose a place randomly up to 300x50 pixels away from the "window_container" box
            default : 
                window_position[el_name+'_y'] = calcOffset(el('window_container'), 'offsetTop')  + 20 + (el('window_container').offsetHeight) + Math.floor(Math.random()*70);
                window_position[el_name+'_x'] = calcOffset(el('window_container'), 'offsetLeft') + 50 + Math.floor(Math.random()*150);
                
        }
    }
    
    // Make sure it's position is absolute (it should be already)
    _el.style.position   = 'absolute';
    _el.className        = 'window';
    _el.style.zIndex     = window_default_zindex;
    
    // The "window" will have some position defined.. either by drag.js
    // or initialize_window(), so we now position the box where it belongs.
    _el.style.top   = window_position[el_name+'_y'] + 'px';
    _el.style.left  = window_position[el_name+'_x'] + 'px';
    //alert('x=' + window_position[el_name+'_x'] + ' y=' + window_position[el_name+'_y']);
    
}


// Function to "focus" the window specified
function focus_window(el_name) {
    var _el = el(el_name);
    var _parent = el('window_container');
    
    // Basically we loop through every window.  If we find any windows
    // that have a higher zIndex than the default we set it to the default.
    // When we find the window we're focusing we set it's zIndex to default + 1.
    nodes = _parent.childNodes;
    for (var i=0; i<nodes.length; i++) {
        if (nodes[i].id == _el.id) {
            nodes[i].style.zIndex = window_default_zindex + 1;
        }
        else if (nodes[i].style.zIndex > window_default_zindex) {
            nodes[i].style.zIndex = window_default_zindex;
        }
    }
}


//////////////////////////////////////////////////////////////////////////////
// Author: Brandon Zehm <caspian@dotconf.net>
// 
// Version: 1.5
// Last Update: 2007-03-19
// 
// LICENSE:
// This script is licenced under the GNU LGPL, which basically means you
// can use it for any purpose whatsoever.  Full details at: 
//   http://www.gnu.org/copyleft/lesser.html
// 
// ABOUT:
//   WebWin Tool Tip Javascript Library (i.e. DomTT Lite)
//   Originally based off of code from the DomTT project: 
//     http://www.mojavelinux.com/projects/domtooltip/
// 
// USAGE:
//   Simply include this file, and webwin.css in your html headers.
//   This file has no other dependancies on any PHP scripts, and can be used
//   stand-alone without the other webwin stuff.
//   NOTICE: This file depends on global.js from Brandon's other websites.
//   NOTICE: This file depends on drag.js from the xajax_drag library.
//   
//   Public Functions:
//     wwTT() - Create a new tool-tip
//   
//   Private Functions:
//     wwTT_create() - Build & display the current tool-tip
//     wwTT_position - (Re)position the current tool-tip
//     wwTT_isDescendantOf() - Determine if one element is a child of another
//   
//   Basic example:
//     <span onMouseOver="wwTT(this, event, 'content', 'See spot run..');">Hi there!</span>
// 
// CHANGELOG:
//   v1.5 - 2007-03-19 - Brandon Zehm
//       * Add workaround for Firefox/Mozilla bug #167801
//       * Fixed some bugs with the greasy tool-tip option
//       * Enabled and documented the lifetime option
//       * Added a lot of documentation
//   
//   v1.4 - 2006-08-22 - Brandon Zehm
//       * Make sure wwTT_position() always returns a value
//   
//   v1.3 - 2006-04-11 - Brandon Zehm
//       * Initial public release 
//////////////////////////////////////////////////////////////////////////////

// Global variables
var wwTTobj = new Object;
wwTTobj.autoId = 0;
wwTTobj.options = new Object;






//////////////////////////////////////////////////////////////////////////////
// Function: wwTT(this, event, option, value, [option, value] ... )
// 
// Description:
//     Displays a tool tip "popup" using options provided
//     Usage based loosly off of the open source domTT package.
// 
// Input:
//     There are several options that can be passed in, here is a list.
//       OPTION        DEFAULT          DESCRIPTION
//       ------        -------          -----------
//       id            (auto)           Override the default element id for the new tool-tip
//       content       ''               Text or html to display in the tool-tip
//       type          'greasy'         Tool-tip type: greasy, velcro, or static
//                                        greasy: tool-tip removed when mouse leaves parent
//                                        velcro: tool-tip removed when the mouse is moved into and then outside of the tool-tip
//                                        static: tool-tip is not removed (unless another tool-tip is created)
//       delay         1000             Millisecond delay before displaying the tool-tip
//       lifetime      0                Millisecond delay before expiring the tool-tip
//                                        greasy: expires after being displayed for X milliseconds
//                                        static: expires after being displayed for X milliseconds
//                                        velcro: expires after the mouse has been into and then outside of the tool-tip for X milliseconds
//       detectEdge    1                Avoid placing tool-tips outside the browser boundaries
//       direction     'southeast'      Position the tool-tip this direction from the mouse cursor:
//                                        northeast, northwest, north, southwest, southeast, south, east, west
//       javascript    ''               Execute this javascript after tool-tip creation
//       styleClass    'wwTT_Classic'   Any valid css class name
//       width         ''               Manual tool-tip width (in pixels)
//       x             0                Manual absolute tool-tip x position
//       y             0                Manual absolute tool-tip y position
//       zIndex        5                Manual tool-tip zIndex
//     
// Example:
//     wwTT(this, event, 'content', 'sample content!', 'type', 'velcro');
//////////////////////////////////////////////////////////////////////////////
function wwTT(in_this, in_event) {
    wwTTobj.autoId++;
    wwTTobj.options.parent = document.body;
    wwTTobj.document = wwTTobj.options.parent.ownerDocument || wwTTobj.options.parent.document;
    
    // make sure in_event is set (for IE, some cases we have to use window.event)
    if (typeof(in_event) == 'undefined') 
        in_event = window.event;
    
    // FIXME: this is using the browser variable defined when drag.js is loaded!
    // Get event position
    if (browser.isNS) {
        wwTTobj.cursorX = in_event.clientX + window.scrollX;
        wwTTobj.cursorY = in_event.clientY + window.scrollY;
    }
    else if (browser.isIE || browser.isKONQ) {
        wwTTobj.cursorX = in_event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
        wwTTobj.cursorY = in_event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
    }
    
    // make sure we have nothing higher than the body element
    if (in_this.nodeType && in_this.nodeType != document.DOCUMENT_NODE)
        wwTTobj.options.owner = in_this;
    
    // make sure the owner has a unique id
    if (!wwTTobj.options.owner.id)
        wwTTobj.options.owner.id = '_wwTT_owner_' + wwTTobj.autoId;
    
    // Define default options
    wwTTobj.options['id']         = 'wwTT_' + wwTTobj.autoId;
    wwTTobj.options['content']    = '';              // Content to display in the tool-tip
    wwTTobj.options['type']       = 'greasy';        // Tool-tip type: greasy, velcro, or static
    wwTTobj.options['delay']      = 1000;            // Millisecond delay before displaying the tool-tip
    wwTTobj.options['lifetime']   = 0;               // Millisecond delay before expiring the tool-tip (0 disables)
    wwTTobj.options['detectEdge'] = 1;               // Avoid placing tool-tips outside the browser boundaries
    wwTTobj.options['direction']  = 'southeast';     // Position the tool-tip this direction from the mouse
    wwTTobj.options['javascript'] = '';              // Execute this javascript after tool-tip creation
    wwTTobj.options['styleClass'] = 'wwTT_Classic';  // Any valid css class name
    wwTTobj.options['width']      = '';              // Manual tool-tip width (in pixels)
    wwTTobj.options['x']          = 0;               // Manual tool-tip x position
    wwTTobj.options['y']          = 0;               // Manual tool-tip y position
    wwTTobj.options['zIndex']     = 5;               // Manual tool-tip zIndex
    
    // Load in the options from the function call 
    // (this is a sweet way to pass key=value pairs into a function!)
    for (var i = 2; i < arguments.length; i += 2)
        wwTTobj.options[arguments[i]] = arguments[i + 1];
    
    // Setup an onMouseOut handler for the owner element
    wwTTobj.options.owner.onmouseout = 
        function(ev) {
            clearTimeout(wwTTobj.timer_create);
            // If a greasy tool-tip was actually created before we leave the parent element, remove it!
            if (wwTTobj.lastID == wwTTobj.options.id && wwTTobj.options.type == 'greasy') {
                clearTimeout(wwTTobj.timer_destroy);
                removeElement(wwTTobj.lastID);
            }
        };
    
    // If the tool-tip doesn't already exist, set a timer to display the popup
    if (!el(wwTTobj.options.id))
        wwTTobj.timer_create = setTimeout('wwTT_create();', wwTTobj.options.delay);
}






//////////////////////////////////////////////////////////////////////////////
// Function: wwTT_create()
// 
// Description:
//     Creates & displays a tool-tip "popup" using options found in the
//     global object wwTTobj.
//     Private function.
//     
// Example:
//     wwTT_create();
//////////////////////////////////////////////////////////////////////////////
function wwTT_create() {
    
    // Clear any old lifetime timers .. they're not needed now ;)
    if (typeof(wwTTobj.timer_destroy) != 'undefined')
        clearTimeout(wwTTobj.timer_destroy);
    
    // Make sure the last tool-tip (if any) is removed
    if (typeof(wwTTobj.lastID) != 'undefined')
        removeElement(wwTTobj.lastID);
    
    // Copy a few things for later reference
    wwTTobj.lastID = wwTTobj.options.id;
    wwTTobj.lastLifetime = wwTTobj.options.lifetime;
    
    // Create the tool-tip div
    var tooltip = wwTTobj.options.parent.appendChild(wwTTobj.document.createElement('div'));
    tooltip.style.visibility = 'hidden';
    tooltip.id = wwTTobj.options.id;
    tooltip.className = wwTTobj.options.styleClass;
    tooltip.style.zIndex = wwTTobj.options.zIndex;
    tooltip.style.position = 'absolute';
    // FIXME: This should be removed someday (year) when Firefox/Mozilla no longer have this bug
    // Bug workaround: "position fixed" below is a workaround for this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=167801
    if (navigator.userAgent.indexOf('Gecko/') != -1)
        tooltip.style.position = 'fixed';
    tooltip.style.left = '0px';
    tooltip.style.top = '0px';
    if (wwTTobj.options.content != '')
        tooltip.innerHTML = wwTTobj.options.content;
    
    // adjust the width if specified
    if (wwTTobj.options.width != '')
        tooltip.style.width = parseInt(wwTTobj.options.width) + 'px';
    
    // Position the tool-tip
    wwTT_position(tooltip.id);
    
    // For "greasy" tool-tips
    //   * Setup a lifetime destroy counter if it's not 0
    if (wwTTobj.options.type == 'greasy') {
        if (wwTTobj.options.lifetime != 0)
            wwTTobj.timer_destroy = setTimeout("removeElement('" + wwTTobj.options.id + "');", wwTTobj.options.lifetime);
    }
    
    
    // For "velcro" tool-tips
    //   * Setup it's onMouseOut handler
    //     * Setup a lifetime countdown timer to destroy the tool-tip
    //   * Add a onMouseOver handler that cancels any pending lifetime "destroy" timers
    //   * Disable the owner's onMouseOut handler (just to keep things clean in the DOM)
    if (wwTTobj.options.type == 'velcro') {
        // Setup a timer to remove the element if the event didn't come from one of our children
        tooltip.onmouseout = 
            function(ev) {
                if (typeof(ev) == 'undefined') ev = event;
                var tag = browser.isIE ? 'toElement' : 'relatedTarget';
                if (!wwTT_isDescendantOf(this, ev[tag])) 
                    wwTTobj.timer_destroy = setTimeout("removeElement('" + wwTTobj.lastID + "');", wwTTobj.lastLifetime);
            };
        
        // Cancel the count-down timer if the mouse comes into the tool-tip
        tooltip.onmouseover = 
            function(ev) {
                clearTimeout(wwTTobj.timer_destroy);
            };
        wwTTobj.options.owner.onmouseout = function(ev) { return true; };
    }
    
    
    // For "static" tool-tips
    //   * Disable the owner's onMouseOut handler (just to keep things clean in the DOM)
    //   * Setup a lifetime destroy counter if it's not 0
    if (wwTTobj.options.type == 'static') {
        wwTTobj.options.owner.onmouseout = function(ev) { return true; };
        if (wwTTobj.options.lifetime != 0)
            wwTTobj.timer_destroy = setTimeout("removeElement('" + wwTTobj.options.id + "');", wwTTobj.options.lifetime);
    }
    
    // Display the tool-tip
    tooltip.style.visibility = 'visible';
    
    // Execute any javascript queued to be run
    if (wwTTobj.options.javascript != '')
        eval(wwTTobj.options.javascript);

}







//////////////////////////////////////////////////////////////////////////////
// Function: wwTT_position(element_id)
// 
// Description:
//     Positions an already existing tool-tip
//     Private function.
//     
// Example:
//     wwTT_position(element_id);
//////////////////////////////////////////////////////////////////////////////
function wwTT_position(element_id) {
    tooltip = el(element_id);
    
    // If an absolute position is specified use it
    if (parseInt(wwTTobj.options.x) != 0 && parseInt(wwTTobj.options.y) != 0) {
        tooltip.style.left = wwTTobj.options.x + 'px';
        tooltip.style.top  = wwTTobj.options.y + 'px';
        return true;
    }
    
    // Otherwise calculate our location from the cursor's position
    // FIXME: uses "browser" variable from drag.js
    var mouseHeight = browser.isIE ? 13 : 19;
    var offsetX = 0;
    var offsetY = 0;
    var padding = 10;
    switch (wwTTobj.options.direction) {
        case 'northeast':
            offsetX = 0;
            offsetY = 0 - tooltip.offsetHeight - padding;
        break;
        case 'northwest':
            offsetX = 0 - tooltip.offsetWidth;
            offsetY = 0 - tooltip.offsetHeight - padding;
        break;
        case 'north':
            offsetX = 0 - parseInt(tooltip.offsetWidth/2);
            offsetY = 0 - tooltip.offsetHeight - padding;
        break;
        case 'southwest':
            offsetX = 0 - tooltip.offsetWidth;
            offsetY = 0 + mouseHeight;
        break;
        case 'southeast':
            offsetX = 0;
            offsetY = 0 + mouseHeight;
        break;
        case 'south':
            offsetX = 0 - parseInt(tooltip.offsetWidth/2);
            offsetY = 0 + mouseHeight;
        break;
        case 'east':
            offsetX = padding;
            offsetY = 0 - parseInt(tooltip.offsetHeight/2);
        break;
        case 'west':
            offsetX = 0 - tooltip.offsetWidth - padding;
            offsetY = 0 - parseInt(tooltip.offsetHeight/2);
        break;
    }
    
    // Calculate new X & Y positions
    var newX = wwTTobj.cursorX + offsetX;
    var newY = wwTTobj.cursorY + offsetY;
    
    // Detect screen edges and adjust the tool-tip position if needed
    if (wwTTobj.options.detectEdge == 1) {
        if (newY < 0) newY = 0;
        if (newX < 0) newX = 0;
        if ( (newX + tooltip.offsetWidth) > parseInt(document.body.clientWidth))
            newX = document.body.clientWidth - tooltip.offsetWidth;
        if ( (newY + tooltip.offsetHeight) > parseInt(document.body.clientHeight))
            newY = document.body.clientHeight - tooltip.offsetHeight;
    }
    
    // Position the tool-tip
    tooltip.style.left = newX + 'px';
    tooltip.style.top  = newY + 'px';
    return true;
}






//////////////////////////////////////////////////////////////////////////////
// Function: wwTT_isDescendantOf(element, potential_child)
// 
// Description:
//     Returns true if potential_child is a descendant of element.
//     Private function.
//////////////////////////////////////////////////////////////////////////////
function wwTT_isDescendantOf(_parent, _object) {
    var cur_el = _object;
    while ( (cur_el) && (cur_el != document.body) ) {
        // If the current element is the same as the parent element, return true.
        if(cur_el == _parent)
            return true;
        
        // Otherwise go up a node
        cur_el = cur_el.parentNode ? cur_el.parentNode : false;
    }
    return false;
}


