function browserdetector() {

  // string comparisons are much easier if we lowercase everything now.
  // to make indexOf() tests more compact/readable, we prepend a space 
  // to the userAgent string (to get around '-1' indexOf() comparison)
  var n = navigator;
  var ua = ' ' + n.userAgent.toLowerCase();

  // browser version
  this.version = n.appVersion;
  this.major = parseInt(this.version);		// note: ie5 says 4
  this.minor = parseFloat(this.version);	// full number
  
  // browser application
  this.opera = ua.indexOf('opera') > 0;
  this.webtv = ua.indexOf('webtv') > 0;
  this.hotjava = ua.indexOf('hotjava') > 0;
  this.tvnav = ua.indexOf('navio') > 0;
  this.ie = ua.indexOf('msie') > 0 && !this.opera;
  this.aol = ua.indexOf('aol') > 0;
  this.omniweb = ua.indexOf('omniweb') > 0;
  this.galeon = ua.indexOf('galeon') > 0;
  this.gecko = ua.indexOf('gecko') > 0;
  this.konq = ua.indexOf('konqueror') > 0;
  this.nav = ua.indexOf('mozilla') > 0 
    && ua.indexOf('compatible') == -1 && ua.indexOf('spoofer') == -1
    && !this.webtv && !this.opera && !this.hotjava;
  
  // browser application version - nav
  this.nav2 = this.nav && this.major == 2;
  this.nav3 = this.nav && this.major == 3;
  this.nav4 = this.nav && this.major == 4;
  this.nav4up = this.nav && this.major >= 4;
  this.nav6 = this.nav && this.major == 5;
  this.nav6up = this.nav && this.major >= 5;

  // browser application version - ie
  this.ie3 = this.ie && this.major < 4;
  this.ie4 = this.ie && this.major == 4 && ua.indexOf('msie 4') > 0;
  this.ie4up = this.ie && this.major >= 4;
  this.ie5 = this.ie && this.major == 4 && ua.indexOf('msie 5.0') > 0;
  this.ie5up = this.ie4up && !this.ie4;
  this.ie55 = this.ie && this.major == 4 && ua.indexOf('msie 5.5') > 0;
  this.ie55up = this.ie5up && !this.ie5;
  this.ie6 = this.ie && this.major == 4 && ua.indexOf('msie 6.') > 0;
  this.ie6up = this.ie55up && !this.ie55;

  // browser application version - aol
  this.aol3  = this.aol && this.ie3;	// unreliable
  this.aol4  = this.aol && this.ie4;	// unreliable
  this.aol5  = ua.indexOf('aol 5') > 0;
  this.aol6  = ua.indexOf('aol 6') > 0;
  
  // browser application version - opera
  this.opera2 = ua.indexOf('opera 2') > 0 || ua.indexOf('opera/2') > 0;
  this.opera3 = ua.indexOf('opera 3') > 0 || ua.indexOf('opera/3') > 0;
  this.opera4 = ua.indexOf('opera 4') > 0 || ua.indexOf('opera/4') > 0;
  this.opera5 = ua.indexOf('opera 5') > 0 || ua.indexOf('opera/5') > 0;
  this.opera5up = this.opera && !this.opera2 && !this.opera3 && !this.opera4;
  //? this.opera6 = ua.indexOf('opera 6') > 0 || ua.indexOf('opera/6') > 0;
  //? this.opera7 = ua.indexOf('opera 7') > 0 || ua.indexOf('opera/7') > 0;

  // browser application version - konqueror - MvZ 
  this.konq3 = ua.indexOf('konqueror/3') > 0;
  this.konq3up = this.konq && this.major >= 5;
  
  // browser application version - hotjava
  this.hotjava3 = this.hotjava && this.major == 3;
  this.hotjava3up = this.hotjava && this.major >= 3;

  // javascript version
  if (this.nav2 || this.ie3) this.js = 1.0;
  else if (this.nav3) this.js = 1.1;
  else if (this.opera5up) this.js = 1.3;
  else if (this.opera) this.js = 1.1;
  else if ((this.nav4 && (this.minor <= 4.05)) || this.ie4) this.js = 1.2;
  else if ((this.nav4 && (this.minor > 4.05)) || this.ie5) this.js = 1.3;
  else if (this.hotjava3up) this.js = 1.4;
  else if (this.nav6 || this.gecko) this.js = 1.5;
  // NOTE: In the future, update this code when newer versions of JS
  // are released. For now, we try to provide some upward compatibility
  // so that future versions of Nav and IE will show they are at
  // *least* JS 1.x capable. Always check for JS version compatibility
  // with > or >=.
  else if (this.nav6up) this.js = 1.5;
  // NOTE: ie5up on mac is 1.4
  else if (this.ie5up) this.js = 1.3
  else js = 0.0;  // we don't know

  // workarounds
  // - IE5/Mac reports itself as version 4.0
  if(this.ie && this.mac) {
    var idx = ua.indexOf("msie 5");
    if(idx>0) {
      this.major = 5;
      var actual_major = ua.substring(idx+5, idx+8);
      this.minor = parseFloat(actual_major);
    }
  }

  return this;
}

