/********************************************************\

\********************************************************/
window.onerror = function( amsg, aurl, aline )
{
  alert(
    "Scripting Error..." +
    "\nMessage: " + amsg +
    "\nURL: " + aurl +
    "\nLine: " + aline );
  return( false );
}

var URL =
{
  // set this so URL.Base knows exactly where the web site is.
  BaseURL : "",

  // returns array of split URL ..
  // 0 = scheme://[/]
  // 1 = server[:port]
  // 2 = /path/file.ext
  // 3 = query string
  // 4 = bookmark
  Parse : function( s )
  {
    // query and bookmark do not include ?#
    var v = /^([A-Za-z]*:[\/]{2,3})?([^\/:]*:?\d*[^\/]?)?(\/[^\?\#]*)?\??([^#]*)?\#?(.*$)?/;
    // query and bookmark include ? #
    //var v = /^([A-Za-z]*:[\/]{2,3})?([^\/:]*:?\d*[^\/]?)?(\/[^\?\#]*)?(\?[^#]*)?(\#.*$)?/;
    // port is seperate
    //var v = /^([A-Za-z]*:[\/]{2,3})?([^\/:]*):?(\d+)?(\/[^\?\#]*)?\??([^#]*)?\#?(.*$)?/;
    var a = v.exec( s );
    if( a )
    {
      a.shift();
      a.scheme  = a[0];
      a.host    = a[1];
      a.path    = a[2];
      a.query   = a[3];
      a.anchor  = a[4];
    }
    return( a );
  },

  Build : function( a )
  {
    s = a[0] + a[1] + a[2];
    if( a[3] )
      s += "?" + a[3];
    if( a[4] )
      s += "#" + a[4];
    return( s );
  },

  Relative : function( s )
  {
    var a = this.Parse( window.location );

    if( !a )
      return( s );

    // get up to last slash
    a.path = a.path.substr( 0, a.path.lastIndexOf( '/' ) );

    return( a.scheme + a.host + a.path + "/" + Format.LTrim( s, "\/" ) );
  },

  Base : function ( sExtra, oParams )
  {
    var s = null;
    if( !this.BaseURL.length )
    {
      var a = this.Parse( window.location );
      var i = a.path.lastIndexOf( '/' );
      if( i >= 0 )
        s = Format.RTrim( a.scheme + a.host + a.path.substr( 0, i ), "\/" );
    }
    else
    {
      s = Format.RTrim( this.BaseURL, "\/" );
    }

    if( s )
    {
      if( sExtra && typeof( sExtra ) == "string" )
        s += "/" + Format.LTrim( sExtra, "\/" );
      if( oParams && typeof( oParams ) == 'object' )
      {
        s += ( s.indexOf( '?' ) == -1 ) ? "?" : "&";
        s += NVP.ToString( oParams );
      }
      s = Format.RTrim( s, "\/\?\&" );
    }

    return( s );
  },

  Self : function( oParams )
  {
    var s = window.location;
    var a = this.Parse( s );
    if( a )
      s = this.Base( a.path.substr( a.path.lastIndexOf( '/' ) ), oParams );
    return( s );
  },

  Action : function( oParams )
  {
    var oQuery = [];
    var a = this.Parse( window.location );
    if( a )
    {
      var q = NVP.ToObject( a.query );
      if( q.pg )
        oQuery.pg = q.pg;
      if( q.cmd )
        oQuery.cmd = q.cmd;
    }

    if( oParams && typeof( oParams ) == 'object' )
    {
      for( var o in oParams )
        oQuery[o] = oParams[o];
    }

    return( this.Self( oQuery ) );
  },

  Page : function( sPg, sCmd, oParams )
  {
    var oQuery = { pg : sPg };

    if( sCmd && typeof( sCmd ) == "string" )
      oQuery.cmd = sCmd;

    if( oParams && typeof( oParams ) == 'object' )
    {
      for( var o in oParams )
        oQuery[o] = oParams[o];
    }

    return( this.Base( 'index.php', oQuery ) );
  },

  Data : function( sDir, nID, sExtra, oParams )
  {
    var s = null;
    var a = /(\d{3})(\d{3})(\d{3})(\d{3})/;
    var r = a.exec( Format.ID( nID ) );
    if( r )
    {
      r.shift();
      if( !sExtra || typeof( sExtra ) != "string" )
        sExtra = "";
      s = this.Base( "/dat/" + sDir + "/" + r.join("/") + "/" + Format.LTrim( sExtra, "\/" ), oParams );
    }
    return( s );
  }

} // URL

var Cookie =
{
  Get : function( name )
  {
    var search = name + "=";
    var offset = 0;
    var end = 0;
    var retval = "";
    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( unescape( retval ) );
  },

  Set : function( name, value, expires )
  {
    var sCookie = name + "=" + escape( value );

    sCookie += ";path=/";

    if( expires )
    {
      if( isNaN( expires ) )
      {
        sCookie += ";expires=" + expires.toUTCString();
      }
      else if( parseInt( expires ) )
      {
        var dt = new Date();
        dt.setMinutes( dt.getMinutes() + parseInt( expires ) );
        sCookie += ";expires=" + dt.toUTCString();
      }
    }

    document.cookie = sCookie;
  },

  GetNVP : function( name, key )
  {
    return( NVP.Get( this.Get( name ), key ) );
  },

  SetNVP : function( name, key, value, expires )
  {
    this.Set( name, NVP.Set( this.Get( name ), key, value ), expires );
  }
} // Cookie

var NVP =
{
  Get : function( str, key )
  {
    var obj = this.ToObject( str );

    return( obj[key] );
  },

  Set : function( str, key, val, dup )
  {
    var obj = this.ToObject( str );

    if( typeof( obj[key] ) == 'undefined' || !dup )
    {
      obj[key] = val;
    }
    else if( dup )
    {
      if( typeof( obj[key] ) != 'object' )
        obj[key] = [ obj[key] ];
      obj[key][obj[key].length] = val;
    }

    return( this.ToString( obj ) );
  },

  ToObject : function( str )
  {
    var obj = {};
    var nvp = new Array();

    if( str && str.length )
      nvp = str.split( "&" );

    for( var i = 0; i < nvp.length; i++ )
    {
      var kv = nvp[i].split( "=" );

      if( typeof( obj[kv[0]] ) != 'undefined' )
      {
        if( typeof( obj[kv[0]] ) != 'object' )
          obj[kv[0]] = [ obj[kv[0]] ];

        obj[kv[0]][obj[kv[0]].length] = unescape( kv[1] );
      }
      else
      {
        obj[kv[0]] = unescape( kv[1] );
      }
    }

    return( obj );
  },

  ToString : function( obj )
  {
    var nvp = new Array();

    for( var k in obj )
    {
      if( typeof( obj[k] ) == 'object' )
      {
        for( var i = 0; i < obj[k].length; i++ )
          nvp[nvp.length] = k + "=" + escape( obj[k][i] );
      }
      else
      {
        nvp[nvp.length] = k + "=" + escape( obj[k] );
      }
    }

    return( nvp.join( "&" ) );
  }
} // NVP

// Is.?????? validation routines
var Is =
{
  // empty or null
  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 )
  {
    return( !isNaN( parseFloat( s ) ) );
  },

  Integer : function( s )
  {
    return( !isNaN( parseInt( s ) ) );
  },

  // address@server.somewhere
  EmailAddress : function( s )
  {
    var v = /^\S+\@\S+\.\S+/;
    return( v.test( s ) );
  },

  // 12345[-1234]
  ZipCode : function( s )
  {
    var v = /^\d{5}-?(\d{4})?$/;
    return( v.test( s ) );
  },

  // 123[-/.]456[-/.]7890
  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: // amex
          rc = ( RegExp.$2.length == 14 );
          break;

        case 4: // visa
        case 5: // mc
        case 6: // discover
          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 );
  },

  Date : function( szDate )
  {
    var dt = new Date( Date.parse( szDate.replace( /-/g, '/' ) ) );
    return( !isNaN( dt ) );
  },

  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 );
  }
} // Is

var Format =
{
  _hexletters : "0123456789ABCDEF",

  HexDec : function( x )
  {
    var n = 0;
    x = x.toString().toUpperCase();
    for( var c = 0; c < x.length; c++ )
    {
      var i = this._hexletters.indexOf( x.charAt( c ) );
      if( i == -1 )
      {
        break;
      }
      n = n << 4;
      n = n + i;
    }

    return( n );
  },

  DecHex : function( n )
  {
    var x = "";

    n = parseInt( n );

    if( !isNaN( n ) )
    {
      while( n )
      {
        var i = n & 15;
        x = this._hexletters.charAt( i ) + x;
        n >>= 4;
      }
    }

    return( x );
  },

  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();

    // are there enough decimals ?
    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 );
  },

  LTrim : function( sz, chars )
  {
    if( sz != null )
    {
      if( !chars )
        chars = "\\s";
      sz = sz.replace( new RegExp( "^[" + chars + "]+" ), "" );
    }
    return( sz );
  },

  RTrim : function( sz, chars )
  {
    if( sz != null )
    {
      if( !chars )
        chars = "\\s";
      sz = sz.replace( new RegExp( "[" + chars + "]+$" ), "" );
    }
    return( sz );
  },

  Trim : function( sz, chars )
  {
    if( sz != null )
    {
      sz = this.LTrim( sz, chars );
      sz = this.RTrim( sz, chars );
    }
    return( sz );
  },

  Duration : function ( nSeconds )
  {
    var dt = {};
    var sz = '';

    // clear negs
    if( nSeconds < 0 )
    {
      sz = '-';
      nSeconds *= -1;
    }

    // clear days
    if( nSeconds >= 86400 )
    {
      dt.day = Math.floor( nSeconds / 86400 );
      nSeconds -= ( dt.day * 86400 );
      sz += this.PadLeft( dt.day, 2, '0' ) + ' ';
    }

    // clear hours
    if( nSeconds >= 3600 )
    {
      dt.hour = Math.floor( nSeconds / 3600 );
      nSeconds -= ( dt.hour * 3600 );
      sz += this.PadLeft( dt.hour, 2, '0' ) + ':';
    }
    else
    {
      if( dt.day )
        sz += '00:';
    }

    // clear minutes
    if( nSeconds >= 60 )
    {
      dt.minute = Math.floor( nSeconds / 60 );
      nSeconds -= ( dt.minute * 60 );
      sz += this.PadLeft( dt.minute, 2, '0' ) + ':';
    }
    else
    {
      sz += '00:';
    }

    sz += this.PadLeft( nSeconds, 2, '0' );

/*    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 dt = new Date( Date.parse( szDate.replace( /-/g, '/' ) ) );

    if( !isNaN( dt ) )
    {
      // modied to take 09 to 2009
      if( dt.getYear() < 20 )
      {
        dt.setYear( dt.getYear() + 2000 );
      }

      szDate =
        this.PadLeft( dt.getFullYear(), 4, '0' ) + '-' +
        this.PadLeft( dt.getMonth() + 1, 2, '0' ) + '-' +
        this.PadLeft( dt.getDate(), 2, '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 );
  },

  ID : function( nID )
  {
    return( isNaN( nID ) ? nID : this.PadLeft( "" + nID, 12, "0" ) );
  },

  Size : function( nSize )
  {
    var sSuffix = "BKMGT";
    var nSuffix = 0;
    while( nSize >= 1024 )
    {
      nSuffix++;
      nSize /= 1024;
    }
    return( this.Float( nSize, ( nSuffix ) ? 1 : 0 ) + sSuffix.charAt( nSuffix ) + (( nSuffix ) ? "B" : "") );
  },

  Parse : function( format )
  {
    var result = "";
    var argn = 1;
    var arg;
    var re = /%(0)?([\d-]+)?\.?([\d]+)?([cdfxs])/;

    // 0 = full match
    // 1 = 0 or undefined
    // 2 = width
    // 3 = precision
    // 4 = dxfs
    // index = position found
    // input = string

    while( true )
    {
      var match = re.exec( format );

      if( !match )
      {
        result += format;
        break;
      }

      if( typeof( match[1] ) == "undefined" )
        match[1] = ' ';

      arg = arguments[argn++];

      switch( match[4] )
      {
        case 'c':
          if( arg.length )
            arg = arg.charAt(0);
          break;
        case 'd':
          arg = parseInt( arg );
          if( match[2] )
            arg = this.PadLeft( arg, match[2], match[1] );
          break;

        case 'f':
          arg = parseFloat( arg );
          if( match[3] )
            arg = this.Float( arg, match[3] );
          if( match[2] )
            arg = this.PadLeft( arg, match[2], match[1] );
          break;

        case 'x':
          arg = this.DecHex( arg );
          if( match[2] )
            arg = this.PadLeft( arg, match[2], match[1] );
          break;

        case 's':
          if( match[3] )
            arg = arg.substr( 0, match[3] );
          if( match[2] > 0 )
            arg = this.PadLeft( arg, match[2], match[1] );
          else if( match[2] < 0 )
            arg = this.PadRight( arg, Math.abs( match[2] ), match[1] );
          break;
      }

      result += format.substr( 0, match.index ) + arg.toString();

      format = format.substr( match.index + match[0].length );
    }

    return( result );
  },

  Suffix : function( d )
  {
      var a = [ "th", "st", "nd", "rd"  ];
      var s = a[0];
      var hund = ( d % 100 ); // 0-99
      var ten = ( d % 10 );   // 0-9
      if( !(hund >= 11 && hund <=13)  && ten < 4 )
          s = a[ten];
      return( s );
  }
} // Format

Date.prototype.IsLeapYear = function()
{
  var nYear = this.getFullYear();
  return((( nYear & 3 ) == 0 &&
      ((( nYear % 400 ) == 0 ) ^
      (( nYear % 100 ) != 0 ))) ? true : false );
}

Date.prototype.GetTimeZone = function( separate )
{
   if( typeof(separate)== "undefined")
    separate = "";

  var tz = this.getTimezoneOffset() * -1 ;
  var sign = (tz> 0 ) ? "+" : "-";
  tz = Math.abs( tz );
  return( Format.Parse("%c%02d%c%02d", sign, tz/ 60, separate, tz% 60) );
}

Date.prototype.DayOfYear = function()
{
  var dayNumber = 0;

  for( var nMonth = 0; nMonth < this.getMonth(); nMonth++ )
    dayNumber += Date.Months.Days[nMonth];

  dayNumber += this.getDate();

  if( ( this.getMonth() + 1 ) == 2 && this.IsLeapYear() )
    dayNumber++;

  return( dayNumber );
}

Date._GetMonthName = false;

Date.prototype.GetMonthName = function( bLong )
{
  if( !Date._GetMonthName )
  {
    var dt = new Date( 2009, 0, 1 );
    var aDate;

    for( var nMonth = 0; nMonth < 12; nMonth++ )
    {
      dt.setMonth(nMonth);

      aDate = dt.toLocaleString().split( /[\s,]+/ );

      for( var a = 1; a < aDate.length; a++ )
      {
        var t = /^\D+$/;
        if( t.test( aDate[a] ) )
        {
          Date.Months.Long[nMonth] = aDate[a];
          Date.Months.Short[nMonth] = aDate[a].substr( 0, 3 );
          break;
        }
      }
    }

    Date._GetMonthName = true;
  }

  return( Date.Months[( bLong ) ? "Long" : "Short"][this.getMonth()] );
}

Date._GetWeekdayName = false;

Date.prototype.GetWeekdayName = function( bLong )
{
  if( !Date._GetWeekdayName )
  {
    var dt = new Date( 2009, 0, 1 );
    var aDate;

    // back up to previous sunday
    dt.setDate( dt.getDate() - dt.getDay() );

    for( var nDOW = 0; nDOW < 7; nDOW++ )
    {
      aDate = dt.toLocaleString().split( /[\s,]+/ );
      Date.Weekdays.Long[nDOW] = aDate[0];
      Date.Weekdays.Short[nDOW] = aDate[0].substr( 0, 3 );
      dt.setDate( dt.getDate() + 1 );
    }

    Date._GetWeekdayName = true;
  }

  return( Date.Weekdays[( bLong ) ? "Long" : "Short"][this.getDay()] );
}

//var t = "Thu, 27 August 2009 22:03:59 UTC";
//var re = /\w+,\s+\d+\s+(\w+)/;
//re.test(t);
//RegExp.$1;


Date.Months =
{
  Long  : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  Short : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],

  Days  : [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
};



Date.Weekdays =
{
  Long  : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
  Short : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]
};

Date.cSecondsMinute  = 60;
Date.cMinutesHour    = 60;
Date.cSecondsHour    = Date.cSecondsMinute * Date.cMinutesHour;
Date.cHoursDay       = 24;
Date.cMinutesDay     = Date.cMinutesHour * Date.cHoursDay;
Date.cSecondsDay     = Date.cSecondsHour * Date.cHoursDay;
Date.cMonthsYear     = 12;
Date.cDaysWeek       = 7;
Date.cDaysYear       = 365;
Date.cDays4Years     = ( Date.cDaysYear * 4 ) + 1;
Date.cDays100Years   = ( Date.cDays4Years * 25 ) - 1;
Date.cDays400Years   = ( Date.cDays100Years * 4 ) + 1;
Date.cDaysTo1970     = 719162;

//    http://wwp.greenwichmeantime.com/time-zone/time-zones.htm

Date.cszTimeZone =
{
  init: false,
  sz  :
  [
    [ 0, "gmt" ],       // Greenwich Mean
    //[ 0, "ut" ],        // Universal (Coordinated)
    //[ 0, "utc" ],
    //[ 0, "wet" ],       // Western European
    [ -1 * 60, "wat" ],     // West Africa
    [ -2 * 60, "at" ],      // Azores
    // For completeness.  BST is also British Summer, and GST is also Guam Standard.
      //[ -3 * 60, "bst" ],   // Brazil Standard
      //[ -3 * 60, "gst" ],   // Greenland Standard
      //[ -3 * 60 -30, "nft" ], // Newfoundland
      //[ -3 * 60 -30, "nst" ], // Newfoundland Standard
    [ -4 * 60, "ast", "adt" ],      // Atlantic Standard
    [ -5 * 60, "est", "edt" ],      // Eastern Standard
    [ -6 * 60, "cst", "cdt" ],      // Central Standard
    [ -7 * 60, "mst", "mdt" ],      // Mountain Standard
    [ -8 * 60, "pst", "pdt" ],      // Pacific Standard
    [ -9 * 60, "yst", "ydt" ],      // Yukon Standard
    [ -10 * 60, "hst","hdt" ],    // Hawaii Standard
    //[ -10 * 60, "cat" ],    // Central Alaska
    //[ -10 * 60, "ahst" ],   // Alaska-Hawaii Standard
    [ -11 * 60, "nt" ],     // Nome
    [ -12 * 60, "idlw" ],   // International Date Line West
    [ +1  * 60, "cet", "cedt" ],    // Central European
    //[ +1  * 60, "met" ],    // Middle European
    //[ +1  * 60, "mewt" ],   // Middle European Winter
    //[ +1  * 60, "swt" ],    // Swedish Winter
    //[ +1  * 60, "fwt" ],    // French Winter
    [ +2  * 60, "eet", "eedt" ],    // Eastern Europe, USSR Zone 1
    [ +3  * 60, "bt" ],     // Baghdad, USSR Zone 2
    //[ +3  * 60 + 30, "it" ],  // Iran
    [ +4  * 60, "zp4" ],      // USSR Zone 3
    [ +5  * 60, "zp5" ],      // USSR Zone 4
    [ +5  * 60 + 30, "ist" ], // Indian Standard
    [ +6  * 60, "zp6" ],      // USSR Zone 5
      // For completeness.  NST is also Newfoundland Stanard, and SST is also Swedish Summer.
    [ +6  * 60 + 30, "nst" ],  // North Sumatra
    //[ +7  * 60, "sst" ],    // South Sumatra, USSR Zone 6
    [ +7  * 60, "wast", "wadt" ],       // West Australian Standard
      //[ +7  * 60 + 30, "jt" ],  // Java (3pm in Cronusland!)
    [ +8  * 60, "cct" ],        // China Coast, USSR Zone 7
    [ +9  * 60, "jst" ],    // Japan Standard, USSR Zone 8
      //[ +9  * 60 +30, "cast" ], // Central Australian Standard
    [ +10 * 60, "east", "eadt" ],       // Eastern Australian Standard
    //[ +10 * 60, "gst" ],        // Guam Standard, USSR Zone 9
    [ +12 * 60, "nzt", "ndzt" ]        // New Zealand
    //[ +12 * 60, "nzst" ],       // New Zealand Standard
    //[ +12 * 60, "idle" ]       // International Date Line East
  ]
};

Date.prototype.GetTZO = function()
{
  return( -this.getTimezoneOffset() );  // comes reversed -- positives should be negs
}

Date.prototype.IsDST = function()
{
  var dt = new Date(this);
  var tz = dt.getTimezoneOffset();
  dt.setMonth(0);             // Jan is always standard time, so compare the curent time
  return( tz != dt.getTimezoneOffset() ); // to the same time in Jan; if not equal, it's DST
}

Date.prototype.GetTimeZoneSZ = function()
{
  if(!Date.cszTimeZone.init)  // if init is still false, then haven't built out the object so do that first
  {
    for( var i = 0; i < Date.cszTimeZone.sz.length; i++ )
      Date.cszTimeZone[Date.cszTimeZone.sz[i][0]] = Date.cszTimeZone.sz[i];

    Date.cszTimeZone.init = true;     // mark as done
  }

  var tzo = this.GetTZO();    // invert the time offset

  if(this.IsDST())        // if it is daylight savings time, subtract 60 mins from value
    tzo -= 60;

  var tz = "";
  var tzinfo = Date.cszTimeZone[tzo];  // retreive the code from the array for that time offset

  if(!tzinfo)              // If empty, then add offset from GMT to the string
    tz = Format.Parse("GMT%c%02d:%02d", (tzo>0) ? "+" : "-", tzo / 60, tzo % 60 );
  else
  {
    if(this.IsDST() && tzinfo.length == 3)        // if it is daylight savings time, get correct abbrev.
      tz = tzinfo[2];
    else
      tz = tzinfo[1];
  }

  return( tz.toUpperCase() );    // show in upper case
}

Date.prototype.GetLongTime = function()
{
  var totalSecs = 0;

  // hours
  totalSecs += ( this.getHours() * Date.cSecondsHour );
  // minutes
  totalSecs += ( this.getMinutes()  * Date.cSecondsMinute );
  // seconds
  totalSecs += ( this.getSeconds()  );

  return( totalSecs );
}

Date.prototype.GetLongDate = function()
{
  return( parseInt( parseInt( this.getTime() / 1000 ) / 86400) );
}

Date.prototype.DayOfWeek = function( bISO )
{
  return( ( bISO ) ? ( ( this.getDay() + 6 ) % 7 ) : this.getDay() );
}

Date.FirstWeekdayOfYear = function( year, bISO )
{
  var dt = new Date( year, 0, ( bISO ) ? 4 : 1 );

  dt.setDate( dt.getDate() - dt.DayOfWeek( bISO ) );

  return( dt );
}

Date.prototype.WeekOfYear = function( bISO )
{
  var fdoy = Date.FirstWeekdayOfYear( this.getFullYear(), bISO );

  if( bISO )
  {
    var ndoy = Date.FirstWeekdayOfYear( this.getFullYear() + 1, bISO );
    if( fdoy.GetLongDate() > this.GetLongDate())
      fdoy = Date.FirstWeekdayOfYear( this.getFullYear() - 1, bISO );
    else if( this.GetLongDate() > ndoy.GetLongDate() )
      fdoy = ndoy;
  }

  return( parseInt(( this.GetLongDate() - fdoy.GetLongDate() ) / 7) + 1 );
}

Date.prototype.ISOYear = function()
{
  var year  = this.getFullYear();
  var month = this.getMonth();

  // check Jan and Dec for possible values
  if( month == 0 || month == 11 )
  {
    // get the ISO week of the year
    var woy = this.WeekOfYear( true );

    // if week 1 and in Dec then use next year
    if( woy == 1 && month == 11 )
      year++;

    // if last week(s) and in Jan then use previous year
    if( woy >= 52 && month == 0 )
      year--;
  }

  return( year );
}

Date.prototype.GetPart = function( p )
{
  switch( p )
  {
    // Year
    // Whether it's a leap year
    case 'L': return( this.IsLeapYear() ? 1 : 0 );
    // A two digit representation of a year
    case 'y': return( Format.Parse( "%02d", this.getFullYear() % 100 ) );
    // A full numeric representation of a year, 4 digits
    case 'Y': return( Format.Parse( "%04d", this.getFullYear() ) );

    // Month
    // Numeric representation of a month, with leading zeros
    case 'm': return( Format.Parse( "%02d", this.getMonth() + 1 ) );
    // Numeric representation of a month, without leading zeros
    case 'n': return( this.getMonth() + 1 );
    // A full textual representation of a month, such as January or March
    case 'F': return( this.GetMonthName( true ) );
    // A short textual representation of a month, three letters
    case 'M': return( this.GetMonthName( false ) );

    // Number of days in the given month
    // Need to see if Feb and a leap year
    case 't': return( Date.Months.Days[this.getMonth()] + (( this.IsLeapYear() && this.getMonth() == 1) ? 1 : 0)  );

    // Day
    // Day of the month, 2 digits with leading zeros
    case 'd': return( Format.Parse( "%02d", this.getDate() ) );
    // A textual representation of a day, three letters
    case 'D': return( this.GetWeekdayName( false ) );
    // Day of the month without leading zeros
    case 'j': return( this.getDate() );
    // A full textual representation of the day of the week
    case 'l': return( this.GetWeekdayName( true ) );
    // ISO-8601 numeric representation of the day of the week 1 - Mon, 7 - Sun
    case 'N': return( this.DayOfWeek( true ) + 1 );
    // English ordinal suffix for the day of the month, 2 chars, st, nd, rd or th
    case 'S': return( Format.Suffix( this.getDate() ) );
    // Numeric representation of the day of the week 0 - Sun, 6 - Sat
    case 'w': return( this.DayOfWeek( false ) );
    // The day of the year ( starting from 0 - 365 )
    case 'z': return( this.DayOfYear() - 1 );

    // Time
    // Lowercase Ante meridiem and Post meridiem
    case 'a': return( ( this.getHours() < 12 ) ? "am" : "pm" );
    // Uppercase Ante meridiem and Post meridiem
    case 'A': return( ( this.getHours() < 12 ) ? "AM" : "PM" );
    // Swatch Internet time
    case 'B': return( Format.Parse( "%03d",(( (this.GetLongTime()+ (this.getTimezoneOffset() * 60) + Date.cSecondsHour)% Date.cSecondsDay ) / Date.cSecondsDay ) * 1000));

    // 24-hour format of an hour without leading zeros
    case 'G': return( this.getHours() );
    // 12-hour format of an hour without leading zeros
    case 'g': return(( ( this.getHours() + 11) % 12 ) + 1 );
    // 12-hour format of an hour with leading zeros
    case 'h': return( Format.Parse( "%02d", this.GetPart( 'g' ) ) );
    // 24-hour format of an hour with leading zeros
    case 'H': return( Format.Parse( "%02d", this.getHours() ) );
    // Minutes with leading zeros
    case 'i': return( Format.Parse( "%02d", this.getMinutes() ) );
    // Seconds, with leading zeros
    case 's': return( Format.Parse( "%02d", this.getSeconds() ) );

    // Timezones
    // Whether or not the date is in daylight saving time
    case 'I': return( this.IsDST() ? 1 : 0  );
    // Timezone abbreviation
    case 'T': return( this.GetTimeZoneSZ());
    // Difference to Greenwich time (GMT) with colon between hours and minutes
    case 'P': return( this.GetTimeZone( ":" ) );
    // Difference to Greenwich time (GMT) in hours
    case 'O': return( this.GetTimeZone() );
    // Timezone offset in seconds.
    case 'Z': return( this.GetTZO() * Date.cSecondsMinute );
    // Timezone identifier
    case 'e': return( this.GetTimeZoneSZ() );

    // PRE FORMATTED
    // ISO-8601
    case 'c': return( this.Format( "Y-m-d\\TH:i:sP" ));
    // RFC2822
    // case 'r': return(  );
    case 'r': return( this.Format( "D, d M Y H:i:s O" ));
    // Timestamp
    case 'U': return( parseInt(this.getTime()  / 1000 ) );

    // ISO Year
    case 'o': return( this.ISOYear() );

    // ISO Week of the year
    case 'W': return( Format.Parse( "%02d", this.WeekOfYear( true ) ) );
    // Calendar Week of year; Not ISO
    case 'C': return( this.WeekOfYear( false ) );
  }

  return( p );
}

Date.prototype.Format = function( format )
{
  var result = "";

  for( var i = 0; i < format.length; i++ )
  {
    if( format.charAt( i ) == '\\' )
      result += format.charAt( ++i );
    else
      result += this.GetPart( format.charAt( i ) );
  }

  return( result );
}

var Form =
{
  IsModified : function ( oForm )
  {
    var b = false;

    for( var f = 0; b == false && f < oForm.elements.length; f++ )
    {
      oInput = oForm.elements[f];
      switch( oInput.type )
      {
        case "hidden":
          if( typeof( FCKeditorAPI ) != 'undefined' )
          {
            var oEditor = FCKeditorAPI.GetInstance( oInput.name );
            if( oEditor )
            {
              b = oEditor.IsDirty();
              break;
            }
          }

        case "text":
        case "textarea":
        case "password":
          b = ( oInput.value != oInput.defaultValue );
          break;

        case "radio":
        case "checkbox":
          b = ( oInput.checked != oInput.defaultChecked );
          break;

        case "select-one":
          b = !oInput.options[oInput.selectedIndex].defaultSelected;
          break;

        case "select":
        case "select-multiple":
          for( var o = 0; b == false && o < oInput.options.length; o++ )
            b = ( oInput.options[o].selected != oInput.options[o].defaultSelected );
          break;

        case "submit":
        case "button":
        case "reset":
          // don't check these
          break;

        default:
          break;
      }
    }

    return( b );
  },

  MakeGetURL : function( oForm )
  {
    var url = "";

    for( var f = 0; f < oForm.elements.length; f++ )
    {
      oInput = oForm.elements[f];
      switch( oInput.type )
      {
        case "hidden":
          if( typeof( FCKeditorAPI ) != 'undefined' )
          {
            var oEditor = FCKeditorAPI.GetInstance( oInput.name );
            if( oEditor )
              oEditor.UpdateLinkedField();
          }

        case "text":
        case "textarea":
        case "password":
          url = NVP.Set( url, oInput.name , oInput.value, true );
          break;

        case "radio":
        case "checkbox":
          if( oInput.checked )
          {
            url = NVP.Set( url, oInput.name , oInput.value, true );
          }
          break;

        case "select-one":
          url = NVP.Set( url , oInput.name , oInput.value, true );
          break;

        case "select":
        case "select-multiple":
          for( var o = 0; o < oInput.options.length; o++ )
          {
            if( oInput.options[o].selected )
              url = NVP.Set( url , oInput.name , oInput.options[o].value, true );
          }
          break;

        case "submit":
        case "button":
        case "reset":
          // don't check these
          break;

        default:
          break;
      }
    }

    return( url );
  },

  SetFieldValue : function( fld, val )
  {
    if( fld )
      fld.value = val;
  },

  DisableFields : function( bDisable, fm, aTypes, aNames )
  {
    if( aTypes != null && aTypes.length )
    {
      for( var f = 0; f < fm.elements.length; f++ )
      {
        for( var t = 0; t < aTypes.length; t++ )
        {
          if( fm.elements[f].type == aTypes[t] )
          {
            fm.elements[f].disabled = bDisable;
          }
        }
      }
    }

    if( aNames != null && aNames.length )
    {
      for( var f = 0; f < fm.elements.length; f++ )
      {
        for( var t = 0; t < aNames.length; t++ )
        {
          if( fm.elements[f].name == aNames[t] )
          {
            fm.elements[f].disabled = bDisable;
          }
        }
      }
    }
  },

  CheckFields :
    function(
      flds, // array of [ field, check ]
      amsg  // alert message if not valid
    )
  {
    var bError = false;

    // check the fields backwards so the focus is at the first bad entry
    for( var f = flds.length-1; f >= 0; f-- )
    {
      var fld = flds[f][0];     // object
      var chk = flds[f][1].split(",");
      var bad = false;
      var fck = null;

      // check for fckeditor, instance is a hidden field
      if( fld.type == 'hidden' && typeof( FCKeditorAPI ) != 'undefined' )
      {
        var oEditor = FCKeditorAPI.GetInstance( fld.name );
        if( oEditor )
        {
          fck = document.getElementById( fld.name + "___Frame" );
          oEditor.UpdateLinkedField();
        }
      }

      // trim everything coming in
      fld.value = Format.Trim( fld.value );

      // check all options from here out...
      for( var c = 0; c < chk.length && !bad; c++ )
      {
        var opts = chk[c].split( ":" );
        var not = false;
        var opt = false;
        var equ = false;
        var eva = false;

        for( var i = 0; i < opts[0].length; i++ )
        {
          switch( opts[0].charAt( i ) )
          {
            case '?': // optional
              opt = true;
              break;

            case '!': // not
              not = true;
              break;

            case '=': // compare to another field, for verification purposes
              equ = true;
              break;

            case '&': // continuation .. if eval is false then check stops
              eva = true;
              break;

            default:
              opts[0] = opts[0].substr( i );
              i = opts[0].length + 10;
              break;
          }
        }

        // optional and nothing in there
        if( opt && !fld.value.length )
          continue;

        // equals another field?
        if( !bad && equ )
        {
          bad = ( fld.value != fld.form[opts[0]].value );
          if( not )
            bad = !bad;
        }

        // evaluation to continue
        if( !bad && eva )
        {
          var v = opts[0].split( /(\!|\=|\.)/ );

          for( var i = 0; i < v.length; i++ )
          {
            if( !v[i].length || Is.Integer(v[i]) )
              continue;

            var aidx = "";
            var r = /(\w+)(\[\])?(\[\d+\])?/;
            if( r.test( v[i] ) )
            {
              v[i] = RegExp.$1 + RegExp.$2;
              aidx = RegExp.$3;
            }

            if( Is.InputField( fld.form, v[i] ) )
              opts[0] = opts[0].replace( v[i] + aidx, "fld.form['" + v[i] + "']" + aidx );
          }

          if( !eval( opts[0] ) )
            break;
        }

        if( bad )
          break;

        switch( opts[0].toLowerCase() )
        {
          // checks
          case 'numeric':
            bad = !Is.Matches( fld.value, "^\\d+$" );
            break;
          case 'email':
            bad = !Is.EmailAddress( fld.value );
            break;

          case 'creditcard':
            bad = !Is.CreditCard( fld.value );
            break;

          case 'zipcode':
            bad = !Is.ZipCode( fld.value );
            if( !bad && opts[1] != null )
              fld.value = Format.ZipCode( fld.value, opts[1] );
            break;

          case 'phone':
            bad = !Is.PhoneNumber( fld.value );
            if( !bad && opts[1] != null )
              fld.value = Format.Phone( fld.value, opts[1] );
            break;

          case 'empty':
            bad = !Is.Empty( fld.value );
            break;

          case 'zero':
            bad = !Is.Zero( fld.value );
            break;

          case 'float':
            bad = !Is.Float( fld.value );
            if( !bad && !isNaN( parseInt( opts[1] ) ) )
              bad = ( parseFloat( fld.value ) < parseFloat( opts[1] ) );
            if( !bad && !isNaN( parseInt( opts[2] ) ) )
              bad = ( parseFloat( fld.value ) > parseFloat( opts[2] ) );
            if( !bad && !isNaN( parseInt( opts[3] ) ) )
              fld.value = Format.Float( parseFloat( fld.value ), parseInt( opts[3] ) );
            break;

          case 'integer':
            bad = !Is.Integer( fld.value );
            if( !bad && !isNaN( parseInt( opts[1] ) ) )
              bad = ( parseInt( fld.value ) < parseInt( opts[1] ) );
            if( !bad && !isNaN( parseInt( opts[2] ) ) )
              bad = ( parseInt( fld.value ) > parseInt( opts[2] ) );
            if( !bad )
              fld.value = parseInt( fld.value );
            break;

          case 'state':
            bad = !Is.State( fld.value );
            break;

          case 'minlength':
            if( !isNaN( parseInt( opts[1] ) ) )
              bad = ( fld.value.length < parseInt( opts[1] ) );
            break;

          case 'maxlength':
            if( !isNaN( parseInt( opts[1] ) ) )
              bad = ( fld.value.length > parseInt( opts[1] ) );
            break;

          // modifications ...
          case 'upper':
            fld.value = fld.value.toUpperCase();
            break;

          case 'lower':
            fld.value = fld.value.toLowerCase();
            break;

          case 'trim':
            fld.value = Format.Trim( fld.value );
            break;

          case 'eval':
            bad = eval( opts[1] );
            break;

          case 'matches':
            if( opts[1] )
              bad = !Is.Matches( fld.value, opts[1] );
            break;

          case 'date':
            bad = !Is.Date( fld.value );
            if( !bad )
              fld.value = Format.Date( fld.value );
            break;

          case 'time':
            bad = !Is.Time( fld.value );
            if( !bad )
              fld.value = Format.Time( fld.value );
            break;

          default:
            continue;
        }
      }

      if( not )
        bad = !bad;

      if( fck )
      {
        fck.style.border = ( bad ) ? "1pt solid red" : "0pt none";
      }
      else
      {
        var cls = fld.className;

        if( cls.length )
        {
          var i = cls.indexOf( "bad" );
          if( i >= 0 )
            cls = cls.substr( 0, i );
          if( cls.length )
            cls += " ";
        }

        if( bad )
        {
          cls += "bad";
          try
          {
            if( !Is.Empty( fld.select ) )
              fld.select();
            if( !Is.Empty( fld.focus ) )
              fld.focus();
          }
          catch( e )
          {
          }
        }

        fld.className = cls;
      }

      bError |= bad;
    }

    if( bError && amsg.length )
      alert( amsg );

    return( bError );
  }

} // Form

var Value =
{
  Min : function( v )
  {
    var r = v;
    for( var i = 0; i < arguments.length; i++ )
    {
      if( r > arguments[i] )
        r = arguments[i];
    }
    return( r );
  },

  Max : function( v )
  {
    var r = v;
    for( var i = 0; i < arguments.length; i++ )
    {
      if( r < arguments[i] )
        r = arguments[i];
    }
    return( r );
  },

  Fit : function( v, a, b )
  {
    return( ( v < a ) ? a : ( v > b ) ? b : v );
  },

  Length : function( obj )
  {
    return( ( typeof(obj.form) == 'undefined' && obj.length ) ? obj.length : ( ( obj ) ? 1 : null ) );
  },

  Object : function ( obj, idx )
  {
    if( typeof(obj.form) == 'undefined' && obj.length )
    {
      if( idx >=0 && idx < obj.length )
        return( obj[idx] );
    }
    else if( idx == 0 )
    {
      return( obj );
    }
    return( null );
  },

  // make a copy of the object
  Copy : function( obj )
  {
    var dst = new Object();

    for( p in obj )
    {
      if( typeof( obj[p] ) == 'function' )
        dst[p] = eval( obj[p] );
      else if( typeof( obj[p] ) == 'object' )
        dst[p] = CopyObject( obj[p] );
      else
        dst[p] = obj[p];
    }

    return( dst );
  }
} // Value

function FileOnChange( oFile, sCmd )
{
  with( document )
  {
    if( sCmd != null && sCmd.length )
      oFile.form.cmd.value = sCmd;
    oFile.form.submit();
    var oDisplay = getElementById( oFile.name + "_block" ).style.display;
    getElementById( oFile.name + "_block" ).style.display = 'none';
    getElementById( oFile.name + "_busy" ).style.display = oDisplay;
    getElementById( oFile.name + "_busy_img" ).src = getElementById( oFile.name + "_busy_img" ).src;
  }
}

function FileUploadOnChange( oFile, oFlds, sAction, sFunc )
{
  for( oFld in oFlds )
  {
    if( oFile.form[oFld] )
      oFile.form[oFld].value = oFlds[oFld];
  }

  with( document )
  {
    if( getElementById( oFile.name + '_target' ) )
      oFile.form.target = oFile.name + '_target';

    if( sAction && sAction.length )
      oFile.form.action = sAction;

    if( sFunc && sFunc.length )
      eval( sFunc );
    else
      oFile.form.submit();

    var oDisplay = getElementById( oFile.name + "_block" ).style.display;
    getElementById( oFile.name + "_block" ).style.display = 'none';
    getElementById( oFile.name + "_busy" ).style.display = oDisplay;
    getElementById( oFile.name + "_busy_img" ).src = getElementById( oFile.name + "_busy_img" ).src;
  }
}

function FileUploadOnLoad( id, target )
{
  var i = document.getElementById(id);
  var d = null;

  if( id.contentDocument )
    d = id.contentDocument;
  else if (id.contentWindow)
    d = id.contentWindow.document;
  else
    d = window.frames[id].document;

  if( d.location.href == "about:blank")
    return;
  var o = document.getElementById( target );
  if( o )
  {
    o.innerHTML = d.body.innerHTML;
    DoRoundedCorners();
  }
}

function ParamString( s )
{
  for( var i = 1; i < arguments.length; i++ )
  {
    var rep = "#" + (i-1) + "#";
    var tmp = s.replace( rep, arguments[i] );
    while( s != tmp )
    {
      s = tmp;
      tmp = s.replace( rep, arguments[i] );
    }
  }

  return( s );
}

function GetBrowserInfo()
{
  var rc = [ "unknown", 0.0 ];

  var re = /(MSIE|FireFox|Safari|Opera).?([\d\.]+)/i;

  if( re.test( navigator.userAgent ) )
  {
    rc[0] = RegExp.$1.toLowerCase();
    rc[1] = RegExp.$2;
  }

  return( rc );
}

function ListProps( o )
{
  var a = [];
  for( p in o )
  {
    if( typeof( o[p] ) != "function" )
      a[a.length] = ( p + " = " + o[p] );
  }
  return( a.join("\r\n") );
}

function ListAllProps( o )
{
  var a = [];

  for( p in o )
  {
    var data = "";

    switch( typeof( o[p] ) )
    {
      case 'function':
        continue;

      case 'object':
        data = ( p + " = { " + ListAllProps( o[p] ) + " }" );
        break;

      default:
        data = ( p + " = " + o[p] );
    }

    a[a.length] = data;
  }

  return( a.join("\r\n") );
}


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 && obj.style.position != 'absolute' )
    {
      rct.top += parseInt( obj.offsetTop );
      rct.left += parseInt( obj.offsetLeft );
      obj = obj.offsetParent;
    }
  }

  return( rct );
}

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 + '_lnk' );
  var rct = GetAbsolutePosition( oTgt );

  oSWF.style.zIndex = 10;
  oSWF.style.position = 'absolute';
  oSWF.style.left = rct.left + 'px';
  oSWF.style.top = rct.top + 'px';
  oSWF.style.right = parseInt( rct.left + rct.width ) + 'px';
  oSWF.style.bottom = parseInt( rct.top + rct.height ) + 'px';
  oSWF.style.width = rct.width + 'px';
  oSWF.style.height = rct.height + 'px';
}

function DoFileUpload( oFileTransfer, sBasename, oOptions )
{
  if( oFileTransfer.GetFileCount() && oFileTransfer.GetFile( 0 ).status < 5 )
    return;

  // function defs
  oFileTransfer.OnOpen = function( oFR )
  {
    if( oFR.Options.target == 'showbusy' )
      document.body.style.cursor = 'wait';
    else
    {
      var oLnk = document.getElementById( oFR.ID + "_lnk" );
      var oTxt = document.getElementById( oFR.ID + "_txt" );
      var oBar = document.getElementById( oFR.ID + "_bar" );
      if( !oFR.Options.target )
        oFR.Options.target = oFR.ID + "_lnk";

      var oTgt = document.getElementById( oFR.Options.target );
      if( !oTgt )
        oTgt = oLnk;

      var oRct = GetAbsolutePosition( oTgt );

      oTxt.innerHTML = "0%";

      // target is same as link
      if( ( oLnk.tagName.toLowerCase() != 'img' || oRct.width < 50 ) && oLnk == oTgt )
      {
        // set height to match
        oTxt.style.height = oRct.height + "px";
      }
      // different .. position in center of target
      else
      {
        oRct.left += 5;
        oRct.width -= 12;
        oRct.top += ( (oRct.height/2) - (parseInt(oTxt.style.height)/2) ); //offsetHeight
      }
      // adjust font size to maximum?
      oTxt.style.fontSize = ( parseInt( oTxt.style.height ) - 8 ) + "px";

      oTxt.style.left = oRct.left + "px";
      oTxt.style.top = oRct.top + "px";
      oTxt.style.width = oRct.width + "px";
      oTxt.style.display = "inline";

      oBar.style.left = ( oRct.left + 1 ) + "px";
      oBar.style.top = (( parseInt( oTxt.style.top ) + parseInt( oTxt.style.height ) ) - ( parseInt( oBar.style.height ) ) ) + "px";
      oBar.style.width = "0px";
      oBar.style.display = "inline";

      oLnk.disabled = true;
    }
  }

  oFileTransfer.OnOverallProgress = function( oFR, nSent, nTotal )
  {
    if( oFR.Options.target == "showbusy" )
      document.body.style.cursor = 'wait';
    else
    {
      var oTxt = document.getElementById( oFR.ID + "_txt" );
      var oBar = document.getElementById( oFR.ID + "_bar" );
      var nPct = ( nSent / nTotal );
      oTxt.innerHTML = parseInt( nPct * 100 ) + "%";
      oBar.style.width = parseInt( nPct * ( oTxt.offsetWidth - 2 )) + "px";

      if( oFR.Options.onprogress )
        eval( oFR.Options.onprogress + "( this, oFR, nSent, nTotal )" );
    }
  }

  oFileTransfer.OnOverallComplete = function( oFR, sError )
  {
    if( oFR.Options.target == "showbusy" )
      document.body.style.cursor = 'Auto';
    else
    {
      var oLnk = document.getElementById( oFR.ID + "_lnk" );
      var oTxt = document.getElementById( oFR.ID + "_txt" );
      var oBar = document.getElementById( oFR.ID + "_bar" );
      oTxt.style.display = "none";
      oBar.style.display = "none";
      oBar.style.width = '0px';
      oLnk.disabled = false;
    }

    if( sError && sError.length )
      alert( sError );
    else if( oFR.Options.oncomplete )
      eval( oFR.Options.oncomplete + "( this, oFR )" );
  }

  // working code ..
  oFileTransfer.Options = oOptions;
  oFileTransfer.ID = sBasename;
  oFileTransfer.AutoUpload = true;
  oFileTransfer.MaxSize = 40 * 1024 * 1024;
  oFileTransfer.oURL = URL.Parse( oFileTransfer.Get( "URL" ) );
  oFileTransfer.oURL.query = NVP.ToObject( oFileTransfer.oURL.query );
  oFileTransfer.FileMask  = GetFileMask( oOptions.type );
  oFileTransfer.MultiFile = oOptions.multifile;
  oFileTransfer.SetAll();
}

// pass the responseXML.documentElement.parentNode to this to retreive the entire structure
function DomNodeToObject( node )
{
  var obj = {};

  for( var child = node.firstChild; child; child = child.nextSibling )
  {
    var value = '';

    if( child.nodeType == 3 && child.nodeName.charAt(0) == '#' )
      continue;

    // if( child.nodeValue )
    if( child.nodeType == 3 )
    {
      value = unescape( child.nodeValue );
    }
    // else if( child.firstChild )
    else if( child.childNodes.length )
    {
      var bText = true;

      // check all children for type Text
      for( var i = 0; i < child.childNodes.length && bText; i++ )
      {
        bText = ( child.childNodes[i].nodeType == 3 );
        value += unescape( child.childNodes[i].nodeValue );
      }

      if( !bText )
        value = DomNodeToObject( child );
    }

    if( obj[child.nodeName] )
    {
      if( !obj[child.nodeName].length )
        obj[child.nodeName] = [ obj[child.nodeName] ];
      obj[child.nodeName][obj[child.nodeName].length] = value;
    }
    else
    {
      obj[child.nodeName] = value;
    }
  }

  return( obj );
}

function CreatePlayer( typ , ids )
{
  var obj = {};

  switch( typ )
  {
    case 'list':
      obj = { pl_id: ids, clean: 1 };
      break;
    case 'tracks':
      obj = { trk_id: ids, clean: 1 };
      break;
  }

  var params = "addressbar=0,status=0,toolbar=0,location=0,resizeable=1,menu=0,width=300,height=400";
  window.Player = window.open( URL.Page( "Player", null, obj ) , "Player" , params );
}

var blinkyThings = [];

function MakeThingsBlink()
{
  if( blinkyThings.length == 0 )
  {
    var v = document.getElementsByTagName('*');
    for( i = 0; i < v.length; i++ )
      if( v[i].className.indexOf( 'blinking' ) != -1 )
        blinkyThings[blinkyThings.length] = v[i];
  }

  if( blinkyThings.length > 0 )
  {
    for( i = 0; i < blinkyThings.length; i++ )
    {
      if( blinkyThings[i].className.indexOf( 'blinking' ) != -1 )
      {
        if( blinkyThings[i].tagName == 'A' )
        {
          blinkyThings[i].style.textDecoration =
            ( blinkyThings[i].style.textDecoration == 'underline' ) ? 'none' : 'underline';
        }
        else
        {
          var clr = blinkyThings[i].style.color;
          blinkyThings[i].style.color = blinkyThings[i].style.backgroundColor;
          blinkyThings[i].style.backgroundColor = clr;
          //blinkyThings[i].style.visibility = ( blinkyThings[i].style.visibility == 'visible' ) ? 'hidden' : 'visible';
        }
      }
    }
    setTimeout( "MakeThingsBlink();", 500 );
  }
}

var LargeText =
{
  Check : function()
  {
    var lnks = document.getElementsByName( "largetext" );

    for( var i = 0; i < lnks.length; i++ )
    {
      var txt = document.getElementById( "text_" + lnks[i].id );
      if( !txt.innerHTML.length || !txt.style.height || txt.scrollHeight <= parseInt( txt.style.height ) )
      {
        lnks[i].style.display = "none";
        txt.style.height = "auto";
        txt.style.overflow = "visible";
      }
      else
      {
        lnks[i].style.display = "block";
        txt.style.height = "150px";
      }
    }
  },

  Expand : function( lnk )
  {
    var txt = document.getElementById( "text_" + lnk.id );
    lnk.style.display = "none";
    txt.style.height = "auto";
    txt.style.overflow = "visible";
  }
}

var Country =
{
  Fetch : function( elem , e )
  {
      // suggest window
    var name = elem.id.substr( 0 , elem.id.indexOf( "_text" ) );
    var node = FindParentElement( elem , "id" , "div_" + name );
    var div = GetChildElementByProperty( node, "id", name + "_select" )

      // event
    var evt = ( e ) ? e : window.event;
      // which key ......everything or safari
    var key = ( evt.keyCode ) ? evt.keyCode : evt.which;

      // only do something if there is a value in the input
    if( elem.value.length > 0 )
    {
        // if down arrow
      if( key == 40 )
      {
          // select first option in select box
        if( div.options.length > 0 )
        {
          div.options[0].selected = 1;
            // set focus on select box
          div.focus();
        }
      }
      else // if down arrow wasn't pressed, submit ajax call to fetch for search
      {
        var a = new AJAX();
        a.URL = URL.Page( "Ajax" , "Country" );
        a.Params = NVP.Set( "" , 'search' , elem.value );
        a.Method = "POST";
        a.Data = elem;
        a.OnComplete = this.Display;
        a.Send();
      }
    }
    else // clear display box and hide
    {
      div.innerHTML = "";
      div.style.display = 'none';
    }
  },

  Display : function( oRequest , elem )
  {
    if( oRequest.responseText )
    {
      var name = elem.id.substr( 0 , elem.id.indexOf( "_text" ) );
      var node = FindParentElement( elem , "id" , "div_" + name );
      var div = GetChildElementByProperty( node, "id", name + "_select" )

      var rct = GetAbsolutePosition( elem );
      {
        div.style.display = 'block';
        div.options.length = 0;
        div.style.position = "absolute";
        div.style.left = rct.left + "px";
        div.style.top = parseInt( rct.top + 20 ) + "px";
        div.style.width = rct.width;
        var obj = eval( "(" + oRequest.responseText + ")" );
        for( p in obj )
        {
          var opt = new Option( obj[p] , p, false, false);
          div.options[div.length] = opt;
        }
      }
    }
  },

  Action : function( elem , e )
  {
    var name = elem.id.substr( 0 , elem.id.indexOf( "_select" ) );
    var node = FindParentElement( elem , "id" , "div_" + name );
    var div = GetChildElementByProperty( node, "id", name + "_text" )

    var evt = ( e ) ? e : window.event;
    var key = ( evt.keyCode ) ? evt.keyCode : evt.which;

      // if enter / return was pressed
    if( key == 13 || evt.type == "click" )
    {
      var hdd = GetChildElementByProperty( node, "id", name )
      hdd.value = elem.options[elem.selectedIndex].value;
      div.value = elem.options[elem.selectedIndex].text;
      elem.style.display = 'none';
      div.focus();
    }

    if( key == 38 ) // up arrow
    {
      if( elem.options[0].selected )
        div.focus();
    }
  }
}

function GetChildElementByProperty( oParent, sProp, sName )
{
  try
  {
    var oNode = null;
    for( var i = 0; !oNode && i < oParent.childNodes.length; i++ )
    {
      if( oParent.childNodes[i][sProp] == sName )
        oNode = oParent.childNodes[i];
      else
        oNode = this.GetChildElementByProperty( oParent.childNodes[i], sProp, sName );
    }
    return( oNode );
  }
  catch( e )
  {
    alert( "Failed Child Elem: " + e );
  }
}

function FindParentElement( oChild, sProp, sData )
{
  try
  {
    var oNode = oChild.parentNode;
    while( oNode && oNode[sProp] != sData )
    {
      oNode = oNode.parentNode;
    }
    return( oNode );
  }
  catch( e )
  {
    alert( "Failed Parent: " + e );
  }
}

function CheckChat( usr )
{
  // if not logged in, return
  if( !usr || !Cookie.GetNVP( 'CLIENT', "usr_id" ) )
    return;

  if( !window.name.length && usr.length )
  {
    var a = new AJAX();
    a.URL = URL.Page( "Ajax", "Page", { page: "Chat", command: "CheckNew" } );
    a.Method = "POST";
    a.Params = NVP.Set( '', "cht_dst_usr_id" , usr );
    a.Data = usr;
    a.OnComplete = ReturnChat;
    a.Send();
  }
}

function ReturnChat( oRequest, usr )
{
  if( oRequest.responseText.length > 0 )
    OpenChat( parseInt( oRequest.responseText ) );

  // if logged in, call it
  if( Cookie.GetNVP( 'CLIENT', "usr_id" ) )
    setTimeout( "CheckChat('" + usr + "');", 15000 );
}

function OpenChat( usr )
{
  var wName = "Chat_" + usr;
  var wChat = window[wName];
  var params = "scrollbars=0,status=0,toolbar=0,location=0,resizable=1,menubar=0,height=520,width=350";

  if( wChat && !wChat.closed )
    wChat.focus();
  else if( !wChat || typeof( wChat ) == 'undefined' || wChat.closed )
    window[wName] = window.open( URL.Page( "Chat", "Default", { dst_usr_id: usr } ), wName, params );
}

// Variables from the client computer...

var dt = new Date();

//Cookie.Set( "CLIENT", "" );
Cookie.SetNVP( "CLIENT", "TZOFS", dt.getTimezoneOffset() * 60, 60 * 24 * 30 );

// browser status
window.defaultStatus = 'xiie.net';
window.status = 'xiie.net';
