//-- ######################################################################## --
//-- # TIMESTAMP: <060824-2028 alant@g3k.local>                             # --
//-- # COPYRIGHT: (c) 2004-present.  Turransky, LLC.  All Rights Reserved.  # --
//-- #            For use only by Author(s) and Gannett Co., Inc.           # --
//-- ######################################################################## --

//-- ######################################################################## --
//-- # CONSTANTS                                                            # --
//-- ######################################################################## --
var kLogError     = 0;
var kLogDebug     = 1;
var kLogTrace     = 2;
var kLogCore      = 4;
var kLogInfo      = 8;
var kLogAlert     = 16;
var kLogNotice    = 32;
var kLogStrict    = 64;
var kLogWarning   = 128;
var kLogCritical  = 256;
var kLogEmergency = 512;
var kLogAll       = 1024;

//-- ######################################################################## --
//-- # GLOBAL VARIABLES                                                     # --
//-- ######################################################################## --
var gBlnDebug = 1;                                                             // GLOBAL DEBUGGING FLAG
var gVarTmp   = false;                                                          // GENERIC, TEMPORARY GLOBAL VARIABLE
var gNumCnt   = 0;                                                              // GENERIC, TEMPORARY GLOBAL COUNTER VARIABLE
var gStrErr   = '';                                                             // GENERIC, TEMPORARY GLOBAL ERROR STRING
var gAryS_R   = new Array(
///\||_VBR_|&#124;/g,
///³|_GE_|&ge;|&#8805;/g,
///²|_LE_|&le;|&#8804;/g,
///±|_PM_|&plusmn;|&#177;/g,
///_|_12_|1\/2|&frac12;|&#189;/g,
///_|_14_|1\/4|&frac14;|&#188;/g,
///_|_34_|3\/4|&frac34;|&#190;/g,
///¹|_314_|3\.14|&pi;|&#960;/g,
///¢| _CNT_ |&cent;|&#162;/g,
///¼| _DEG_ |&deg;|&#176;/g,
///¥| _BUL_ |&bull;|&#8226;/g,
  /\_|_UDS_|&#95;/g,
  /\<|_LT_|&lt;|&#60;|&#x3C;/g,
  /\>|_GT_|&gt;|&#62;|&#x3E;/g,
  /\(|_LP_|&#40;/g,
  /\)|_RP_|&#41;/g,
  /\{|_LCB_|&#123;/g,
  /\}|_RCB_|&#125;/g,
  /\[|_LSB_|&#91;/g,
  /\]|_RSB_|&#93;/g,
  /\?|_QM_|&#63;/g,
  /\!|_EM_|&#33;/g,
  /\.|_PER_|&#46;/g,
  /\,|_COM_|&#44;/g,
  /\:|_COL_|&#58;/g,
  /\;|_SC_|&#59;/g,
  /\~|_TIL_|&#126;/g,
  /\$|_DOL_|&#36;/g,
  /\%|_PCT_|&#37;/g,
  /\#|_NUM_|&#35;/g,
  /\@|_ATS_|&#64;/g,
  /\^|_CRT_|&#94;/g,
  /\=|_EQ_|&#61;/g,
  /\+|_ADD_|&#43;/g,
  /\-|_HYP_|&#45|_MIN_|&minus;|&#8722;|&#x2212;/g,
  /\*|_AST_|&lowast;|&#42;|&#x2217|_MUL_|&times;|&#215;|&#xD7;/g,
  /\/|_SLH_|&divide;|&#247;|&#xF7|_DIV_|&#47;/g,
  /\\|_BKS_|&#92;/g,
  /"|_QT_|&quot;|#34;|&#x22;|&ldquo;|&#8220;|&#x201C;|_LDQ_|&rdquo;|&#8221;|&#x201D;|_RDQ_/g,
  /'|_APS_|&apos;|&#39;|&lsquo;|&#8216;|&#x2018;|_LQ_|&rsquo;|&#8217;|&#x2019;|_RQ_/g,
  /&|_AMP_|&amp;|&#38;|&#x26;/g,
  /QED|_QED_/g
);

//-- ######################################################################## --
//-- # PRIVATE UTILITY FUNCTIONS                                            # --
//-- #   _guid_: create a unique id name                                    # --
//-- #   _nnil_: test if a value is non-nil                                 # --
//-- #   _inil_: test if a value is nil                                     # --
//-- #   _tvof_: returns either a non-nil value or false                    # --
//-- #                                                                      # --
//-- # USAGE:                                                               # --
//-- #   new_id   = _guid_();                                               # --
//-- #   variable = _nnil_(value);                                          # --
//-- #   boolean  = _inil_(value);                                          # --
//-- #   boolean  = _tvof_(value);                                          # --
//-- ######################################################################## --
function _guid_(){ var x=new Date();   return(x.getTime()); };
function _nnil_(){ var x=arguments[0]; return((x!=''&&x!=0&&x!=false||x!=null&&x!=undefined)?(true):(false)); };
function _inil_(){ var x=arguments[0]; return((x==''||x==0||x==false||x==null||x==undefined)?(true):(false)); };
function _tvof_(){ var x=arguments[0]; return((_nnil_(x))?(x):(false)); };
function _tvoe_(){ var x=arguments[0]; return((_nnil_(x))?(x):(''));    };

//-- ######################################################################## --
//-- # PUBLIC UTILITY FUNCTIONS                                             # --
//-- ######################################################################## --
function getUid(){ return(_guid_());                   };                       // GET A NEW ID NAME
function notNil(){ return(_nnil_(arguments[0]));       };                       // TEST IF A VALUE IS NOT NIL
function itsNil(){ return(_inil_(arguments[0]));       };                       // TEST IF A VALUE IS NIL
function  toVOE(){ return(_tvoe_(arguments[0]));       };                       // RETURN A VALUE OR EMPTY STRING
function  toVOF(){ return(_tvof_(arguments[0]));       };                       // RETURN A VALUE OR FALSE
function  toTOF(){ return(toBln(toVOF(arguments[0]))); };                       // RETURN TRUE OR FALSE
function  toBln(){ return(notNil(arguments[0]));       };                       // CONVERT TO A BOOLEAN
function  toStr(){ return(arguments[0]+'');            };                       // CONVERT TO A STRING
function  toNum(){ return(arguments[0]-0 );            };                       // CONVERT TO A NUMBER

//-- ######################################################################## --
//-- # STRING EXTENSIONS:                                                   # --
//-- #   contains: see if one or more words are in a string                 # --
//-- #   qsa2ary:  convert a querystring into array of key=value elements   # --
//-- #   decodeit:  unescape a string + hex-to-ascii conversion of '"&:/,.  # --
//-- #   noCache:  adds 'nocache=milliseconds_since_1970_01_01_0000' as a   # --
//-- #             querystring argument                                     # --
//-- # USAGE:                                                               # --
//-- #   boolean_flag = string.contains('x|y|z');                           # --
//-- #   new_array    = querystring.qsa2ary();                              # --
//-- #   ascii_string = hex_string.decodeit();                              # --
//-- #   query_string = query_string.noCache();                             # --
//-- ######################################################################## --
function docWrite(){ document.write((arguments[0])?(arguments[0]):(this)); };
String.prototype.docWrite = docWrite;
String.prototype.noCache  = function (){ return(this+((this.indexOf("?")==-1)?('?'):('&'))+'nocache='+(new Date().getTime())); };
String.prototype.contains = function (){ var a=arguments[0]; a=((a.indexOf('|')>-1)?(a.split('|')):(new Array(a))); for(var x=0; x<a.length; x++) if(this.indexOf(a[x])>-1) return(true); return(false); };
String.prototype.qsa2ary  = function (){ var x=((this.indexOf('?')>-1)?((this.split('?'))[1]):(this)); return(x.split('&')); };
String.prototype.decodeit = function (){ return(this._encode_(0)); };
String.prototype.encodeit = function (){ return(this._encode_(1)); };
String.prototype._encode_ = function (){
  var s,r,x,w=arguments[0]+0, a=gAryS_R, t=this;
  for(x=0; x<a.length; x++){
    s=a[x];   r=a[x].toString();   r=r.substring(1,r.length-1); r=r.split('|')[w];
    if(!w&&r.substring(0,1)=='\\') r=r.substring(1,r.length);   t=t.replace(s,r);
  };
  t=((!w)?(unescape(t)):(escape(t)));
  return(t);
};

//-- ######################################################################## --
//-- # ARRAY EXTENSIONS                                                     # --
//-- #   valueIs: set an array element to key=value                         # --
//-- #   valueOf: see if a value exists in an array of key=value elements   # --
//-- #                                                                      # --
//-- # USAGE:                                                               # --
//-- #   old_value = array.valueOf('key');                                  # --
//-- #   new_value = array.valueIs('key','value');                          # --
//-- ######################################################################## --
Array.prototype.valueIs = function (){ for(var x=y=0; x<this.length; x++) if((this[x]).indexOf(arguments[0])==0) y=(this[x])=arguments[0]+'='+arguments[1]; if(!y) y=this[this.length]=arguments[0]+'='+arguments[1]; return(y); };
Array.prototype.valueOf = function (){ for(var x=y=k=v=0; x<this.length; x++){ y=(((this[x]).split)?((this[x]).split('=')):(false)); k=((y)?(y[0]):(false)); v=((k)?(y[1]):(false)); if(k==arguments[0]) return(v); }; return(false); };

//-- ######################################################################## --
//-- # WINDOW EXTENSIONS                                                    # --
//-- ######################################################################## --
function gciExtendWindowExtensions(){                                           // EXTEND WINDOW OBJECT FUNCTION
  window.urlHtm = window.location+'';                                           // REMEMBER THE WINDOW'S URL
  window.aryQsa = window.urlHtm.qsa2ary();                                      // REMEMBER THE WINDOW'S QUERYSTRING ARGUMENTS

  window.addLoadEvent = function (){                                            // ADD A NEW FUNCTION CALL TO THE window.onLoad EVENT HANDLER
    var n=arguments[0];                                                         // GET THE NEW FUNCTION CALL
    var o=window.onload;                                                        // GET THE OLD onLoad FUNCTION
    window.onload=((typeof(o)!='function')?(n):(function(){ o(); n(); }));      // RESET OR APPEND ON THE NEW FUNCTION CALL
	};

  window.addUnloadEvent = function (){                                          // ADD A NEW FUNCTION CALL TO THE window.onUnLoad EVENT HANDLER
    var n=arguments[0];                                                         // GET THE NEW FUNCTION CALL
    var o=this.onunload;                                                        // GET THE OLD onUnLoad FUNCTION
    window.onunload = ((typeof(o)!='function')?(n):(function(){ o(); n(); }));   // RESET OR APPEND ON THE NEW FUNCTION CALL
	};

  // WINDOW COUNTER
  window.numCount = 0;                                                          // WINDOW COUNTER
  window.getCount = function (){ return(this.numCount); };                      // GET CURRENT COUNT
  window.setCount = function (){ this.numCount=parseInt(arguments[0]); };       // SET COUNTER VALUE
  window.incCount = function (){ this.numCount+=1; return(this.numCount); };    // INCREMENT THE COUNTER VALUE
  window.decCount = function (){ this.numCount-=1; return(this.numCount); };    // DECREMENT THE COUNTER VALUE

  // WINDOW TIMER
  window.numTimer = 0;                                                          // WINDOW TIMER
  window.setTimer = function (){ window.numTimer=parseInt(_guid_()); };         // START THE TIMER
  window.getTimer = function (){                                                // STOP THE TIMER AND RETURN THE DIFFERENCE
    var x=parseInt(getUid());
    x=((window.numTimer>0)?(x-window.numTimer):(0));
    window.numTimer=0; return(x);
  };

  // WINDOW POPUP
  window.popup = function (){                                                   // CREATE A NEW POPUP WINDOW
    var d=((arguments.length==2)?(arguments[1]):("popup"+_guid_()+""));         // SEE IF WE HAVE A NAME TO USE, ELSE MAKE ONE
    var w=window.open("",d,'');                                                 // CREATE THE NEW WINDOW
    w.document.open();                                                          // OPEN THE DOCUMENT FOR WRITING
    w.document.write(arguments[0]);                                             // WRITE IN THE CONTENTS
    w.document.close();                                                         // CLOSE WRITING TO THE DOCUMENT
    w.owner=window;                                                             // REMEMBER WHO CREATED IT
    return(w);                                                                  // RETURN THE NEWLY CREATED WINDOW
	};
};

//-- ######################################################################## --
//-- # NAVIGATOR EXTENSIONS                                                 # --
//-- ######################################################################## --
function gciExtendNavigatorExtensions(){                                        // EXTEND NAVIGATOR OBJECT FUNCTION
  // NONE AT THIS TIME
};

//-- ######################################################################## --
//-- # DOCUMENT EXTENSIONS                                                  # --
//-- ######################################################################## --
function gciExtendDocumentExtensions(){                                         // EXTEND DOCUMENT OBJECT FUNCTION
  document.urlHtm = self.location.toString();                                   // REMEMBER THE DOCUMENT'S URL
  document.aryQsa = document.urlHtm.qsa2ary();                                  // REMEMBER THE DOCUMENT'S QUERYSTRING ARGUMENTS
  document.strQsa = (document.urlHtm.split('?'))[1];                            // REMEMBER THE DOCUMENT'S QUERYSTRING
  document.addJs  = function (){ };
  document.addDiv = function (){                                                // ADD A NEW DIV TO THE DOCUMENT
    var x=this.getElementById(arguments[0]);                                    // FIRST SEE IF IT ALREADY EXISTS
    if(x==null){                                                                // IF IT DOESN'T
       x=this.createElement('div');                                             // CREATE THE ELEMENT
       x.id=((arguments[0])?(arguments[0]):(new Date.getTime()));               // GIVE IT AN ID
       if(arguments[1]) x.style.cssText=arguments[1];                           // GIVE IT STYLE PROPERTIES
       if(arguments[2]) x.innerHTML=arguments[2];                               // INSERT ANY CONTENT
       this.body.appendChild(x);                                                // ATTACH IT TO THE BODY ELEMENT
    }; return(x);                                                               // AND RETURN THE NEW DIV
  };
  document.addCss = function (){                                                // ADD CSS RULES TO THE DOCUMENT
    var i,a,r,x;                                                                // DEFINE LOCAL TEMP VARIABLES
    try{ x=toVOF(document.styleSheets[0]); } catch(i){ x=false; };              // SEE IF THERE'S AN EXISTING STYLESHEET
    if(x==false){                                                               // IF THERE ISN'T
       x=this.createElement('style');                                           // CREATE A NEW ONE
       x.type="text/css";                                                       // OF TYPE CSS
       (this.getElementsByTagName('head')[0]).appendChild(x);                   // AND ATTACHE IT TO THE HEAD ELEMENT
    }; x=document.styleSheets[0]; a=(arguments[0]).split("}");                  // SPLIT THE ARGUMENTS INTO INDIVIDUAL RULES
    // ADD EACH NEW STYLESHEET RULE USING THE CORRECT BROWSER-SUPPORTED METHOD
    if     (x.rules)   { for(i=0; i<a.length-1; i++){ r=a[i].split("{"); x.addRule(r[0],r[1]);   }; } // IE
    else if(x.cssRules){ for(i=0; i<a.length-1; i++){ if(toVOF(a[i])) x.insertRule(a[i]+'}', 0); }; } // FIREFOX, ETC
  };
};

//-- ######################################################################## --
//-- # EXECUTE NOW                                                          # --
//-- ######################################################################## --
gciExtendWindowExtensions();
gciExtendNavigatorExtensions();
gciExtendDocumentExtensions();

//-- ######################################################################## --
//-- # PRIVATE UTILITY FUNCTIONS                                            # --
//-- ######################################################################## --
function _type_(a){ var t,m;                                                    // DETAILED VERSTION OF 'typeof' FUNCTION
  // THIS IS PETER BELESIS' "dltypeof v1.0" FUNCTION, WITH SOME SLIGHT CHANGES
  // ORIGINAL CAN BE FOUND AT  http://www.webreference.com/dhtml/column68/
  //
  if(typeof(a)=='String') return('string');                                     // SIMPLE STRING TEST
  if(typeof(a)=='Number') return('number');                                     // SIMPLE NUMBER TEST

//  try { t=a.callee; } catch(e) { t=null; };
//  if(t!=null) return('arguments');

  try { t=a.toString(); } catch(e) { var t=null; };                             // TRY TO CONVERT ARGUMENT TO A STRING
  if(t!=null){                                                                  // IF WE COULD
    m=t.match( /^\[object (.*)\]$/i );                                          // SEE IF ITS AN OBJECT
    if(m!=null){                                                                // IF IT IS AN OBJECT
      switch((m[1]).toLowerCase()){                                             // SEE IF ITS IN OUR LIST
      case "nodelist":                                                          // IF ITS A "nodelist" OBJECT OR A
      case "htmlcollection":                                                    // OR AN 'htmlcollection' OBJECT OR AN
      case "elementarray":     return("domcollection"); break;                  // 'elementarray' OBJECT, RETURN 'domcollection'
      case "event":            return("event"); break;                          // WAS IT AN EVENT OBJECT?
      case "math":             return("math"); break;                           // WAS IT A MATH OBJECT?
      case "error":            return("error"); break;                          // WAS IT AN ERROR OBJECT?
      case "mimetypearray":    return("mimetypecollection"); break;             // WAS IT A MIME-TYPE ARRAY?
      case "pluginarray":      return("plugincollection"); break;               // WAS IT A PLUG-IN ARRAY
      case "windowcollection": return("window"); break;                         // WAS IT A WINDOW OBJECT?
      default: if(m[1])        return((m[1]).toLowerCase()); break;             // ELSE, RETURN ITS INTERNAL TYPE IF IT HAS ONE
      }
    }
  }                                                                             // CONTINUE IF NOTHING MATCHED
  try { t=a.constructor; } catch(e) { t=null; };                                // SEE IF IT WAS CREATED BY A CLASS CONSTRUCTOR
  if(t!=null){                                                                  // IF THERE IS A CONSTRUCTOR FUNCTION
    switch(t){                                                                  // SEE IF ITS IN OUT LIST
    case Array:           return("array");    break;                            // WAS IT CREATED VIA 'new Array()' ?
    case Date:            return("date");     break;                            // WAS IT CREATED VIA 'new Date()' ?
    case RegExp:          return("regexp");   break;                            // WAS IT CREATED VIA 'new RegExp()' ?
    case Object:          return("jsobject"); break;                            // WAS IT CREATED VIA 'new Object()' ?
    case ReferenceError:  return("error");    break;                            // WAS IT CREATED VIA 'new Error()' ?
    }
  }                                                                             // CONTINUE IF NOTHING MATCHED
  try { t=a.constructor.toString(); } catch(e) { t=null; };                     // TRY TO GUESS BASED ON ITS CONSTRUCTOR NAME
  if(t!=null){                                                                  // IF THERE IS ONE
    t=t.match(/\s*function (.*)\(/);                                            // WAS IT CREATED VIA 'new functionName()' ?
    if(t!=null) return((t[1]).toLowerCase());                                   // IF SO, RETURN THE FUNCTION'S NAME
  };                                                                            // CONTINUE IF NOTHING MATCHED
  try { t=a.nodeType; } catch(e) { t=null; };                                   // TRY TO GUESS BASED ON ITS NODE TYPE
  if(t!=null){                                                                  // IF THERE IS ONE
    switch(t){                                                                  // SEE IF ITS IN OUR LIST
    case 1: if(a.item==null) return("domelement"); break;                       // IF ITS NOT A TEXT NODE & NO 'item' PROPERTY, ASSUME GENERIC 'domelement'
    case 3: return("textnode"); break;                                          // ELSE ITS A TEXT MODE
    };
  };                                                                            // CONTINUE IF NOTHING MATCHED
  try { t=window.event; m=event.type; e=a.type; } catch(e) { t=m=e=null; };
  if(t!=null&&m!=null) if(m==e) return('event');

  try { t=a.item; } catch(e) { t=null; };
  if(t!=null) return('domcollection');

  return(t);                                                                    // OTHERWISE RETURN WHAT WE'RE LEFT WITH
};

function _isit_(){ var a=arguments; return(_type_(a[0])==a[1]?true:false); };   // IS ARGUMENT 1 OF TYPE ARGUMENT 2
function _isnt_(){ var a=arguments; return(_type_(a[0])!=a[1]?true:false); };   // IS ARGUMENT 1 NOT OF TYPE ARGUMENT 2

function _test_(){ var x=navigator.userAgent; alert(x); return(x); };           // TEST FUNCTION THAT ALERTS THE USER AGENT STRING
function _exam_(){ var x;                                                       // TEST ENVIRONMENT'S FUNCTIONALITY
  debug(window.addLoadEvent);                                                   // TEST FOR OUR WINDOW EXTENSIONS
  debug(window.urlHtm);                                                         // TEST FOR OUR NAVIGATOR EXTENSIONS
  debug(document.addDiv);                                                       // TEST FOR OUR DOCUMENT EXTENSIONS
  debug(_test_());                                                              // INCLUDE OUR SIMPLE TEST FUNCTION
  x=/\n/;              x.debug();                                               // CAN WE CREATE A REGULAR EXPRESSION?
  x={ a:1, b:2, c:3 }; x.debug();                                               // CAN WE CREATE AN OBJECT?
  x=[ 'a', 'b', 'c' ]; x.debug();                                               // CAN WE CREATE AN ARRAY?
  x=10000000.00000001; x.debug();                                               // CAN WE CREATE A NUMBER?
  x='The quick brown'; x.debug();                                               // CAN WE CREATE A STRING?
  x=x.contains('The'); x.debug();                                               // TEST FOR OUR STRING EXTENSIONS
};

function _prep_(){                                                              // PREPARE OUR DEBUGGING ENVIRONMENT
  var t,d=document.getElementById('divDebug');                                  // SEE IF THERE'S A DEBUG DIV ALREADY CREATED
  if(d==null){                                                                  // IF NOT THEN CREATE THE NECESSARY TEXT STYLES
    t='#infoText { font-family:monospace; font-size:8pt; } '+                   // FOR ELEMENT NAMES
      '#infoProp { color:#880000; font-weight:bold; } '+                        // FOR ELEMENT PROPERTIES
      '#infoType { color:#000088; text-decoration:underline; } '+               // FOR ELEMENT TYPES AND
      '#infoValue{ color:#006600; }';                                           // FOR ELEMENT VALUES
    document.addCss(t);                                                         // AND ADD THEM TO THE CURRENT STYLE SHEET
    t='position:absolute; left:1px; width:90%; top:1px; height:25%; '+
      'overflow:scroll; font-family:monospace; font-size:8pt; '+
      'z-index:999; background-color:#aaaaaa; visibility:visible; '+
      'padding:9px; margin:9px; '+ ((navigator.appGid=='micro')?
     ('filter:alpha(opacity=85); '):('opacity:.85; '));
    d=document.addDiv('divDebug',t);                                            // CREATE THE DIV IF IT DOESN'T ALREADY EXIST
  } return(d);                                                                  // RETURN THE DIV
};

function _info_(){                                                              // GIVE DETAILED OUTPUT OF AN ELEMENTS PROPERTIES
  if(gBlnDebug){                                                                // IF WE'RE DEBUGGING
    var a=arguments[0];                                                         // GRAB THE ARGUMENT
    var d=document.getElementById('divDebug');                                  // SEE IF THERE IS A DEBUG LAYER
    var h,t,e='<br>';                                                           // DEFINE TEMP AND ERROR VARIABLES
    if(d==null) d=_prep_();                                                     // IF THERE ISN'T A DEBUG LAYER, CREATE ONE
    if(d){                                                                      // IF WE NOW HAVE A DEBUG LAYER
      if(arguments.length==2){ h=window.incCount()+' '+a; }                     // DO THEY WANT A SIMPLE PRINTOUT
      else{                                                                     // OR A DETAILED PRINTOUT
        t=((toVOF(a))?(toVOF(a)):(a));                                          // DOES THE ARGUMENT HAVE A VALUE
        t=((t.length)?(t.toString()):(t));                                      // IF ITS AN ARRAY, CONVERT IT DO A STRING
        t=((t.id)    ?(t.id):(t));                                              // SET ITS NAME TO BE ITS ID PROPERTY IF IT HAS ONE
        t=((t.name)  ?(t.name):(t));                                            // SET ITS NAME TO BE ITS ID PROPERTY IF IT HAS ONE
        h='<b>'+_type_(a)+': '+t+'</b><br>\n'+                                  // PRINT 'argumentType : argumentId'
          '<span id="infoProp">'+(_tvof_(a.id)?'id:':'typeof:') +'</span>'+     // PRINT 'id : ' or 'typeof: ' LABEL
          '<span id="infoType">'+(_tvof_(a.id)?a.id : typeof(a))+'</span><br>'; // PRINT ARGUMENT'S ID OR TYPE
        for(var p in a){                                                        // FOR EACH PROPERTY IN OUR ARGUMENT
          t = _type_(a[p]);                                                     // GET ITS TYPE
          h+='<nobr><span id=infoProp>'+p+'</span>:';                           // SET THE PROPERTY NAME
          h+='<span id=infoType>'+t+'</span> = ';                               // SET THE PROPERTY TYPE
          switch(t){                                                            // SET THE PROPERTY VALUE
          case 'object':   t='[object]'; break;                                 // OR AN OBJECT
          case 'array':    t=a[p].toString(); break;                            // IF ITS AN ARRAY SET THE VALUE TO THE ENTIRE ARRAY AS ONE STRING
          case 'function': t='[function]'+a[p].name;; break;                    // UNLESS ITS A FUNCTION
          default:         try { t=a[p]; } catch(e){ t='Unknown'; }; break;     // OTHERWISE, SEE IF WE CAN GET ITS VALUE
          };
          h+='<span id=infoValue>'+t+'</span></nobr><br>\n';                    // AND PRINT IT
        };
      }; if(h) d.innerHTML+=h+e;                                                // ADD IN A LINE BREAK AND PRINT IT OUT TO THE LAYER
    };
  };
};

//-- ######################################################################## --
//-- # PUBLIC API                                                           # --
//-- ######################################################################## --
function itsNum(){ return(_isit_(arguments[0],'number'));   };
function itsStr(){ return(_isit_(arguments[0],'string'));   };
function itsBln(){ return(_isit_(arguments[0],'boolean'));  };
function itsFun(){ return(_isit_(arguments[0],'function')); };
function itsObj(){ return(_isit_(arguments[0],'object'));   };
function notNum(){ return(_isnt_(arguments[0],'number'));   };
function notStr(){ return(_isnt_(arguments[0],'string'));   };
function notBln(){ return(_isnt_(arguments[0],'boolean'));  };
function notFun(){ return(_isnt_(arguments[0],'function')); };
function notObj(){ return(_isnt_(arguments[0],'object'));   };
function whatis(){ return(_type_(arguments[0]));            };
function  debug(){ return(_info_(arguments[0]));            };
function  trace(){
  var l=arguments.length==2?arguments[1]:0;
  if(l<gBlnDebug) return(_info_(arguments[0],1));
};

//-- ######################################################################## --
//-- # GLOBAL VARIABLES                                                     # --
//-- ######################################################################## --
var gHasVbs=gSax=gVbs=gWmp=gSwf=false;                                          // VBScript FLAG AND SHORTHAND GLOBAL VARIABLE NAMES
var gStrWin='win|16bit';                                                        // WINDOW'S IDs
var gStrMac='mac|apple|osx|os x|darwin';                                        // MACINTOSH IDs
var gStrBsd='bsd|gnu|sun|darwin';                                               // BSD DERIVATIVE IDs
var gStrSv4='aix|alpha|dec|hpux|irix|osf|sco|solaris|tru|ultrix|unix|x11';      // SYSTEM V REV. 4 DERIVATIVE IDs
var gStrLnx='debian|fedora|gentoo|gnu|man|pix|red|slack|suse|ubuntu|nux';       // MAJOR LINUX DISTRIBUTION IDs
var gStrUnx='damnsmall|dog|free|kate|kom|penguin|tux|ppc';                      // ALL OTHER UNICES DERIVATIVE ID's
var gStrNix=gStrBsd+'|'+gStrSv4+'|'+gStrLnx+'|'+gStrUnx;                        // NIX IDs

//-- ######################################################################## --
//-- # WINDOW EXTENSIONS                                                    # --
//-- ######################################################################## --
function gciExtendWindowSniffer(){                                              // EXTEND WINDOW OBJECT FUNCTION
  window.blnTax = ((window.ActiveXObject)?(true):(false));                      // TRIDENT (IE) ACTIVE X FLAG
  window.blnGax = ((window.GeckoActiveXObject)?(true):(false));                 // GECKO ACTIVE X FLAG
  window.getAxo = function (){                                                  // TRY TO GET AN ACTIVE X OBJECT
    try{                                                                        // IF WE CAN, MEANING:
      if     (window.blnTax){ return(new ActiveXObject(arguments[0]));      }   // RETURN THE ActiveXOjbect FUNCTION RESULTS
      else if(window.blnGax){ return(new GeckoActiveXObject(arguments[0])); };  // OR THE GeckoActiveXObject FUNCTION RESULTS
    } catch(gStrErr){ };                                                        // DIE GRACEFULLY
    return(false);                                                              // WE DON'T HAVE THE ACTIVE X OBJECT
  };
};

//-- ######################################################################## --
//-- # NAVIGATOR EXTENSIONS                                                 # --
//-- ######################################################################## --
function gciExtendNavigatorSniffer(){                                           // EXTEND NAVIGATOR OBJECT FUNCTION
  navigator.getPlugin=function (){ var x,y,z,f=false;                           // CHECK PLUGIN ARRAY FUNCTION
    if(navigator.plugins&&navigator.plugins.length>0){                          // IF THE ARRAY EXISTS AND IT ISN'T EMPTY
      for(x=0; x<navigator.plugins.length; x++){                                // GO THROUGH EACH PLUG-IN AND
        for(z=y=0; y<arguments.length; y++)                                     // ALL ARGUMENTS TO MATCH AGAINST
          if((navigator.plugins[x].name.indexOf(arguments[y])>=0)||             // IF THE NAME MATCHES OR
             (navigator.plugins[x].description.indexOf(arguments[y])>=0)) z++;  // OR THE DESCRIPTION DOES, FLAG IT
        if(z==arguments.length){ f=true; break; };                              // IF ANYTHING WAS FLAGGED RETURN TRUE
    }; }; return(f);                                                            // RETURN FALSE
  };

  navigator.getWmp=function (){                                                 // CHECK FOR WINDOWS MEDIA PLAYER
    return((gHasVbs)?                                                           // IF WERE ON IE CHECK FOR EITHER
           (getActiveXControl('MediaPlayer.MediaPlayer.1')||                    // MediaPlayer ACTIVE X CONTROL OR
            getActiveXControl('WMPlayer.OCX.7')):                               // THE WMPlayer ACTIVE X CONTROL
           (navigator.getPlugin('Windows Media')));                             // ELSE CHECK THE PLUG-IN ARRAY
  };
  
  navigator.getSwf=function (){                                                 // CHECK FOR MACROMEDIA FLASH PLAYER
    return((gHasVbs)?                                                           // IF WERE ON IE CHECK FOR 
           (getActiveXControl('ShockwaveFlash.ShockwaveFlash.1')):              // ITS ACTIVE X CONTROL (.# can be 1-8)
           (navigator.getPlugin('Shockwave','Flash')));                         // ELSE CHECK THE PLUG-IN ARRAY
  };

  navigator.getEnv=function (){                                                 // GET ENVIRONMENT DATA
    var x='<pre><h1>Browser Info:</h1>'+                                        // PRINT HEADER
          'Browser is part of group: '+navigator.appGid+'<br>'+                 // BROWSER GROUP
          'Engine build number:      '+navigator.appVer+'<br>'+                 // BROWSER VERSION
          'Has Windows Media Player: '+navigator.hasWmp+'<br>'+                 // IF WMP IS INSTALLED
          'Has Macromedia Flash:     '+navigator.hasSwf+'</pre>';               // IF SWF IS INSTALLED
    document.write(x);                                                          // AND WRITE IT ALL OUT
  };

  navigator.getBW=function (){                                                  // GET BANDWIDTH SPEED
    navigator.strBwSpeed     = '';                                              // INITIALIZE TO NOTHING
    navigator.numBwThreshold = 5000;                                            // ~25KB file/~4.9kbs connection * 1000 milliseconds seconds
    navigator.numBwStart     = (new Date()).getTime();                          // START THE TIMER
		if(typeof(kUrlInc)=='undefined') kUrlInc='/scripts/gciplayer/common/';      // COMMON INCLUDES DIRECTORY
    var u=(kUrlInc+'25k.png?'+navigator.numBwStart);                            // DEFINE BANDWIDTH IMAGE URL
    var x='<div id="divBw" style="position:absolute; visibility:hidden; '+      // DEFINE BANDWIDTH IMAGE DIV
          ' display:none; left:-2000; top:-2000; width:100px; height:100px;">'+ // CONTAINER'S STYLE
          '<img src="'+u+'" onLoad="navigator.setBW()" /></div>';               // LOAD THE IMAGE AND TEST BANDWIDTH
    document.write(x);                                                          // ADD IT TO THE DOCUMENT
  };

  navigator.setBW=function (){                                                  // SET THE BANDWIDTH DEFAULT SPEED
    var x = (((new Date()).getTime())-navigator.numBwStart);                    // GET THE TIME IT TOOK TO LOAD THE 25k IMAGE
    navigator.strBwSpeed=((x<navigator.numBwThreshold)?('2'):('1'));            // IF ITS < OUR THRESHOLD, WE HAVE HIGH BANDWIDTH
  };

  navigator.setVB=function (){                                                  // SET THE VBSCRIPT FLAG
    if((navigator.userAgent.indexOf('MSIE')!=-1)&&                              // IF WE'RE RUNNING IE
       (navigator.userAgent.indexOf('Win') !=-1)){                              // ON WINDOWS
      document.writeln('<script language="VBscript">');                         // WRITE THE FOLLOWING VBSCRIPT
      document.writeln('gHasVbs = False');                                      // INITIALIZE FLAG TO FALSE
      document.writeln('If ScriptEngineMajorVersion >= 2 then');                // IF WERE ON IE 4.0 OR ABOVE
      document.writeln('  gHasVbs = True');                                     // THEN SET THE FLAG TO TRUE
      document.writeln('End If');                                               // OTHERWISE LEAVE IT AS FALSE
      document.writeln('Function getActiveXControl(activeXControlName)');       // ACTIVE X CONTROL LOOKUP FUNCTION
      document.writeln('  on error resume next');                               // KEEP GOING IF WE GET AN ERROR
      document.writeln('  getActiveXControl = False');                          // INITIALIZE FLAG TO FALSE
      document.writeln('  If gHasVbs Then');                                    // IF WE HAVE VBSCRIPT
      document.write  ('     getActiveXControl = ');                            // SET THE FLAG TO THE OUTCOME OF
      document.writeln('        IsObject(CreateObject(activeXControlName))');   // CREATING AND TESTING THE CONTROL
      document.writeln('  End If');
      document.writeln('End Function');
      document.writeln('</scr' + 'ipt>');
    };
  };

  navigator.setJS=function (){                                                  // SET THE JAVASCRIPT FLAG
    if(!navigator.jsVer){                                                       // IF IT HASN'T BEEN SET ALREADY
      document.write('<scr'+'ipt language="JavaScript1.1">navigator.jsVer=1.1;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript1.2">navigator.jsVer=1.2;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript1.3">navigator.jsVer=1.3;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript1.4">navigator.jsVer=1.4;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript1.5">navigator.jsVer=1.5;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript1.6">navigator.jsVer=1.6;</scr'+'ipt>');
      document.write('<scr'+'ipt language="JavaScript2.0">navigator.jsVer=2.0;</scr'+'ipt>');
    };
  };
  
  navigator.setUA=function (){ var u=navigator.userAgent.toLowerCase();         // SET THE USERAGENT FLAGS
    if(!navigator.appGid||!navigator.appVer||!navigator.appSys){                // IF THEY HAVEN'T BEEN SET ALREADY
      if     (u.contains(gStrWin))         navigator.appSys='win';              // RUNNING ON WIN
      else if(u.contains(gStrMac))         navigator.appSys='mac';              // RUNNING ON MAC
      else if(u.contains(gStrNix))         navigator.appSys='nix';              // RUNNING ON NIX
      if     (u.match(/mac_powerpc/)){     navigator.appGid='macro'; navigator.appVer=parseFloat(u.match(/msie ([0-9.]+)/)[1]); }
      else if(u.match(/safari/)){          navigator.appGid='khtml'; navigator.appVer=parseFloat(u.match(/[0-9.]+$/));          }
      else if(window.opera){               navigator.appGid='opera'; navigator.appVer=parseFloat(u.match(/[\d.\d]+$/));         }
      else if(!(u.match(/firefox/)) && window.external){            navigator.appGid='micro'; navigator.appVer=parseFloat(u.match(/msie ([0-9.]+)/)[1]); }
      else if(navigator.vendor=='Camino'){ navigator.appGid='gecko'; navigator.appVer=navigator.vendorSub;                      }
      else if(navigator.product=='Gecko'){ navigator.appGid='gecko'; navigator.appVer=parseFloat(u.match(/rv:([0-9.]+)/)[1]);   }
    }
  };
  navigator.getBW();                                                            // START THE BANDWIDTH SPEED TEST
  navigator.setVB();                                                            // SET VBSCRIPT FLAG
  navigator.setJS();                                                            // SET JAVASCRIPT FLAG
  navigator.setUA();                                                            // SET BROWSER ID & VERSION FLAGS
  navigator.hasVbs = gVbs = gHasVbs;                                            // ADD VB FLAG
  navigator.hasWmp = gWmp = navigator.getWmp();                                 // ADD WMP FLAG
  navigator.hasSwf = gSwf = navigator.getSwf();                                 // ADD FLASH FLAG
};

//-- ######################################################################## --
//-- # EXECUTE NOW                                                          # --
//-- ######################################################################## --
gciExtendWindowSniffer();
gciExtendNavigatorSniffer();
