//###############################################################################
//# Copyright© 2000-2009, Overnite Software Inc.
//###############################################################################
//# Warning: This program is protected by copyright law and international
//# treaties. Unauthorized reproduction or distribution of this program, or any
//# portion of it, may result in severe civil and criminal penalties, and will
//# be prosecuted to the maximum extent possible under law.
//###############################################################################
//# Common Javascript Routines
//###############################################################################
//# Revision History
//# init   date   rev modifications
//# ---- -------- --- ----------------------------------------------------------
//# crh  01/25/00 001 ParseURL function
//# crh  02/02/00 002 Added better handling for timeout.
//# jar  08/13/00 003 Changed crc32tab to signed dec instead of hex (Mac JS needed it)
//# kpc  07/07/06 372 Added https as valid URL protocol.
//# kpc  08/02/06 004 Allowed ChkNull to work on Drop Downs.
//# kjh  12/07/06 372 Changed cmd qc to pm (proof mode) because qc was too well known.
//# kpc  12/14/07 400 #1044 Fixed the TestURL function for GRP_RUN / GRP_HOME
//# kjh  01/18/08 400 #1204 Fix Quotes when open window
//# kpc  02/20/08 400 #1155 Corrected Format Date to handle 2 digit years
//# kpc  02/25/08 400 #881 Fixed TBGetObject for Firefox, and MOC
//# kpc  02/28/08 400 #1332 Fixed popup tracking with GetMouseLocation function
//# kpc  03/14/08 400 #1481 Fixed the IsValidDate and IsValidTime functions to allow nulls
//# kpc  03/17/08 400 #984 Added a character limit(14) to the number validation functions
//# kpc  04/03/08 400 #1551 Fixed the ChkDateRange and ChkIntRange functions for From/To fields
//# kpc  04/08/08 400 #1537 Changed the way the validation functions work
//#                   ( IsFloat, IsInteger, IsValidDate, IsValidTime, ChkDateRange, ChkIntRange )
//#                   Removed the popup for improper format, and red fielded on check
//#                   Removed the 14 character limit from int and float, moved it to the field maxlength.
//# kpc  04/21/08 401 #1613 Changed the way freq fields are checked (no more than 120 months)
//# kpc  05/07/08 401 #1692 Fixed erroneous red field on FT_FREQ
//# kpc  05/07/08 401 #1700 Made a change to the OpenFKEdit function to allow null values to be passed.
//# kpc  05/08/08 401 #1711 Added the RQ param to the OpenSearch, OpenFKSearch, and OpenPKSearch
//# kpc  05/23/08 401 #1735 Added flash uploader
//# kjh  06/12/08 401 #1446 Added OpenAdminSupport
//# kjh  06/20/08 401 #1881 Pass error object when UploadFile complete
//# kpc  08/22/08 401 #1869 Added the SubmitHalt function to stop safari from posting
//# kpc  09/17/08 401 #2176 Fixed the ability to uncheck items after they have been saved to global array
//# kpc  09/25/08 401 #2203 Fixed the ChkNull for file fields
//# kjh  11/03/08 401 #2312 Removed hardcoded http://
//# kpc  01/08/09 401 #2653 Fixed IsValidInteger function range check.
//# kpc  02/23/09 401 #2862 Fixed IsValidFreq.
//# kpc  02/27/09 401 #2894 Fixed IsValidDate for FireFox.
//# kpc  03/03/09 401 #2905 Fixed uploader for http addresses
//# kpc  03/19/09 401 #2786 Added functions for supporting utf8
//# kpc  03/26/09 401 #2993 Changed the TestURL to use the Launch Redirect
//# kpc  03/30/09 401 #3000 Fixed issue with PageNext and PageGoto with SEARCH Value
//# kpc  04/13/09 401 #1812 Added AudioControl for audio playback
//# kpc  05/07/09 401 #3169 Added anything file type.
//# kpc  05/19/09 401 #3232 Fixed filename characters on the js side.
//# kpc  05/27/09 401 #3258 Fixed unlink/upload issue
//# kpc  06/25/09 401 Added Set Cursor function to Replace HourGlassOn and HousrGlassOff functions.
//# kpc  06/29/09 401 #2672 Changed OpenAdminSupport function
//# kpc  06/26/09 401 #2625 Added FCK fields to the SubmitCheck
//# kpc  08/03/09 401 #3464 Fixed IsValidDate for international dates
//# kpc  09/08/09 401 #3537 Fixed the child window timeout.
//###############################################################################

var cjs_ver = "1.5";
var current_user = 0;
var script_path = "";
var script_name = "";
var script_extn = "";
var virt_syspath = "";
var virt_mbopath = "";
var cookiePrefix = "";
var brUnknown   = 0;            // Unknown
var brNS            = 1;        // Netscape
var brIE            = 2;        // Internet Explorer
var nBrowser = brUnknown;       // 0 = NA, 1 = NS, 2 = IE
var nBrowserVersion = 0;
var aWindowList = new Array();
var req_fld = new Array();
var CatFields = new Array();
var bLoaded = false;
var bEuroDate = false;
var bDebug = false;

var DATA_SEP = "##";
var TEXT_SEP = "&&";

var sItemExists = "Item (%0) already exists in list!";
var sInvalidNumber = "Invalid number (%0) entered! Restore to original value?" ;
var sOutofRange = "Number (%0) out of range! Must be between %0 and %1.  Restore to original value?";
var sInvalidDate = "Invalid date (%0) entered!  Restore to original value?";
var sInvalidTime = "Invalid time (%0) entered!  Restore to original value?";
var sInvalidFreq = "Invalid or missing frequency value. Restore to original value?";
var sUniqueIdentifier = "The %0 is the unique identifier for this record. Are you sure you want to change it from %1 to %2?";
var sNetIEPrintlink = "Print link is for Netscape users.  Internet Explorer users, right-click on an open area of the document and select Print from the menu.";
var sNoFutureDates = "Future dates (%0) not allowed.  Restore to original value?";

function Logout()
{
  if( window.opener ) // if child window then close this
    window.close();
  else
  {
    document.global.command.value = "LOGOUT";
    document.global.submit();
  }
}

function SetStatus( status )
{
    parent.status = unescape(status);
    return( true );
}

function SwapImage( btn, img, status )
{
  if( document.images )
    document[btn].src = img;

  SetStatus( status );

  return( true );
}

function ArrayHas( array, data )
{
  if( typeof( array ) != 'object' ) return false;
  for ( var i=0;i<array.length;i++ )
  {
    if( array[i] == data ) return true;
  }
  return false;
}
// Parses URL and replaces parameters with correct paths. Also makes
// complete path for browser or redirect
function ParseURL( str, grp ) // REV 001
{
    if( str == null || grp == null || StrTrim( str ) == "" )
        return( null );

    grppath = "";

    // create group pathname if needed
    if( parseInt(grp) > 1 ) grppath = "/g" + PadLeft( grp, 7, "0" );

    str = str.replace( /<GRP_HOME>/g, virt_mbopath + grppath );
    str = str.replace( /<GRP_RUN>/g, virt_mbopath + grppath + "/run" );
    str = str.replace( /<GRP_DNLD>/g, virt_mbopath + grppath + "/download" );
    str = str.replace( /^SPLITVIEW:/gi, virt_syspath + "/html/splitview.htm?" );
    str = str.replace( /^LOADER:/gi, virt_syspath + "/html/loader.htm?" );

    // does it start with a valid protocol ??
    if( !str.match( /^(http:|https:|ftp:|file:|.:|\\\\)/ ) )
    {
        if( str.charAt(0) == "/" ) // from root ?
            str = "http://" + parent.location.hostname + str;
        else
        {
            path = parent.location.href;
            str = path.substr( 0, path.lastIndexOf( "/" ) + 1 ) + str;
        }
    }

    return( str );
}

///////////////////////////////////////////////////////////////////////////////
/// Window Functions
///////////////////////////////////////////////////////////////////////////////

function ScrollToTop()
{
  window.scrollTo(0,0);
}

function WindowName( sName )
{
  return( "mbo_" + sName.toLowerCase() );
}

function GetWindowList()
{
    var sWindows = "";

    for( var i = 0; i < window.length; i++ )
        sWindows += window[i].name + "\r\n";

    return( sWindows );
}

function CloseWindow( nam )
{
  if( nBrowser != 2 ) return;
  var win = "";
  if( nam )
  {
    var win_name = WindowName( nam );
    win = eval("window." + win_name);
  }
  else
  {
    win = window;
  }
  if( win && !win.closed ) win.close();
}

// opens a new window or sets the location for an existing window with the
// same name. preserves the state of an existing window.
function OpenWindow( loc, nam, opt )
{
    var win_name = WindowName( nam );

    // replace \ with \\, ' with \'
    loc = loc.replace( /\\/g, "\\\\" );
    loc = loc.replace( /\'/g, "\\\'" );

    if( eval( "!window." + win_name ) || eval( "window." + win_name + ".closed" ) )
    eval( "window." + win_name + "=window.open( '" + loc + "', '" + win_name + "', '" + opt + "' )" )
  else
    eval( "window." + win_name + ".location = '" + loc + "'" );

  if( eval( "window." + win_name ) && eval( "!window." + win_name + ".closed" ) )
    eval( "window." + win_name + ".focus()" );

    aWindowList[aWindowList.length] = eval( "window." + win_name );
}

var WindowOnLoad = null;
var WindowOnUnload = null;

function DefaultWindowOnLoad()
{
    bLoaded = true;

    if( WindowOnLoad && typeof(WindowOnLoad) == 'function' )
        WindowOnLoad();

    var login_user = parseInt( GetHashValue( "MBOL.UsrInfo", "USERID" ) || 0 );

    if( current_user && current_user != login_user )
        Logout();
}

function DefaultWindowOnUnload()
{
    bLoaded = false;
    for( var i = 0; i < aWindowList.length; i++ )
    {
        var w = aWindowList[i];
        if( w && !w.closed && w.name != 'mbo_download' )
            w.close();
    }
    if( WindowOnUnload && typeof(WindowOnUnload) == 'function' )
        WindowOnUnload();
}

function TestWindow( loc )
{
  var nam = "test";
  w = 700;
  h = 500;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenAdminSupport( loc )
{
  var nam = "mboladmin";
  w = 850;
  h = 650;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenHelp( bkmk )
{
  var loc = virt_syspath + "/help/index.htm?" + self.name + ".htm#" + bkmk;
  var nam = "mbolhelp";
  w = 600;
  h = 400;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenCalendarWindow(date,ctl)
{
  if( date )
  {
    if( typeof( date ) == 'string' && ctl)
      this.dateField = GetPrevCtl(ctl,date);
    else if( typeof( date ) == 'object' )
      this.dateField = date;
  }
  if( !this.dateField ) return;
  var loc = virt_syspath + "/html/calendar.htm?bEuroDate=" + bEuroDate;
  var nam = "calendar";
  w = 375;
  h = 260;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=0,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenDetails( cmd )
{
  var loc = "details." + script_extn + "?do_what=" + cmd;
  var nam = "details";
  w = 640;
  h = 480;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenDetails2( SR_TABLE, PK )
{
  var loc = "details." + script_extn + "?do_what=GENERAL&SR_TABLE=" + SR_TABLE + "&PK=" + PK;
  var nam = "details";
  w = 640;
  h = 480;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

//function OpenSearch( ST, SR, UF, AF, SL, SN, SC, RQ, SV, SR_FIELD, PK, REF_TYPID, DS )
function OpenSearch( ST, SR, UF, AF, SL, SN, SC, RQ, SV, PK_FLD, PK_ID, FK_TID, DS, RT )
{
  if( !ST ) ST = 0;
  if( !SR ) SR = 0;
  if( !UF ) UF = 0;
  if( !AF ) AF = 0;
  if( !SL ) SL = 0;
  if( !SN ) SN = 0;
  if( !SC ) SC = 0;
  if( !RQ ) RQ = 0;
  // added rq - required flag only used for primary key field searches at this time.
  var loc = "search." + script_extn +
                        "?ST=" + ST +
                        "&SR=" + SR +
                        "&UF=" + UF +
                        "&AF=" + AF +
                        "&SL=" + ((SL==null) ? "" : escape(SL)) +
                        "&SN=" + SN +
                        "&SC=" + SC +
                        "&RQ=" + RQ;
  if( SV ) loc += "&SV=" + SV;
  if( PK_ID ) loc += "&PK_ID=" + PK_ID;
//  if( PK ) loc += "&PK=" + PK;
  if( PK_FLD ) loc += "&PK_FLD=" + PK_FLD;
//  if( SR_FIELD ) loc += "&SR_FIELD=" + SR_FIELD;
  if( FK_TID ) loc += "&FK_TID=" + FK_TID;
//  if( REF_TYPID ) loc += "&REF_TYPID=" + REF_TYPID;
  if( DS ) loc += "&do_what=DATASET";
  if( RT ) loc += "&RT="+RT;

  var nam = "search";
  w = 750;
  h = 480;
  x = (screen.availWidth - w) / 2;
  y = (screen.availHeight - h) / 2;
  p = new Array( "screenx=" + x,
                 "screeny=" + y,
                 "left=" + x,
                 "top=" + y,
                 "width=" + w,
                 "height=" + h,
                 "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=0" );
  OpenWindow( loc, nam, p.toString() );
}

function OpenUploadWindow( loc )
{
    var nam = "upload";
    var w = 475;
    var h = 300;
    var x = (screen.availWidth - w) / 2;
    var y = (screen.availHeight - h) / 2;
    var p = new Array( "screenx=" + x,
                                         "screeny=" + y,
                                         "left=" + x,
                                         "top=" + y,
                                         "width=" + w,
                                         "height=" + h,
                                         "resizable=1,toolbar=0,scrollbars=1,menubar=0,status=1" );
    OpenWindow( loc, nam, p.toString() );
}

///////////////////////////////////////////////////////////////////////////////
/// Window Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Dashboard Window Functions
///////////////////////////////////////////////////////////////////////////////
function Rectangle( left, top, width, height )
{
  this.type = "Rectangle";
  this.left = left;
  this.top = top;
  this.width = width;
  this.height = height;
}

function GetAbsolutePosition( obj )
{
  var rct = new Rectangle( 0, 0, obj.offsetWidth, obj.offsetHeight );
  if( obj.x != undefined && obj.y != undefined )
  {
    rct.left = obj.x;
    rct.top = obj.y;
  }
  else
  {
    while( obj )
    {
      rct.top += parseInt( obj.offsetTop );
      rct.left += parseInt( obj.offsetLeft );
      obj = obj.offsetParent;
    }
  }

  return( rct );
}

///////////////////////////////////////////////////////////////////////////////
/// DHTML Window Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Data Modify Functions
///////////////////////////////////////////////////////////////////////////////

function  StrTrim( sz, l )
{
    if( !sz )
        return( "" );
    sz = sz.replace( /^\s+/, "" );
    sz = sz.replace( /\s+$/, "" );
  l = sz.length;
  if( l == null || l == "" )
    l = sz.length;
  return(sz.substring(0,l)); // substr
}

function ParamString( s )
{
    for( var i = 1; i < arguments.length; i++ )
    {
        var tmp = s.replace( "%" + (i-1), arguments[i] );
        while( s != tmp )
        {
            s = tmp;
            tmp = s.replace( "%" + (i-1), arguments[i] );
        }
    }

    return( s );
}

function Encrypt( sz )
{
    var szRet = "";
    for( i = 0; i < sz.length; i++ )
    {
        szRet += String.fromCharCode(sz.charCodeAt(i)+96);
    }
    return( szRet );
}

function Decrypt( sz )
{
    var szRet = "";
    for( i = 0; i < sz.length; i++ )
    {
        szRet += String.fromCharCode(sz.charCodeAt(i)-96);
    }
    return( szRet );
}

function FormatFloat( f, d )
{
    t = f.toString();
    p = t.split(".");
    if( p.length == 1 )
    {
        p[1] = 0;
    }
    p[1] = PadRight( p[1], d, "0" );
    if( p[1].length > d )
    {
      var keep = p[1].substring(0,d);
      var round = p[1].substring(d,(d+1));
      if( round > 4 ) keep++;
      keep = keep.toString();
      if( keep.length > d )
      {
        p[1] = keep.substring(1,(d+1));
        p[0]++;
      }
      else
      {
        p[1] = keep;
      }
    }
    return p.join(".");
}

function PadLeft( sz, cnt, ch )
{
  if( cnt == null || cnt == 0 )
    return( sz );
  if( ch == null || ch == "" )
    ch = " ";
  var retval = "" + sz;
  while( retval.length < cnt )
    retval = ch + retval;
  return( retval );
}

function PadRight( sz, cnt, ch )
{
  if( cnt == null || cnt == 0 )
    return( sz );
  if( ch == null || ch == "" )
    ch = " ";
  var retval = "" + sz;
  while( retval.length < cnt )
    retval = retval + ch;
  return( retval );
}

function DateToStr( dt,tm )
{
  szdt = "";
  if( dt != null )
    {
        if( !bEuroDate )
            szdt += PadLeft( dt.getMonth() + 1, 2, "0" ) + "/" + PadLeft( dt.getDate(), 2, "0" ) + "/";
        else
            szdt += PadLeft( dt.getDate(), 2, "0" ) + "/" + PadLeft( dt.getMonth() + 1, 2, "0" ) + "/";

        szdt += PadLeft( dt.getFullYear(), 4, "0" );
        if( tm )
        {
          szdt += " ";
          szdt += PadLeft( dt.getHours(), 2, "0" ) + ":";
          szdt += PadLeft( dt.getMinutes(), 2, "0" ) + ":";
          szdt += PadLeft( dt.getSeconds(), 2, "0" );
        }
  }
  return( szdt );
}

function TimeToStr( tm )
{
  sztm = "";
  if( tm != null )
    {
    sztm += PadLeft( tm.getHours(), 2, "0" ) + ":";
    sztm += PadLeft( tm.getMinutes(), 2, "0" );
  }
  return( sztm );
}

function StrToDate( s )
{
    var a, t, m, d = null;

    if( s.toLowerCase() == "now" )                  // if string is 'now' then use current date
    {
        d = new Date();
    }
    else                                            // !'now' so split and figure out
    {
        a = s.split( /\/|-/ );                      // might have / or - as delimiter
        if( a.length >= 2 )                         // need at least 2 m/d or d/m
        {
            if( bEuroDate )                         // if sidate then swap month and day for check
            {
                t           = a[0];
                a[0]    = a[1];
                a[1]    = t;
            }
            m = Date.parse( a.join("/") );          // let Date.parse figure it out
            if( !isNaN( m ) )                       // returns NaN if not a valid date
                d = new Date( m );                  // or must be good, set return
        }
    }
    return( d );
}

function StrToTime( s )
{
    var m, d = null;

    if( s.toLowerCase() == "now" )
    {
        d = new Date();
    }
    else
    {
        m = Date.parse( s );
        if( !isNaN( m ) )
            d = new Date( m );
    }

    return( d );
}

var Base64 =
{
  // private property
  _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

  // public method for encoding
  Encode : function (input)
  {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    input = UTF8.Encode(input);

    while (i < input.length)
    {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2))
      {
        enc3 = enc4 = 64;
      }
      else if (isNaN(chr3))
      {
        enc4 = 64;
      }

      output = output +
      this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
      this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

    }

    return output;
  },

  // public method for decoding
  Decode : function (input)
  {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while( i < input.length )
    {
      enc1 = this._keyStr.indexOf(input.charAt(i++));
      enc2 = this._keyStr.indexOf(input.charAt(i++));
      enc3 = this._keyStr.indexOf(input.charAt(i++));
      enc4 = this._keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64)
      {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64)
      {
        output = output + String.fromCharCode(chr3);
      }

    }

    output = UTF8.Decode(output);

    return output;
  }
}

var UTF8 =
{
  // public method for url encoding
  Encode : function (string)
  {
    string += "";
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++)
    {
      var c = string.charCodeAt(n);

      if (c < 128)
      {
        utftext += String.fromCharCode(c);
      }
      else if((c > 127) && (c < 2048))
      {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      }
      else
      {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }

    }

    return utftext;
  },

  // public method for url decoding
  Decode : function (utftext)
  {
    var string = "";
    var i = 0;
    var c = c1 = c2 = 0;

    while ( i < utftext.length )
    {

      c = utftext.charCodeAt(i);

      if (c < 128)
      {
        string += String.fromCharCode(c);
        i++;
      }
      else if((c > 191) && (c < 224))
      {
        c2 = utftext.charCodeAt(i+1);
        string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
        i += 2;
      }
      else
      {
        c2 = utftext.charCodeAt(i+1);
        c3 = utftext.charCodeAt(i+2);
        string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
        i += 3;
      }

    }

    return string;
  }
}

function CRC16UPD(c, crc)
{
  var x;
  c <<= 8;
  for( x = 0; x < 8; x++ )
  {
    if((crc ^ c) & 0x8000)
      crc = (crc << 1) ^ 0x1021;
    else
      crc = (crc << 1);
    c = (c << 1) & 0xFFFF;
    crc = crc & 0xFFFF;
  }
  return( crc )
}

function CRC16STR(s, seed, upper)
{
  var i, crc
  if( upper )
    s = s.toUpperCase();
  crc = seed;
  for( i = 0; i < s.length; i++ )
    crc = CRC16UPD(s.charCodeAt(i), crc);
  return( crc >= (1<<15) ? crc - (1<<16) : crc );
}

///////////////////////////////////////////////////////////////////////////////
// CRC32 function

var crc32tab = new Array(
0, 1996959894, -301047508, -1727442502, 124634137, 1886057615, -379345611, -1637575261,
249268274, 2044508324, -522852066, -1747789432, 162941995, 2125561021, -407360249, -1866523247,
498536548, 1789927666, -205950648, -2067906082, 450548861, 1843258603, -187386543, -2083289657,
325883990, 1684777152, -43845254, -1973040660, 335633487, 1661365465, -99664541, -1928851979,
997073096, 1281953886, -715111964, -1570279054, 1006888145, 1258607687, -770865667, -1526024853,
901097722, 1119000684, -608450090, -1396901568, 853044451, 1172266101, -589951537, -1412350631,
651767980, 1373503546, -925412992, -1076862698, 565507253, 1454621731, -809855591, -1195530993,
671266974, 1594198024, -972236366, -1324619484, 795835527, 1483230225, -1050600021, -1234817731,
1994146192, 31158534, -1731059524, -271249366, 1907459465, 112637215, -1614814043, -390540237,
2013776290, 251722036, -1777751922, -519137256, 2137656763, 141376813, -1855689577, -429695999,
1802195444, 476864866, -2056965928, -228458418, 1812370925, 453092731, -2113342271, -183516073,
1706088902, 314042704, -1950435094, -54949764, 1658658271, 366619977, -1932296973, -69972891,
1303535960, 984961486, -1547960204, -725929758, 1256170817, 1037604311, -1529756563, -740887301,
1131014506, 879679996, -1385723834, -631195440, 1141124467, 855842277, -1442165665, -586318647,
1342533948, 654459306, -1106571248, -921952122, 1466479909, 544179635, -1184443383, -832445281,
1591671054, 702138776, -1328506846, -942167884, 1504918807, 783551873, -1212326853, -1061524307,
-306674912, -1698712650, 62317068, 1957810842, -355121351, -1647151185, 81470997, 1943803523,
-480048366, -1805370492, 225274430, 2053790376, -468791541, -1828061283, 167816743, 2097651377,
-267414716, -2029476910, 503444072, 1762050814, -144550051, -2140837941, 426522225, 1852507879,
-19653770, -1982649376, 282753626, 1742555852, -105259153, -1900089351, 397917763, 1622183637,
-690576408, -1580100738, 953729732, 1340076626, -776247311, -1497606297, 1068828381, 1219638859,
-670225446, -1358292148, 906185462, 1090812512, -547295293, -1469587627, 829329135, 1181335161,
-882789492, -1134132454, 628085408, 1382605366, -871598187, -1156888829, 570562233, 1426400815,
-977650754, -1296233688, 733239954, 1555261956, -1026031705, -1244606671, 752459403, 1541320221,
-1687895376, -328994266, 1969922972, 40735498, -1677130071, -351390145, 1913087877, 83908371,
-1782625662, -491226604, 2075208622, 213261112, -1831694693, -438977011, 2094854071, 198958881,
-2032938284, -237706686, 1759359992, 534414190, -2118248755, -155638181, 1873836001, 414664567,
-2012718362, -15766928, 1711684554, 285281116, -1889165569, -127750551, 1634467795, 376229701,
-1609899400, -686959890, 1308918612, 956543938, -1486412191, -799009033, 1231636301, 1047427035,
-1362007478, -640263460, 1088359270, 936918000, -1447252397, -558129467, 1202900863, 817233897,
-1111625188, -893730166, 1404277552, 615818150, -1160759803, -841546093, 1423857449, 601450431,
-1285129682, -1000256840, 1567103746, 711928724, -1274298825, -1022587231, 1510334235, 755167117);

function CRC32UPD(c, crc)
{
  return( crc32tab[((crc & 0xFFFF) ^ c) & 0xFF] ^ ((crc >> 8) & 0x00FFFFFF) );
}

function CRC32STR( str, upper )
{
  var crc = -1;

    if( upper )
        str = str.toUpperCase();

  for( i = 0; i < str.length; i++ )
    crc = CRC32UPD( str.charCodeAt(i), crc );

 return crc;
}

function CBool( v )
{
    var b = false;
    switch( typeof( v ) )
    {
        case 'boolean':
            b = v;
            break;
        case 'string':
            if( isNaN( parseInt( v ) ) )
                b = ( v.toLowerCase() == 'true' ) ? true : false;
            else
                b = ( parseInt( v ) ) ? true : false;
            break;
        case 'number':
            b = ( v ) ? true : false;
            break;
    }

    return( b );
}

function CInt( v )
{
    var i = 0;
    switch( typeof( v ) )
    {
        case 'boolean':
            i = ( v ) ? -1 : 0;
            break;
        case 'string':
            if( v.toLowerCase() == 'false' )
                i = 0;
            else if( v.toLowerCase() == 'true' )
                i = -1;
            else
                i = parseInt( v );
            break;
        case 'number':
            i = v;
            break;
    }

    return( i );
}

///////////////////////////////////////////////////////////////////////////////
/// Data Modify Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Data Validation Functions
///////////////////////////////////////////////////////////////////////////////

function IsIntInRange( v, a, b )
{
  return( v >= a && v <= b );
}

///////////////////////////////////////////////////////////////////////////////
/// Data Validation Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Search List Functions
///////////////////////////////////////////////////////////////////////////////
function PageNext( n,s )
{
  if( GetValue( 'SV' ) == "" ) SetValue('SEARCH', '');
  SetValue('research', 1);
  var controls = GetFieldControls('CurPage'+s);
  if( controls.length != 1 ) return;
  var pge = parseInt(GetValue(controls[0]));
  SetValue(controls[0],(pge+parseInt(n)));
  SubmitForm( 'PAGE_NEXT',s );
}

function PageGoto( p,s )
{
  if( GetValue( 'SV' ) == "" ) SetValue('SEARCH', '');
  SetValue('research', 1);
  var controls = GetFieldControls('CurPage'+s);
  if( controls.length != 1 ) return;
  SetValue(controls[0],p);
  SubmitForm( 'PAGE_GOTO',s );
}

function PageFilter( nam, typ, fld, val, val2 )
{
  var controls = GetFieldControls( fld )
  if( controls.length != 1 ) return;
  for( var i=0;i<controls.length;i++ )
  {
    switch( typ )
    {
      case 507: // FT_CATID
        if( controls[i].type == 'select-one' )
        {
          var ok = SetValue( controls[i], val );
          if( !ok )
            controls[i].options[controls[i].options.length] = new Option((val,val2),val);
          SetValue( controls[i], val );
        }
        else
        {
          controls[i].value = val;
        }
        break;
      case 500: // FT_FLAGS
      case 501: // FT_VARCHAR
      case 502: // FT_MEMO
      case 503: // FT_FKEY
      case 504: // FT_PKEY
      case 508: // FT_TYPID
      case 509: // FT_BOOL
      case 510: // FT_UPFILE
      case 511: // FT_COMPANY
      case 512: // FT_UPHTTP
      case 513: // FT_GRPID
      case 514: // FT_URL
      case 516: // FT_SELECT
      case 517: // FT_OPN2
      case 515: // FT_FREQ
      case 505: // FT_INTEGER
      case 506: // FT_DATETIME
      case 518: // FT_DATE
      case 519: // FT_TIME
        SetValue( controls[i], val );
        break;
    }
  }
  SetValue(('CurPage'+nam),'');
  SetValue(('CurTotal'+nam),'');
  SubmitForm('FILTERBY');
}

function PageSearch( s )
{
  var ok = true;
  ok = SetValue(('CurPage'+s),'');
  ok = SetValue(('CurTotal'+s),'');
  if( ok && document.getElementsByName('SEARCH') ) ok = SetValue('SV',GetValue('SEARCH'));
  if( ok ) ok = SetValue('openSection','');
  if( ok ) SubmitForm('SRCH');
}

function PageSearchReset( s )
{
  var ok = true;
  ok = SetValue('clrparams',1);
  if( ok ) SubmitForm('CLRSRCH');
}

function PageSave( c,s,a1,a2,a3,a4 )
{
  var params = new Array( c,s );
  SetValue('clrparams',0);
  if( c != 'SAVEALLANDCONTINUE' )
  {
    SetValue('SV','');
    SetValue('SEARCH','');
  }
  SubmitForm( c,s,a1,a2,a3,a4 );
}

function CheckAll( lbl, chkall )
{
  var stat;
  if( typeof( chkall ) == 'boolean' )
  {
    stat = chkall;
  }
  else
  {
    stat = ( chkall.checked ) ? true : false;
  }
  var chk = eval( "document.entryForm."+lbl );
  if( !chk ) return;
  var cnt = 0;
  if( chk.length == null )
  {
    prestat = chk.checked;
    chk.checked = stat;
    if( prestat != stat )
    {
      UpdateChecked( chk, lbl );
    }
  }
  else
  {
    for( i = 0; i <chk.length; i++ )
    {
      prestat = chk[i].checked;
      chk[i].checked = stat;
      if( prestat != stat )
      {
        UpdateChecked( chk[i], lbl );
      }
    }
  }
}

function UpdateChecked( chk, lbl )
{
  var fm = document.entryForm;
  var fld = eval( "document.entryForm.ChkCount"+lbl );
  if( !fld ) return;
  var cnt = parseInt( fld.value );
  if( 2 == 1 )
  {
    cnt = 0;
  }
  if( chk )
  {
    cnt += ( chk.checked ) ? 1 : -1;
    fld.value = cnt;
    if( !chk.checked )
    {
      UncheckChecked( chk.value, lbl );
    }
  }
  if( TBGetObject( document, ("lbl_chkd"+lbl) ) )
  {
    TBSetText( document, ("lbl_chkd"+lbl), ParamString( "%0 selected", cnt ) );
  }
}

function UncheckChecked( val, lbl )
{
  var fm = document.entryForm;
  var fld = eval( "document.entryForm.Checked"+lbl );
  if( !fld || !fld.value.length ) return;
  var chkarray = fld.value.split(',');
  var newarray = new Array();
  for( var i=0; i<chkarray.length; i++ )
  {
    if( chkarray[i] != val ) newarray[newarray.length] = chkarray[i];
  }
  fld.value = newarray.join(',');
}

///////////////////////////////////////////////////////////////////////////////
/// Form Field Functions
///////////////////////////////////////////////////////////////////////////////

this.searchInfoLabel  = null;
this.searchInfoData   = null;
this.searchInfoApplet = null;
this.searchInfoPrefix = '';

function SetupFKSearch( prefix, st, sr, uf, af, sl, sn, sc, rq )
{
  this.searchInfoLabel = prefix+"Title";
  this.searchInfoData = prefix+"ID";
  this.searchInfoFunc = SetFKInfo; OpenSearch( st, sr, uf, af, sl, sn, sc, rq );
}

function SetFKInfo( cnt, txt )
{
  if(this.searchInfoData) TBSetText( document, this.searchInfoData, cnt );
  if(this.searchInfoLabel) TBSetText( document, this.searchInfoLabel, txt );
}

function SetupPKSearch( prefix, st, sr, uf, af, sl, sn, sc, rq, ds )
{
  // added the rq had to modify the !ds call
  this.searchInfoLabel = prefix+"Title";
  this.searchInfoData  = prefix+"ID";
  this.searchInfoFunc = SetPKInfo;
  if( ds ) OpenSearch( st, sr, uf, af, sl, sn, sc, rq, '', '', '', '', ds );
  if( !ds ) OpenSearch( st, sr, uf, af, sl, sn, sc, rq );
}

function SetPKInfo( cnt, txt )
{
  if(this.searchInfoData) TBSetText( document, this.searchInfoData, cnt );
  if(this.searchInfoLabel) TBSetText( document, this.searchInfoLabel, txt );
}

function OpenFKEdit( loc, ctl, btn )
{
  if( typeof( ctl ) == 'string' && btn )
    ctl = GetPrevCtl( btn,ctl );
  var val = GetValue(ctl);
  loc = ParamString( loc, val );
  OpenWindow( loc, 'edit', 'scrollbars=yes,resizable=yes,menubar=yes');
}

function TestURL( fld, grp )
{
  var loc = null;
  fld = eval( 'document.entryForm.'+fld );
  if( !fld ) return;
  loc = unescape(fld.value);
  cmp = eval( 'document.entryForm.'+grp+'CompID' );
  grp = eval( 'document.entryForm.'+grp+'GrpID' );
  if( cmp ) cmp = cmp.value;
  else cmp = false;
  if( grp ) grp = grp.value;
  else grp = false;
  if( loc.match( /^lmscript:/ ) )
  {
    loc = "launch."+script_extn+"?do_what=REDIRECT,0,"+escape(loc);
  }
  if( cmp ) loc = ParseURL( loc, cmp );
  if( !cmp && grp ) loc = ParseURL( loc, grp );
  if( loc )
  {
    TestWindow( "launch."+script_extn+"?do_what=REDIRECT,0,"+escape(loc) );
  }
}

var  AudioControl_Error    = -1;
var  AudioControl_Loading  = 0;
var  AudioControl_Playing  = 1;
var  AudioControl_Paused   = 2;
var  AudioControl_Stopped  = 3;

function AudioControl( cmd, name, ctrl )
{
  var siblings = GetSiblings(ctrl);
  var file = "";
  for( var i=0; i<siblings.length; i++ )
  {
    if( siblings[i].name == name+"_thumb" )
    {
      file = escape(siblings[i].value);
    }
  }
  var swf = ( navigator.appName.indexOf("Microsoft") != -1 ) ? document.getElementById('audioplayer') : document['audioplayer'];
  switch( cmd )
  {
    case "PLAY":
      try
      {
        switch( swf.App_GetStatus() )
        {
          case AudioControl_Paused:
            swf.App_Resume();
            break;
          case AudioControl_Playing:
            break;
          default:
            if( file ) swf.App_Load( file, true );
            swf.App_Play();
            break;
        }
      }
      catch( e )
      {
      }
      break;
    case "STOP":
      try
      {
        swf.App_Stop();
      }
      catch( e )
      {
      }
      break;
  }
}

function ChkDateTimeRange( nam )
{
  var date0 = null;
  var date1 = null;
  var d1 = eval( 'document.entryForm.da'+nam );
  var d2 = eval( 'document.entryForm.db'+nam );
  var t1 = eval( 'document.entryForm.ta'+nam );
  var t2 = eval( 'document.entryForm.tb'+nam );
  if( !(d1 && d2) && !(t1 && t2) ) return true;
  var dtnow = new Date();
  var valid = true;
  var limit = GetTableFieldLimit(nam,518);
  var noFutureDate = ( limit && limit.DATENOFUT && limit.DATENOFUT == 1 ) ? 1 : 0;
  var noPastDate = ( limit && limit.DATENOPST && limit.DATENOPST == 1 ) ? 1 : 0;
  if( d1 )
  {
    if( IsValidDate( d1,noFutureDate,noPastDate ) && d1.value.length )
    {
      var adt = d1.value.split( /\/|-/ );
      if( adt[2] == null ) adt[2] = dtnow.getFullYear();
      else if( adt[2] < 50 ) adt[2] = 2000 + parseInt(adt[2]);
      else if( adt[2] < 100 ) adt[2] = 1900 + parseInt(adt[2]);
      if( bEuroDate )
      {
        var tmp = adt[0];
        adt[0]  = adt[1];
        adt[1]  = tmp;
      }
      date0 = Date.parse( adt.join("/") );
    }
  }
  if( d2 )
  {
    if( IsValidDate( d2,noFutureDate,noPastDate ) && d2.value.length )
    {
      var adt = d2.value.split( /\/|-/ );
      if( adt[2] == null ) adt[2] = dtnow.getFullYear();
      else if( adt[2] < 50 ) adt[2] = 2000 + parseInt(adt[2]);
      else if( adt[2] < 100 ) adt[2] = 1900 + parseInt(adt[2]);
      if( bEuroDate )
      {
        var tmp = adt[0];
        adt[0]  = adt[1];
        adt[1]  = tmp;
      }
      date1 = Date.parse( adt.join("/") );
    }
  }
  if( t1 )
  {
    if( IsValidTime( t1 ) && t1.value.length )
    {
      var atm = t1.value.split( /:/ );
      atm[0] *= 1200;
      atm[1] *= 60;
      date0 += (atm[0]+atm[1]);
    }
  }
  if( t2 )
  {
    if( IsValidTime( t2 ) && t2.value.length )
    {
      var atm = t2.value.split( /:/ );
      atm[0] *= 1200;
      atm[1] *= 60;
      date1 += (atm[0]+atm[1]);
    }
  }
  if( date0 > date1 && date1 > 0 )
  {
    valid = false;
    alert( sInvalidRange );
    if( d1 ) IsValid( d1, false );
    if( d2 ) IsValid( d2, false );
    if( t1 ) IsValid( t1, false );
    if( t2 ) IsValid( t2, false );
  }
  return valid;
}

function ChkIntRange( nam )
{
  var intlo = eval( 'document.entryForm.a'+nam );
  var inthi = eval( 'document.entryForm.b'+nam );
  if( !(intlo && inthi) ) return true;
  var valid = true;
  var limit = GetTableFieldLimit(nam,505);
  var decimals = ( limit.INTDEC ) ? limit.INTDEC : 0;
  var lval = ( limit.INTMIN ) ? limit.INTMIN : 0;
  var uval = ( limit.INTMAX ) ? limit.INTMAX : 100;
  if( valid ) valid = IsFloat( intlo, true, decimals, lval, uval );
  if( valid ) valid = IsFloat( inthi, true, decimals, lval, uval );
  if( valid )
  {
    var vallo = GetValue(intlo);
    var valhi = GetValue(inthi);
    if( !Is.Empty(vallo) && !Is.Empty(valhi) )
    {
      if( parseFloat(vallo) > parseFloat(valhi) )
      {
        valid = false;
        alert( sInvalidRange );
        IsValid( intlo, false );
        IsValid( inthi, false );
      }
    }
  }
  return valid;
}

function GrpChange()
{
  for( i = 0; i < CatFields.length; i++ )
  {
    TBSetText( document, CatFields[i]+"Title", sNoneSelected );
    TBSetText( document, CatFields[i]+"ID", 0 );
  }
}

function SetGroup( sGroup, nGroup, nComp )
{
  this.searchInfoLabel = null;
  this.searchInfoData = null;
  var prefix = this.searchInfoPrefix;
  TBSetText( document, prefix+'CompGrpTitle', sGroup );
  TBSetText( document, prefix+'GrpID', nGroup );
  orgCmpID = eval("document.entryForm."+prefix+"CompID.value");
  TBSetText( document, prefix+'CompID', nComp );
  if ( orgCmpID != nComp ) GrpChange();
}

function ClearGroup(prefix,nGroup, nComp)
{
  this.searchInfoPrefix = prefix;
  SetGroup( sNoneSelected,nGroup, nComp );
}

function OpenGroupSelect(x,y)
{
  this.searchInfoPrefix = y;
  z = eval("document.entryForm."+y+"GrpID.value");
  if( !z ) z = 0;
  n = eval("document.entryForm."+y+"CompGrpTitle.value");
//  loc = "groups.pl?do_what=GRP_SELECT," + x + "," + z + "&prefix=" + y;
  loc = "groups.pl?do_what=GRP_MAP," + z + "&prefix=" + y + "&AF=" + x;
  OpenWindow( loc, 'group', 'width=640,height=480,scrollbars=yes' );
}

function ItemsChecked( chk )
{
  if( chk == null ) return( 0 );
  if( chk.length == null ) return ( chk.checked ) ? 1 : 0;
  for( count = 0, i = 0; i < chk.length; i++ )
  {
    count += chk[i].checked;
  }
  return( count );
}

function ChkCategory( fld, typ, af )
{
  var val = GetValue( fld.name );
  if( val == '+' )
  {
    OpenWindow('utility.pl?do_what=UTIL_CATSELECT,'+typ+','+af, 'group','width=550, height=300, scrollbars=yes');
    this.searchInfoLabel = new Array();
    this.searchInfoLabel[0] = fld;
    SetValue( fld.name, 0 );
  }
}

function IsFloat( fld, allowNull, decimals, lval, uval )
{
  var val = GetValue( fld );
  var valid = true;
  if( Is.Empty(val) && !allowNull ) valid = false;
  if( !Is.Empty(val) )
  {
    if( !decimals ) decimals = 2;
    if( isNaN(parseFloat(val)) ) valid = false;
    if( valid )
    {
      val = FormatFloat(parseFloat(val), decimals);
      if( lval != 0 || uval != 0 )
      {
        rangebad = false;
        if( !rangebad ) rangebad = ( lval != null && parseFloat(val) < lval );
        if( !rangebad ) rangebad = ( uval != null && parseFloat(val) > uval );
        if( rangebad )
        {
          alert( ParamString( sOutofRange, val, lval, uval ) );
          valid = false;
        }
      }
    }
  }
  if( valid ) SetValue( fld, val );
  IsValid( fld, valid );
  return valid;
}

function IsInteger( fld, allowNull, lval, uval )
{
  var val = GetValue( fld );
  var valid = true;
  if( Is.Empty(val) && !allowNull ) valid = false;
  if( !Is.Empty( val ) )
  {
    if( isNaN(parseInt(fld.value)) ) valid = false;
    if( valid )
    {
      val = parseInt(val);
      if( lval != 0 || uval != 0 )
      {
        rangebad = false;
        if( !rangebad ) rangebad = ( lval != null && fld.value < lval );
        if( !rangebad ) rangebad = ( uval != null && fld.value > uval );
        if( rangebad )
        {
          alert( ParamString( sOutofRange, val, lval, uval ) );
          valid = false;
        }
      }
    }
  }
  if( valid ) SetValue( fld, val );
  IsValid( fld, valid );
  return valid;
}

function ClearForm(fm)
{
  for( i = 0; i < fm.elements.length; i++ )
  {
    switch( fm.elements[i].type )
    {
      case "text":
      case "textarea":
      case "hidden":
      case "password":
        fm.elements[i].value = "";
        break;
      case "select-one":
        fm.elements[i].selectedIndex = -1;
        break;
      case "checkbox":
      case "radio":
        fm.elements[i].checked = 0;
        break;
    }
  }
}

function SelectValue( lbox, val )
{
  for( i = 0; i < lbox.options.length; i++ )
  {
    if( lbox.options[i].value == val )
    {
      lbox.selectedIndex = i;
      lbox.options[i].defaultSelected = true;
      return true;
    }
  }
  lbox.selectedIndex = -1;
  return false;
}

function LB_DefaultValue( lb )
{
  lb_val = null;
  for( i = 0; i < lb.options.length; i++ )
  {
    if( lb.options[i].defaultSelected )
    {
      lb_val = lb.options[i].value;
      break;
    }
  }
  return( lb_val );
}

function LB_Value( lb )
{
  lb_val = null;
  if( lb.selectedIndex >= 0 ) lb_val = lb.options[lb.selectedIndex].value;
  return( lb_val );
}

function LB_Text( lb )
{
  lb_val = null;
  if( lb.selectedIndex >= 0 ) lb_val = lb.options[lb.selectedIndex].text;
  return( lb_val );
}

function ChkNullAll(ctl)
{
  var ok = false;
  for( var i = 0; i < ctl.length; i++ )
  {
    if( ChkNull(ctl[i]) ) ok = true;
  }
  return( ok );
}

function ChkNull(ctl)
{
  if( ctl.length && ctl.type != "select-one" ) return ChkNullAll(ctl);
  var ok = false;
  switch( ctl.type )
  {
    case "select-one":
      ok = ChkPopup(ctl);
      break;
    case "text":
    case "textarea":
    case "password":
    case "hidden":
    case "file":
      ctl.value = StrTrim(ctl.value);
      ok = (ctl.value.length > 0);
      break;
    case "checkbox":
      ok = (ctl.checked == true);
      break;
  }
  if( !ok )
  {
    switch( ctl.type )
    {
      case "select-one":
      case "text":
      case "textarea":
      case "password":
      case "file":
        if( ctl.style.visibility == 'visible' ) ctl.focus();
    }
  }
  return( ok );
}

function ChkPopup(ctl)
{
  lb_val = LB_Value( ctl );
  var ok = (lb_val != null && lb_val != 0);
  if( !ok ) ctl.focus();
  return( ok );
}

function ChkRequired( fm )
{
  var ok = true;
  for( var i = 0; i < req_fld.length; i++ )
  {
    fld = eval( "fm."+req_fld[i] );
    switch( fld.type )
    {
      case "select-one":
        if( ok ) ok = ChkPopup( fld );
        break;
      case "text":
      case "textarea":
      case "password":
      case "hidden":
        if( ok ) ok = ChkNull( fld );
        break;
      case "checkbox":
        if( ok )
        {
          ok = false;
          for( var n = 0; n < fld.length; n++ )
          {
            if( fld[n].checked == true ) ok = true;
          }
        }
        break;
      case "radio":
        break;
      default:
        alert("Unknown Type: "+ fld.type );
    }
  }
  return( ok );
}

function ChkCode( fld )
{
  var val = GetValue( fld );
  var def = GetValueDefault( fld );
      val = StrTrim(val.toUpperCase());
  var nam = fld.name;
  var valid = true;
  if( !Is.Empty( def ) )
  {
    if( def.toUpperCase() != val ) valid = confirm( ParamString( sUniqueIdentifier, nam, def.toUpperCase(), val ));
    if( !valid ) val = StrTrim( def.toUpperCase() );
  }
  SetValue( fld, val );
  return( valid );
}

function IsValidDate ( fld, noFutureDate, noPastDate )
{
  var val = GetValue( fld );
  var def = GetValueDefault( fld );
  var valid = true;
  if( !Is.Empty(val) )
  {
    val = Format.Date(GetValue( fld ));
    def = Format.Date(GetValueDefault( fld ));
    var today = GetDateObject();
    var now = 0;
    if( bEuroDate )
      now = Format.Date( today.getDate()+'/'+(today.getMonth()+1)+'/'+today.getFullYear() );
    else
      now = Format.Date( (today.getMonth()+1)+'/'+today.getDate()+'/'+today.getFullYear() );
    if( val != def )
    {
      if( val.toUpperCase() == 'NOW' ) val = now;
      if( !Is.Date(val) ) valid = false;
      if( ( noFutureDate == 1 ) && ( Date.parse( GetDateObject(val) ) > Date.parse( today ) ) )
      {
        alert( ParamString( sNoFutureDates, now ) );
        valid = false;
      }
      if( ( noPastDate == 1 ) && ( Date.parse( GetDateObject(val) ) < Date.parse( GetDateObject('01/02/1970') ) ) )
      {
        alert( sNoPastDates );
        valid = false;
      }
    }
  }
  if( valid ) SetValue(fld,val);
  IsValid( fld, valid );
  return valid;
}

function IsValidDateTime ( fld, noFutureDate, noPastDate )
{
  var main = GetFieldControls( fld );
  var date = GetFieldControls( fld+"Date" );
  var time = GetFieldControls( fld+"Time" );
  if( !main.length || main.length != date.length || main.length != time.length ) return true;
  for( var c=0;c<main.length;c++ )
  {
    var ok = true;
    if( ok ) ok = IsValidDate( date[c], noFutureDate, noPastDate );
    if( ok ) ok = IsValidTime( time[c], true );
    SetValue(main[c],(GetValue(date[c])+" "+GetValue(time[c])));
    return ok;
  }
}

function IsValidTime ( fld )
{
  var val = GetValue( fld );
  var def = GetValueDefault( fld );
  var valid = true;
  if( !Is.Empty( val ) )
  {
    val = Format.Time(GetValue( fld ));
    def = Format.Time(GetValueDefault( fld ));
    var now = Format.Time(new Date().toString());
    if( val != def )
    {
      if( val.toUpperCase() == "NOW" ) val = now;
      if( !Is.Time(val) ) valid = false;
    }
  }
  if( valid ) SetValue(fld,val);
  IsValid( fld, valid );
  return valid;
}

function IsValidFreq ( fld, noDone )
{
  var val = GetValue(fld);
  if( !isNaN( parseInt( val ) ) ) val = parseInt( val ) + "";
  val = Format.Freq(val);
  var def = GetValueDefault(fld);
  if( !isNaN( parseInt( def ) ) ) def = parseInt( def ) + "";
  def = Format.Freq(def);
  var valid = true;
  if( !Is.Empty(val) )
  {
    if( Is.Integer(val,0,0) ) return IsInteger( fld, true, 0, 120 );
    if( !Is.Freq(val) ) valid = false;
    if( noDone && val.toUpperCase() == sDone.toUpperCase() )
    {
      alert( sNoDoneFreq );
      valid = false;
    }
  }
  if( valid ) SetValue(fld,val);
  IsValid( fld, valid );
  return valid;
}

function IsValidInteger ( fld, lval, uval, deci )
{
  var val = GetValue( fld );
  var valid = true;
  if( isNaN(parseInt(uval) ) ) uval = 999999999;
  if( !Is.Empty( val ) )
  {
    if( isNaN(parseInt(fld.value)) ) valid = false;
    if( valid )
    {
      if( !isNaN(parseInt(deci)) ) val = FormatFloat(parseFloat(val), deci);
      else val = parseInt(val);
      rangebad = false;
      if( !rangebad ) rangebad = ( !isNaN(parseInt(lval)) && parseFloat(val) < lval );
      if( !rangebad ) rangebad = ( !isNaN(parseInt(uval)) && parseFloat(val) > uval );
      if( rangebad )
      {
        if( isNaN(parseInt(lval)) ) lval = '--';
        if( isNaN(parseInt(uval)) ) uval = '--';
        alert( ParamString( sOutofRange, val, lval, uval ) );
        valid = false;
      }
    }
  }
  if( valid ) SetValue( fld, val );
  IsValid( fld, valid );
  return valid;
}

function IsValidRe ( fld, re ) // using a number?
{
  var val = GetValue( fld );
  var def = GetValueDefault( fld );
  var valid = true;
  if ( !Is.Empty( val ) )
  {
    switch( re )
    {
      case "1":
        valid = Is.Hex(val);
        break;
      case "2":
        valid = Is.EmailAddress(val);
        break;
      case "3":
        valid = Is.ZipCode(val);
        break;
      case "4":
        valid = Is.PhoneNumber(val);
        break;
      case "5":
        valid = Is.State(val);
        break;
      case "6":
        valid = Is.CreditCard(val);
        break;
    }
  }
  IsValid( fld, valid );
  return valid;
}

function GetFieldControls( ctl )
{
  var a = new Array();
  if( typeof( ctl ) == 'string' ) a = document.getElementsByName( ctl );
  if( a.length == 0 ) a[0] = ctl;
  return a;
}

function GetNextCtl( c,ctl )
{
  var p = c.parentNode;
  var s = c.nextSibling;
  var pcount = 0;
  while ( c.nodeName.toUpperCase() != 'BODY' && pcount < 100 )
  {
    var scount = 0;
    while( s && scount < 100 )
    {
      if( s.name && s.name == ctl ) return s;
      var kids = GetAllChildren(s);
      for( var n=0;n<kids.length;n++ )
      {
        if( kids[n].name && kids[n].name == ctl ) return kids[n];
      }
      c = s;
      s = c.nextSibling;
      scount++;
    }
    c = p;
    p = c.parentNode;
    pcount++;
  }
  return false;
}

function GetPrevCtl( c,ctl )
{
  var p = c.parentNode;
  var s = c.previousSibling;
  var pcount = 0;
  while ( c.nodeName.toUpperCase() != 'BODY' && pcount < 100 )
  {
    var scount = 0;
    while( s && scount < 100 )
    {
      if( s.name && s.name == ctl ) return s;
      var kids = GetAllChildren(s);
      for( var n=(kids.length-1);n>=0;n-- )
      {
        if( kids[n].name && kids[n].name == ctl ) return kids[n];
      }
      c = s;
      s = c.previousSibling;
      scount++;
    }
    c = p;
    s = c;
    p = c.parentNode;
    pcount++;
  }
  return false;
}

function GetAllChildren(p)
{
  var kids = GetSiblings(p.firstChild);
  for( var i=0;i<kids.length;i++ )
  {
    if( kids[i].firstChild )
    {
      spliceArray( kids, GetSiblings(kids[i].firstChild), i );
    }
  }
  return kids;
}

function spliceArray( x, y, i )
{
  var narray = new Array();
  for ( var n=0; n<=i; n++ )
  {
    narray[narray.length] = x[n];
  }
  for ( var n=0; n<y.length; n++ )
  {
    narray[narray.length] = y[n];
  }
  for ( var n=(i+1); n<x.length; n++ )
  {
    narray[narray.length] = x[n];
  }
  return narray;
}

function GetPopupText( ctl )
{
  var controls = GetFieldControls( ctl );
  var values = new Array();
  if( controls.length == 0 ) return false;
  for( var i=0;i<controls.length;i++ )
  {
    if( !controls[i].type || controls[i].type != 'select-one' ) continue;
    values[values.length] = controls[i].options[controls[i].selectedIndex].text;
  }
  return values.toString();
}

function GetValue( ctl )
{
  var controls = GetFieldControls( ctl );
  var values = new Array();
  if( controls.length == 0 ) return false;
  for( var i=0; i<controls.length; i++ )
  {
    switch( controls[i].type )
    {
      case "text":
      case "textarea":
      case "hidden":
      case "password":
        values[values.length] = controls[i].value;
        break;
      case "select-one":
        if( controls[i].selectedIndex >= 0 ) values[values.length] = controls[i].options[controls[i].selectedIndex].value;
        break;
      case "radio":
      case "checkbox":
        if( controls[i].checked == true ) values[values.length] = controls[i].value;
        break;
    }
  }
  return values.toString();
}

function GetValueDefault( ctl )
{
  var controls = GetFieldControls( ctl );
  var values = new Array();
  if( controls.length == 0 ) return false;
  for( var i=0; i<controls.length; i++ )
  {
    switch( controls[i].type )
    {
      case "text":
      case "textarea":
      case "hidden":
      case "password":
        values[values.length] = controls[i].defaultValue;
        break;
      case "select-one":
        for( var n = 0; n < controls[i].options.length; n++ )
        {
          if( controls[i].options[n].defaultSelected ) values[values.length] = controls[i].options[n].value;
        }
        break;
      case "radio":
      case "checkbox":
        if( controls[i].defaultChecked == true ) values[values.length] = controls[i].value;
        break;
    }
  }
  return values.toString();
}

function SetUCASE( ctl )
{
  ctl.value = ctl.value.toUpperCase();
}

function SetValue( ctl, val )
{
  var controls = GetFieldControls(ctl);
  var values = new Array();
  if( controls.length == 0 ) return false;
  if( typeof ( val ) == 'string' && controls.length > 1 ) values = val.split(",");
  else values[0] = val;
  if( values.length != controls.length ) return false;
  for( var i=0; i<controls.length; i++ )
  {
    var ctl = controls[i];
    var val = values[i];
    switch( ctl.type )
    {
      case "text":
      case "textarea":
      case "hidden":
      case "password":
        ctl.value = val;
        break;
      case "select-one":
        var foundit = false;
        for( opt = 0; opt < ctl.options.length; opt++ )
        {
          if( ctl.options[opt].value == val )
          {
            ctl.selectedIndex = opt;
            foundit = true;
          }
        }
        if( !foundit ) return false;
        break;
      case "checkbox":
        var vals = new Array();
        val = val.toString();
        vals = val.split(',');
        var ctl = eval( "document.entryForm."+ctl.name );
        if( ctl.length )
        {
          for( cb = 0; cb < ctl.length; cb++ )
          {
            ctl[cb].checked = false;
            for( v = 0; v < vals.length; v++ )
            {
              if( ctl[cb].value == vals[v] ) ctl[cb].checked = true;
            }
          }
        }
        else
        {
          ctl.checked = false;
          for( v = 0; v < vals.length; v++ )
          {
            if( ctl.value == vals[v] ) ctl.checked = true;
          }
        }
        break;
      case "radio":
        var ctl = eval( "document.entryForm."+ctl.name );
        for( rb = 0; rb < ctl.length; rb++ )
        {
          if( ctl[rb].value == val ) ctl[rb].checked = true;
        }
        break;
    }
  }
  return true;
}

function GetSiblings( node )
{
  var narray = new Array();
  if( node ) narray[0] = node;
  while( narray.length > 0 && narray[(narray.length-1)].nextSibling )
  {
    narray[narray.length] = narray[(narray.length-1)].nextSibling;
  }
  return narray;
}

function GetRelatedControl( ctl, name )
{
  var parent = ctl.parentNode;
  var related = false;
  var count = 0;
  while ( parent && ( count < 100 ) )
  {
    var kids = GetSiblings( parent.firstChild );
    for( var i=0;i<kids.length;i++ )
    {
      if( kids[i].name == name )
      {
        related = kids[i];
        break;
      }
    }
    count++;
    parent = parent.parentNode;
  }
  return(related);
}

function GetTableFieldLimit( nam, typ )
{
  for( var i=0;i<tablefieldinfo.length;i++ )
  {
    if( tablefieldinfo[i][0] == nam && tablefieldinfo[i][1] == typ )
    {
      var obj = new Object();
      var data = tablefieldinfo[i][2].split('##');
      for ( var n=0;n<data.length;n++ )
      {
        var tmp = data[n].split("=");
        eval( "obj."+tmp[0]+" = tmp[1]" );
      }
      return obj;
    }
  }
}

function SubmitHalt()
{
  if( navigator.appVersion.toUpperCase().indexOf('SAFARI') > 0 )
  {
    var hassubmit = false;
    for( var i=0; i<document.entryForm.elements.length; i++ )
    {
      if( document.entryForm.elements[i].type == "submit" )
        hassubmit = true;
    }
    if( !hassubmit )
    {
      return false;
    }
  }
}

function SubmitCheck()
{
  var ok = true;
  var used = new Array();
  for( var i=0; i<tablefieldinfo.length; i++ )
  {
    if( typeof( tablefieldinfo[i][0] ) == 'string' )
    {
      if( !ArrayHas( used, tablefieldinfo[i][0] ) )
      {
        used[used.length] = tablefieldinfo[i][0]
      }
      else
      {
        continue;
      }
    }
    var valid = true;
    var type = tablefieldinfo[i][1];
    var limit = tablefieldinfo[i][2].split(",");
    var allowNull = true;
    if( tablefieldinfo[i][3] == 1 ) allowNull = false;
    var controls = GetFieldControls(tablefieldinfo[i][0]);
    if( controls.length == 0 )
    {
      var tst = true;
      switch( type )
      {
        case 505: //FT_INTEGER
          if( typeof( tablefieldinfo[i][0] ) == 'string' ) tst = ChkIntRange( tablefieldinfo[i][0] );
          break;
        case 506: //FT_DATETIME
        case 518: //FT_DATE
        case 519: //FT_TIME
          if( typeof( tablefieldinfo[i][0] ) == 'string' ) tst = ChkDateTimeRange( tablefieldinfo[i][0] );
          break;
      }
      if( ok ) ok = tst;
      continue;
    }
    for( var c=0; c<controls.length; c++ )
    {
      if( controls[c].type == 'radio' || controls[c].type == 'checkbox' )
      {
        var allval = GetValue( controls[c].name );
        if( Is.Empty( allval ) )
        {
          if( allowNull )
            IsValid( controls[c], true );
          else
          {
            IsValid( controls[c], false );
            ok = false;
          }
        }
        continue;
      }
      var val = GetValue(controls[c]);
      if( Is.Empty( val ) )
      {
        if( allowNull )
          IsValid( controls[c], true );
        else
        {
          IsValid( controls[c], false );
          ok = false;
        }
        continue;
      }
      switch( type )
      {
        case 500: // FT_FLAGS
        case 501: // FT_VARCHAR
        case 502: // FT_MEMO
          var maxlength = GetValueFromKey(limit[0],'VARLENGTH');
          if( maxlength && maxlength > 0 )
          {
            valid = ( maxlength >= val.length );
          }
        case 503: // FT_FKEY
          if( limit[0] == '!zero' ) valid = (!Is.Zero(val));
          IsValid( controls[c], valid );
          break;
        case 504: // FT_PKEY
        case 507: // FT_CATID
        case 508: // FT_TYPID
        case 509: // FT_BOOL
        case 510: // FT_UPFILE
        case 511: // FT_COMPANY
        case 512: // FT_UPHTTP
        case 513: // FT_GRPID
        case 514: // FT_URL
        case 516: // FT_SELECT
        case 517: // FT_OPN2
          IsValid( controls[c], true );
        break;
        case 515: // FT_FREQ
          if( !isNaN( parseInt( val ) ) ) val = parseInt( val ) + "";
          val = Format.Freq( val );
          if( GetValueFromKey(limit[0],'FREQDONE') != 1 ) valid = ( val.toUpperCase() != sDone.toUpperCase() );
          if( valid && Is.Integer( val,0,0 ) ) valid = Is.Integer( val,0,120 );
          if( valid )    valid = Is.Freq( val );
          SetValue( controls[c], val );
          IsValid(controls[c], valid);
          break;
        case 505: // FT_INTEGER
          var lval = GetValueFromKey(limit[0],'INTMIN');
          var uval = GetValueFromKey(limit[0],'INTMAX');
          var deci = 0 + GetValueFromKey(limit[0],'INTDEC');
          if( val.length > 14 ) valid = false;
          else
          {
            val = Format.Float( val, deci );
            SetValue( controls[c], val );
            if( deci > 0 )
              valid = Is.Float( val, lval, uval );
            else
              valid = Is.Integer( val, lval, uval );
          }
          IsValid(controls[c], valid);
          break;
        case 506: // FT_DATETIME
          val = Format.DateTime( val );
          SetValue( controls[c], val );
          if( GetValueFromKey(limit[0],'DATENOFUT') == 1 ) valid = Is.PastDateTime( val );
          else valid = Is.DateTime( val );
          dates = GetFieldControls( tablefieldinfo[i][0]+"Date" );
          times = GetFieldControls( tablefieldinfo[i][0]+"Time" );
          IsValid(dates[c], valid);
          IsValid(times[c], valid);
          break;
        case 518: // FT_DATE
          val = Format.Date( val );
          SetValue( controls[c], val );
          if( GetValueFromKey(limit[0],'DATENOFUT') == 1 ) valid = Is.PastDate( val );
          else valid = Is.Date( val );
          IsValid(controls[c], valid);
          break;
        case 519: // FT_TIME
          val = Format.Time( val );
          SetValue( controls[c], val );
          valid = Is.Time( val );
          IsValid(controls[c], valid);
          break;
      }
      if( ok ) ok = valid;
    }
  }
  return ok;
}

function GetValueFromKey( a,k )
{
  if( typeof( a == 'string' ) )
    a = a.split(data_sep);
  for( var i=0; i<a.length; i++ )
  {
    var h = a[i].split('=');
    if( h[0] == k )
      return h[1];
  }
  return '';
}

function GetDateObject( v )
{
  var da = new Array()
  if( v )
  {
    v = v.replace( /-/g, '/' );
    da = v.split('/');
  }
  else
  {
    v = new Date();
    v = (v.getMonth()+1)+'/'+v.getDate()+'/'+v.getFullYear();
  }
  if( da.length == 3 )
  {
    if( bEuroDate )
      v = da[1] + '/' + da[0] + '/' + da[2];
    else
      v = da[0] + '/' + da[1] + '/' + da[2];
  }
  var o = new Date( Date.parse( v ) );
  return o;
}

var Is = {
  Integer : function( s,l,u ) { if( isNaN( parseInt( s ) ) ) return false; if( !isNaN( parseInt( l ) ) && parseInt( l ) > parseInt( s ) ) return false; if( !isNaN( parseInt( u ) ) && parseInt( s ) > parseInt( u ) ) return false; return true; },
  Empty : function( v ) { if( v == null ) return( true ); if( v.length == 0 ) return( true ); return( false ); },
  Zero : function( v ) { if( v == null ) return( true ); if( v.length == 0 ) return( true ); if( v == 0 ) return( true ); return( false ); },
  Float : function( s,l,u ) { if( isNaN( parseFloat( s ) ) ) return false; if( !isNaN( parseFloat( l ) ) && parseFloat( l ) > parseFloat( s ) ) return false; if( !isNaN( parseFloat( u ) ) && parseFloat( s ) > parseFloat( u ) ) return false; return true; },
  Hex: function( s ) { var v = /^(0x|#)?[0-9A-Fa-f]+$/; return( v.test( s ) ); },
  EmailAddress : function( s ) { var v = /^\S+\@\S+\.\S+/; return( v.test( s ) ); },
  ZipCode : function( s ) { var v = /^\d{5}-?(\d{4})?$/; return( v.test( s ) ); },
  PhoneNumber : function( s ) { var v = /^\d{3}[-\/\.]?\d{3}[-\/\.]?\d{4}$/; return( v.test( s ) ); },
  State : function( s ) { var v = /^(A[LKZR]|C[AOT]|D[EC]|FL|GA|HI|I[DLNA]|K[SY]|LA|M[EDAINSOT]|N[EVHJMYCD]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[TA]|W[AVIY])$/; return( v.test( s.toUpperCase() ) ); },
  CreditCard : function( s ) { var rc = false; var v = /^(\d)(\d+)$/; if( v.test( s ) ) { switch( parseInt( RegExp.$1 ) ) { case 3: rc = ( RegExp.$2.length == 14 ); break; case 4: case 5: case 6: rc = ( RegExp.$2.length == 15 ); break; }} return( rc ); },
  Matches : function( s, p ) { var v = new RegExp( p ); return( v.test( s ) ); },
  InputField : function( fm, fldname ) { with( fm ) { for( var f = 0; f < elements.length; f++ ) { if( elements[f].name == fldname ) return( true ); }} return( false ); },
  DateTime : function ( szDateTime ) { szDateTime = szDateTime.replace( /\.\d{3}/, '' ); szDateTime = szDateTime.replace( /-/g, '/' ); var dt = GetDateObject(szDateTime); return( Is.Date(szDateTime) && Is.Time(dt.getHours()+1 +":"+dt.getMinutes()) ); },
  PastDateTime : function ( szDateTime ) { szDateTime = szDateTime.replace( /\.\d{3}/, '' ); szDateTime = szDateTime.replace( /-/g, '/' ); var dt = GetDateObject(szDateTime); return( Is.PastDate(szDateTime) && Is.Time(dt.getHours()+1 +":"+dt.getMinutes()) ); },
  Date : function( szDate ) { var dt = GetDateObject(szDate.replace( /-/g, '/' )); return( !isNaN( dt ) ); },
  PastDate : function( szDate ) { var dt = GetDateObject(szDate.replace( /-/g, '/' )); var dn = GetDateObject(); if( isNaN( dt ) ) return false; if( Date.parse( dt ) > Date.parse( dn ) ) return false; return true; },
  Time : function( szTime ) { var v = /^(\d+):(\d+):?(\d+)?$/; var r = v.test( szTime ); if( r ) { r = ( RegExp.$1 >= 0 && RegExp.$1 <= 23 ) && ( RegExp.$2 >= 0 && RegExp.$2 <= 59 ) && ( !RegExp.$3.length || ( RegExp.$3 >= 0 && RegExp.$3 <= 59 ) ); } return( r );  },
  Freq : function( sz ) { if( !isNaN( parseInt( sz ) ) && parseInt( sz ) > -2 ) return true; if( sz.toUpperCase() == sDone.toUpperCase() || sz.toUpperCase() == sOnce.toUpperCase() ) return true; return false; } };

var Format = {
  Phone : function( p, s )  { var r = p; var v = /^(\d{3})[-\/\.]?(\d{3})[-\/\.]?(\d{4})$/; if( v.test( p ) ) { if( Is.Empty( s ) ) s = ''; r = this.PadLeft( RegExp.$1, 3, 0 ) + s +         this.PadLeft( RegExp.$2, 3, 0 ) + s +         this.PadLeft( RegExp.$3, 4, 0 );    } return( r ); },
  ZipCode : function( p, s ) { var r = p; var v = /^(\d{5})-?(\d{4})?$/;    if( v.test( p ) )     { if( Is.Empty( s ) ) s = ''; r = this.PadLeft( RegExp.$1, 5, 0 );            if( RegExp.$2.length ) r += s + this.PadLeft( RegExp.$2, 4, 0 );     } return( r ); },
  Float : function( f, d ) { var re = new RegExp( /^([+-]?\d+)?\.?(\d+)?$/ ); if( !re.test( f.toString() ) ) return( f ); if( d <= 0 ) return( Math.round( f ).toString() ); var num = RegExp.$1.toString(); var dec = RegExp.$2.toString(); if( dec.length < d ) dec = this.PadRight( dec, d, '0' ); f = Math.round( num + dec.substr( 0, d ) + '.' + dec.substr( d ) ).toString(); num = this.PadLeft( f.substr( 0, f.length - d ), 1, '0' ); dec = this.PadRight( f.substr( f.length - d ), d, '0' ); return( num + '.' + dec ); },
  PadLeft : function( sz, cnt, ch )   { if( cnt == null || cnt == 0 ) return( sz ); if( ch == null || ch == "" ) ch = " "; var retval = "" + sz; while( retval.length < cnt ) retval = ch + retval; return( retval ); },
  PadRight : function( sz, cnt, ch ) { if( cnt == null || cnt == 0 ) return( sz ); if( ch == null || ch == "" ) ch = " "; var retval = "" + sz; while( retval.length < cnt ) retval = retval + ch; return( retval ); },
  Trim : function( sz ) { if( sz != null ) { sz = sz.replace( /^\s+/, "" ); sz = sz.replace( /\s+$/, "" ); } return( sz ); },
  Duration : function ( nSeconds )  {     var dt = new Date( nSeconds * 1000 ); var d2 = new Date( 0 ); var sz = ""; if( dt.getHours() - d2.getHours() ) sz += this.PadLeft( dt.getHours() - d2.getHours(), 2, '0' ) + ':'; sz += this.PadLeft( dt.getMinutes(), 2, '0' ) + ':' +         this.PadLeft( dt.getSeconds(), 2, '0' ); return( sz ); },
  Date : function( szDate ) { var date = szDate.replace( /-/g, '/' ); var darray = date.split( '/' ); if( darray.length == 3 ) { darray[3] = ""; if( darray[2].length > 4 ) { var tmp = darray[2]; darray[2] = tmp.substring(0,tmp.indexOf(' ')); darray[3] = tmp.substring(tmp.indexOf(' ')); } if( darray[2].length < 4  && parseInt(darray[2]) < 50 ) { if( darray[2].length < 2 ) darray[2] = "0"+darray[2]; darray[2] = "20" + darray[2]; } if( darray[2].length < 4  && parseInt(darray[2]) >= 50 ) { darray[2] = "19" + darray[2]; } date = darray[0]+"/"+darray[1]+"/"+darray[2]+darray[3]; } var dt = GetDateObject(date); if( !isNaN( dt ) ) { if( bEuroDate ) szDate =  this.PadLeft( dt.getDate(), 2, '0' ) + '/' + this.PadLeft( (dt.getMonth()+1), 2, '0' ) + '/' + this.PadLeft( dt.getFullYear(), 4, '0' ); else szDate =  this.PadLeft((dt.getMonth()+1),2,'0') + '/' + this.PadLeft(dt.getDate(),2,'0') + '/' + this.PadLeft( dt.getFullYear(), 4, '0' ); } return( szDate ); },
  Time : function( szTime )   { if( Is.Time( szTime ) ) { var v = /^(\d+):(\d+):?(\d+)?$/; if( v.test( szTime ) ) { szTime =  this.PadLeft( RegExp.$1, 2, '0' ) + ':' + this.PadLeft( RegExp.$2, 2, '0' ); if( RegExp.$3.length ) szTime += ':' + this.PadLeft( RegExp.$3, 2, '0' ); } } return( szTime ); },
  DateTime : function( szDateTime ) { szDateTime = szDateTime.replace( /\.\d{3}/, '' ); szDateTime = szDateTime.replace( /-/g, '/' ); var dt = GetDateObject(szDateTime); if( !isNaN( dt ) ) { szDateTime = Format.Date(szDateTime) + " " + Format.Time( dt.getHours()+1 + ":" + dt.getMinutes() ); } return(szDateTime); },
  Freq : function( sz ) { if( Is.Freq ) { sz = sz.toUpperCase(); if( sz == '-1' ) sz = sDone; if( sz == '0' ) sz = sOnce; } return sz; },
  FileName : function( sz ) { if( sz.length ) { sz = sz.replace( /,|%|#|\(|\)|\[|\]/g, '' ); } return( sz ); } };

function IsValid(ctl, good)
{
  var controls = GetFieldControls(ctl);
  var on = true;
  if( controls.length == 0 ) return;
  for( var c=0; c<controls.length; c++ )
  {
    if( controls[c].className == 'hidden' || controls[c].type == 'hidden' )
    {
      var controlname = controls[c].name;
      var prefix = controlname.substring(0, controlname.lastIndexOf('ID'));
          controlname = prefix+"Title";
      var title = GetPrevCtl( controls[c], controlname );
      if( !title && controls[c].name.indexOf('GrpID') > -1 )
      {
        prefix = controls[c].name.substring(0, controls[c].name.lastIndexOf('GrpID'));
        controlname = prefix+"CompGrpTitle";
        title = GetPrevCtl( controls[c], controlname );
      }
      controls[c] = title;
    }
    if( controls[c].type == 'textarea' )
    {
      controls[c] = controls[c].parentNode;
    }
    var cname = controls[c].className;
    if( cname && cname.substring(-3) == 'bad' ) cname = cname.substring(0,cname.lastIndexOf('bad'));
    if( !good )
    {
      cname += "bad";
      var p = controls[c].parentNode;
      var count = 0;
      while( count < 100 )
      {
        if( p.nodeName == 'BODY' ) break;
        p.style.visibility = 'visible';
        p.style.overflow = 'visible';
        if( p.style.height == '1px' ) p.style.height = '100%';
        p = p.parentNode;
      }
    }
    if( on ) on == false;
    controls[c].className = cname;
  }
}

function SubmitOverride(cmd,action)
{
  var fm = document.goTo;
  fm.do_what.value = cmd;
  fm.action = action;
  fm.submit();
}

function SetCursor( cursor )
{
  if( !cursor ) cursor = "auto";
  document.body.style.cursor = cursor;
}

///////////////////////////////////////////////////////////////////////////////
/// Form Field Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Unused Functions
///////////////////////////////////////////////////////////////////////////////
// creates a category item with group id
//function CatItem( aGrpID, aCatID, aCatTitle )
//{
//    this.GrpID = aGrpID;
//    this.CatID = aCatID;
//    this.CatTitle = aCatTitle;
//}
//function CatToArray( )
//{
//    var ret = new Array();
//    ret[ret.length] = this.GrpID;
//    ret[ret.length] = this.CatID;
//    ret[ret.length] = this.CatTitle;
//    return ret;
//}
//CatItem.prototype.toArray = CatToArray;
// refills listbox based upon change in group id
//function CatGrpChange( GrpID, CatLst, CatArray, CatDefault )
//{
//    var stopat = 0;
//    while( CatLst.options.length > stopat )
//    {
//        if( CatLst.options[CatLst.options.length-1].value == 0 )
//            stopat = 1;
//        else
//            CatLst.options[CatLst.options.length-1] = null;
//    }
//  if( !CatDefault )
//    CatDefault = 0;
//    for( i = 0; i < CatArray.length; i++ )
//    {
//        //if( GrpID == 0 || CatArray[i].GrpID == 0 || CatArray[i].GrpID == GrpID )
//        if( GrpID != 0 && ( CatArray[i].GrpID == 0 || CatArray[i].GrpID == GrpID ) )
//        {
//            CatLst.options[CatLst.options.length] =
//                new Option( CatArray[i].CatTitle,
//                    CatArray[i].CatID,
//                    false,
//                    false );
//        }
//    }
//    SelectValue( CatLst, CatDefault );
//    if( CatLst.selectedIndex == -1 )
//        CatLst.selectedIndex = 0;
//    return true;
//}
// adds a new CatItem to the category list if it does not exist already
//function CatAddItem( GrpID, CatLst, CatArray, CatPrompt ) {
//    var newItem = prompt( CatPrompt, "" );
//    newItem = StrTrim( newItem );
//    if( newItem.length )
//    {
//        var newID = 0;
//        for( i = 0; i < CatArray.length; i++ )
//        {
//            if( CatArray[i].CatID < newID )
//                newID = CatArray[i].CatID;
//            if(( CatArray[i].GrpID == GrpID || CatArray[i].GrpID == 0 ) &&
//                    CatArray[i].CatTitle.toUpperCase() == newItem.toUpperCase() )
//            {
//                alert( ParamString( sItemExists, newItem));
//                return false;
//            }
//        }
//        newID--;
//        CatArray[CatArray.length]= new CatItem( GrpID, newID, newItem );
//        CatLst.options[CatLst.options.length] =
//            new Option( newItem, newID, false, true );
//    }
//    return true;
//}
// places new items in catalog array into hidden input box for save
//function CatSaveNewItems( catarray, cathidden )
//{
//    var newItems = new Array();
//    cathidden.value = "";
//    for( i = 0; i < catarray.length; i++ )
//        if( catarray[i].CatID < 0 )
//            newItems[newItems.length] = catarray[i].toArray().join(TEXT_SEP);
//    if( newItems.length )
//        cathidden.value = newItems.join(DATA_SEP);
//}
///////////////////////////////////////////////////////////////////////////////
/// Unused Functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
/// Saving Data Functions
///////////////////////////////////////////////////////////////////////////////

function SetStickyGroup( grp )
{
  if( !grp ) grp = 0;
  var loc = "groups.pl?"
//          + "do_what=GRP_SELECT,0," + grp
          + "do_what=GRP_MAP,"+grp
          + "&STICKY=1"
          + "&AF=0"
          + "&UF=0";
  OpenWindow( loc, 'group', '' );
}

function StickGroup( grp )
{
  fm = document.entryForm;
  SetHashValue( "MBOL.UsrInfo", "STICKY", grp );
  fm.clrparams.value = 1;
  fm.submit();
}

function SavePost()
{
  document.entryForm.saveposttitle.value = prompt("Save Query As:","");
  if( document.entryForm.saveposttitle.value.length > 0 )
    document.entryForm.savepost.value = 1;
}

function SetCookie( name, value, expires )
{
  var sCookie = name + "=" + value;
  sCookie += ";path=/";
  if( expires )
    sCookie += ";expires=" + expires.toUTCString();
  document.cookie = sCookie;
}

function GetCookie( name )
{
  var search = name + "=";
  var offset = 0;
  var end = 0;
  var retval = null;
  if( document.cookie.length > 0 )
  {
    offset = document.cookie.indexOf( search );
    if( offset != -1 )
    {
      end = document.cookie.indexOf(";",offset);
      if( end == -1 )
        end = document.cookie.length;
      offset += search.length;
      retval = document.cookie.substring(offset,end);
    }
  }
  return( retval );
}

function GetHashValue( hash, param )
{
  var hashString = GetCookie( hash );
  if( hashString == null )
    return( null );
  var tempArray = hashString.split( "&" );
  for( i = 0; i < tempArray.length-1; i += 2 )
    if( unescape(tempArray[i]) == param )
      return( Base64.Decode( unescape(tempArray[i+1]) ) );
  return( null );
}

function SetHashValue( hash, param, value )
{
  var bFound = false;
  var hashString = GetCookie( hash );
  if( hashString == null )
    return( false );
  var tempArray = hashString.split( "&" );
  for( i = 0; i < tempArray.length-1; i += 2 )
  {
    if( unescape(tempArray[i]) == param )
    {
      tempArray[i+1] = escape( Base64.Encode( value ) );
      bFound = true;
      break;
    }
  }
  if( !bFound )
  {
    tempArray[tempArray.length] = escape( param );
    tempArray[tempArray.length] = escape( Base64.Encode(value) );
  }
  SetCookie( hash, tempArray.join( "&" ) );
  return( true );
}

///////////////////////////////////////////////////////////////////////////////
/// Saving Data Functions END
///////////////////////////////////////////////////////////////////////////////

// REV 002 use parent to hold variable for timer. fixes frame versions

var mbTimeout = 0;
var mbLastX = 0;
var mbLastY = 0;
var mbLastKeyDown = 0;
var mbType  = null;
var mbLastType = null
var mbString = "";

function ProcessCommand( s )
{
    var i = s.indexOf( '=' );
    if( i < 1 )
        i = s.length;
    var cmd = s.substr( 0, i ).toLowerCase();
    var val = s.substr( i + 1 );
    switch( cmd )
    {
        case "debug":
            SetHashValue( "MBOL.DbgInfo", cmd, CInt( CBool( val ) ) );
            bDebug = CBool( val );
            break;
        case "ccon":
            SetHashValue( "MBOL.DbgInfo", cmd, CInt( CBool( val ) ) );
            break;
        case "showlangkeys":
        case "keys":
            SetHashValue( "MBOL.DbgInfo", "showlangkeys", CInt( CBool( val ) ) );
            break;
        case "showcookie":
            if( bDebug )
                alert( val + ":\n" + GetCookie( val ) );
            break;
        case "runscript":
            if( bDebug )
                eval( prompt( "Enter Script To Run:", "" ) );
            break;
    }
}

function resetWindowTimer()
{
  if( parent.windowTimer )
      clearTimeout( parent.windowTimer );
  parent.windowTimer = null;
  parent.windowTimer = window.setTimeout("Logout()", (mbTimeout * 60 * 1000));
}

function ProcessEvent( e )
{
  var nKeyDown = 0;

  if( mbTimeout > 0 )
  {
    resetWindowTimer();
    if( window.opener && window.opener.windowTimer )
      window.opener.resetWindowTimer();
  }

    if( nBrowser == brNS )
    {
        if( e )
        {
            mbType  = e.type;
            if( mbType == 'mousemove' )
            {
                if( nBrowserVersion < 5 )
                {
                    mbLastX = e.x;
                    mbLastY = e.y;
                }
                else
                {
                    mbLastX = e.screenX;
                    mbLastY = e.screenY;
                }
            }
            else if( mbType ==  'click' )
            {
//                CloseMenu();
                if( menuLit ) LowLightMenu( document, menuLit );
            }
            else if( mbType == 'keypress' )
            {
                nKeyDown = e.which;
            }
        }
    }
    else
    {
        if( window.event )
        {
            mbType  = window.event.type;
            if( mbType == 'mousemove' )
            {
                mbLastX = (window.event.screenX - window.screenLeft)+window.document.documentElement.scrollLeft;
                mbLastY = (window.event.screenY - window.screenTop)+window.document.documentElement.scrollTop;
            }
            else if( mbType ==  'click' )
            {
//                CloseMenu();
                if( menuLit ) LowLightMenu( document, menuLit );
            }
            else if( mbType == 'keypress' )
            {
                nKeyDown = window.event.keyCode;
            }
        }
    }

    if( nKeyDown )
    {
        mbLastKeyDown = nKeyDown;
        if( nKeyDown == 13 )
        {
            ProcessCommand( mbString );
            mbString = "";
        }
        else
        {
            mbString += String.fromCharCode( nKeyDown );
        }
    }

    if( bDebug )
        SetStatus( "TYPE=" + mbType + " COMMAND=" + mbString + " X=" + mbLastX + " Y=" + mbLastY );
}

function GetMouseLocation(e)
{
  var pntx = 0;
  var pnty = 0;
  var tag = null;
  if( e.target )      tag = e.target;     //FireFox
  if( e.srcElement )  tag = e.srcElement; //Internet Explorer
  if( tag.nodeType == 3 )                 //Safari Bug
    tag = tag.parentNode;
  var tscroll = 0;
  var lscroll = 0;
  if( document.pageXOffset )
  {
    tscroll = document.pageYOffset;
    lscroll = document.pageXOffset;
  }
  else
  {
    tscroll = document.body.scrollTop;
    lscroll = document.body.scrollLeft;
  }
  var xoff = tag.offsetLeft;
  var xtemp = tag.offsetParent;
  while ( xtemp != null )
  {
    if( xtemp.style && xtemp.style.position.toUpperCase() == 'ABSOLUTE' ) break;
    xoff += xtemp.offsetLeft;
    xtemp = xtemp.offsetParent;
  }
  var yoff = tag.offsetTop;
  var ytemp = tag;
  while ( ytemp != null )
  {
    if( ytemp.style && ytemp.style.position.toUpperCase() == 'ABSOLUTE' ) break;
    yoff += ytemp.offsetTop;
    ytemp = ytemp.offsetParent;
  }
  pntx = xoff;
  pnty = yoff;
  return [pntx,pnty];
}

function SetProgramTimeout( timeout, userid )
{
    // capture events
    if( nBrowser == brNS )
    {
        window.captureEvents( Event.MOUSEMOVE | Event.KEYPRESS );
        window.onmousemove = ProcessEvent;
        window.onkeypress = ProcessEvent;
        window.onclick = ProcessEvent;
//        window.addEventListener('mousemove',ProcessEvent,false);
//        window.addEventListener('keypress',ProcessEvent,false);
//        window.addEventListener('click',ProcessEvent,false);
    }
    else if( nBrowser == brIE )
    {
        document.onmousemove = ProcessEvent;
        document.onkeypress = ProcessEvent;
        document.onclick = ProcessEvent;
    }

    mbTimeout = 0;

    if( userid.length && parseInt( timeout ) > 0 )
    {
        mbTimeout = timeout;
        ProcessEvent();
    }
}

function DoPrint()
{
    if( navigator.appName == "Netscape" )
    {
        window.print()
    }
    else
    {
        alert( sNetIEPrintlink )
    }
}

var menuOpen = '';
///////////////////////////////////////////////////////////////////////////////
// ChangeOrder
///////////////////////////////////////////////////////////////////////////////
function ChangeOrder()
{
  var fld = document.entryForm.SrchOrderTyp;
  switch( fld.value )
  {
    case 'ASC':
      fld.value = 'DESC';
      break;
    case 'DESC':
      fld.value = 'ASC';
      break;
  }
  SubmitForm('SRCH');
}

///////////////////////////////////////////////////////////////////////////////
// ShowDIV
///////////////////////////////////////////////////////////////////////////////
function ShowDIV( n )
{
  obj = TBGetObject( document, n );
  if(obj.style.display == 'none')
  {
    SwapImage( ('btn'+n), gbl_img_arrowdn, '' );
    obj.style.display = 'block';
    if( document.entryForm.openSection )
      document.entryForm.openSection.value = n;
  }
  else
  {
    SwapImage( ('btn'+n), gbl_img_arrowrgt, '' );
    obj.style.display = 'none';
    if( document.entryForm.openSection )
      document.entryForm.openSection.value = '';
  }
}

///////////////////////////////////////////////////////////////////////////////
// LowlightMenu
///////////////////////////////////////////////////////////////////////////////
function LowLightMenu( oDoc, sName )
{
    if( sName == menuOpen ) return;
    tobj = TBGetObject( oDoc, "TBTAB_"+sName );
    tobj.style.backgroundColor = sCLR_HDRBG;
    tobj.style.color = sCLR_HDRTX;
    menuLit = '';
}

///////////////////////////////////////////////////////////////////////////////
// HighlightMenu
///////////////////////////////////////////////////////////////////////////////
function HighLightMenu( oDoc, sName )
{
    if( menuOpen.length && menuOpen != sName ) return;
    tobj = TBGetObject( oDoc, "TBTAB_"+sName );
    tobj.style.backgroundColor = sCLR_HLIGHT0;
    tobj.style.color = sCLR_TX;
    if( menuLit.length && menuLit != sName )
      LowLightMenu( oDoc, menuLit );
    menuLit = sName;
}

///////////////////////////////////////////////////////////////////////////////
// OpenMenu
///////////////////////////////////////////////////////////////////////////////
function OpenMenu( oDoc, sName )
{
//  document.getElementById(sName).style.visibility="visible";
    mobj = TBGetObject( oDoc, "TB_"+sName );
    mobj.style.display = 'block';
    if( menuOpen.length && menuOpen != sName ) CloseMenu();
    menuOpen = sName;
    HighLightMenu( oDoc, sName );
}

var menuLit = "";

///////////////////////////////////////////////////////////////////////////////
// CloseMenu
///////////////////////////////////////////////////////////////////////////////
function CloseMenu()
{
//  document.getElementById(menuOpen).style.visibility="hidden";
    if( !menuOpen ) return;
    tobj = TBGetObject( document, "TBTAB_"+menuOpen );
    tobj.style.backgroundColor = sCLR_HDRBG;
    tobj.style.color = sCLR_HDRTX;
    mobj = TBGetObject( document, "TB_"+menuOpen );
    mobj.style.display = 'none';
    menuOpen = '';
}

function SetMenu( name, label, value, onchange )
{
  var deflabel = eval("document.entryForm.LB_"+name+".value");
  eval("document.entryForm.LB_"+name+".value = label");
  eval("document.entryForm."+name+".value = value");
  CloseMenu();
  if( onchange && deflabel != label )
  {
    eval(onchange);
  }
}

function HlightMenu(name)
{
  obj = TBGetObject( document, name );
  obj.style.backgroundColor = sCLR_HLIGHT0;
  obj.style.color = sCLR_TX;
}
function LlightMenu(name)
{
  obj = TBGetObject( document, name );
  obj.style.backgroundColor = "#FFFFFF";
  obj.style.color = "#000000";
}

///////////////////////////////////////////////////////////////////////////////
// RunMenuItem
///////////////////////////////////////////////////////////////////////////////
function RunMenuItem( form, menu )
{
    var action = eval( "document."+form+"."+menu+".options[document."+form+"."+menu+".selectedIndex].value");
    var uAction = action.toUpperCase();
    if( uAction.indexOf("javascript:") >= 0 )
    {
        action = action.substring( 11 );
        eval( action );
    }
    else
    {
        document.location.href = action;
    }
}

///////////////////////////////////////////////////////////////////////////////
// TBGetObject( oDoc, sName )
// Used by this script only to find an existing object.
// returns object if found, otherwise null
///////////////////////////////////////////////////////////////////////////////
function TBGetObject( oDoc, sName )
{
    var obj = null;

    if( oDoc )
    {
        if( nBrowser == brNS && nBrowserVersion < 5 )
        {
            obj = oDoc.layers[sName];
        }
        else if( nBrowser == brIE && nBrowserVersion < 5 )
        {
            obj = oDoc.all[sName];
        }
        else
        {
            obj = oDoc.getElementsByName(sName);
            obj = obj[0];
        }
    }
    return( obj );
}

///////////////////////////////////////////////////////////////////////////////
// TBSetText( oDoc, sName, sText )
// Sets the text of an object.
// returns void
///////////////////////////////////////////////////////////////////////////////
function TBSetText( oDoc, sName, sText, sData )
{
    hobj = eval("document.entryForm."+sName);
    if( nBrowser == brNS && nBrowserVersion < 5 )
    {
        var o = TBGetObject( oDoc, "TB_Outer_" + sName );
        var i = TBGetObject( o.document, "TB_Inner_" + sName );
        var w = o.clip.width;
        var h = o.clip.height;
        var sHTML = "";
        sHTML += "<FONT COLOR=" + i.fgColor;
        sHTML += " >";
        sHTML += sText;
        sHTML += " </FONT>";
        i.document.open();
        i.document.write( sHTML );
        i.document.close();
        i.resizeTo( w, h );
    }
    else
    {
        var obj = TBGetObject( oDoc, "TB_" + sName);
        if( obj != null )
            obj.innerHTML = sText;
    }
    if( hobj )
    {
        if( typeof(sData) != 'undefined' )
        {
            hobj.value = sData;
        }
        else
        {
            hobj.value = sText;
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
// TBGetValue( oDoc, sName, sText )
// returns the value of an object.
///////////////////////////////////////////////////////////////////////////////
function TBGetValue( sName )
{
    hobj = eval("document.entryForm."+sName);

    if( hobj )
    {
        return hobj.value;
    }
    else
    {
        return null;
    }
}

///////////////////////////////////////////////////////////////////////////////
// TBSetAll( oDoc, sName, sBGColor, sFGColor, sText )
// Sets the background, foreground and text of an object.
// returns void
///////////////////////////////////////////////////////////////////////////////
function TBSetAll( oDoc, sName, sBGColor, sFGColor, sText )
{
    TBSetBackground( oDoc, sName, sBGColor );
    TBSetForeground( oDoc, sName, sFGColor );
    TBSetText( oDoc, sName, sText );
}

///////////////////////////////////////////////////////////////////////////////
// TBSetBackground( oDoc, sName, sColor )
// Sets the background color of an object.
// returns void
///////////////////////////////////////////////////////////////////////////////
function TBSetBackground( oDoc, sName, sColor )
{
    var obj = null;

    if( nBrowser == brNS && nBrowserVersion < 5 )
    {
        obj = TBGetObject( oDoc, "TB_Outer_" + sName );
        if( obj != null )
            obj = TBGetObject( obj.document, "TB_Inner_" + sName );
        if( obj != null )
            obj.bgColor = sColor;
    }
    else
    {
        obj = TBGetObject( oDoc, "TB_" + sName );
        if( obj != null )
            obj.style.backgroundColor = sColor;
    }
}

///////////////////////////////////////////////////////////////////////////////
// TBSetForeground( oDoc, sName, sColor )
// Sets the foreground color of an object.
// returns void
///////////////////////////////////////////////////////////////////////////////
function TBSetForeground( oDoc, sName, sColor )
{
    var obj = null;

    if( nBrowser == brNS && nBrowserVersion < 5 )
    {
        obj = TBGetObject( oDoc, "TB_Outer_" + sName );
        if( obj != null )
            obj = TBGetObject( obj.document, "TB_Inner_" + sName );
        if( obj != null )
            obj.fgColor = sColor;
    }
    else
    {
        obj = TBGetObject( oDoc, "TB_" + sName );
        if( obj != null )
            obj.style.color = sColor;
    }
}

///////////////////////////////////////////////////////////////////////////////
/// AJAX communication functions
///////////////////////////////////////////////////////////////////////////////
function FormToURL( fm )
{
  var o = fm.elements;
  var a = new Array();
  for( var i=0; i<o.length; i++ )
  {
    switch( o[i].type )
    {
      case "text":
      case "textarea":
      case "hidden":
      case "password":
        a[a.length] = o[i].name +"="+ escape(o[i].value)
        break;
      case "select-one":
        if( o[i].selectedIndex >= 0 ) a[a.length] = o[i].name +"="+ escape( o[i].options[o[i].selectedIndex].value);
        break;
      case "radio":
      case "checkbox":
        if( o[i].checked == true ) a[a.length] = escape(o[i].value);
        break;
    }
  }
  return a.join('&');
} // FormToArray

function AJAX()
{
  this.Method = "GET";
  this.URL  = "";
  this.Async  = true;
  this.Params = "";

  this.OnChange = function() {};
  this.OnComplete = function() {};
  this.OnError  = function() {};
  this.OnTimeout  = null;
  this.Timeout  = 0;
  this.Data   = null;

  var oRequest = null;
  // need this to hold a reference to this object.
  var me = this;

  if( window.ActiveXObject )
  {
    var XMLHttpVersions =
    [
      'MSXML2.XMLHTTP.6.0',
      'MSXML2.XMLHTTP.5.0',
      'MSXML2.XMLHTTP.4.0',
      'MSXML2.XMLHTTP.3.0',
      'MSXML2.XMLHTTP',
      'Microsoft.XMLHTTP'
    ];

    for( var i = 0; i < XMLHttpVersions.length && !oRequest; i++ )
    {
      try
      {
        oRequest = new ActiveXObject(XMLHttpVersions[i]);
      }
      catch (e)
      {
      }
    }
  }
  else if( window.XMLHttpRequest )
  {
    oRequest = new XMLHttpRequest();
  }

  this.IsValid = function()
  {
    return( oRequest != null );
  };

  this.Send = function()
  {
    oRequest.open( this.Method, this.URL, this.Async );

    switch( this.Method.toUpperCase() )
    {
      case "GET":
        break;

      case "POST":
        //oRequest.setRequestHeader( "Method", "POST "+ this.URL + " HTTP/1.1" );
        oRequest.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
        break;

      default:
        break;
    }

    oRequest.onreadystatechange = function()
    {
      me.OnChange( oRequest, me.Data );
      if( oRequest.readyState == 4 )
      {
        if( oRequest.status == 200 )
        {
          me.OnComplete( oRequest, me.Data );
          if( me.OnTimeout && me.Timeout )
            setTimeout( me.OnTimeout, me.Timeout );
        }
        else
        {
          me.OnError( oRequest, me.Data );
        }
      }
    };

    oRequest.send( this.Params );
  };

  this.SetTimeout = function( afnOnTimeout, anTimeout )
  {
    this.OnTimeout = afnOnTimeout;
    this.Timeout = anTimeout;
  };
} // AJAX

function HourGlassOn()
{
  document.body.style.cursor = 'wait';
} // HourGlassOn

function HourGlassOff()
{
  document.body.style.cursor = 'auto';
} // HourGlassOff

///////////////////////////////////////////////////////////////////////////////
/// AJAX communication functions END
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// PopUp Functions
///////////////////////////////////////////////////////////////////////////////
function SelectCat( typ, flag ) // This function is depreciated
{
  return;
}

function SetCat( id, txt, ctl )
{
  if ( ctl )
  {
    this.searchInfoLabel = GetFieldControls( ctl );
  }
  if( this.searchInfoLabel.length == 0 ) return false;
  for( var i=0; i<this.searchInfoLabel.length; i++ )
  {
    var ctl = this.searchInfoLabel[i];
    if( SetValue( ctl, id ) ) continue;
    for( var opts=0; opts<ctl.options.length; opts++ )
    {
      if( ctl.options[opts].value == "+" && ctl.options[opts+1] ) ctl.options[opts+1] = null;
    }
    ctl.options[ctl.options.length] = new Option( txt, id );
    return SetValue( ctl, id );
  }
}

function setFK( n, s, name )
{
  if( name )
  {
    this.searchInfoLabel = name + 'Title';
    this.searchInfoData = name + 'ID';
  }
  if(this.searchInfoLabel) TBSetText( document, this.searchInfoLabel, s );
  if(this.searchInfoData)  TBSetText( document, this.searchInfoData, n );
}

this.UploadInfoFunc = SetUploadInfo;
this.UploadInfoLabel = null;
this.UploadInfoFile = null;

function SetUploadInfo( nType, sNewFile, sPhysPath )
{
  TBSetText(document, this.UploadInfoLabel, sNewFile );
  if( nType != nUpTypeHttp )
    TBSetText(document, this.UploadInfoFile, sNewFile );
  if( this.UploadInfoSubmit )
    this.UploadInfoSubmit();
}

function UploadDoc( fld, fltr, allow )
{
  var usrid = GetHashValue( 'MBOL.UsrInfo', 'USERID' );
  this.UploadInfoFile = fld+"Uploaded";
  this.UploadInfoLabel = fld;
  var loc = "upload." + script_extn +
            "?do_what=UPLD_FILE" +
            "&FileExts=" + fltr +
            "&Allow=" + allow +
            "&DestPath=<exttemp>/" + usrid

  OpenUploadWindow( loc );
}

function UnlinkDoc( sBasename )
{
  var ctls = GetAllChildren( document.getElementById(sBasename+"_div") );
  var field_name = sBasename.substr(0,sBasename.lastIndexOf('_'));
  var field_uploaded = field_name+"Uploaded";
  var field_unlink = field_name+"Unlink";
  var thumbnail = field_name+"_thumb";
  for( var i=0; i<ctls.length; i++ )
  {
    if( ctls[i].name == field_name ) field_name = ctls[i];
    if( ctls[i].name == field_uploaded ) field_uploaded = ctls[i];
    if( ctls[i].name == field_unlink ) field_unlink = ctls[i];
    if( ctls[i].name == thumbnail ) thumbnail = ctls[i];
  }
  SetValue( field_name, '' );
  SetValue( field_uploaded, '' );
  SetValue( field_unlink, 1 );
  thumbnail.src = gbl_img_noimage;
}

function GetFileMask( type )
{
  var oMask = [];
  switch( type )
  {
    case 'image':
      oMask[oMask.length] = { description: "Image Files", extension: "*.gif;*.jpg;*.jpeg;*.png;*.bmp" };
      break;
    case 'audio':
      oMask[oMask.length] = { description: "MP3 Files", extension: "*.mp3" };
      break;
    case 'music':
      oMask[oMask.length] = { description: "Midi Files", extension: "*.midi" };
      break;
    case 'compressed':
      oMask[oMask.length] = { description: "Compressed Files", extension: "*.zip;*.tar" };
      break;
    case 'scorm':
      oMask[oMask.length] = { description: "SCORM Files", extension: "*.zip" };
      break;
    case 'records':
      oMask[oMask.length] = { description: "Record Files", extension: "*.txt;*.cvs" };
      break;
    case 'terms':
      oMask[oMask.length] = { description: "TERMS Records", extension: "*.t3" };
      break;
    case 'question':
      oMask[oMask.length] = { description: "Question Files", extension: "*.qst" };
      break;
    case 'multimedia':
      oMask[oMask.length] = { description: "Multimedia Files", extension: "*.gif;*.jpg;*.jpeg;*.png;*.bmp;*.swf;*.mov;*.mpeg;*.avi" };
      break;
    case 'anything':
      oMask[oMask.length] = { description: "Files", extension: "*.gif;*.jpg;*.png;*.bmp;*.swf;*.mov;*.mpeg;*.avi;*.pdf;*.xls;*.doc;*.ppt;*.pps;*.txt;*.mp3;*.zip" };
      break;
    default:
      oMask[oMask.length] = { description: "File Types", extention: type };
  }
  return oMask;
}

//function UploadFile( sName, oOptions )
//{
//  var jname = sName+"_js";
//  var sname = sName+"_swf";
//  var uobj = new FileTransfer( jname, sname );
//  uobj.Options = oOptions;
//  uobj.MaxSize = 40 * 1024 * 1024;
//  uobj.AutoUpload = false;
//  uobj.ID = sName;
//  uobj.UploadInfoFile = sName+"Uploaded";
//  uobj.UploadInfoLabel = sName;
//  uobj.Mask = GetFileMask( uobj.Options.EXTS );
//
//  uobj.OnSelect = function(o)
//  {
//    var upload = false;
//    var fn = o.name.substring(0, o.name.lastIndexOf('.'));
//    var fe = o.name.substring(o.name.lastIndexOf('.'));
//        fn = fn.replace(/[%,#,(,),\[,\]]/g,'');
//    if( !this.Options.DSTFILE.length ) this.Options.DSTFILE = fn+fe;
//    var oURL = uobj.Get("URL");
//        oURL += "?";
//        oURL += "DSTFILE="+this.Options.DSTFILE;
//        oURL += "&";
//        oURL += "DSTPATH="+this.Options.DSTPATH;
//    if( o.Mask[0].extension.length )
//    {
//      var exts = o.Mask[0].extension.split(';');
//      for( var i=0; i< exts.length; i++ )
//      {
//        if( exts[i].substring(1).toUpperCase() == fe.toUpperCase() ) upload = true;
//      }
//    }
//    else
//    {
//      upload = true;
//      var exts = ('.exe','.pl','.vbs','.asp','.bat','.com','.scr','.pif');
//      for( var i=0; i< exts.length; i++ )
//      {
//        if( exts[i].toUpperCase() == fe.toUpperCase() ) upload = false;
//      }
//    }
//    if( upload )
//    {
//      this.Upload( oURL );
//    }
//    else
//    {
//      alert( "wrong file type" );
//      this.Cancel();
//    }
//  }
//  uobj.OnOpen = function(o)
//  {
//    var oBar = document.getElementById( o.ID + "_bar" );
//    var oPrg = document.getElementById( o.ID + "_prg" );
//    oBar.style.visibility = 'visible';
//  }
//  uobj.OnProgress = function(o,p,t)
//  {
//    var oBar = document.getElementById( o.ID + "_bar" );
//    var oPrg = document.getElementById( o.ID + "_prg" );
//    oBar.style.visibility = 'visible';
//    oPrg.style.width = parseInt(( p / t ) * 150 ) + "px";
//  }
//  uobj.OnComplete = function(o,bError)
//  {
//    var oBar = document.getElementById( o.ID + "_bar" );
//    var oPrg = document.getElementById( o.ID + "_prg" );
//    oBar.style.visibility = 'hidden';
//    oPrg.style.width = '0px';
//    var dest = o.Options.DSTPATH+o.Options.DSTFILE;
//    TBSetText(document, o.ID, o.name );
//    TBSetText(document, o.ID+"Uploaded", dest );
//    if( o.Options.ONCOMPLETE.length ) eval( o.Options.ONCOMPLETE + "( this, o, bError )" );
//  }
//  uobj.Browse(uobj.Mask);
//}

//function UploadExpand( div, sName )
//{
//  var swf = document.getElementById( "swf_"+sName );
//  var d_rect = GetAbsolutePosition( div );
//  var s_rect = GetAbsolutePosition( swf );
//  var top = d_rect.top - s_rect.top;
//  var left = d_rect.left - s_rect.left;
//  swf.style.top = top;
//  swf.style.left = left;
//  swf.style.width = d_rect.width;
//  swf.style.height = d_rect.height;
//}

function CallUploader( sBasename, oOptions )
{
  var oFileTransfer = GetFileTransfer( sBasename );
  DoFileUpload( oFileTransfer, sBasename, oOptions );
  MoveUploader( oFileTransfer, sBasename, oOptions );
}

function GetFileTransfer( sBasename )
{
  var oFileTransfer = window.FileTransfer[sBasename + "_js"];
  if( !oFileTransfer )
    oFileTransfer = new FileTransfer( sBasename + "_js", sBasename + "_swf" );
  return oFileTransfer;
}

function MoveUploader( oFileTransfer, sBasename, oOptions )
{
  var sSWF = sBasename + "_swf";
  var oSWF = (( document[sSWF] ) ? document[sSWF] : window[sSWF] );
  var oTgt = document.getElementById( sBasename + "_link" );
  var d_rct = GetAbsolutePosition( oTgt );
  var s_rct = GetAbsolutePosition( oSWF );

  if( d_rct.top == s_rct.top && d_rct.left == s_rct.left ) return;

  var top = Math.abs(d_rct.top - s_rct.top);
  var left = d_rct.left - s_rct.left;

  oSWF.style.position = "absolute";
  oSWF.style.zIndex = 20;
  oSWF.style.left = left + "px";
  oSWF.style.top  = top + "px";

  oSWF.style.width = d_rct.width + "px";
//  oSWF.style.width = "400px";
  oSWF.style.height = d_rct.height + "px";
//  oSWF.style.height = "180px";
}

function DoFileUpload( oFileTransfer, sBaseName, oOptions )
{
//  need more info on this ??
//  if( oFileTransfer.GetFileCount() && oFileTransfer.GetFile( 0 ).status < 5 ) return;

  oFileTransfer.Options = oOptions;
  oFileTransfer.MaxSize = 40 * 1024 * 1024;
  oFileTransfer.AutoUpload = true;
  oFileTransfer.ID = sBaseName;
  oFileTransfer.UploadInfoFile = sBaseName+"Uploaded";
  oFileTransfer.UploadInfoLabel = sBaseName;
  oFileTransfer.URL = oOptions.URL+"?DSTPATH="+oOptions.DSTPATH+"&DSTFILE="+oOptions.DSTFILE;

//  how has this changed??
//  oFileTransfer.Mask = GetFileMask( oFileTransfer.Options.EXTS );

  oFileTransfer.OnSelect = function(o)
  {
  }
  oFileTransfer.OnOpen = function(o)
  {
    var oBar = document.getElementById( o.ID + "_bar" );
    if( oBar )
    {
      oBar.style.visibility = 'visible';
      SetBar( ( o.ID + "_bar" ), 0, 1 );
    }
  }
  oFileTransfer.OnProgress = function(o,p,t)
  {
    var oBar = document.getElementById( o.ID + "_bar" );
    if( oBar )
    {
      oBar.style.visibility = 'visible';
      SetBar( ( o.ID + "_bar" ), p, t );
    }
  }
  oFileTransfer.OnComplete = function(o,bError)
  {
    if( !o.Options.DSTFILE.length || o.Options.DSTFILE == 'null' ) o.Options.DSTFILE = o.name;
    o.Options.DSTFILE = Format.FileName( o.Options.DSTFILE );
    // Set Uploader Controls
    var ctls = GetAllChildren( document.getElementById(o.ID+"_div") );
    var field_name = o.ID.substr(0,o.ID.lastIndexOf('_'));
    var field_uploaded = field_name+"Uploaded";
    var field_unlink = field_name+"Unlink";
    var thumbnail = field_name+"_thumb";
    for( var i=0; i<ctls.length; i++ )
    {
      if( ctls[i].name == field_name ) field_name = ctls[i];
      if( ctls[i].name == field_uploaded ) field_uploaded = ctls[i];
      if( ctls[i].name == field_unlink ) field_unlink = ctls[i];
      if( ctls[i].name == thumbnail ) thumbnail = ctls[i];
    }
    if( o.Options.TFINAME && o.Options.EXTS == 'multimedia' )
    {
      var file_ext = o.Options.DSTFILE.substr( o.Options.DSTFILE.lastIndexOf(".") ).toUpperCase();
      switch( file_ext )
      {
        case ".GIF":
        case ".JPG":
        case ".BMP":
        case ".PNG":
          thumbnail.src = o.Options.DSTVIRTPATH+o.Options.DSTFILE;
          break;
      }
    }
    var oBar = document.getElementById( o.ID + "_bar" );
    if( oBar )
    {
      oBar.style.visibility = 'hidden';
    }
    var dest = o.Options.DSTPATH+o.Options.DSTFILE;
    SetValue( field_name, o.Options.DSTFILE );
    SetValue( field_uploaded, o.Options.DSTFILE );
    SetValue( field_unlink, '' );
    if( o.Options.TFINAME && o.Options.EXTS == 'image' )
    {
      thumbnail.src = o.Options.DSTVIRTPATH+o.Options.DSTFILE;
    }
    if( o.Options.TFINAME && o.Options.EXTS == 'audio' )
    {
      thumbnail.value = o.Options.DSTVIRTPATH+o.Options.DSTFILE;
    }
    if( o.Options.ONCOMPLETE.length ) eval( o.Options.ONCOMPLETE + "( this, o, bError )" );
  }
//  this is called by the flash now.
//  oFileTransfer.Browse(oFileTransfer.Mask);

  oFileTransfer.FileMask = GetFileMask( oFileTransfer.Options.EXTS );
//  oFileTransfer.MultiFile = 0;
  oFileTransfer.SetAll();
}

function SetBar( name, count, total )
{
  var oBar = document.getElementById( name );
  if( !oBar || !total || total <= 0 ) return;
  if( !count ) count = 0;
  if( parseInt( count ) > parseInt( total ) )
    count = total;
  var percent = ( parseInt( count ) / parseInt( total ) ) * 100;
  var iBar = oBar.firstChild;
  iBar.style.width = percent+"%";
} // SetBar

///////////////////////////////////////////////////////////////////////////////
// make Date and Time functions (localtime)
///////////////////////////////////////////////////////////////////////////////
function makeDate()
{
    tNow = new Date();
    m = tNow.getMonth();
    m++;
    if( m < 10 )
        m = '0'+m.toString();
    d = tNow.getDate();
    if( d < 10 )
        d = '0'+d.toString();
    y = tNow.getYear();
    sDate = m+'/'+d+'/'+y;
    return sDate;
}

function makeTime()
{
    tNow = new Date();
    h = tNow.getHours();
    if( h < 10 )
        h = '0'+h.toString();
    m = tNow.getMinutes();
    if( m < 10 )
        m = '0'+m.toString();
    s = tNow.getSeconds();
    if( s < 10 )
        s = '0'+s.toString();
    sTime = h+':'+m;
    return sTime;
}

if( navigator.appName == "Netscape" )
{
    nBrowser = brNS;
    nBrowserVersion = parseFloat( navigator.appVersion );
}
else if( navigator.appName == "Microsoft Internet Explorer" )
{
    nBrowser = brIE;
    nBrowserVersion = parseFloat( navigator.appVersion.substr( navigator.appVersion.indexOf( "MSIE " ) + 5 ) );
}
else
{
    nBrowser = brUnknown;
    nBrowserVersion = 0;
}

bDebug = CBool( GetHashValue( "MBOL.DbgInfo", "debug" ) );
