// Detect the client's browser
// ---------------------------
function detectBrowser() {
   window.DOM = window.IE = window.NS4 = window.NS6 = window.OP = window.KQ = false;
   if (document.getElementById)                                DOM = true;
   if (window.opera)                                           OP  = true;
   if (navigator.vendor == 'KDE')                              KQ  = true;
   if (document.all && !OP && !KQ)                             IE  = true;
   if (!DOM && !OP && !KQ && window.netscape && window.screen) NS4 = true;
}
detectBrowser();


// Extend the String object
// ------------------------
String.prototype.decodeEntities = function()       { return this.replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&Auml;/g, 'Ä').replace(/&Ouml;/g, 'Ö').replace(/&Uuml;/g, 'Ü').replace(/&auml;/g, 'ä').replace(/&ouml;/g, 'ö').replace(/&uuml;/g, 'ü').replace(/&szlig;/g, 'ß'); }
String.prototype.endsWith       = function(suffix) { var pos = this.lastIndexOf(suffix); return (pos != -1 && this.length == pos+suffix.length); }
String.prototype.startsWith     = function(prefix) { return (this.indexOf(prefix) === 0); }
String.prototype.trim           = function()       { return this.replace(/(^\s+)|(\s+$)/g, ''); }
if (IE) {
   String.prototype.substr_orig = String.prototype.substr;
   String.prototype.substr = function(start, length) {
      if (start < 0) {
         return this.substr_orig(this.length + start, length);
      }
      return this.substr_orig(start, length);
   }
}


// Find an object in the DOM and return it's reference
// ---------------------------------------------------                  // type: 'id', 'name' or 'tag'
function getObject(type, name, index) {                                 // name:  id or name value
   type = type.toLowerCase();                                           // index: the element's collection index
   var objects;
   if (DOM) {
      if (type=='id') {
         return document.getElementById(name);
      }
      else if (type=='name') {
         if (typeof(document.getElementsByName(name))=='object') {
            objects = document.getElementsByName(name);
            if (index === undefined && objects.length > 1)
               return alert("More than 1 object named '"+ name +"' found,\nplease specify an index !");
            if (index === undefined)
               index = 0;
            if (index < objects.length)
               return objects[index];
         }
      }
      else if (type=='tag') {
         if (typeof(document.getElementsByTagName(name))=='object' || (OP && typeof(document.getElementsByTagName(name))=='function')) {
            objects = document.getElementsByTagName(name);
            if (index === undefined && objects.length > 1)
               return alert('More than 1 '+ name +' tag found,\nplease specify an index !');
            if (index === undefined)
               index = 0;
            if (index < objects.length)
               return objects[index];
         }
      }
   }
   else if (IE) {
      if (type=='id') {
         return document.all[name];
      }
      else if (type=='tag') {
         if (typeof(document.all.tags(name))=='object') {
            objects = document.all.tags(name);
            if (index === undefined && objects.length > 1)
               return alert('More than 1 '+ name +' tag found,\nplease specify an index !');
            if (index === undefined)
               index = 0;
            if (index < objects.length)
               return objects[index];
         }
      }
      else if (type=='name') {
         return document[name];
      }
   }
   else if (NS4) {
      if (type=='id' || type=='name') {
         return document[name];
      }
      else if(type=='index') {
         return document.layers[name];
      }
   }
   return null;
}
window.$  = function(id) { return window.getObject('id', id); }
window.$$ = function(id) { return window.getObject('id', id); }


// Get the true body element (see http://www.quirksmode.org/viewport/compatibility.html)
// -------------------------------------------------------------------------------------
function getBody() {
   return (!OP && document.compatMode && document.compatMode!='BackCompat') ? document.documentElement : document.body;
}


// Show all known properties of an object
// --------------------------------------
function showProperties(object) {
   var properties = [],
       property   = '';
   for (var i in object) {
      try {
         property = object.toString() +'.'+ i +' = '+ object[i];
      }
      catch (ex) {
         property = object.toString() +'.'+ i +' = Exception while reading property (name: '+ ex.name +', message: '+ ex.message +')';
      }
      properties[properties.length] = property.replace(/</g, '&lt;').replace(/>/g, '&gt;');
   }
   if (properties.length) {
      properties = properties.sort();
      var win = open('', 'logWindow', 'resizable,scrollbars,width=700,height=800');
      if (win) {
         win.document.open();
         win.document.write('<span style="font:13px arial,helvetica,sans-serif">\n'+ properties.join('<br>\n') +'\n</span>');
         win.document.close();
         win.focus();
      }
      else
         alert('Cannot show properties of object '+ object +'.\nPlease disable popup blocker.');
   }
   else alert('Object '+ object +' has no known properties.');
}


// Log a message to the bottom of the current page or to a log window
// ------------------------------------------------------------------
var Logger = {
   out:      null,
   popup:    null,
   popupOut: null,

   log:     function(msg, target) { Logger.writeln(msg          , target); },
   writeln: function(msg, target) { Logger.write  (msg +'<br>\n', target); },

   write: function(msg, target) {
      if (!target) {
         if (!Logger.out) {
            var bodies = document.getElementsByTagName('body');
            if (!bodies || bodies.length===0)
               return alert('Logging error,\nyou can only log from inside the <body> tag !');
            var div = document.createElement('div');
            bodies[0].appendChild(div);
            Logger.out = div;
         }
         target = Logger.out;
      }

      if (target === true) {
         if (!Logger.popupOut) {
            var popup = open('', 'logWindow', 'resizable,scrollbars,width=600,height=400');
            if (!popup)
               return alert('Cannot open log window.\nPlease disable popup blocker.');

            popup.document.open();
            popup.document.write('<html><body style="font:13px arial,helvetica,sans-serif"></body></html>');
            popup.document.close();

            var div = popup.document.createElement('div');
            var bodies = popup.document.getElementsByTagName('body');
            bodies[0].appendChild(div);

            Logger.popup = popup;
            Logger.popupOut = div;
         }
         else if (Logger.popup.closed) {
            Logger.popup = Logger.popupOut = null;
            return Logger.write(msg, target);
         }
         target = Logger.popupOut;
      }

      /*
      if (type(target) == window) {
      }
      else if (target.innerHTML == undefined) {
      }
      */

      target.innerHTML += msg;
   },

   clear: function() {
      if (Logger.out)
         Logger.out.innerHTML = '';
      if (Logger.popup && !Logger.popup.closed && Logger.popupOut)
         Logger.popupOut.innerHTML = '';
   }
}
window.log = Logger.log;


// Log a message to the status bar
// -------------------------------
function logStatus(msg) {
   if (typeof(msg)=='object' && msg=='[object Event]') {
      logEvent(msg);
   }
   else {
      self.status = msg;
   }
   return true;
}


// Log event infos to the status bar
// ---------------------------------
function logEvent(ev) {
   ev = ev || window.event;
   if (IE) {
      logStatus(ev.type +' event,  window: ['+ ev.clientX +','+ ev.clientY +']  page: ['+ (getBody().scrollLeft + ev.clientX) +','+ (getBody().scrollTop + ev.clientY) +']');
   }
   else {
      logStatus(ev.type +' event,  window: ['+ (ev.pageX - pageXOffset) +','+ (ev.pageY - pageYOffset) +']  page: ['+ ev.pageX +','+ ev.pageY +']');
   }
   return true;
}

