////
// Some convenience functions for dealing with Javascript arrays
////
var ArrayUtil = new Object();
ArrayUtil.toString = function toString (theArray, separator) {
    var rtnString = "";
    for(var i = 0; i < theArray.length; i ++) {
        rtnString += theArray[i] + separator;
    }

    return rtnString;
}

ArrayUtil.shiftArrayTo = function (arr, value)
{
    var i = 0;
    var len = arr.length;
    while (i < len && value != arr[0])
    {
        var entry = arr.shift();
        arr.push(entry);
        i++;
    }
}

// proto.js - adds functionality to JS base types

//---------- String

// Formats a string similar to Java's MessageFormat.format()
//
// this - this string should be the format string
// saReplace - array of objects to replace the {n} variables with
// [0..n arguments] - either single array, or list of arguments
String.prototype.format = function ()
{
    var saArgs;
    if (1 == arguments.length
// would prefer to use this line, but isPrototypeOf(...) is introducted in IE 5.5
//        && Array.prototype.isPrototypeOf(arguments[0]))
        && null != arguments[0] &&  null != arguments[0].sort && "undefined" != arguments[0].sort)
    {
        saArgs = arguments[0];
    }
    else
    {
        saArgs = arguments;
    }

    var re = /^[0-9]+$/;
    var saParts = getFormatParts(this);
    for (var i = 0; i < saParts.length; i++)
    {
        if (saParts[i].match(re))
            saParts[i] = saArgs[saParts[i]];
    }
    return saParts.join("");
}


// break this method out so we can override it if we need to
function getFormatParts(s) { return s.split(/[{}]/); }

String.prototype.trim = function ()
{
    return this.replace(/^\s+/,'').replace(/\s+$/,'');
}

////
// ImageUtil - convenience functions for dealing with images.
////
var ImageUtil = new Object();

// scaleImages.js - proportionally scales images on the client side
// @param baseName - The name of the image to scale.  All images in the
//            document with the supplied name will be scaled.
// @param maxWidth - the widest an image is allowed to be
// @param maxHeight - the tallest an image is allowed to be

ImageUtil.scaleImages = function (baseName, maxWidth, maxHeight, onerror)
{
    var fn;
    if (onerror == undefined)
    {
        fn = "ImageUtil.reallyScaleImages('" + baseName + "', " + maxWidth + ", " + maxHeight + ")";
    }
    else
    {
        fn = "ImageUtil.reallyScaleImages('" + baseName + "', " + maxWidth + ", " + maxHeight + ", '" + onerror + "')";
    }
    setTimeout (fn, 250);
}

ImageUtil.reallyScaleImages =  function  (baseName, maxWidth, maxHeight, errorImg)
{
    var images = document.getElementsByName(baseName);

    var len = images.length;

    for (var index = 0; index < len; index++) {
        var image = images[index];
        var newImage = new Image();   // current image reports size as 0 x 0, need new image to query actual size
        newImage.src = null;
        newImage.proxy = image;

        if (errorImg != undefined && errorImg != '' && errorImg != null)
        {
            newImage.onerror = function(evt) {
                var self = this;
                self.src = errorImg;
            }
        }

        newImage.onload = function(evt) {
            var self = this;
            var iWidth = self.width;
            var iHeight = self.height;

            if (iWidth > maxWidth || iHeight > maxHeight)
            {
                var nWidth;
                var nHeight;

                if (iWidth/maxWidth > iHeight/maxHeight) {      // wider
                    nWidth = maxWidth;
                    nHeight = (iHeight * maxWidth) / iWidth;
                }
                else {                                          // higher
                    nHeight = maxHeight;
                    nWidth = (iWidth * maxHeight) / iHeight;
                }

                iWidth = nWidth;
                iHeight = nHeight;
            }

            self.proxy.style.display = "inline";
            self.proxy.width = iWidth;
            self.proxy.height = iHeight;

        }
        newImage.src = image.src;
    }
}
////
// EventUtils - A wrapper for attaching events using W3C/Microsoft APIs.
// Required for attaching more than one event handler to a given object
// formerly documentSupport.js
////
var EventUtils = new Object();
EventUtils.addListener = function (evtSrc, evtName, handler, bubbleEvt)
{
    var eventName = evtName.substr(0, 2) != 'on' ? 'on'+evtName : evtName;
    if (evtSrc.attachEvent)
    {
        evtSrc.attachEvent(evtName, handler);
    }
    else if (evtSrc.addEventListener)
    {
        evtName = (evtName.substr(0, 2) != 'on' ? evtName : evtName.substr(2, evtName.length-2));
        evtSrc.addEventListener(evtName, handler, bubbleEvt == undefined ? true : bubbleEvt);
    }
    else
    {
        eval(evtSrc + "." + eventName + "= handler;");
    }
}

EventUtils.addLoadEvent = function (func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

////
// CookieUtils - Utilities for adding/removing cookies (formerly cookie.js)
////
var CookieUtils = new Object();

// @param name - name of the cookie
// @param value - value of the cookie
// @param [expires] - expiration date of the cookie (defaults to end of current session)
// @param [path] - path for which the cookie is valid (defaults to path of calling document)
// @param [domain] - domain for which the cookie is valid (defaults to domain of calling document)
// @param [secure] - Boolean value indicating if the cookie transmission requires a secure transmission
//  an argument defaults when it is assigned null as a placeholder
//  a null placeholder is not required for trailing omitted arguments
CookieUtils.setCookie = function (name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}

CookieUtils.setCookieExpireNDays = function (cookieName,cookieValue,nDays) {
 var today = new Date();
 var expire = new Date();
 if (nDays==null || nDays==0) nDays=1;
 expire.setTime(today.getTime() + 3600000*24*nDays);
 document.cookie = cookieName+"="+escape(cookieValue)
                 + ";expires="+expire.toGMTString();
}


// @param name - name of the desired cookie
// @return return string containing value of specified cookie or null if cookie does not exist
CookieUtils.getCookie = function (name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  var s = unescape(dc.substring(begin + prefix.length, end));
  if (s != null && s != "" && s.indexOf("\"") == 0 && s.lastIndexOf("\"") == s.length-1)
  {
      return s.substring(1, s.length-1);
  }
  return s;
}

// @param name - name of the cookie
// @param [path] - path of the cookie (must be same as path used to create cookie)
// @param [domain] - domain of the cookie (must be same as domain used to create cookie)
// * path and domain default if assigned null or omitted if no explicit argument proceeds
CookieUtils.deleteCookie = function (name, path, domain) {
  if (this.getCookie(name)) {
    document.cookie = name + "=" +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
}

// I'm too lazy to write my own browser sniffer.  This is
// from http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html.

// NOTE: USE THIS CAREFULLY, this is no longer considered the best way to
// handle cross-browser issues.
// See http://devedge.netscape.com/viewsource/2002/browser-detection/

//<!--
// Ultimate client-side JavaScript client sniff. Version 3.03
// (C) Netscape Communications 1999-2001.  Permission granted to reuse and distribute.
// Revised 17 May 99 to add is_nav5up and is_ie5up (see below).
// Revised 20 Dec 00 to add is_gecko and change is_nav5up to is_nav6up
//                      also added support for IE5.5 Opera4&5 HotJava3 AOLTV
// Revised 22 Feb 01 to correct Javascript Detection for IE 5.x, Opera 4,
//                      correct Opera 5 detection
//                      add support for winME and win2k
//                      synch with browser-type-oo.js
// Revised 26 Mar 01 to correct Opera detection
// Revised 02 Oct 01 to add IE6 detection

// Everything you always wanted to know about your JavaScript client
// but were afraid to ask. Creates "is_" variables indicating:
// (1) browser vendor:
//     is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV
// (2) browser version number:
//     is_major (integer indicating major version number: 2, 3, 4 ...)
//     is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
// (3) browser vendor AND major version number
//     is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,
//     is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,
//     is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up
// (4) JavaScript version number:
//     is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
// (5) OS platform and version:
//     is_win, is_win16, is_win32, is_win31, is_win95, is_winnt, is_win98, is_winme, is_win2k
//     is_os2
//     is_mac, is_mac68k, is_macppc
//     is_unix
//     is_sun, is_sun4, is_sun5, is_suni86
//     is_irix, is_irix5, is_irix6
//     is_hpux, is_hpux9, is_hpux10
//     is_aix, is_aix1, is_aix2, is_aix3, is_aix4
//     is_linux, is_sco, is_unixware, is_mpras, is_reliant
//     is_dec, is_sinix, is_freebsd, is_bsd
//     is_vms
//
// See http://www.it97.de/JavaScript/JS_tutorial/bstat/navobj.html and
// http://www.it97.de/JavaScript/JS_tutorial/bstat/Browseraol.html
// for detailed lists of userAgent strings.
//
// Note: you don't want your Nav4 or IE4 code to "turn off" or
// stop working when new versions of browsers are released, so
// in conditional code forks, use is_ie5up ("IE 5.0 or greater")
// is_opera5up ("Opera 5.0 or greater") instead of is_ie5 or is_opera5
// to check version in code which you want to work on future
// versions.
var BrowserSniffer = new Object();

BrowserSniffer.init = function()
{
    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    // *** BROWSER VERSION ***
    // Note: On IE5, these return 4, so use is_ie5up to detect IE5.
    this.is_major = parseInt(navigator.appVersion);
    this.is_minor = parseFloat(navigator.appVersion);

    // Note: Opera and WebTV spoof Navigator.  We do strict client detection.
    // If you want to allow spoofing, take out the tests for opera and webtv.
    this.is_nav  = agt.indexOf('mozilla')!=-1 && agt.indexOf('spoofer')==-1
                && agt.indexOf('compatible') == -1 && agt.indexOf('opera')==-1
                && agt.indexOf('webtv')==-1 && agt.indexOf('hotjava')==-1;
    this.is_nav2 = this.is_nav && this.is_major == 2;
    this.is_nav3 = this.is_nav && this.is_major == 3;
    this.is_nav4 = this.is_nav && this.is_major == 4;
    this.is_nav4up = this.is_nav && this.is_major >= 4;
    this.is_navonly = this.is_nav && (agt.indexOf(";nav") != -1 || agt.indexOf("; nav") != -1);
    this.is_nav6 = this.is_nav && this.is_major == 5;
    this.is_nav6up = this.is_nav && this.is_major >= 5;
    this.is_gecko = agt.indexOf('gecko') != -1;


    this.is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
    this.is_ie3    = (this.is_ie && (this.is_major < 4));
    this.is_ie4    = (this.is_ie && (this.is_major == 4) && (agt.indexOf("msie 4")!=-1) );
    this.is_ie4up  = (this.is_ie && (this.is_major >= 4));
    this.is_ie5    = (this.is_ie && (this.is_major == 4) && (agt.indexOf("msie 5.0")!=-1) );
    this.is_ie5_5  = (this.is_ie && (this.is_major == 4) && (agt.indexOf("msie 5.5") !=-1));
    this.is_ie5up  = (this.is_ie && !this.is_ie3 && !this.is_ie4);
    this.is_ie5_5up =(this.is_ie && !this.is_ie3 && !this.is_ie4 && !this.is_ie5);
    this.is_ie6    = (this.is_ie && (this.is_major == 4) && (agt.indexOf("msie 6.")!=-1) );
    this.is_ie6up  = (this.is_ie && !this.is_ie3 && !this.is_ie4 && !this.is_ie5 && !this.is_ie5_5);
    this.is_ie7    = (this.is_ie && (agt.indexOf("msie 7.")));

    // KNOWN BUG: On AOL4, returns false if IE3 is embedded browser
    // or if this is the first browser window opened.  Thus the
    // variables is_aol, is_aol3, and is_aol4 aren't 100% reliable.
    this.is_aol   = (agt.indexOf("aol") != -1);
    this.is_aol3  = (this.is_aol && this.is_ie3);
    this.is_aol4  = (this.is_aol && this.is_ie4);
    this.is_aol5  = (agt.indexOf("aol 5") != -1);
    this.is_aol6  = (agt.indexOf("aol 6") != -1);

    this.is_opera = (agt.indexOf("opera") != -1);
    this.is_opera2 = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
    this.is_opera3 = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
    this.is_opera4 = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
    this.is_opera5 = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
    this.is_opera5up = (this.is_opera && !this.is_opera2 && !this.is_opera3 && !this.is_opera4);

    this.is_webtv = (agt.indexOf("webtv") != -1);

    this.is_TVNavigator = ((agt.indexOf("navio") != -1) || (agt.indexOf("navio_aoltv") != -1));
    this.is_AOLTV = this.is_TVNavigator;

    this.is_hotjava = (agt.indexOf("hotjava") != -1);
    this.is_hotjava3 = (this.is_hotjava && (this.is_major == 3));
    this.is_hotjava3up = (this.is_hotjava && (this.is_major >= 3));

    // *** JAVASCRIPT VERSION CHECK ***
    this.is_js = '';
    if (this.is_nav2 || this.is_ie3) this.is_js = 1.0;
    else if (this.is_nav3) this.is_js = 1.1;
    else if (this.is_opera5up) this.is_js = 1.3;
    else if (this.is_opera) this.is_js = 1.1;
    else if ((this.is_nav4 && (this.is_minor <= 4.05)) || this.is_ie4) this.is_js = 1.2;
    else if ((this.is_nav4 && (this.is_minor > 4.05)) || this.is_ie5) this.is_js = 1.3;
    else if (this.is_hotjava3up) this.is_js = 1.4;
    else if (this.is_nav6 || this.is_gecko) this.is_js = 1.5;
    // NOTE: In the future, update this code when newer versions of JS
    // are released. For now, we try to provide some upward compatibility
    // so that future versions of Nav and IE will show they are at
    // *least* JS 1.x capable. Always check for JS version compatibility
    // with > or >=.
    else if (this.is_nav6up) this.is_js = 1.5;
    // NOTE: ie5up on mac is 1.4
    else if (this.is_ie5up) this.is_js = 1.3

    // HACK: no idea for other browsers; always check for JS version with > or >=
    else this.is_js = 0.0;

    // *** PLATFORM ***
    this.is_win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
    // NOTE: On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all
    //        Win32, so you can't distinguish between Win95 and WinNT.
    this.is_win95 = ((agt.indexOf("win95")!=-1) || (agt.indexOf("windows 95")!=-1));

    // is this a 16 bit compiled version?
    this.is_win16 = ((agt.indexOf("win16")!=-1) ||
               (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) ||
               (agt.indexOf("windows 16-bit")!=-1) );

    this.is_win31 = ((agt.indexOf("windows 3.1")!=-1) || (agt.indexOf("win16")!=-1) ||
                    (agt.indexOf("windows 16-bit")!=-1));

    this.is_winme = ((agt.indexOf("win 9x 4.90")!=-1));
    this.is_win2k = ((agt.indexOf("windows nt 5.0")!=-1));
    this.is_winxp = ((agt.indexOf("windows nt 5.1")!=-1));

    // NOTE: Reliable detection of Win98 may not be possible. It appears that:
    //       - On Nav 4.x and before you'll get plain "Windows" in userAgent.
    //       - On Mercury client, the 32-bit version will return "Win98", but
    //         the 16-bit version running on Win98 will still return "Win95".
    this.is_win98 = ((agt.indexOf("win98")!=-1) || (agt.indexOf("windows 98")!=-1));
    this.is_winnt = ((agt.indexOf("winnt")!=-1) || (agt.indexOf("windows nt")!=-1));
    this.is_win32 = (this.is_win95 || this.is_winnt || this.is_win98 ||
                    ((this.is_major >= 4) && (navigator.platform == "Win32")) ||
                    (agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1));

    this.is_os2   = ((agt.indexOf("os/2")!=-1) ||
                    (navigator.appVersion.indexOf("OS/2")!=-1) ||
                    (agt.indexOf("ibm-webexplorer")!=-1));

    this.is_mac    = (agt.indexOf("mac")!=-1);
    // hack ie5 js version for mac
    if (this.is_mac && this.is_ie5up) this.is_js = 1.4;
    this.is_mac68k = (this.is_mac && ((agt.indexOf("68k")!=-1) ||
                               (agt.indexOf("68000")!=-1)));
    this.is_macppc = (this.is_mac && ((agt.indexOf("ppc")!=-1) ||
                                (agt.indexOf("powerpc")!=-1)));

    this.is_sun   = (agt.indexOf("sunos")!=-1);
    this.is_sun4  = (agt.indexOf("sunos 4")!=-1);
    this.is_sun5  = (agt.indexOf("sunos 5")!=-1);
    this.is_suni86= (this.is_sun && (agt.indexOf("i86")!=-1));
    this.is_irix  = (agt.indexOf("irix") !=-1);    // SGI
    this.is_irix5 = (agt.indexOf("irix 5") !=-1);
    this.is_irix6 = ((agt.indexOf("irix 6") !=-1) || (agt.indexOf("irix6") !=-1));
    this.is_hpux  = (agt.indexOf("hp-ux")!=-1);
    this.is_hpux9 = (this.is_hpux && (agt.indexOf("09.")!=-1));
    this.is_hpux10= (this.is_hpux && (agt.indexOf("10.")!=-1));
    this.is_aix   = (agt.indexOf("aix") !=-1);      // IBM
    this.is_aix1  = (agt.indexOf("aix 1") !=-1);
    this.is_aix2  = (agt.indexOf("aix 2") !=-1);
    this.is_aix3  = (agt.indexOf("aix 3") !=-1);
    this.is_aix4  = (agt.indexOf("aix 4") !=-1);
    this.is_linux = (agt.indexOf("inux")!=-1);
    this.is_sco   = (agt.indexOf("sco")!=-1) || (agt.indexOf("unix_sv")!=-1);
    this.is_unixware = (agt.indexOf("unix_system_v")!=-1);
    this.is_mpras    = (agt.indexOf("ncr")!=-1);
    this.is_reliant  = (agt.indexOf("reliantunix")!=-1);
    this.is_dec   = ((agt.indexOf("dec")!=-1) || (agt.indexOf("osf1")!=-1) ||
           (agt.indexOf("dec_alpha")!=-1) || (agt.indexOf("alphaserver")!=-1) ||
           (agt.indexOf("ultrix")!=-1) || (agt.indexOf("alphastation")!=-1));
    this.is_sinix = (agt.indexOf("sinix")!=-1);
    this.is_freebsd = (agt.indexOf("freebsd")!=-1);
    this.is_bsd = (agt.indexOf("bsd")!=-1);
    this.is_unix  = ((agt.indexOf("x11")!=-1) || this.is_sun || this.is_irix || this.is_hpux ||
                 this.is_sco ||this.is_unixware || this.is_mpras || this.is_reliant ||
                 this.is_dec || this.is_sinix || this.is_aix || this.is_linux || this.is_bsd || this.is_freebsd);

    this.is_vms   = ((agt.indexOf("vax")!=-1) || (agt.indexOf("openvms")!=-1));
    this.is_safari  = (agt.indexOf("safari") != -1);
    this.is_safari3 = (agt.indexOf("3.0 safari") !=-1);
    this.is_safari2 = (agt.indexOf("2.0 safari") !=-1);
}

BrowserSniffer.isSupportedPlatform = function (){
        if (this.is_win) {
            if(this.is_win2k || this.is_winxp){
                return true;
            }
        }

        return false;
    }

BrowserSniffer.isSupportedBrowser = function () {
    return this.is_ie && this.is_ie5_5up
}

BrowserSniffer.isClientSupportedEnv = function () {
    return (this.isSupportedBrowser() && this.isSupportedPlatform());
}

BrowserSniffer.init();

///////////////////////////////////////////////// DOM Utilities ////////////////////////////////////////////////

var DomUtils = new Object();
// Shows or hides a page element.  If the page element doesn't exist, it does
// nothing.
//
// oElem - page element to show or hide
// [bShow] - show if true, hide if false (defaults to true)
DomUtils.showElement = function (oElem, bShow)
{
    if (null == bShow || "undefined" == bShow)
        bShow = true;
    if (null != oElem)
        oElem.style.display = (bShow ? "" : "none");
}

DomUtils.hideElement = function (oElem)
{
    this.showElement(oElem, false);
}

DomUtils.hideElementById = function (sElemId)
{
    this.showElementById(sElemId, false);
}

DomUtils.showElementById = function (sElemId, bShow)
{
    var oShow = document.getElementById(sElemId);
    if (oShow != null)
    {
        this.showElement(oShow, bShow);
    }
}

DomUtils.setElementVisibility = function (elem, state)
{
    if (null == state || "undefined" == state)
        state = ""; // makes it visible
    if (null != elem)
        elem.style.visibility = state;
}

////
// Similar to getElementsByTagName, but get elements by a certain style class
// @param className the className to look for
// @param [tagName] the tag to filter with.  This should speed up the lookup
// @param [fromElement] the starting point to start searching.
DomUtils.getElementsByClassName = function (className, tagName, fromElement)
{
    var els = [];
    if (fromElement == undefined || !fromElement.getElementsByTagName)
        fromElement = document;

    if (tagName == undefined || tagName == '' || tagName == null)
        tagName = '*';

    var elem = fromElement.getElementsByTagName(tagName);
    if (elem != null && elem.length() > 0)
    {
        var re = new RegExp('\\b' + className + '\\b');
        for (var i = 0; i < elem.length; i++) {
            var classes = elem[i].className;
            if (re.test(classes))
            {
                els.push(elem[i]);
            }
        }
    }
    return els;
}

////
// Hide all known elements except one and do nothing that one.
//
// @param oaElems - array of elements to hide
// @param sExceptionId - id of the element to ignore
////
DomUtils.hideAllElemsButId = function (oaElems, sExceptionId)
{
    for (var i = 0; i < oaElems.length; i++)
    {
        if (null == oaElems[i]) continue;  // skip nulls
        if (oaElems[i].id == sExceptionId) continue;  // skip exception
        this.showElement(oaElems[i], false);
    }
}

////
// Hides a page element if it is currently shown, or shows it if it's
// currently hidden.
//
// @param sId - id of the object to hide or show
////
DomUtils.toggleElementById = function (sId)
{
    var oElem = document.getElementById(sId);
    this.showElement(oElem, this.isElementHidden(oElem));
}

// Determines if a page element is currently hidden.
//
// oElem - page element to determine hidden or shown status
// returns - true if the page is hidden; false otherwise
DomUtils.isElementHidden = function (oElem)
{
    return (oElem
            && oElem.style
            && oElem.style.display
            && "none" == oElem.style.display);
}

////
// Resolve to either parentElement or parentNode
// @param el the element to test
////
DomUtils.resolveParentElement = function (el)
{
    if (el.parentElement)
        return el.parentElement;
    else if (el.parentNode)
        return el.parentNode;
    else return null;
}

DomUtils.getRelativeParent = function(el)
{
    if (el == null || el == undefined)
        return;

    if (el.style.position == "relative")
    {
        return el;
    }
    return this.getRelativeParent(this.resolveParentElement(el));
}

DomUtils.getContainerDiv = function (elem)
{
    if (elem == null) return null;

    var parentElem = elem.parentNode;

    while (true)
    {
        if (parentElem == null)
        {
            return null;
        }

        if (DomUtils.hasDynamicClassName(parentElem))
        {
            return parentElem;
        }

        parentElem = parentElem.parentNode;
    }
}

DomUtils.FIND_ME_CLASSNAME = /\bdynamicContent\b/;

// does a class string match FIND_ME_CLASSNAME
// if so we're in a panel
DomUtils.hasDynamicClassName = function(el)
{
    return this.hasStyleClass(el, this.FIND_ME_CLASSNAME);
}

DomUtils.hasStyleClass = function (el, reLookupClassName)
{
    if (!el || !el.className)
        return false;
    
    var className = el.className;

    if (reLookupClassName == className)
        return true;

    if (className == "" || className == null)
    {
        return false;
    }
    return reLookupClassName.test(className);
}

DomUtils.removeStyleClass = function(el, clsName)
{
    if (el != null && el != undefined && el.className)
    {
        var re = new RegExp("\\b" + clsName + "\\b");
        el.className = el.className.replace(re, "");
    }
}

DomUtils.replaceStyleClass = function(el, clsName)
{
    if (el != null && el != undefined && el.className)
    {
        el.className = clsName;
    }
}


DomUtils.addStyleClass = function(el, clsName)
{
    if (el != null && el != undefined && el.className)
    {
        var re = new RegExp("\\b" + clsName + "\\b");
        if (!el.className.match(re))
            el.className += (el.className.length > 0 ? " " : "") + clsName;
    }
}

DomUtils.getAbsolutePos = function getAbsolutePos(el) {
	var SL = 0, ST = 0;
	var is_div = /^div$/i.test(el.tagName);
	if (is_div && el.scrollLeft)
		SL = el.scrollLeft;
	if (is_div && el.scrollTop)
		ST = el.scrollTop;
	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
	if (el.offsetParent) {
		var tmp = this.getAbsolutePos(el.offsetParent);
		r.x += tmp.x;
		r.y += tmp.y;
	}
//    alert("x,y="+r.x+','+r.y);
    return r;
}

DomUtils.isElementNestedChildOfElement = function (child, parent)
{
    if (child == parent)
    {
        return true;
    }
    else
    {
        var currentParent = child.parentNode;

        var isChild = false;
        while (currentParent != null && !isChild)
        {
//            if ( !confirm("id = "+currentParent.id+": "+currentParent+"\nContinue?")) break;
            if (currentParent == parent)
            {
                isChild = true;
            }
            else
            {
                currentParent = currentParent.parentNode;
            }
        }
        return isChild;
     }
}

DomUtils.loadScript = function(script, containerId)
{
    var container;
    if (containerId)
    {
        container = document.getElementById(containerId);
    }

    if (!container)
        container = document.getElementsByTagName('head')[0];

    var scriptId = script.indexOf("http://") == -1 ? script.substr(script.lastIndexOf('/') + 1) : script;
    if (!document.getElementById(scriptId))
    {
        var scriptLoader = document.createElement('script');
        scriptLoader.type = 'text/javascript';
        scriptLoader.src = script;
        scriptLoader.id = scriptId;
        container.appendChild(scriptLoader);
    }
}

// Accessor utilities for buttons, since button now have spans inside
DomUtils.getButtonValue = function(btn)
{
    return btn.getElementsByTagName('SPAN')[0].innerText;
}

DomUtils.setButtonValue = function(btn, newValue)
{
    btn.getElementsByTagName('SPAN')[0].innerText = newValue;
}

DomUtils.getInnerDimensions = function() {
    var x,y;
    if (self.innerHeight) // all except Explorer
    {
        x = self.innerWidth;
        y = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
    // Explorer 6 Strict Mode
    {
        x = document.documentElement.clientWidth;
        y = document.documentElement.clientHeight;
    }
    else if (document.body) // other Explorers
    {
        x = document.body.clientWidth;
        y = document.body.clientHeight;
    }
    return { x: x, y : y };
}

DomUtils.getScrollingOffsets = function() {
    var x,y;
    if (self.pageYOffset) // all except Explorer
    {
        x = self.pageXOffset;
        y = self.pageYOffset;
    }
    else if (document.documentElement && document.documentElement.scrollTop)
    // Explorer 6 Strict
    {
        x = document.documentElement.scrollLeft;
        y = document.documentElement.scrollTop;
    }
    else if (document.body) // all other Explorers
    {
        x = document.body.scrollLeft;
        y = document.body.scrollTop;
    }
    return { x: x, y : y };    
}

DomUtils.getPageHeight = function() {
    var x,y;
    var test1 = document.body.scrollHeight;
    var test2 = document.body.offsetHeight
    if (test1 > test2) // all but Explorer Mac
    {
        x = document.body.scrollWidth;
        y = document.body.scrollHeight;
    }
    else // Explorer Mac;
    //would also work in Explorer 6 Strict, Mozilla and Safari
    {
        x = document.body.offsetWidth;
        y = document.body.offsetHeight;
    }
    return { x: x, y : y };
}

DomUtils.getMousePos = function(evt) {
	var posx = 0;
	var posy = 0;
	if (!evt) evt = window.event;

    if (evt.pageX || evt.pageY) 	{
		posx = evt.pageX;
		posy = evt.pageY;
	}
	else if (evt.clientX || evt.clientY) 	{
		posx = evt.clientX + document.body.scrollLeft
			+ document.documentElement.scrollLeft;
		posy = evt.clientY + document.body.scrollTop
			+ document.documentElement.scrollTop;
	}
    return { x : posx, y : posy };
}

DomUtils.getSelectedOptionIndexes = function(sel) {
    var arr = [];
    for (var i=0; i < sel.options.length; i++)
    {
        if (sel.options[i].selected)
        {
            arr[arr.length] = i;
        }
    }
    return arr;
}

///////////////////////////////////////////////// Window Utilities ////////////////////////////////////////////////

// windowManager.js - utility functions to manage windows

var WindowUtils = new Object();
// Open a window named sName to sURL.  If a window of sName already exists,
// it gets that window, and dynamically sets the window properties.
//
// sName - window name
// sURL - url
// [iWidth] - optional window width
// [iHeight] - optional window height
// [bHaveScrollBar] - optional toggle for scrollbars
// [bResizable] - optional toggle for resizability
//
WindowUtils.openWindow = function (sName, sURL, iWidth, iHeight, bHaveScrollBar, bResizable, bToolbar)
{
    var sFeatures = "";
    if ("undefined" != iWidth && null != iWidth)
        sFeatures += ("" == sFeatures ? "" : ",")
                  + "width=" + iWidth;
    if ("undefined" != iHeight && null != iHeight)
        sFeatures += ("" == sFeatures ? "" : ",")
                  + "height=" + iHeight;
    if ("undefined" != bHaveScrollBar && null != bHaveScrollBar)
        sFeatures += ("" == sFeatures ? "" : ",")
                  + "scrollbars=" + (bHaveScrollBar ? "1" : "0");
    if ("undefined" != bResizable && null != bResizable)
        sFeatures += ("" == sFeatures ? "" : ",")
                  + "resizable=" + (bResizable ? "1" : "0");
    if ("undefined" != bToolbar && null != bToolbar)
        sFeatures += ("" == sFeatures ? "" : ",")
                  + "toolbar=" + (bToolbar ? "1" : "0");

    var oWin = window.open("", sName, sFeatures);

    // dynamically set window properties in case window was already open
    if ("undefined" != sURL && null != sURL)
        oWin.location = sURL;
    if ("undefined" == iWidth || null == iWidth)
        iWidth = oWin.innerWidth;
    if ("undefined" == iHeight || null == iHeight)
        iHeight = oWin.innerHeight;
    try
    {
        oWin.resizeTo(iWidth, iHeight);
    }
    catch (exception)
    {
        // probably failed to resize because oWin is pointing at a page
        // outside of our control so ignore
    }

    // unfortunately, it's a wee bit difficult hiding the scrollbar dynamically
    // so we don't handle it

    oWin.focus();
    return oWin;
}

// utility function to open help
WindowUtils.openHelp = function (sTarget)
{
    // The help targets are all #links, and as a result, it doesn't
    // change the page view when we set the location in openWindow,
    // probably because it thinks it's at the right place.  To get around
    // this, we force the page to blank.html first, and then set it to the
    // help target.
    // Note: for some reason, Mozilla gets stuck on blank.html and it takes
    //       a second help click to move it to the right place.  Oh well.
    openWindow("spokeHelp", "/shared/html/blank.html", 900, 750, true);
    var sSrc = "/robohelp/spoke.htm";
    if (null != sTarget && "undefined" != sTarget)
        sSrc += "#" + sTarget;
    openWindow("spokeHelp", sSrc, 900, 750, true);
}

// utility function to open dossier
WindowUtils.openDossier = function (sUrl)
{
    this.openWindow('spokeDossier', sUrl, 800, 700, true, true);
}

WindowUtils.openWebSearch = function (sUrl)
{
    window.open(sUrl);      //open a window with default property.
}

WindowUtils.newWindow = function (url, height, width) {
    var nameW='feature'
    var openedWindow;

    if (navigator.appVersion.indexOf('4') != -1) {
        var xTop = screen.width/2 - (width/2);
        var yTop = screen.height/2 - (height/2);
        openedWindow = window.open(url, nameW, 'height='+height+',width='+width+',scrollbars=1,resizable=1,menubar=0,toolbar=0,status=0,location=0,directories=0,left=' + xTop + ',top=' + yTop + '');
    } else {
        openedWindow = window.open(url, nameW, 'height='+height+',width='+width+',scrollbars=0,resizable=0,menubar=0,toolbar=0,status=0,location=0,directories=0,left=150,top=200');
    }

    return openedWindow;
}

WindowUtils.showSample = function(width, height, src)
{
    var win = this.newWindow(src, height, width);
    win.document.body.style.margin = 0;
    win.document.body.style.padding = 0;
    win.document.title = "Spoke Software";
    win.focus();
    win.title = "Spoke Software";
}

WindowUtils.newWindowAndFocus = function (url, height, width) {
    var theWindow = this.newWindow(url, height, width);
    theWindow.focus();
}

// Close the window.  Works for Firefox 1.x and IE6, IE7; need to test in FF 2.0.
// win - the window to close
WindowUtils.closeWindow = function (win) {
    win.open('', '_parent', '');
    win.close();
}

// Picker support

WindowUtils.openPicker = function (type, id, memberId, companyId, columnKeyKey, preload)
{
    var self = this;
    var uri = '/secure/search/picker/load.spoke?pickerType=' + type + '&regCode=' + id;

    if (memberId != null && memberId != "undefined" && memberId.length != 0) {
        uri += '&criteria.memberId=' + memberId;
    }
    if (companyId != null && companyId != "undefined" && companyId.length != 0) {
        uri += '&criteria.companyId=' + companyId;
    }
    if (columnKeyKey != null && columnKeyKey != "undefined" && columnKeyKey.length != 0) {
        uri += '&columnKeyKey=' + columnKeyKey;
    }
    if (preload != null && preload != "undefined" && preload.length != 0) {
        uri += '&preload=' + preload;
    }
    self.openWindow('spokePicker', uri, 700, 700, true);
}

WindowUtils.openCompanyPicker = function (preloadCompanyName, id)
{
    var self = this;
    var uri = '/secure/picker/companyPicker.spoke?regCode=' + id;

    if (preloadCompanyName != null && preloadCompanyName != "undefined" && preloadCompanyName.length != 0) {
        uri += '&searchName=' + preloadCompanyName;
    }
    self.openWindow('spokePicker', uri, 700, 700, true);
}

function pickerCallback (selectedObjs, id, picker) {
    if (selectedObjs != null && selectedObjs.length != 0) {
        if (pickerListener != null && pickerListener != "undefined")
            pickerListener(selectedObjs, id);
    }
    picker.close();
}

///////////////////////////////////////////////// Animation Utilities ////////////////////////////////////////////////

var AnimationUtils = new Object();
AnimationUtils.fadeInterval = new Array();

AnimationUtils.fadeIn = function (d, start, end) {
    var c = d + "Count";
    if (window[c] === undefined) {
        window[c] = start;
    }
    window[c] += (end - start)/10;
    var fadeCount = window[c];

    var elem = document.getElementById(d);
    if (fadeCount >= 100) {
        clearInterval(this.fadeInterval[d]);
            elem.style.MozOpacity="0.999";
            elem.style.filter="alpha(opacity=100)";
    } else if (fadeCount >= end) {
        clearInterval(this.fadeInterval[d]);
            elem.style.MozOpacity=""+fadeCount/100;
            elem.style.filter="alpha(opacity="+fadeCount+")";
    } else {
            elem.style.MozOpacity=""+fadeCount/100;
            elem.style.filter="alpha(opacity="+fadeCount+")";
    }
}

AnimationUtils.startFadeIn = function(tagName, interval, callBack)
{
    this.fadeInterval[tagName] = setInterval(callBack, interval);
}

AnimationUtils.completeFade = function(elem) {
    elem.style.MozOpacity="0.999";
    elem.style.filter="alpha(opacity=100)";
}

AnimationUtils.noFade = function(elem) {
    elem.style.MozOpacity="0.0";
    elem.style.filter="alpha(opacity=0)";
}

AnimationUtils.showLoading = function ()
{
    var elem = document.getElementById("loading");
    elem.style.display = "block";

    this.startFadeIn('loading', 15,
            function() {
                AnimationUtils.fadeIn('loading', 0, 75);
            });
}

AnimationUtils.loading = function (elem, timeout)
{
    if (timeout == null)
    {
        timeout = 200;
    }

    var containerDiv = DomUtils.getContainerDiv(elem);

    if (elem != null && containerDiv == null)
    {
        window.setTimeout(function() { AnimationUtils.showLoading() }, timeout);
    }
}

AnimationUtils.unloading = function ()
{
    var elem = document.getElementById("loading");
    if (elem != null)
    {
        elem.style.display = "none";
        AnimationUtils.completeFade(elem);
    }
}

///////////////////////////////////////////////// Misc Utilities ////////////////////////////////////////////////
var MiscUtils = new Object();
MiscUtils.logout = function (evt, rememberMe)
{
    if (rememberMe == "true")
    {
        var answer = confirm("This will log you out of Spoke. To return to Spoke, you will have to enter your username and password");
        if (!answer)
        {
            if (!evt)
                evt = window.event;
            evt.cancelBubble = true;
        }
        return answer;
    }
    return true;
}

//tab support for nav tabs
MiscUtils.navTabMouseOver = function (evt) {
    if (!evt)
    {
        evt = window.event;
    }

    var elem = evt.srcElement || evt.target;
    if (elem.parentNode.className.indexOf ("activeTab") < 0 && elem.parentNode.className.indexOf ("disabled") < 0) {
//        elem.className = "forceHover";
        elem.parentNode.className = "forceHover";
        //change the style of the tab
    }
}

MiscUtils.navTabMouseOut = function (evt) {
    if (!evt)
    {
        evt = window.event;
    }

    var elem = evt.srcElement || evt.target;
    if (elem.parentNode.className.indexOf ("activeTab") < 0 && elem.parentNode.className.indexOf ("disabled") < 0) {
//        elem.className = "forceOut";
        elem.parentNode.className = "forceOut";
        //change the style of the tab
    }
}


MiscUtils.moreOrLess = function(togglerId, contentId, moreLabel, lessLabel)
{
    var toggler = document.getElementById(togglerId);
    var content = document.getElementById(contentId);
    if (content.style.display == "none")
    {
        content.style.display = '';
        toggler.childNodes[0].data = lessLabel;
    }
    else
    {
        content.style.display = 'none';
        toggler.childNodes[0].data = moreLabel;
    }
}

// Fix the flickering problem for < ie7
// @see http://www.mister-pixel.com/#Content__state=is_that_simple
function fixIEFlicker()
{
    if (document.execCommand && BrowserSniffer.is_ie && !BrowserSniffer.is_ie7)
    {
        try
        {
            document.execCommand("BackgroundImageCache",false,true);
        }
        catch (e)
        {
//            alert(e)
        }
    }
}
