var scrollfeld_div_position = 0;
var scroll_counter = 0;
var overflow = true;
var bAnimate = false;
var start_pos=1;
var sAnimate=false;
var start_counter = 0;
var last_pos = 1;
var event;
var _global = this;
var _done = true;
var pos = 1;
var ua = navigator.userAgent.toLowerCase();

var isIE = ua.indexOf('msie') > -1;

function PreloadImages() {
  if (document.images) {
    if (typeof(document.rm) == 'undefined'){
      document.rm = new Object();
    }
    document.rm.loadedImages = new Array();
    var argLength = PreloadImages.arguments.length;
    for(arg=0;arg<argLength;arg++) {
      document.rm.loadedImages[arg] = new Image();
      document.rm.loadedImages[arg].src = PreloadImages.arguments[arg];
    }
  }
}

function setOpacity(n,oopacity)
{

   //if (window.opera) {} else 
    img = document.getElementById(n); 
   // img = document.n; 
	if (isIE) {
		img.style.filter = 'Alpha(opacity=' + (oopacity*100) + ')';
	} else {
		if (!setStyleProperty(img, 'opacity', oopacity)) {
			setStyleProperty(img, 'mozOpacity', oopacity);
		}
    }
}


function fadeOut()
{
  n = 'bildtop';
  n2 = 'bildbottom';
  var me = arguments.callee;
  if (me.opacity > 0)
  {
    var op = (me.opacity -= 0.1);
    if (op < 0)
    {
      me.opacity = 0;
    }
  
    //if (window.opera) {} else 
    img = document.getElementById(n); 
   // img = document.n; 

    //if (window.opera) {} else 
    img2 = document.getElementById(n2); 
   // img2 = document.n2; 
	if (isIE) {
		img.style.filter = 'Alpha(opacity=' + (me.opacity*100) + ')';
		img2.style.filter = 'Alpha(opacity=' + ((1-me.opacity)*100) + ')';
	} else {
		
		if (!setStyleProperty(img, 'opacity', me.opacity))
		{
			setStyleProperty(img, 'mozOpacity', me.opacity);
		}
		if (!setStyleProperty(img2, 'opacity', 1-me.opacity))
		{
			setStyleProperty(img2, 'mozOpacity', 1-me.opacity);
		}
	}
  }
  else
  {
	  //var rmImage = "containertop";
	  //objStr = 'document.' + rmImage;
	  //obj = eval(objStr);
	  //obj.src = "";  
	  _done = true;
	  window.clearInterval(me.interval);
  }
}
      
function fadeStart(f, interval)
{
  if (isMethod(window, "setInterval")
      && isMethod(window, "clearInterval"))
  {
    var a;
    
    if (isMethod("Array")
        && isMethod(Array.prototype, "slice")
        && isMethod(Array.prototype.slice, "call"))
    {
      a = Array.prototype.slice.call(arguments, 2);
    }
    else
    {
      a = [];
      
      for (var i = 1, len = arguments.length; ++i < len;)
      {
        a[a.length] = arguments[i];
      }
    }

    if (typeof f == "string")
    {
      _done= false;
      _global[f].interval = window.setInterval(
        f + "(" + a.join(",") + ");", interval);
    }
    else if (typeof f == "function")
    {
      _done= false;
      f.interval = window.setInterval(function() { f(); }, interval, a);
    }
  }
}

function ImageSwap(Modus){
  var objStr,obj;
  var rmImage = "containertop";
  var rmImage2 = "containerbottom";
  var oldsub = eval("bildsub"+pos);
 
  switch (Modus) {
  case "next": if (pos<picmax) pos++; break;
  case "last": if (1<pos) pos--; break;
  }
  
  if (pos == 1) { show_div('nextpage'); hide_div('lastpage'); }
  if (pos == picmax) { hide_div('nextpage'); show_div('lastpage'); }
  if ((pos < picmax)&&(pos>1)) { show_div('nextpage'); show_div('lastpage'); }
	  
  rmSrc = eval("bildurl"+pos);
  alt = eval("bildalt"+pos);
  sub = eval("bildsub"+pos);
  //setCont('id','topsub',null,oldsub);
  //setCont('id','bottomsub',null,sub);

  if(_done==true) {
  if(document.images){
    if (typeof(rmImage) == 'string') {
      objStr = 'document.' + rmImage;
      objStr2 = 'document.' + rmImage2;
      obj = eval(objStr);
      obj2 = eval(objStr2);
               		  
      if (obj2.src.substr(obj2.src.length-rmSrc.length)!=rmSrc) {
      setOpacity("bildtop",0);
      setOpacity("bildbottom",1);
      obj.src = obj2.src; 
      obj.alt = obj2.alt;
      
      setCont('id','topsub',null,oldsub);
      setCont('id','bottomsub',null,sub);
	  
      //obj.onload = function()
      //{
          setOpacity("bildtop",1);
          setOpacity("bildbottom",0);
          obj2.src = rmSrc;
          obj2.alt = alt;


    	  obj2.onload = function()
    	  	{
    		  fadeOut.opacity = 1.0;
    		  fadeStart('fadeOut', 50);
    	  	} // function
      	} // if
      //}
      
    } else if ((typeof(rmImage) == 'object') && rmImage && rmImage.src) {
      if (rmImage2.src.substr(rmImage2.src.length-rmSrc.length)!=rmSrc) {
      setOpacity("bildtop",0);
      setOpacity("bildbottom",1);      
      rmImage.src = rmImage2.src;
      rmImage.alt = rmImage2.alt;
      setCont('id','topsub',0,oldsub);
      setCont('id','bottomsub',0,sub);
 
      rmImage.onload = function()
{
          setOpacity("bildtop",1);
          setOpacity("bildbottom",0);      
          rmImage2.src = rmSrc;
          rmImage2.alt = alt;
          
          rmImage2.onload = function() {
        	  fadeOut.opacity = 1.0;
        	  fadeStart('fadeOut', 50);
          } // function
          } // function
      } // if
      } //elseif
    } // if images
  } else {
	objStr = 'document.' + rmImage;
    objStr2 = 'document.' + rmImage2;
    obj = eval(objStr);
    obj2 = eval(objStr2);
               		  
    if (obj2.src.substr(obj2.src.length-rmSrc.length)!=rmSrc) {
 
    obj.src = obj2.src; 
    obj2.src = rmSrc;
    obj2.alt = alt;   
    obj.alt = obj2.alt;
    hide_div('bildtop');
    } // if
} // if done
} // function


function show_div(n) {
 //if (window.opera) {} else {
 document.getElementById(n).style.visibility = "visible"; 
// document.n.style.visibility = "visible"; 

}

function hide_div(n) {
 //if (window.opera) {} else 
 document.getElementById(n).style.visibility = "hidden"; 
// document.n.style.visibility = "hidden"; 
}





function scroll(richtung)
{
 var scrollfeld_div;

 if(richtung == "unten" && overflow)
  {
   if (-scrollfeld_div_position < (document.getElementById('scrollfeld').offsetHeight-450)) {
   scroll_counter++;
 
   scrollfeld_div_position -= 3;
   scrollfeld_div = document.getElementById('scrollfeld');
   scrollfeld_div.style.top = scrollfeld_div_position+"px";
   scrollfeld_div.style.clip = "rect("+(scroll_counter*3)+"px,263px,"+((scroll_counter*3)+415)+"px,0px)";
   if (bAnimate) setTimeout("scroll('unten');", 25);
   }
  }
 else
  { 
   if(scroll_counter != 0)
    {
     scroll_counter--;
   
     scrollfeld_div_position += 3;
     scrollfeld_div = document.getElementById('scrollfeld');
   
     scrollfeld_div.style.top = scrollfeld_div_position+"px";
     scrollfeld_div.style.clip = "rect("+(scroll_counter*3)+"px,263px,"+((scroll_counter*3)+415)+"px,0px)";
     if (bAnimate) setTimeout("scroll('oben');", 25);
    }  
  }
}



/**
 * <title>PointedEars' DOM Library</title>
 * @partof
 *   PointedEars JavaScript Extensions (JSX)
 * @requires types.js
 * @source Based upon
 *   @link{
 *     selfhtml#dhtml/beispiele/dhtml_bibliothek.htm,
 *     dhtml.js from SELFHTML (8.0)
 *   }
 *
 * @section Copyright & Disclaimer
 *
 * @author
 *   (C) 2002-2008 Thomas Lahn <dhtml.js@PointedEars.de>,
 *       2001      SELFHTML e.V. <stefan.muenz@selfhtml.org> et al.,
 *       2004      Ulrich Kritzner <droeppez@web.de> (loadScript),
 *       2005      MozillaZine Knowledge Base contributors (DOM XPath):
 *                 Eric H. Jung <grimholtz@yahoo.com> et al.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License (GPL) for more details.
 *
 * You should have received a copy of the GNU GPL along with this
 * program (COPYING file); if not, go to [1] or write to the Free
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 * 
 * [1] <http://www.gnu.org/licenses/licenses.html#GPL>
 *
 * @section Enhancements
 * 
 * - New features:
 *   + getElem("tagname", "$TAGNAME") : HTML(Options)Collection
 *   + setAttr(...)
 *   + radioChkdVal(...)
 *   + removeOptions(...)
 *   + addOption(...)
 *   + selectRadioBtn(...)
 *   + disableElementGroup(...)
 * 
 * - Pretty printing and detailed documentation
 * - Removed unnecessary variables and DHTML_init() function
 * - Use references and initialization wherever possible
 * - Introducing @link{#DHTML()} prototype and @link{#dhtml}
 *   instance, using boolean properties instead of numeric
 *   global variables.
 *   Note: This enhancement makes this library incompatible to
 *   the source code it is based upon and to previous versions
 *   of this library (if you used the global variables that
 *   were defined herein, otherwise _not_.)
 * 
 * - Argument renaming and checking
 * - if...else if...else --> switch...case...default
 * - Calling exception function on invalid arguments
 * - Do not try to access undefined properties (prevents
 *   warnings), use the "typeof" operator instead
 *
 * @section Bugfixes
 * 
 * - When the result is an object, return `null' instead of
 *   `void (0)'.  Otherwise return a null-string (`""') or
 *   true/false on success/failure, so that each function
 *   has a defined return value.
 */
/*
 * Refer dhtml.js.diff for changes to the last version,
 * and dhtml.htm file for a printable documentation. 
 *
 * This document contains JavaScriptDoc. See
 * http://pointedears.de/scripts/JSdoc/
 * for details.
 */

function DHTML()
{
  this.version   = "0.9.4.2008011717";
// var dhtmlDocURL = dhtmlPath + "dhtml.htm";
  this.copyright = "Copyright \xA9 2002-2008";
  this.author    = "Thomas Lahn";
  this.email     = "dhtml.js@PointedEars.de";
  this.path      = "http://pointedears.de/scripts/";
  this.URI       = this.path + "dhtml.js";
//  this.docURI    = this.path + "dhtml.htm";
  this.allowExceptionMsg = true;

  if (typeof document != "undefined")
  {
    var hasDocumentAll = false;

    this.getElemById = this.gEBI = (function dhtml_getElemById()
    {
      if (isMethod(document, "getElementById"))
      {
        return function dhtml_getElemById(s)
        {
          // wrapper method required to avoid "invalid op. on prototype" exception
          return document.getElementById(s);
        };
      }
      else if ((hasDocumentAll = isMethod(document, "all")))
      {
        return function dhtml_getElemById(s)
        {
          return document.all(s);
        };
      }
      else
      {
        return function dhtml_getElemById(s)
        {
          return document[s];
        };
      }
    })();

    var hasDocumentLayers = false;
  
    this.getElemByName = this.gEBN = (function dhtml_getElemByName()
    {
      if (isMethod(document, "getElementsByName"))
      {
        // W3C DOM Level 2 HTML
        return function dhtml_getElemByName(s, i)
        {
          var result = document.getElementsByName(s);
          if (result && !isNaN(i) && i > -1)
          {
            result = result[i];
          }
          return result;
        };
      }
      else if (hasDocumentAll)
      {
        // IE4 DOM
        return function dhtml_getElemByName(s, i)
        {
          var result = document.all(s);
          if (result && !isNaN(i) && i > -1)
          {
            result = result[i];
          }
          return result;
        };
      }
      else if ((hasDocumentLayers = (typeof document.layers == "object")))
      {
        // NN4 DOM
        return function dhtml_getElemByName(s, i)
        {
          var result = document.layers[s];
          if (result && !isNaN(i) && i > -1)
          {
            result = result[i];
          }
          return result;
        };
      }
      else
      {
        return function dhtml_getElemByName()
        {
          return null;
        };
      }
    })();

    var hasGetElementsByTagName;
    
    this.getElemByTagName = this.gEBTN = (function dhtml_getElemByTagName()
    {
      if (isMethod(document, "evaluate"))
      {
        // W3C DOM Level 3 XPath
        return function dhtml_getElemByTagName(s, i)
        {
          if (!s)
          {
            s = '*';
          }
  
          var result = document.evaluate('//' + s, document, null, 0, null);
          if (result)
          {
            var found = [], res;
            while ((res = result.iterateNext()))
            {
              found.push(res);
            }
              
            if (!isNaN(i) && i > -1)
            {
              result = found[i];
            }
            else
            {
              result = found;
            }
          }
  
          return result;
        };
      }
      else if ((hasGetElementsByTagName =
                  isMethod(document, "getElementsByTagName")))
      {
        // W3C DOM Level 2 Core
        return function dhtml_getElemByTagName(s, i)
        {
          if (!s)
          {
            s = '*';
          }
  
          var result = document.getElementsByTagName(s);
          if (result && !isNaN(i) && i > -1)
          {
            result = result[i];
          }
          return result;
        };
      }
      else if (hasDocumentAll && isMethod(document.all, "tags"))
      {
        return function dhtml_getElemByTagName(s, i)
        {
          var result = document.all.tags(s);
          if (result && !isNaN(i) && i > -1)
          {
            result = result[i];
          }
          return result;
        };
      }
      else
      {
        return function dhtml_getElemByTagName()
        {
          return null;
        };
      }
    })();
    
    this.getElemByIndex = this.gEBIdx = (function dhtml_getElemByIndex()
    {
      if (hasGetElementsByTagName)
      {
        return function dhtml_getElemByIndex(i)
        {
          return (result = document.getElementsByTagName('*')[i]);
        };
      }
      else if (hasDocumentAll)
      {
        return function dhtml_getElemByIndex(i)
        {
          return document.all(i);
        };
      }
      else if (hasDocumentLayers)
      {
        return function dhtml_getElemByIndex(i)
        {
          return document.layers[i];
        };
      }
      else
      {
        return function dhtml_getElemByIndex()
        {
          return null;
        };
      }
    })();
  }  

  this.getElemByClassName = this.gEBCN =
  function dhtml_getElemByClassName(s)
  {
    var
      coll = this.getElemByTagName(),
      result = new Array();
  
    if (coll)
    {
      var rx = new RegExp("\\b" + s + "\\b");
      for (var i = 0, len = coll.length; i < len; i++)
      {
        if (rx.test(coll[i].className))
        {
          result[result.length] = coll[i];
        }
      }
    }

    return result;
  };
  
  // Apart from isNS4DOM, none of these object-inference properties is used
  // anymore; they are still here for backwards compatibility only 
  this.isW3CDOM = isMethod(document, "getElementById");
  this.isOpera  = typeof window.opera != "undefined";
  this.isNS4DOM = typeof document.layers != "undefined";
  this.isIE4DOM  = typeof document.all == "object" && !this.isOpera;
  this.supported = this.isW3CDOM || this.isNS4DOM || this.isOpera
    || this.isIE4DOM;

  // DOM preselection (why?)
  this.W3CDOM = 3;
  this.IE4DOM = 2;
  this.NS4DOM = 1;
  this.DOM = this.supported   
    && (this.isW3CDOM && this.W3CDOM)
    || (this.isIE4DOM && this.IE4DOM)
    || (this.isNS4DOM && this.NS4DOM);
}

// imports from types.js, for backwards compatibility only
DHTML.prototype.isMethod = isMethod;
DHTML.prototype.isMethodType = isMethodType;

var dhtml = new DHTML();

/**
 * Shows an exception alert and allows for
 * displaying a stack trace.
 *
 * @param sMsg : optional string = ""
 *   Error message to be displayed.
 * @return type boolean
 */
function DHTMLException(sMsg)
{
  // Prevent exceptions from "bubbling" on (keyboard) event
  if (!dhtml.allowExceptionMsg)
  {
    return false;
  }
  dhtml.allowExceptionMsg = false;
  
  setErrorHandler();
  eval(
      'try {'
    + '  delete bar;'
    + '  var foo = bar;'
    + '} catch (e) {'
    + '  var stackTrace = e.stack || "";'
    + '}');
  clearErrorHandler();
  
  alert(
    "dhtml.js "
      + dhtml.version + "\n"
      + dhtml.copyright + "  "
      + dhtml.author + " <" + dhtml.email + ">\n"
      + 'The latest version can be obtained from:\n'
      + + "<" + dhtml.URI + ">\n\n"
      + sMsg + "\n"
      + "__________________________________________________________\n"
      + "Stack trace"
      + (stackTrace
          ? ":\n\n" + stackTrace
          : " not available in this DOM."));

  dhtml.allowExceptionMsg = true;
  return false;
}

/**
 * Retrieves an HTMLElement object or a collection of such
 * objects that match certain criteria.
 * 
 * @author
 *   (C) 2003, 2004  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param sType : string
 *   Defines the type of <code>sValue</code>. Valid values are
 *   "id", "name", "tagname", "index" and "classname". The
 *   argument is case-insensitive.
 * @param sValue : optional string
 *   Case-sensitive ID, name or tag name of object (collection).
 * @param index : optional number
 *   Optional. Numeric index of an element of the selected
 *   collection. For IDs must be unique throughout a document,
 *   this argument is ignored if <code>sType</code> is "id".
 * @return type object
 *   A reference to an object if <code>sType</code> is "id", or
 *   if it is "name" or "tagname" and <code>index</code> is
 *   specified; otherwise a collection of objects matching the
 *   specified criteria; <code>null</code> if no matching object
 *   exists.
 */
function getElem(sType, sValue, index)
{
  function invalidType()
  {
    DHTMLException(
        'getElem: Invalid type "' + sType + '"\n'
      + 'Must be one of "id", "name", "tagname", "index" or "classname"'
      + ' (case-insensitive).');
  }

  if (!sType || typeof sType != "string" || !sType.toLowerCase)
  {
    DHTMLException(
        "getElem: Invalid type: " + sType + "\n"
      + "Must be String.");
  }

  if (!sValue || typeof sValue != "string")
  {
    DHTMLException(
        "getElem: Invalid value: " + sValue + "\n"
      + "Must be String.");
  }
    
  var o = null;
    
  switch ((sType = sType.toLowerCase()))
  {
    case 'id':
    case 'index':
    case 'classname':
      o = dhtml["getElemBy" + {
        id:        "Id",
        index:     "Index",
        classname: "ClassName"
      }[sType]](sValue);
      break;

    case 'name':
    case 'tagname':
      o = dhtml["getElemBy" + {
        name:    "Name",
        tagname: "TagName"
      }[sType]](sValue, index);
      break;

    default:
      invalidType();
  }
  
  return o;
}
DHTML.prototype.getElem = getElem;

/**
 * Retrieves the content of an HTMLElement object.
 * 
 * @author
 *   (C) 2003-2005  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param o : HTMLElement
 *   Element which content is to be retrieved.
 * @param bHTML : optional boolean
 *   If <code>true</code>, returns the HTML content instead of
 *   the text content in case the latter cannot be retrieved.
 * @return type string
 *  A string with the content of the element; a null-string if
 *  no such element object exists or if the DOM does not provide
 *  retrieval of the element's content.
 */
function getCont(o, bHTML)
{
  var sResult = "";

  if (o)
  {
    // W3C DOM Level 2 Core
    if (typeof o.firstChild != "undefined")
    {
      if (typeof o.firstChild.nodeType != "undefined"
          && o.firstChild.nodeType ==
            /* W3C-DOM 2 o.firstChild.TEXT_NODE constant is N/A in IE and O7 */
            ((typeof o.firstChild.TEXT_NODE != "undefined"
              && o.firstChild.TEXT_NODE)
             || 3))
      {
        sResult = o.firstChild.nodeValue;
      }
    }
    else
    {
      if (typeof o.innerText != "undefined")
      {
        sResult = o.innerText;
      }

      if ((bHTML || typeof o.innerText == "undefined")
          && typeof o.innerHTML != "undefined")
      {
        sResult = o.innerHTML;
      }
    }
  }

  return sResult;
}
DHTML.prototype.getCont = getCont;

/**
 * Specifies the content of an HTMLElement object.
 *
 * @author
 *   (C) 2003-2005  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param o : HTMLElement
 *   Element which content is to be changed.
 * @param sNodeValue : string
 *   New content of the element.
 * @returns
 *   <code>true</code> if successful, <code>false</code>
 *   otherwise.
 */
function setCont(o, sNodeValue)
{
  if (o)
  {
    // DOM Level 2 Core
    if (typeof o.firstChild != "undefined")
    {
      o.firstChild.nodeValue = sNodeValue;
      return true;
    }
    else if (typeof o.nodeValue != "undefined")
    {
      o.nodeValue = sNodeValue;
      return true;
    }
    
    // IE4 DOM
    else if (typeof o.innerText != "undefined")
    {
      o.innerText = sNodeValue;
      return true;
    }
    
    // NS4 DOM
    else if (dhtml.isNS4DOM
             && o.document
             && o.document.open
             && o.document.write
             && o.document.close)
    {
      o.document.open();
      o.document.write(sNodeValue);
      o.document.close();
      return true;
    }
  }

  return false;
}
DHTML.prototype.setCont = setCont;

/**
 * Returns the text content of a document node.
 *
 * @author
 *   (C) 2005 Thomas Lahn <dhtml.js@PointedEars.de>
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oNode : Node
 *   Reference to the document node.
 * @return type string
 *   The text content of @{(oNode)}.
 */
function getTextContent(oNode)
{
  var text = "";

  if (oNode)
  {
    // W3C DOM Level 3
    if (typeof oNode.textContent != "undefined")
    {
      text = oNode.textContent;
    }

    // W3C DOM Level 2
    else if (oNode.childNodes && oNode.childNodes.length) 
    {
      for (var i = oNode.childNodes.length; i--;)
      {
        var o = oNode.childNodes[i];
        if (o.nodeType == ((Node && Node.TEXT_NODE) || 3))
        {
          text = o.nodeValue + text;
        }
        else
        {
          text = getTextContent(o) + text;
        }
      }
    }

    // proprietary: IE4+
    else if (typeof oNode.innerText != "undefined")
    {
      text = oNode.innerText;
    }
  }

  return text;
}
DHTML.prototype.getTextContent = getTextContent;

/**
 * Sets the text content of a document node.
 *
 * @author
 *   (C) 2005 Thomas Lahn <dhtml.js@PointedEars.de>
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oNode : Node
 *   Reference to the document node.
 * @return type boolean
 *   <code>true</code> if successful, <code<false</code> otherwise.
 */
function setTextContent(oNode, sContent)
{
  var result = false;

  if (oNode)
  {
    // W3C DOM Level 3
    if (typeof oNode.textContent != "undefined")
    {
      oNode.textContent = sContent;
      result = (oNode.textContent == sContent);
    }

    // W3C DOM Level 2
    else if (oNode.removeChild && oNode.firstChild) 
    {
      while (oNode.firstChild)
      {
        oNode.removeChild(oNode.firstChild);
      }
 
      result = !!oNode.appendChild(document.createTextNode(sContent));
    }

    // proprietary: IE4+
    else if (typeof oNode.innerText != "undefined")
    {
      oNode.innerText = sContent;
      result = (oNode.innerText == sContent);
    }
  }
  return result;
}
DHTML.prototype.setTextContent = setTextContent;
  
/**
 * Retrieves the value of an attribute of an HTMLElement object
 * that matches certain criteria.
 * 
 * @author
 *   (C) 2003  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param sType : string
 *   Defines the type of <code>sValue</code>. Valid
 *   values are "id", "name" and "tagname". The argument is
 *   case-insensitive.
 * @param sValue : string
 *   Case-sensitive ID, name or tag name of object
 *   (collection).
 * @param index : optional number
 *   Optional. Numeric index of an element of the
 *   selected collection. For IDs must be unique throughout a
 *   document, this argument is ignored if <code>sType</code>
 *   is "id".
 * @param sAttrName : string
 *   Name of the attribute from which the value
 *   should be retrieved.
 * @return
 *   The value of the object if <code>sType</code> is "id",
 *   or if it is "name" or "tagname" and <code>index</code>
 *   is specified;
 *   a null-string if no matching object exists or if the DOM
 *   does not provide retrieval of the attribute's values.
 */
function getAttr(sType, sValue, index, sAttrName)
{
  var result = "";
  var o = getElem(sType, sValue, index);

  if (o && isMethod(o, "getAttribute"))
  {
    result = o.getAttribute(sAttrName);
  }
  else if (dhtml.isNS4DOM) 
  {
    o = getElem(sType, sValue); 
    if (typeof o == "object")
    {
      if (typeof o[index] == "object")
      {
        result = o[index][sAttrName];
      }
      else
      {
        result = o[sAttrName];
      }
    }
  }
  
  return result;
}
DHTML.prototype.getAttr = getAttr;

/**
 * Sets the value of an attribute of an HTMLElement object.
 * 
 * @author
 *   (C) 2003, 2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param sAttrName:string
 *   Name of the attribute for which the value should be set.
 *   Attribute names for which an ECMAScript language binding
 *   is defined in W3C DOM Level 2 HTML, are automatically
 *   mapped to the corresponding element object property.
 *   All attribute names are automatically mapped to their
 *   camelCased equivalent.
 * 
 *   Semicolon-separated style property declarations (in
 *   form of colon-separated name-value pairs each) of a
 *   <code>style</code> attribute value are mapped to the
 *   corresponding properties of the object referenced by
 *   the <code>style</code> property of the element object.
 *   Declarations are evaluated from left to right, where
 *   property values complement or replace the previously
 *   defined ones.
 * @param attrValue
 *   Value of the attribute to be set.  The value is
 *   converted to number if it can be interpreted as such.
 * @returns
 *   The value of the attribute of the element object;
 *   a null-string if no matching object exists or if the DOM
 *   does not provide retrieval of the attribute's values.
 */
function setAttr(o, sAttrName, attrValue)
{
  var result = "";
  
  if (o && sAttrName)
  {
    var attrMap = {
      alink: "aLink",
      accesskey: "accessKey",
      bgcolor: "bgColor",
      cellpadding: "cellPadding",
      cellspacing: "cellSpacing",
      "char": "ch",
      charoff: "chOff",
      "class": "className",
      codebase: "codeBase",
      codetype: "codeType",
      colSpan: "colSpan",
      datetime: "dateTime",
      frameborder: "frameBorder",
      "for": "htmlFor",
      ismap: "isMap",
      longdesc: "longDesc",
      maxlength: "maxLength",
      marginheight: "marginHeight",
      marginwidth: "marginWidth",
      nohref: "noHref",
      noresize: "noResize",
      noshade: "noShade",
      nowrap: "noWrap",
      readonly: "readOnly",
      rowspan: "rowSpan",
      tabindex: "tabIndex",
      usemap: "useMap",
      valuetype: "valueType",
      vlink: "vLink"
    };
  
    // camel-case specific attribute names
    if (typeof attrMap[sAttrName] != "undefined")
    {
      sAttrName = attrMap[sAttrName];
    }
    
    var
      hyphenatedToCamelCase = function(s)
      {
        return s.replace(
          /-([a-z])/g,
          function(match, p1, offset, input)
          {
            return p1.toUpperCase();
          })
      },
    
      strToValue = function(s)
      {
        s = s.replace(/^["']|["']$/g, "");
        return isNaN(s) ? s : +s;
      };
    
    // camel-case hyphenated attribute names
    sAttrName = hyphenatedToCamelCase(sAttrName);
    
    if (typeof attrValue != "undefined")
    {
      attrValue = strToValue(attrValue);
      if (sAttrName == "style" && typeof attrValue == "string")
      {
        var styleProps = attrValue.split(/\s*;\s*/);
        for (var j = 0, len = styleProps.length; j < len; j++)
        {
          var
            stylePair = styleProps[j].split(/\s*:\s*/),
            stylePropName =
              hyphenatedToCamelCase(stylePair[0].toLowerCase());
          
          dhtml.setStyleProperty(o, stylePropName,
            strToValue(stylePair[1]));
          result = dhtml.getStyleProperty(o, stylePropName);
        }
      }
      else
      {
        result = o[sAttrName] = attrValue;
      }
    }
    else if (!(o[sAttrName] = true))
    {
      result = o[sAttrName] = sAttrName;
    }
  }
  
  return result;
}
DHTML.prototype.setAttr = setAttr;

/**
 * Retrieves the value of a style property of an HTMLElement object.
 * 
 * @author
 *   (C) 2005  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument o : HTMLElement
 *   Reference to the element object which style is to be modified.
 * @argument sPropertyName : string
 *   Name of the style property of which the value should be retrieved.
 *   If "display", and there is no
 *   <code>style[<var>sPropertyName</var>]</code> property,
 *   "visibility" is used instead (fallback for the NN4 DOM).
 * @return
 *   <code>null</code> if no matching object exists or if the
 *   DOM does not provide for retrieval of the property value.
 */
function getStyleProperty(o, sPropertyName)
{
  if (o)
  {
    sPropertyName = sPropertyName.replace(
      /-([a-z])/gi,
      function(m, p1) { return p1.toUpperCase(); });

    if (typeof o.style != "undefined")
    {
      // handle the `float' property
      var tested = false;
      
      if (sPropertyName == "float")
      {
        // W3C DOM Level 2 CSS
        if (typeof o.style.cssFloat != "undefined")
        {
          sPropertyName = "cssFloat";
          tested = true;
        }
        
        // MSHTML DOM
        else if (typeof o.style.styleFloat != "undefined")
        {
          sPropertyName = "styleFloat";
          tested = true;
        }        
      }
      
      if (tested || typeof o.style[sPropertyName] != "undefined")
      {
        return o.style[sPropertyName];
      }
    }
    else
    {
      if (sPropertyName == "display") sPropertyName = "visibility";
      
      if (typeof o[sPropertyName] != "undefined")
      {
        return o[sPropertyName];
      }
    }
  }

  return null;
}
DHTML.prototype.getStyleProperty = getStyleProperty;

/**
 * Determines whether an HTMLElement object has a style property or not.
 * 
 * @author
 *   (C) 2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument o : HTMLElement
 *   Reference to the element object which style property is to be retrieved.
 * @argument sPropertyName : string
 *   Name of the style property which is to be checked.
 *   If "display", and there is no
 *   <code>style[<var>sPropertyName</var>]</code> property,
 *   "visibility" is used instead (fallback for the NN4 DOM).
 * @return
 *   <code>false</code> if no matching object exists or if the
 *   DOM does not provide for retrieval of the property value;
 *   <code>true</code> otherwise.
 */
function hasStyleProperty(o, sPropertyName)
{
  return (getStyleProperty(o, sPropertyName) != null);
}
DHTML.prototype.hasStyleProperty = hasStyleProperty;

/**
 * Sets the value of a style property of an HTMLElement object.
 * 
 * @author
 *   (C) 2003-2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument o: HTMLElement
 *   Reference to the element object which style is to be modified.
 * @argument sPropertyName: string
 *   Name of the style property of which the value should be set.
 *   If "display", there is no <code>style[<var>sPropertyName</var>]</code>
 *   property, and <code>altValue</code> was provided, "visibility" is used
 *   instead (fallback for the NN4 DOM).
 * @argument propValue
 *   Value of the style property to be set.
 * @argument altValue: optional _
 *   Alternative value to be set if the the style property is a property of
 *   the object itself instead of its `style' property.  Fallback for the
 *   NN4 DOM.
 * @return
 *   <code>false</code> if no such object exists or if the
 *   DOM does not provide for setting the property value.
 * @type boolean
 */
function setStyleProperty(o, sPropertyName, propValue, altValue)
{
  if (o)
  {
    sPropertyName = sPropertyName.replace(
      /-([a-z])/gi,
      function(m, p1) { return p1.toUpperCase(); });
       
    if (typeof o.style != "undefined")
    {
      // handle the `float' property
      var tested = false;
      
      if (sPropertyName == "float")
      {
        // W3C DOM Level 2 CSS
        if (typeof o.style.cssFloat != "undefined")
        {
          sPropertyName = "cssFloat";
          tested = true;
        }
        
        // MSHTML DOM
        else if (typeof o.style.styleFloat != "undefined")
        {
          sPropertyName = "styleFloat";
          tested = true;
        }        
      }
      
      if (tested || typeof o.style[sPropertyName] != "undefined")
      {
        // NOTE: Shortcut evaluation changed behavior
        o.style[sPropertyName] = propValue;
        return (String(o.style[sPropertyName]).toLowerCase()
          == String(propValue).toLowerCase());
      }
    }
    else
    {
      if (sPropertyName == "display" && altValue)
      {
        sPropertyName = "visibility";
      }

      if (typeof o[sPropertyName] != "undefined")
      {
        var newValue = (altValue || propValue);
        o[sPropertyName] = newValue;
        return (String(o[sPropertyName]).toLowerCase()
          == String(newValue).toLowerCase());
      }
    }
  }
  
  return false;
}
DHTML.prototype.setStyleProperty = setStyleProperty;

/**
 * Retrieves the rendering state or (dis)allows rendering of a DOM object.
 *
 * @author
 *   (C) 2004-2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument o: HTMLElement
 *   Reference to the DOM object to be rendered or not.
 * @argument bRender: boolean
 *   Renders the object referenced by <code>o</code> if
 *   <code>true</code>, does not render it if <code>false</code>.
 *   Note that not to render an element is different from
 *   hiding it, as the space it would take up is then no
 *   longer reserved.
 *   
 *   If this argument is omitted, the current property value is returned.
 * @return type boolean
 *   When retrieving: <code>true</code> if visible, <code>false</code>
 *   otherwise; when setting: <code>true</code> if successful,
 *   <code>false</code> otherwise.
 * @see
 *   visibility()
 */
function display(o, bShow)
{
  var result;

  if (o)
  {
    if (arguments.length > 1)
    {
      result = setStyleProperty(o, "display",
        bShow ? ""     : "none",
        bShow ? "show" : "hide");
    }
    else
    {
      result = /^(\s*|show)$/.test(getStyleProperty(o, "display"));
    }
  }
  
  return result;
}
DHTML.prototype.display = display;

/**
 * Retrieves or sets the visibility of a DOM object.
 *
 * @author
 *   (C) 2004-2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument o : HTMLElement
 *   Reference to the DOM object to be either shown or hidden.
 * @argument bVisible: optional boolean
 *   Shows the object referenced by <code>o</code> if <code>true</code>,
 *   hides it if <code>false</code>.  Note that hiding an element is
 *   different from not rendering it, as the space it takes up is still
 *   reserved.
 *   
 *   If this argument is omitted, the current property value is returned.
 * @return
 *   When retrieving: <code>true</code> if visible, <code>false</code>
 *   otherwise; when setting: <code>true</code> if successful,
 *   <code>false</code> otherwise.
 * @type boolean
 * @see #display()
 */
function visible(o, bVisible)
{
  var result;

  if (o)
  {
    if (arguments.length > 1)
    {
      result = setStyleProperty(o, "visibility",
        bVisible ? "visible" : "hidden",
        bVisible ? "show" : "hide");
    }
    else
    {
      result = /^(visible|show)$/.test(getStyleProperty(o, "visibility"));
    }
  }
  
  return result;
}
var visibility = visible;
DHTML.prototype.visibility = visible;
DHTML.prototype.visible = visible;

/**
 * Sets the value property of an HTMLInput element,
 * and its "title" property accordingly if specified.
 * 
 * @author
 *   (C) 2004  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oInput : HTMLInputElement
 *   Required.  Reference to an HTMLInputElement object.
 * @param sValue : string
 *   New value of the "value" property of the
 *   HTMLInputElement object.
 * @param bSetTitle : optional boolean = false
 *   Specifies if the "title" property should be set to
 *   the same value as the "value" property.  The default
 *   is <code>false</code>.
 * @return type boolean
 *   If <code>bSetTitle</code> evaluates to <code>false</code>
 *   or is left out:
 * 
 *   <code>true</code> if the "value" property could be set
 *   properly, <code>false</code> otherwise.
 * 
 *   If <code>bSetTitle</code> is <code>true</code>:
 * 
 *   <code>true</code> if _both_ "value" and "title" property
 *   could be set properly, <code>false</code> otherwise.
 */
function setValue(oInput, sValue, bSetTitle)
{
  if (oInput && typeof oInput.value != "undefined")
  {
    oInput.value = sValue;
    if (bSetTitle && typeof oInput.title != "undefined")
    {
      oInput.title = sValue;
      return (oInput.value == sValue && oInput.title == sValue);
    }
    return (oInput.value == sValue);
  }

  return false;
}
DHTML.prototype.setValue = setValue;

/**
 * @argument number|string imgID
 * @param state : optional number
 * @return type boolean
 */
function hoverImg(imgID, state)
{
  var img = null;

  if (document.images)
  {
    img = document.images[imgID];
  }

  return setStyleProperty(
    img,
    "borderColor",
    (state == 0 ? hoverImg.clMouseout : hoverImg.clMouseover));
}
hoverImg.clMouseout = "#000",
hoverImg.clMouseover = "#fff";
DHTML.prototype.hoverImg = hoverImg;

/**
 * Retrieves the checked radio button of a radio button group.
 * 
 * @author
 *   Copyright (C) 2004, 2007  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oForm : HTMLFormElement
 *   Required. Reference to an HTMLFormElement object to contain
 *   the radio button group.
 * @param sGroup : string
 *   Name of the radio button group from which the
 *   checked radio button should be retrieved.
 * @return type object
 *   null,  if @{(oForm)} is invalid or there is no such @{(sGroup)}
 * @return type boolean
 *   false, if no radio button of @{(sGroup)} is checked
 * @return type HTMLInputElement
 *   A reference to the checked radio button otherwise
 */
function getCheckedRadio(oForm, sGroup)
{
  var result = null, e, ig;
  if (oForm
      && (e = oForm.elements)
      && (ig = e[sGroup]))
  {
    result = false;
    for (var i = ig.length; i--;)
    {
      if (ig[i].checked)
      {
        result = ig[i];
        break;
      }
    }
  }

  return result;
}
DHTML.prototype.getCheckedRadio = getCheckedRadio;

/**
 * Removes all options from a HTMLSelectElement object.
 * 
 * @author
 *   (C) 2003  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oSelect : HTMLSelectElement
 *   Reference to a HTMLSelectElement object.
 * @param bAllowReload : boolean
 *   If <code>true</code>, reloads the document.
 * @return type boolean
 *   <code>true</code> if successful, <code>false</code>
 *   otherwise.
 */
function removeOptions(oSelect, bAllowReload)
{
  if (oSelect
    && oSelect.tagName
    && oSelect.tagName.toLowerCase() == "select")
  {
    var o = oSelect.options;
    if (o && o.length)
    {
      // shortcut if "length" property is not read-only
      o.length = 0;
      while (o.length > 0)
      {
        if (o.remove)
        {
          o.remove(o.length - 1);
        }
        else
        {
          o[o.length - 1] = null;
          if (bAllowReload)
          {
            history.go(0);
          }
        }
      }
      return true;
    }
  }

  return false;
}
DHTML.prototype.removeOptions = removeOptions;

/**
 * Adds an option to an HTMLSelectElement object.
 * 
 * @author
 *   (C) 2003  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oSelect : HTMLSelectElement
 *   Required reference to an HTMLSelectElement object.
 * @param sText : string
 *   Required text of the new HTMLOptionElement object.
 * @param iPosition : optional number
 *   Optional. If supported, inserts the new option there;
 *   otherwise the option is appended as last item.
 * @param sValue : optional string
 *   Optional value of the new HTMLOptionElement object.
 * @return type object
 *   A reference to the new option if successful,
 *   <code>null</code> otherwise.
 */
function addOption(oSelect, sText, iPosition, sValue)
{
  if (oSelect
    && oSelect.tagName
    && typeof oSelect.tagName == "string"
    && oSelect.tagName.toLowerCase
    && oSelect.tagName.toLowerCase() == "select")
  {
    var oNew = new Option(sText);

    var o = oSelect.options;
    if (o)
    {
      if (o.add)
      {
        if (arguments.length >= 4
            && typeof oNew.value != "undefined")
        {
          oNew.value = sValue;
        }
          
        if (arguments.length > 2)
        {
          o.add(oNew, iPosition);
        }
        else
        {
          o.add(oNew);
        }
      }
      else
      {
        o[o.length] = oNew;
        o[o.length - 1].value =
          (arguments.length < 4
            ? ""
            : sValue);
      }

      return oNew;
    }
  }

  return null;
}
DHTML.prototype.addOption = addOption;

/**
 * Select a radio button depending on its value and, optionally,
 * its name.
 * 
 * @author
 *   (C) 2003  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param oForm : HTMLFormElement
 *   Reference to the <code>HTMLFormElement</code> object
 *   which contains the <code>HTMLInputElement</code> object.
 * @param aName : _
 *   Name of the radio button, i.e. the value of the
 *   <code>name</code> attribute of the respective
 *   <code>input</code> (X)HTML element or the value
 *   of the <code>name</code> property of the respective 
 *   <code>HTMLInputElement</code> object.  Use an expression
 *   that is evaluated to <code>false</code> for the argument
 *   to be ignored.
 * @param sValue : string
 *   Value of the radio button, i.e. the value of the
 *   <code>value</code> attribute of the respective
 *   <code>input</code> (X)HTML element or the value
 *   of the <code>value</code> property of the respective 
 *   <code>HTMLInputElement</code> object.
 */
function selectRadioBtn(oForm, aName, sValue)
{
  for (var i = 0; i < oForm.elements.length; i++)
  {
    var curEl = oForm.elements[i];

    if (!curEl.disabled
        && curEl.type == "radio"
        && (!sName || curEl.name == sName)
        && curEl.value == sValue)
    {
      curEl.checked = true;
    }
  }
}
DHTML.prototype.selectRadioBtn = selectRadioBtn;

/**
 * Disables a form element or a collection of form elements.
 *
 * @author
 *   (C) 2003  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @argument HTMLElement|HTML(Options)Collection oElementGroup
 *   Reference to the <code>HTMLElement</code> or to
 *   the <code>HTML(Options)Collection</code> object.
 * @optional number|string index
 *   Optional number or string to specify
 *   one element within the collection.
 */
function disableElementGroup(oElementGroup, index)
{
  if (oElementGroup)
  {
    if (oElementGroup[index]
        && typeof oElementGroup[index].disabled != "undefined")
    {
      oElementGroup[index].disabled = true;
    }
    else if (typeof oElementGroup.disabled != "undefined")
    {
      oElementGroup.disabled = true;
    }
  }
}
DHTML.prototype.disableElementGroup = disableElementGroup;

/**
 * Disables or enables form elements by name/ID.
 * 
 * @argument  HTMLFormElement oForm
 *   Reference to the <code>form</code> element object.
 * @arguments string|HTMLElement
 *   Names/IDs of the elements or references
 *   to the element objects to disable/enable.
 * @optional  boolean bDisable
 *   If <code>false</code>, elements will be
 *   enabled, otherwise disabled.
 */
function disableElements(oForm)
{
  if (oForm)
  {
    var len = arguments.length - 1, bDisable = arguments[len];
    if (bDisable && typeof bDisable == "boolean")
    {
      len = arguments.length - 2;
    }

    for (var i = 1; i < len; i++)
    {
      var a = arguments[i], o;
      if (typeof a != "object")
      {
        o = oForm.elements[a];
      }
      else
      {
        o = a;
      }

      var len2;
      if (typeof o.disabled != "undefined")
      {
        o.disabled = bDisable;
      }
      else if (typeof (len2 = o.length) != "undefined")
      {
        for (var j = len2; j--; 0)
        {
          var o2;
          if (typeof (o2 = o[j]).disabled != "undefined")
          {
            o2.disabled = bDisable;
          }
        }
      }
    }
  }
}
DHTML.prototype.disableElements = disableElements;

/**
 * Creates an element of the type specified, using the
 * <code>document.createElement()</code> method if supported.
 * This method works with MSIE, too, for if JScript is used,
 * it is tried to use the start tag as is instead of passing
 * only the element type, and adding properties later.
 * 
 * @author
 *   (C) 2004, 2006  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param sTag : string
 *   Start tag or element type of the element to be created.
 *   Passing a start tag even works if the UA is not MSIE,
 *   as attributes and values given are parsed from left to
 *   right into the corresponding element object properties.
 * @return type object
 *   A reference to a new <code>Element</code> object with the
 *   <code>nodeName</code> property set to <code>sTagName</code>,
 *   and the <code>localName</code>, <code>prefix</code>,
 *   and <code>namespaceURI</code> properties set to
 *   <code>null</code>.
 * @see
 *   @link{dom2-core#ID-2141741547},
 *   @link{msdn#workshop/author/dhtml/reference/methods/createelement.asp}
 *   http://pointedears.de/scripts/JSdoc/
 */
function createElement(sTag)
{
  var o = null;

  if (sTag
      && typeof document != "undefined"
      && isMethod(document, "createElement"))
  {
    /*@cc_on @*/
    /*@if (@_jscript)
      o = document.createElement(sTag);
    @end @*/
    
    if (!o)
    {
      var aTagComponents = sTag.replace(/^<?\s*|\s*>?$/g, "")
        .replace(/\s+/, " ").replace(/ = /g, "=").split(" ");
      o = document.createElement(aTagComponents[0]);
      if (o)
      {
        aTagComponents.shift();
        var attrs = aTagComponents.join(" ");
        var m;
        while ((m = /([^\s=]+)\s*(=\s*(\S+)\s*)?/g.exec(attrs)))
        {
          setAttr(o, m[1].toLowerCase(), m[3]);
        }
      }
    }
  }

  return o;
}
DHTML.prototype.createElement = createElement;

function getFirstChild(o)
{
  var result = null;

  if (o)
  {
    if (o.firstChild)
    {
      result = o.firstChild;
    }
    else if (o.document && o.document.all)
    {
      result = o.document.all(0);
    }
  }

  return result;
}
DHTML.prototype.getFirstChild = getFirstChild;

function getParent(o)
{
  var result = null;

  if (o)
  {
    if (o.parentNode)
    {
      result = o.parentNode;
    }
    else if (o.parentElement)
    {
      result = o.parentElement;
    }
  }

  return result;
}
DHTML.prototype.getParent = getParent;

function getAbsPos(o)
{
  var result = new Object();
  result.x = result.y = 0;
  result.toString = function()
  {
    return "{x: " + this.x + ", y: " + this.y + "}";
  };
  
  if (o.offsetParent)
  {
    while (o.offsetParent)
    {
      result.x += o.offsetLeft;
      result.y += o.offsetTop;
      o = o.offsetParent;
    }
  }
  else if (typeof o.x != "undefined"
           && typeof o.y != "undefined")
  {
    result.x += o.x;
    result.y += o.y;
  }
  
  return result;
}

/**
 * Adds an event-handling function (event listener) for a
 * DOM object as event target.  The following methods are
 * used (in order of preference):
 *
 * - addEventListener(...) method (W3C-DOM Level 2)
 * - Assignment to event-handling property (MSIE 4+ and others)
 * 
 * The attachEvent(...) method (proprietary to MSIE 5+) is not
 * used anymore because of the arbitrary execution order of
 * event listeners attached with it and because of `this' in
 * the event listener not referring to the event target then.
 * See also http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html
 * 
 * @author
 *   (C) 2004-2007  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param o : DOMObject
 *   Reference to the DOM object.
 * @param sEvent : string
 *   Required string to be used as event identifier.
 *   If the addEventListener(...) method is not available,
 *   `on' is used as its prefix to reference the respective
 *   proprietary event-handling property.
 * @param fListener : Function
 *   Reference to the Function object that provides
 *   event-handling code.  Use <code>null</code> to
 *   detach the event listener if, and only if, the
 *   proprietary event handler property is available.
 * @return type boolean
 *   <code>true</code> on success, <code>false</code> otherwise.
 *   Since addEventListener(...) returns no value and throws
 *   no exceptions (what a bad design!), it is considered to be
 *   successful always, while the new value of the proprietary
 *   event-handling property must match the assigned value for
 *   the method to be successful.
 * @see
 *   dom2-events#Events-EventTarget-addEventListener,
 *   msdn#workshop/author/dhtml/reference/methods/attachevent.asp,
 *   http://pointedears.de/scripts/JSdoc/
 */
function _addEventListener(o, sEvent, fListener)
{
  var result = false, sHandler = "on" + sEvent;

  if (o && sEvent && isMethodType(fListener) && fListener)
  {
    if (isMethod(o, "addEventListener"))
    {
      o.addEventListener(sEvent, fListener, false);
      result = true;
    }
    else if (typeof o[sHandler] != "undefined")
    {
      // We don't attempt to use MSHTML's buggy attachEvent() anymore;
      // thanks to Peter-Paul Koch for insight:
      // http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html
      
      var oldListener = o["on" + sEvent];
      var newListener = function(e)
      {
        if (!e)
        {
          e = (typeof window != "undefined" && window 
               && typeof window.event != "undefined"
               && window.event);
        }
        
        if (oldListener)
        {
          oldListener(e);
        }
        
        fListener(e);
      }; 

      o[sHandler] = newListener; 
      
      result = (o[sHandler] == newListener);
    }
    else
    {
      result = false;
    }
  }

  // break the circular reference created by the closure
  o = null;
  
  return result;
}
DHTML.prototype.addEventListener = _addEventListener;

/**
 * Adds a capturing event-handling function (event listener) for
 * a DOM object as event target.  Capturing means that the event
 * target receives the event before all other targets, before
 * event bubbling.  The following methods are used (in order of
 * preference):
 *
 * - addEventListener(...) method (W3C-DOM Level 2)
 * - TODO: captureEvent(...) method (NS 4)
 * 
 * @author
 *   (C) 2007  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param o : DOMObject
 *   Reference to the DOM object.
 * @param sEvent : string
 *   Required string to be used as event identifier.
 *   If the addEventListener(...) method is not available,
 *   `on' is used as its prefix to reference the respective
 *   proprietary event-handling property.
 * @param fListener : Function
 *   Reference to the Function object that provides
 *   event-handling code.  Use <code>null</code> to
 *   remove the event handler if, and only if, the
 *   proprietary event-handling property is available.
 * @return type boolean
 *   <code>true</code> on success, <code>false</code> otherwise.
 * @see
 *   dom2-events#Events-EventTarget-addEventListener,
 *   http://pointedears.de/scripts/JSdoc/
 */
function _addEventListenerCapture(o, sEvent, fListener)
{
  var result = false;

  if (o && sEvent && isMethodType(typeof fListener) && fListener)
  {
    if (isMethod(o, "addEventListener"))
    {
      o.addEventListener(sEvent, fListener, true);
      result = true;
    }
    else
    {
      result = false;
    }
  }
  
  return result;
}
DHTML.prototype.addEventListenerCapture = _addEventListenerCapture;

/**
 * Replaces the event-handling function (event listener) for a
 * DOM object as event target.  The following methods are
 * used (in order of preference):
 *
 * - removeEventListener() and addEventListener(...) methods
 *   (W3C-DOM Level 2)
 * - detachEvent() and attachEvent(...) methods
 *   (proprietary to MSIE 5+)
 * - Assignment to event-handling property (MSIE 4+ and others)
 * 
 * Note that this still relies on the existence of the proprietary
 * event-handling property that yields a reference to the (first added)
 * event listener for the respective event.
 * 
 * @author
 *   (C) 2007  Thomas Lahn &lt;dhtml.js@PointedEars.de&gt;
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @param o : DOMObject
 *   Reference to the DOM object.
 * @param sEvent : string
 *   Required string to be used as event identifier.
 *   `on' is used as its prefix to reference the respective
 *   proprietary event-handling property.
 * @param fListener : Function
 *   Reference to the Function object that provides
 *   event-handling code.  Use <code>null</code> to
 *   remove the event handler if, and only if, the
 *   proprietary event-handling property is available.
 * @param bUseCapture : optional boolean
 *   Optional. If <code>true</code>, the argument indicates that
 *   the user wishes to initiate capture.  Corresponds to the
 *   third parameter of the addEventListener(...) method, is
 *   ignored if that method is not supported by the DOM (object).
 * @return type boolean
 *   <code>true</code> on success, <code>false</code> otherwise.
 *   Since addEventListener(...) returns no value and throws
 *   no exceptions (what a bad design!), it is considered to be
 *   successful always, while attachEvent(...) returns success
 *   or failure, and the new value of the proprietary
 *   event-handling property must match the assigned value for
 *   the method to be successful.
 * @see
 *   dom2-events#Events-EventTarget-removeEventListener,
 *   dom2-events#Events-EventTarget-addEventListener,
 *   msdn#workshop/author/dhtml/reference/methods/detachevent.asp,
 *   msdn#workshop/author/dhtml/reference/methods/attachevent.asp,
 *   http://pointedears.de/scripts/JSdoc/
 */
function _replaceEventListener(o, sEvent, fListener, bUseCapture)
{
  var result = false, sHandler = "on" + sEvent, fOldListener;

  if (o && sEvent && isMethodType(typeof o[sHandler])
      && (fOldListener = o[sHandler])
      && isMethodType(typeof fListener) && fListener)
  {    
    if (isMethod(o, "removeEventListener", o, "addEventListener"))
    {
      o.removeEventListener(sEvent, fOldListener, !!bUseCapture);
      o.addEventListener(sEvent, fListener, !!bUseCapture);
      result = true;
    }
    else
    {
      if (isMethod(o, "detachEvent") && isMethod(o, "attachEvent"))
      {
        o.detachEvent(sHandler, fOldListener);
        result = o.attachEvent(sHandler, fListener);
      }

      if (!result)
      {
        o[sHandler] = fListener;
        result = (o[sHandler] == fListener);
      }
    }
  }
  
  return result;
}
DHTML.prototype.replaceEventListener = _replaceEventListener;

/**
 * Appends a JavaScript include to the <code>head</code> element
 * of an (X)HTML document.
 *
 * Appends the include <code>sURI</code> to the <code>head</code>
 * element of the current (X)HTML document.  (Is not wise to be
 * applied on script files that contain code to append content on
 * the fly (esp. document.write(...)) -- the existing content
 * would be overwritten.)
 * 
 * Note: Tested successfully with MSIE and Mozilla/5.0, do not
 * rely on that the script was included, but _test_ for it.
 *
 * @version
 *   0.2.2004053003
 * @author
 *   (C) 2004-2006  Thomas Lahn <dhtml.js@PointedEars.de>,
 *       2004       Ulrich Kritzner <droeppez@web.de>
 * 
 * @partof
 *   http://PointedEars.de/scripts/dhtml.js
 * @requires
 *   types.js#isMethod()
 * @param sURI : string
 *   URI of the script resource to be loaded.
 * @param sType : optional string = "text/javascript"
 *   MIME type of the script to be loaded.  Used as value of the
 *   <code>type</code> attribute, the default is (still proprietary,
 *   but commonly used) "text/javascript".
 * @param sLanguage : optional string
 *   Value of the <code>language</code> attribute (deprecated in
 *   HTML 4.01 and XHTML 1.0, absent from XHTML 1.1 and later
 *   versions) to specify the version of the script language.
 *   Unused by default.
 */
function loadScript(sURI, sType, sLanguage)
{
  var result = false;
  
  if (isMethod(document, "createElement"))
  {
    var oScript = document.createElement("script");
    if (oScript)
    {
      // no exception handling for backwards compatibility reasons
      if (typeof oScript.src != "undefined")
      {
        oScript.src  = sURI;
      }

      if (typeof oScript.type != "undefined")
      {
        oScript.type = sType || "text/javascript";
      }
      
      if (sLanguage)
      {
        oScript.language = sLanguage;
      }

      if (typeof oScript.defer != "undefined")
      {
        oScript.defer = true;
      }
      
      var aHeads;
      if (isMethod(document, "getElementsByTagName"))
      {
        aHeads = document.getElementsByTagName("head");
      }
      else if (typeof document.all != "undefined" && document.all.tags)
      {
        aHeads = document.all.tags["head"];
      }
      
      if (aHeads && typeof aHeads[0] != "undefined")
      {
        if (isMethod(aHeads[0], "appendChild"))
        {
          aHeads[0].appendChild(oScript);
          result = (
            typeof aHeads[0].lastChild != "undefined"
            && aHeads[0].lastChild == oScript);
        }
        else if (isMethod(aHeads[0], "insertAdjacentElement"))
        {
          aHeads[0].insertAdjacentElement("beforeEnd", oScript);
          result = true;
        }
      }
    }
  }

  return result;
}
DHTML.prototype.loadScript = loadScript;

/**
 * Retrieves descendant focusable elements in order of their
 * "tabindex" attribute.
 *
 * @author
 *   (C) 2004  Thomas Lahn <dhtml.js@PointedEars.de>
 * @partof
 *   http://pointedears.de/scripts/dhtml.js
 * @requires
 *   http://pointedears.de/scripts/collection.js
 * @optional Document|Element o
 *   Reference to a @link{dom2-core#Document} or
 *   @link{dom2-core#Element} object from which to retrieve
 *   descendant elements.  If omitted or evaluated to
 *   <code>false</code>, it is tried to use the calling object.
 * @return type Collection
 *   A reference to a @link{#Collection} object containing
 *   the descendant elements of @link{(o)} or the calling
 *   @link{dom2-core#Document}/@link{dom2-core#Element} object in
 *   "tabindex" order: Elements with "tabindex" > 0 come first,
 *   followed by elements with "tabindex" == 0 or where either
 *   "tabindex" is not set or not applicable.  Note: An element
 *   with a "tabindex" of 1 will will be the first element
 *   in the resulting collection but for design reasons will
 *   have an index of 0 (but since the Collection prototype
 *   provides an iterator, this does not need to disturb you).
 *   Additional note: Unlike specified, disabled elements will
 *   participate in the tabbing order (so they can be enabled
 *   later without this method to be re-called.)
 */
function getElementsByTabIndex(o)
{
  var aIndexedElements = new Array();
  var aUnindexedElements = new Array();

  // makes the method applicable to Document and Element objects
  if (!o
      && typeof this.constructor != "undefined"
      && /Document|Element/.test(this.constructor))
  {
    o = this;
  }

  if (o && isMethod(o, "getElementsByTagName"))
  {
    var es = o.getElementsByTagName("*");

    if (es && typeof es.length != "undefined")
    {
      var l = es.length;

      for (var i = 0, e; i < l; i++)
      {
        e = es[i];
        
        if (typeof e.tabIndex != "undefined")
        {
          if (e.tabIndex) // !null && !0
          {
            // tabindex="1" --> index == 0; use e.tabIndex
            // and a "zero dummy" if you do not like this
            aIndexedElements[e.tabindex - 1] = e;
          }
          else
          {
            aUnindexedElements[aUnindexedElements.length] = e;
          }
        }
      }
    }
  }

  return new Collection(aIndexedElements.concat(aUnindexedElements));
}
DHTML.prototype.getElementsByTabIndex = getElementsByTabIndex;

if (typeof HTMLDocument != "undefined"
    && typeof HTMLDocument.prototype != "undefined")
{
  HTMLDocument.prototype.getElementsByTabIndex = getElementsByTabIndex;
}

if (typeof HTMLElement != "undefined"
    && typeof HTMLElement.prototype != "undefined")
{
  HTMLElement.prototype.getElementsByTabIndex = getElementsByTabIndex;
}



/**
* <title>Type Function Library</title>
*/
function Types()
{
 this.version = "1.29.6.2008011715";
/**
* @file types.js
* @partof PointedEars' JavaScript Extensions (JSX)
* @requires object.js
* @author
*   (C) 2001-2006  Thomas Lahn &lt;types.js@PointedEars.de&gt;
*/
 this.copyright = "Copyright \xA9 1999-2008";
 this.author    = "Thomas Lahn";
 this.email     = "types.js@PointedEars.de";
 this.path      = "http://pointedears.de/scripts/";
 this.URI       = this.path + "types.js";
//var typesDocURL = typesPath + "types.htm";
}

var types = new Types();
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licnse
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License (GPL) for more details.
*
* You should have received a copy of the GNU GPL along with this
* program (COPYING file); if not, go to [1] or write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
* 
* [1] <http://www.gnu.org/licenses/licenses.html#GPL>
*/
/*
* This script file contains JSdoc[tm] comments
* to create an API documentation of it from them, see
* <http://PointedEars.de/scripts/JSdoc/> for details.
*/

/**
* @optional string sMsg
* @return type boolean
*   false
*/ 
function TypesException(sMsg)
{
 alert(
   "types.js "
     + types.version
     + "\n"
     + types.copyright
     + "  "
     + types.author
     + " <"
     + types.email
     + ">\n\n"
     + sMsg);
 return false;
}

function isDefined(a)
{
 return (typeof a != "undefined");
}

function isUndefined(a)
{
 return (typeof a == "undefined");
}

/**
* Implements the instanceof operator of JavaScript 1.5
* down to JavaScript 1.1 for *one* inheritance level:
* <pre><code>
*   var o = new Object();
*   o instanceof Object; // yields `true'
* 
*   function Foo()
*   {
*   }
*   var o = new Foo();
*   o instanceof Object;     // yields `true'
*   o instanceof Foo;        // yields `true' also
*   isInstanceOf(o, Object); // yields `false'
*   isInstanceOf(o, Foo);    // yields `true'
* </code></pre>
*
* @author
*   (C) 2003  Thomas Lahn &lt;types.js@PointedEars.de&gt;
* @argument Object a
*   Expression to be determined a <var>Prototype</var> object.
* @argument Object Prototype
*   Function object to be determined the prototype of a.
* @return type boolean
*   <code>true</code> if <code>a</code> is an object derived
*   from <var>Prototype</var>, <code>false</code> otherwise.
*/ 
function isInstanceOf(a, Prototype)
{
 return !!(
   a && Prototype
   && typeof a.constructor != "undefined"
   && a.constructor == Prototype);
}

/**
* @author
*   (C) 2003  Thomas Lahn &lt;types.js@PointedEars.de&gt;
* @partof
*   http://pointedears.de/scripts/types.js
* @requires
*   isInstanceOf
* @argument Object a
*   Expression to be determined an array.
* @return type boolean
*   <code>true</code> if <code>a</code> is an object
*   derived from Array, <code>false</code> otherwise.
*   Returns also <code>false</code> if the language
*   version does not support Array objects (JavaScript
*   before 1.1).
*/
function isArray(a)
{
 return isInstanceOf(a, typeof Array != "undefined" ? Array : null);
}

/**
* @author
*   (C) 2003  Thomas Lahn &lt;types.js@PointedEars.de&gt;
* @argument Object o
*   Object to be determined iterable, i.e. to be determined
*   whether it provides the <code>length</code> property and
*   has at least the <code>0<code> (zero) property.  This
*   applies for non-empty <code>Array</code> objects with
*   at least a first non-undefined element as well as, e.g.,
*   for DOM objects implementing one of the
*   <code>HTMLCollection</code> or
*   <code>HTMLOptionsCollection</code> interfaces defined in
*   the W3C DOM Level 2 Specification.
* @return type boolean
*   <code>true</code> if <code>o</code> is an iterable object,
*   <code>false</code> otherwise.
*/
function isIterable(o)
{
 return !!(
   o
   && typeof o.length != "undefined"
   && typeof o[0] != "undefined");
}

/**
* @param s : string 
*   String of the form "root['branch']['leaf']['...']..." or
*   "root[branch][leaf][...]..." to be converted.  Required.
* @return type string
*   A string of the form `root.branch.leaf...' converted from
*   <code>s</code>.
*/
function bracketsToDots(s)
{
 return s.replace(/\['?/g, '.').replace(/'?\]/g, '');
}

/**
* @param s: string
*   of the form `root.branch.leaf' to be converted.
*   Required.
* @param bStringsOnly: optional boolean
*   Specifies if all parts of the tree should be converted
*   or not.  Optional.
*   If not provided or <code>false</code>, all parts are
*   converted.  If <code>true</code>, only parts are converted
*   that are required to (because JavaScript identifiers as
*   required by dot notation must start with a character in
*   <code>[A-Za-z_$]</code>, though arguments of bracket
*   notation may be of any format.)
* @return type string
*   A string of the form "root['branch']['leaf']" converted
*   from <code>s</code>.
*/
function dotsToBrackets(s, bStringsOnly)
{
 var a = s.split(".");
 s = [a[0]];
 
 for (var i = 1, len = a.length; i < len; i++)
 {
   if (!bStringsOnly)
   {
     s.push("['", a[i], "']");
   }
   else
   {
     if (/^[a-z_$]/i.test(a[i]))
     {
       s.push(".", a[i]);
     }
     else
     {
       s.push("[", a[i], "]");
     }
   }
 }
 
 return s.join("");
}

/**
* Sets the handler for the proprietary <code>error</code> event.
* 
* NOTE: This method has previously been provided by {@link debug.js};
* optimizations in code reuse moved it here.
* 
* @type boolean
* @return <code>true</code> if the error handler could be assigned
*   successfully, <code>false</code> otherwise.  Note that one reason
*   for failure is that this event handler is no longer supported
*   by the UA's DOM due to efforts towards adherence to Web standards.
*/ 
function setErrorHandler(fHandler)
{
 if (!fHandler) fHandler = clearErrorHandler;
 
 if (typeof window != "undefined" && typeof window.onerror != "undefined")
 {
   // debug.js 0.99.5.2006041101 BUGFIX:
   // onerror is defined as a property of window, not of the Global Object
   window.onerror = fHandler;
 }
 
 return (typeof window.onerror != "undefined"
   && window.onerror == fHandler);
}

/**
* Clears the handler for the proprietary <code>error</code> event.
* 
* NOTE: This method has previously been provided by {@link debug.js};
* optimizations in code reuse moved it here.
* 
* @type boolean
* @return Always <code>true</code>
*/ 
function clearErrorHandler()
{
 if (typeof window != "undefined" && window.onerror)
 {
   // debug.js 0.99.5.2006041101 BUGFIX:
   // onerror is defined as a property of window, not of the Global Object
   window.onerror = null;
 }

 return true;
}

/**
* @author
*   (C) 2003-2008  Thomas Lahn &lt;types.js@PointedEars.de&gt;
* @params :optional Object|string|(Object,string)
*   Objects to be determined a method, i.e. a
*   <code>Function</code> object assigned as property of
*   another object.  Each argument may also be a string
*   to be evaluated and so is applicable to unknown properties.
*   If an argument is followed by a string argument, it is
*   assumed that the argument is the object and the string
*   argument is the name of the property to be tested.
* @return type boolean
*   <code>true</code> if all arguments refer to methods,
*   <code>false</code> otherwise.
* @see #isMethodType()
*/
function isMethod()
{
 for (var i = 0, len = arguments.length,
          rxMethod = /^\s*(function|object)\s*$/i;
      i < len; i++)
 {
   var arg = arguments[i];

   if (rxMethod.test(typeof arg) && arg
       && typeof arguments[i + 1] == "string")
   {
     // if the property is not a method
     if (!(rxMethod.test(typeof arg[arguments[i + 1]])
           && arg[arguments[i + 1]]))
     {
       return false;       
     }
     
     i++;
     continue;
   }
   
   if (typeof arg == "string") arg = eval(arg);

   // if the property is not a method
   if (!(rxMethod.test(typeof arg) && arg))
   {
     return false;
   }
 }
 
 return true;
}

function isMethod2()
{
 for (var i = 0, len = arguments.length; i < len; i++)
 {
   var arg = arguments[i];

   if (typeof arg == "string")
   {
     setErrorHandler();
     arg = eval(arg);
     clearErrorHandler();
   }
   else if (arg.constructor == Array)
   {
     setErrorHandler();
     var o = (typeof arg[0] == "string")
       ? eval(arg[0])
       : arg[0];
     clearErrorHandler();
     
     if (o && arg.length > 1)
     {     
       setErrorHandler();
       if (typeof o[arg[1]] == "string")
         arg = eval(o[arg[1]]);
       clearErrorHandler();
     }
     else
     {
       arg = 0;
     }
   }

   // if the property is not a method
   if (!(/\b(function|object)\b/i.test(typeof arg) && arg))
   {
     return false;
   }
 }
 
 return true;
}
/**
* @author
*   (C) 2003, 2004  Thomas Lahn &lt;types.js@PointedEars.de&gt;
*   Distributed under the GNU GPL v2.
* @partof
*   http://pointedears.de/scripts/types.js
* @optional string s
*   String to be determined a method type, i.e. "object"
*   in IE, "function" otherwise.  The type must have been
*   retrieved with the `typeof' operator, thus this method
*   is applicable to unknown properties while
*   @link{#isMethod()} is not.  Note that this method
*   may also return <code>true</code> if the value of
*   the <code>typeof</code> operand is <code>null</code>; to
*   be sure that the operand is a method reference, you have
*   to && (AND)-combine the <code>isMethodType(...)</code>
*   expression with the method reference identifier.
* @return type boolean
*   <code>true</code> if <code>s</code> is a method type,
*   <code>false</code> otherwise.
* @see #isMethod()
*/
function isMethodType(s)
{
 return /\b(function|object)\b/i.test(s);
}

