/*----------------------------------------------------------------------------\
|                            Sortable Table 1.12                              |
|-----------------------------------------------------------------------------|
|                         Created by Erik Arvidsson                           |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
| A DOM 1 based script that allows an ordinary HTML table to be sortable.     |
|-----------------------------------------------------------------------------|
|                  Copyright (c) 1998 - 2004 Erik Arvidsson                   |
|-----------------------------------------------------------------------------|
| This software is provided "as is", without warranty of any kind, express or |
| implied, including  but not limited  to the warranties of  merchantability, |
| fitness for a particular purpose and noninfringement. In no event shall the |
| authors or  copyright  holders be  liable for any claim,  damages or  other |
| liability, whether  in an  action of  contract, tort  or otherwise, arising |
| from,  out of  or in  connection with  the software or  the  use  or  other |
| dealings in the software.                                                   |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| This  software is  available under the  three different licenses  mentioned |
| below.  To use this software you must chose, and qualify, for one of those. |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| The WebFX Non-Commercial License          http://webfx.eae.net/license.html |
| Permits  anyone the right to use the  software in a  non-commercial context |
| free of charge.                                                             |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| The WebFX Commercial license           http://webfx.eae.net/commercial.html |
| Permits the  license holder the right to use  the software in a  commercial |
| context. Such license must be specifically obtained, however it's valid for |
| any number of  implementations of the licensed software.                    |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| GPL - The GNU General Public License    http://www.gnu.org/licenses/gpl.txt |
| Permits anyone the right to use and modify the software without limitations |
| as long as proper  credits are given  and the original  and modified source |
| code are included. Requires  that the final product, software derivate from |
| the original  source or any  software  utilizing a GPL  component, such  as |
| this, is also licensed under the GPL license.                               |
|-----------------------------------------------------------------------------|
| 2003-01-10 | First version                                                  |
| 2003-01-19 | Minor changes to the date parsing                              |
| 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator)               |
| 2003-02-01 | Sloppy typo like error fixed in getInnerText                   |
| 2003-07-04 | Added workaround for IE cellIndex bug.                         |
| 2003-11-09 | The bDescending argument to sort was not correctly working     |
|            | Using onclick DOM0 event if no support for addEventListener    |
|            | or attachEvent                                                 |
| 2004-01-13 | Adding addSortType and removeSortType which makes it a lot     |
|            | easier to add new, custom sort types.                          |
| 2004-01-27 | Switch to use descending = false as the default sort order.    |
|            | Change defaultDescending to suit your needs.                   |
| 2004-03-14 | Improved sort type None look and feel a bit                    |
| 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you    |
|            | can use another tHead or no tHead, and you can chose some      |
|            | other tBody.                                                   |
|-----------------------------------------------------------------------------|
| Created 2003-01-10 | All changes are in the log above. | Updated 2004-08-26 |
\----------------------------------------------------------------------------*/


function SortableTable(oTable, oSortTypes) {

	this.sortTypes = oSortTypes || [];

	this.sortColumn = null;
	this.descending = null;

	var oThis = this;
	this._headerOnclick = function (e) {
		oThis.headerOnclick(e);
	};

	if (oTable) {
		this.setTable( oTable );
		this.document = oTable.ownerDocument || oTable.document;
	}
	else {
		this.document = document;
	}


	// only IE needs this
	var win = this.document.defaultView || this.document.parentWindow;
	this._onunload = function () {
		oThis.destroy();
	};
	if (win && typeof win.attachEvent != "undefined") {
		win.attachEvent("onunload", this._onunload);
	}
}

SortableTable.gecko = navigator.product == "Gecko";
SortableTable.msie = /msie/i.test(navigator.userAgent);
// Mozilla is faster when doing the DOM manipulations on
// an orphaned element. MSIE is not
SortableTable.removeBeforeSort = SortableTable.gecko;

SortableTable.prototype.onsort = function () {};

// default sort order. true -> descending, false -> ascending
SortableTable.prototype.defaultDescending = false;

// shared between all instances. This is intentional to allow external files
// to modify the prototype
SortableTable.prototype._sortTypeInfo = {};

SortableTable.prototype.setTable = function (oTable) {
	if ( this.tHead )
		this.uninitHeader();
	this.element = oTable;
	this.setTHead( oTable.tHead );
	this.setTBody( oTable.tBodies[0] );
};

SortableTable.prototype.setTHead = function (oTHead) {
	if (this.tHead && this.tHead != oTHead )
		this.uninitHeader();
	this.tHead = oTHead;
	this.initHeader( this.sortTypes );
};

SortableTable.prototype.setTBody = function (oTBody) {
	this.tBody = oTBody;
};

SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
	if ( this.tHead )
		this.uninitHeader();
	this.sortTypes = oSortTypes || [];
	if ( this.tHead )
		this.initHeader( this.sortTypes );
};

// adds arrow containers and events
// also binds sort type to the header cells so that reordering columns does
// not break the sort types
SortableTable.prototype.initHeader = function (oSortTypes) {
	if (!this.tHead) return;
	var cells = this.tHead.rows[0].cells;
	var doc = this.tHead.ownerDocument || this.tHead.document;
	this.sortTypes = oSortTypes || [];
	var l = cells.length;
	var img, c;
	for (var i = 0; i < l; i++) {
		c = cells[i];
		if (this.sortTypes[i] != null && this.sortTypes[i] != "None") {
			img = doc.createElement("IMG");
			img.src = "http://blog.austria.info/static/austriainfo/layouts/austriainfo1/blank.gif";
			c.appendChild(img);
			if (this.sortTypes[i] != null)
				c._sortType = this.sortTypes[i];
			if (typeof c.addEventListener != "undefined")
				c.addEventListener("click", this._headerOnclick, false);
			else if (typeof c.attachEvent != "undefined")
				c.attachEvent("onclick", this._headerOnclick);
			else
				c.onclick = this._headerOnclick;
		}
		else
		{
			c.setAttribute( "_sortType", oSortTypes[i] );
			c._sortType = "None";
		}
	}
	this.updateHeaderArrows();
};

// remove arrows and events
SortableTable.prototype.uninitHeader = function () {
	if (!this.tHead) return;
	var cells = this.tHead.rows[0].cells;
	var l = cells.length;
	var c;
	for (var i = 0; i < l; i++) {
		c = cells[i];
		if (c._sortType != null && c._sortType != "None") {
			c.removeChild(c.lastChild);
			if (typeof c.removeEventListener != "undefined")
				c.removeEventListener("click", this._headerOnclick, false);
			else if (typeof c.detachEvent != "undefined")
				c.detachEvent("onclick", this._headerOnclick);
			c._sortType = null;
			c.removeAttribute( "_sortType" );
		}
	}
};

SortableTable.prototype.updateHeaderArrows = function () {
	if (!this.tHead) return;
	var cells = this.tHead.rows[0].cells;
	var l = cells.length;
	var img;
	for (var i = 0; i < l; i++) {
		if (cells[i]._sortType != null && cells[i]._sortType != "None") {
			img = cells[i].lastChild;
			if (i == this.sortColumn)
				img.className = "sort-arrow " + (this.descending ? "descending" : "ascending");
			else
				img.className = "sort-arrow";
		}
	}
};

SortableTable.prototype.headerOnclick = function (e) {
	// find TD element
	var el = e.target || e.srcElement;
	while (el.tagName != "TD")
		el = el.parentNode;

	this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
};

// IE returns wrong cellIndex when columns are hidden
SortableTable.getCellIndex = function (oTd) {
	var cells = oTd.parentNode.childNodes
	var l = cells.length;
	var i;
	for (i = 0; cells[i] != oTd && i < l; i++)
		;
	return i;
};

SortableTable.prototype.getSortType = function (nColumn) {
	return this.sortTypes[nColumn] || "String";
};

// only nColumn is required
// if bDescending is left out the old value is taken into account
// if sSortType is left out the sort type is found from the sortTypes array

SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
	if (!this.tBody) return;
	if (sSortType == null)
		sSortType = this.getSortType(nColumn);

	// exit if None
	if (sSortType == "None")
		return;

	if (bDescending == null) {
		if (this.sortColumn != nColumn)
			this.descending = this.defaultDescending;
		else
			this.descending = !this.descending;
	}
	else
		this.descending = bDescending;

	this.sortColumn = nColumn;

	if (typeof this.onbeforesort == "function")
		this.onbeforesort();

	var f = this.getSortFunction(sSortType, nColumn);
	var a = this.getCache(sSortType, nColumn);
	var tBody = this.tBody;

	a.sort(f);

	if (this.descending)
		a.reverse();

	if (SortableTable.removeBeforeSort) {
		// remove from doc
		var nextSibling = tBody.nextSibling;
		var p = tBody.parentNode;
		p.removeChild(tBody);
	}

	// insert in the new order
	var l = a.length;
	for (var i = 0; i < l; i++)
		tBody.appendChild(a[i].element);

	if (SortableTable.removeBeforeSort) {
		// insert into doc
		p.insertBefore(tBody, nextSibling);
	}

	this.updateHeaderArrows();

	this.destroyCache(a);

	if (typeof this.onsort == "function")
		this.onsort();
};

SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) {
	var oThis = this;
	this._asyncsort = function () {
		oThis.sort(nColumn, bDescending, sSortType);
	};
	window.setTimeout(this._asyncsort, 1);
};

SortableTable.prototype.getCache = function (sType, nColumn) {
	if (!this.tBody) return [];
	var rows = this.tBody.rows;
	var l = rows.length;
	var a = new Array(l);
	var r;
	for (var i = 0; i < l; i++) {
		r = rows[i];
		a[i] = {
			value:		this.getRowValue(r, sType, nColumn),
			element:	r
		};
	};
	return a;
};

SortableTable.prototype.destroyCache = function (oArray) {
	var l = oArray.length;
	for (var i = 0; i < l; i++) {
		oArray[i].value = null;
		oArray[i].element = null;
		oArray[i] = null;
	}
};

SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
	// if we have defined a custom getRowValue use that
	if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
		return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);

	var s;
	var c = oRow.cells[nColumn];
	if (typeof c.innerText != "undefined")
		s = c.innerText;
	else
		s = SortableTable.getInnerText(c);
	return this.getValueFromString(s, sType);
};

SortableTable.getInnerText = function (oNode) {
	var s = "";
	var cs = oNode.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				s += SortableTable.getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				s += cs[i].nodeValue;
				break;
		}
	}
	return s;
};

SortableTable.prototype.getValueFromString = function (sText, sType) {
	if (this._sortTypeInfo[sType])
		return this._sortTypeInfo[sType].getValueFromString( sText );
	return sText;
	/*
	switch (sType) {
		case "Number":
			return Number(sText);
		case "CaseInsensitiveString":
			return sText.toUpperCase();
		case "Date":
			var parts = sText.split("-");
			var d = new Date(0);
			d.setFullYear(parts[0]);
			d.setDate(parts[2]);
			d.setMonth(parts[1] - 1);
			return d.valueOf();
	}
	return sText;
	*/
	};

SortableTable.prototype.getSortFunction = function (sType, nColumn) {
	if (this._sortTypeInfo[sType])
		return this._sortTypeInfo[sType].compare;
	return SortableTable.basicCompare;
};

SortableTable.prototype.destroy = function () {
	this.uninitHeader();
	var win = this.document.parentWindow;
	if (win && typeof win.detachEvent != "undefined") {	// only IE needs this
		win.detachEvent("onunload", this._onunload);
	}
	this._onunload = null;
	this.element = null;
	this.tHead = null;
	this.tBody = null;
	this.document = null;
	this._headerOnclick = null;
	this.sortTypes = null;
	this._asyncsort = null;
	this.onsort = null;
};

// Adds a sort type to all instance of SortableTable
// sType : String - the identifier of the sort type
// fGetValueFromString : function ( s : string ) : T - A function that takes a
//    string and casts it to a desired format. If left out the string is just
//    returned
// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
//    compare function. Takes two values and compares them. If left out less than,
//    <, compare is used
// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function
//    that takes the row and the column index and returns the value used to compare.
//    If left out then the innerText is first taken for the cell and then the
//    fGetValueFromString is used to convert that string the desired value and type

SortableTable.prototype.addSortType = function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) {
	this._sortTypeInfo[sType] = {
		type:				sType,
		getValueFromString:	fGetValueFromString || SortableTable.idFunction,
		compare:			fCompareFunction || SortableTable.basicCompare,
		getRowValue:		fGetRowValue
	};
};

// this removes the sort type from all instances of SortableTable
SortableTable.prototype.removeSortType = function (sType) {
	delete this._sortTypeInfo[sType];
};

SortableTable.basicCompare = function compare(n1, n2) {
	if (n1.value < n2.value)
		return -1;
	if (n2.value < n1.value)
		return 1;
	return 0;
};

SortableTable.idFunction = function (x) {
	return x;
};

SortableTable.toUpperCase = function (s) {
	return s.toUpperCase();
};

SortableTable.toDate = function (s) {
	var parts = s.split("-");
	var d = new Date(0);
	d.setFullYear(parts[0]);
	d.setDate(parts[2]);
	d.setMonth(parts[1] - 1);
	return d.valueOf();
};


// add sort types
SortableTable.prototype.addSortType("Number", Number);
SortableTable.prototype.addSortType("CaseInsensitiveString", SortableTable.toUpperCase);
SortableTable.prototype.addSortType("Date", SortableTable.toDate);
SortableTable.prototype.addSortType("String");
// None is a special case


/*
  Lightbox JS: Fullsize Image Overlays 
  by Lokesh Dhakar - http://www.huddletogether.com

  For more information on this script, visit:
  http://huddletogether.com/projects/lightbox/

  Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
  (basically, do anything you want, just leave my name and link)
  
  Table of Contents
  -----------------
  Configuration
  
  Functions
  - getPageScroll()
  - getPageSize()
  - pause()
  - getKey()
  - listenKey()
  - showLightbox()
  - hideLightbox()
  - initLightbox()
  - addLoadEvent()
  
  Function Calls
  - addLoadEvent(initLightbox)

*/

//
// Configuration
//

// If you would like to use a custom loading image or close button reference them in the next two lines.
var loadingImage = 'http://blog.austria.info/static/austriainfo/layouts/austriainfo1/loading.gif';
var closeButton = 'http://blog.austria.info/static/austriainfo/layouts/austriainfo1/close.gif';


//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.org
//
function getPageScroll(){

  var yScroll;

  if (self.pageYOffset) {
    yScroll = self.pageYOffset;
  } else if (document.documentElement && document.documentElement.scrollTop){   // Explorer 6 Strict
    yScroll = document.documentElement.scrollTop;
  } else if (document.body) {// all other Explorers
    yScroll = document.body.scrollTop;
  }

  arrayPageScroll = new Array('',yScroll) 
  return arrayPageScroll;
}


//
// getPageSize()
// Returns array with page width, height and window width, height
// Core code from - quirksmode.org
// Edit for Firefox by pHaez
//
function getPageSize(){
  
  var xScroll, yScroll;
  
  if (window.innerHeight && window.scrollMaxY) {  
    xScroll = document.body.scrollWidth;
    yScroll = window.innerHeight + window.scrollMaxY;
  } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
    xScroll = document.body.scrollWidth;
    yScroll = document.body.scrollHeight;
  } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
    xScroll = document.body.offsetWidth;
    yScroll = document.body.offsetHeight;
  }
  
  var windowWidth, windowHeight;
  if (self.innerHeight) {  // all except Explorer
    windowWidth = self.innerWidth;
    windowHeight = self.innerHeight;
  } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
    windowWidth = document.documentElement.clientWidth;
    windowHeight = document.documentElement.clientHeight;
  } else if (document.body) { // other Explorers
    windowWidth = document.body.clientWidth;
    windowHeight = document.body.clientHeight;
  }  
  
  // for small pages with total height less then height of the viewport
  if(yScroll < windowHeight){
    pageHeight = windowHeight;
  } else { 
    pageHeight = yScroll;
  }

  // for small pages with total width less then width of the viewport
  if(xScroll < windowWidth){  
    pageWidth = windowWidth;
  } else {
    pageWidth = xScroll;
  }


  arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
  return arrayPageSize;
}


//
// pause(numberMillis)
// Pauses code execution for specified time. Uses busy code, not good.
// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
//
function pause(numberMillis) {
  var now = new Date();
  var exitTime = now.getTime() + numberMillis;
  while (true) {
    now = new Date();
    if (now.getTime() > exitTime)
      return;
  }
}


//
// getKey(key)
// Gets keycode. If 'x' is pressed then it hides the lightbox.
//
function getKey(e){
  if (e == null) { // ie
    keycode = event.keyCode;
  } else { // mozilla
    keycode = e.which;
  }
  key = String.fromCharCode(keycode).toLowerCase();
  
  if(key == 'x'){ hideLightbox(); }
}


//
// listenKey()
//
function listenKey () {  document.onkeypress = getKey; }


//
// showLightbox()
// Preloads images. Pleaces new image in lightbox then centers and displays.
//
function showLightbox(objLink)
{
  // prep objects
  var objOverlay = document.getElementById('overlay');
  var objLightbox = document.getElementById('lightbox');
  var objCaption = document.getElementById('lightboxCaption');
  var objImage = document.getElementById('lightboxImage');
  var objLoadingImage = document.getElementById('loadingImage');
  var objLightboxDetails = document.getElementById('lightboxDetails');

  
  var arrayPageSize = getPageSize();
  var arrayPageScroll = getPageScroll();

  // center loadingImage if it exists
  if (objLoadingImage) {
    objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 - objLoadingImage.height) / 2) + 'px');
    objLoadingImage.style.left = (((arrayPageSize[0] - 20 - objLoadingImage.width) / 2) + 'px');
    objLoadingImage.style.display = 'block';
  }

  // set height of Overlay to take up whole page and show
  objOverlay.style.height = (arrayPageSize[1] + 'px');
  objOverlay.style.display = 'block';

  // preload image
  imgPreload = new Image();

  imgPreload.onload=function(){
    objImage.src = objLink.href;

    // center lightbox and make sure that the top and left values are not negative
    // and the image placed outside the viewport
    var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 - imgPreload.height) / 2);
    var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2);
    
    objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px";
    objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft + "px";


    objLightboxDetails.style.width = imgPreload.width + 'px';
    
    if(objLink.getAttribute('title')){
      objCaption.style.display = 'block';
      //objCaption.style.width = imgPreload.width + 'px';
      objCaption.innerHTML = objLink.getAttribute('title');
    } else {
      objCaption.style.display = 'none';
    }
    
    // A small pause between the image loading and displaying is required with IE,
    // this prevents the previous image displaying for a short burst causing flicker.
    if (navigator.appVersion.indexOf("MSIE")!=-1){
      pause(250);
    } 

    if (objLoadingImage) {  objLoadingImage.style.display = 'none'; }

    // Hide select boxes as they will 'peek' through the image in IE
    selects = document.getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
                selects[i].style.visibility = "hidden";
        }

    objLightbox.style.display = 'block';

    // After image is loaded, update the overlay height as the new image might have
    // increased the overall page height.
    arrayPageSize = getPageSize();
    objOverlay.style.height = (arrayPageSize[1] + 'px');
    
    // Check for 'x' keypress
    listenKey();

    return false;
  }

  imgPreload.src = objLink.href;
}


//
// hideLightbox()
//
function hideLightbox()
{
  // get objects
  objOverlay = document.getElementById('overlay');
  objLightbox = document.getElementById('lightbox');

  // hide lightbox and overlay
  objOverlay.style.display = 'none';
  objLightbox.style.display = 'none';

  // make select boxes visible
  selects = document.getElementsByTagName("select");
    for (i = 0; i != selects.length; i++) {
    selects[i].style.visibility = "visible";
  }

  // disable keypress listener
  document.onkeypress = '';
}


//
// initLightbox()
// Function runs on window load, going through link tags looking for rel="lightbox".
// These links receive onclick events that enable the lightbox display for their targets.
// The function also inserts html markup at the top of the page which will be used as a
// container for the overlay pattern and the inline image.
//
function initLightbox()
{
  
  if (!document.getElementsByTagName){ return; }
  var anchors = document.getElementsByTagName("a");

  // loop through all anchor tags
  for (var i=0; i<anchors.length; i++){
    var anchor = anchors[i];

    if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "lightbox")){
      anchor.onclick = function () {showLightbox(this); return false;}
    }
  }

  // the rest of this code inserts html at the top of the page that looks like this:
  //
  // <div id="overlay">
  //    <a href="#" onclick="hideLightbox(); return false;"><img id="loadingImage" /></a>
  //  </div>
  // <div id="lightbox">
  //    <a href="#" onclick="hideLightbox(); return false;" title="Click anywhere to close image">
  //      <img id="closeButton" />    
  //      <img id="lightboxImage" />
  //    </a>
  //    <div id="lightboxDetails">
  //      <div id="lightboxCaption"></div>
  //      <div id="keyboardMsg"></div>
  //    </div>
  // </div>
  
  var objBody = document.getElementsByTagName("body").item(0);
  
  // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
  var objOverlay = document.createElement("div");
  objOverlay.setAttribute('id','overlay');
  objOverlay.onclick = function () {hideLightbox(); return false;}
  objOverlay.style.display = 'none';
  objOverlay.style.position = 'absolute';
  objOverlay.style.top = '0';
  objOverlay.style.left = '0';
  objOverlay.style.zIndex = '90';
  objOverlay.style.width = '100%';
  objBody.insertBefore(objOverlay, objBody.firstChild);
  
  var arrayPageSize = getPageSize();
  var arrayPageScroll = getPageScroll();

  // preload and create loader image
  var imgPreloader = new Image();
  
  // if loader image found, create link to hide lightbox and create loadingimage
  imgPreloader.onload=function(){

    var objLoadingImageLink = document.createElement("a");
    objLoadingImageLink.setAttribute('href','#');
    objLoadingImageLink.onclick = function () {hideLightbox(); return false;}
    objOverlay.appendChild(objLoadingImageLink);
    
    var objLoadingImage = document.createElement("img");
    objLoadingImage.src = loadingImage;
    objLoadingImage.setAttribute('id','loadingImage');
    objLoadingImage.style.position = 'absolute';
    objLoadingImage.style.zIndex = '150';
    objLoadingImageLink.appendChild(objLoadingImage);

    imgPreloader.onload=function(){};  //  clear onLoad, as IE will flip out w/animated gifs

    return false;
  }

  imgPreloader.src = loadingImage;

  // create lightbox div, same note about styles as above
  var objLightbox = document.createElement("div");
  objLightbox.setAttribute('id','lightbox');
  objLightbox.style.display = 'none';
  objLightbox.style.position = 'absolute';
  objLightbox.style.zIndex = '100';  
  objBody.insertBefore(objLightbox, objOverlay.nextSibling);
  
  // create link
  var objLink = document.createElement("a");
  objLink.setAttribute('href','#');
  objLink.setAttribute('title','Schließen');
  objLink.onclick = function () {hideLightbox(); return false;}
  objLightbox.appendChild(objLink);

  // preload and create close button image
  var imgPreloadCloseButton = new Image();

  // if close button image found, 
  imgPreloadCloseButton.onload=function(){

    var objCloseButton = document.createElement("img");
    objCloseButton.src = closeButton;
    objCloseButton.setAttribute('id','closeButton');
    objCloseButton.style.position = 'absolute';
    objCloseButton.style.zIndex = '200';
    objLink.appendChild(objCloseButton);

    return false;
  }

  imgPreloadCloseButton.src = closeButton;

  // create image
  var objImage = document.createElement("img");
  objImage.setAttribute('id','lightboxImage');
  objLink.appendChild(objImage);
  
  // create details div, a container for the caption and keyboard message
  var objLightboxDetails = document.createElement("div");
  objLightboxDetails.setAttribute('id','lightboxDetails');
  objLightbox.appendChild(objLightboxDetails);

  // create caption
  var objCaption = document.createElement("div");
  objCaption.setAttribute('id','lightboxCaption');
  objCaption.style.display = 'none';
  objLightboxDetails.appendChild(objCaption);

  // create keyboard message
  var objKeyboardMsg = document.createElement("div");
  objKeyboardMsg.setAttribute('id','keyboardMsg');
  objKeyboardMsg.innerHTML = '<a href="#" onclick="hideLightbox(); return false;">Schließen</a>';
  objLightboxDetails.appendChild(objKeyboardMsg);
}


//
// addLoadEvent()
// Adds event to window.onload without overwriting currently assigned onload functions.
// Function found at Simon Willison's weblog - http://simon.incutio.com/
//
function addLoadEvent(func)
{  
  var oldonload = window.onload;
  if (typeof window.onload != 'function'){
      window.onload = func;
  } else {
    window.onload = function(){
    oldonload();
    func();
    }
  }

}

addLoadEvent(initLightbox);  // run initLightbox onLoad


var imgWindow = "";

function openPopup(img, width, height) {
   if (img && width && height) {
      width = Math.min(width + 36, 640);
      height = Math.min(height + 30, 480);
      if (imgWindow.location && !imgWindow.closed)
         imgWindow.close();
      imgWindow = window.open(img, "imgWindow" + width + height, "toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=yes,width=" + width + ",height=" + height);
      // imgWindow.focus();
   }
}
Antville = {};
Antville.prefix = "Antville_";

Antville.pixel = new Image();
Antville.pixel.src = "http://blog.austria.info/static/pixel.gif";

Antville.colors = {"aliceblue": true, "antiquewhite": true, "aqua": true,  "aquamarine": true, "azure": true, "beige": true, "bisque": true,  "black": true, "blanchedalmond": true, "blue": true, "blueviolet": true,  "brown": true, "burlywood": true, "cadetblue": true, "chartreuse": true,  "chocolate": true, "coral": true, "cornflowerblue": true,  "cornsilk": true, "crimson": true, "cyan": true, "darkblue": true,  "darkcyan": true, "darkgoldenrod": true, "darkgray": true,  "darkgreen": true, "darkkhaki": true, "darkmagenta": true,  "darkolivegreen": true, "darkorange": true, "darkorchid": true,  "darkred": true, "darksalmon": true, "darkseagreen": true,  "darkslateblue": true, "darkslategray": true, "darkturquoise": true,  "darkviolet": true, "deeppink": true, "deepskyblue": true, "dimgray": true,  "dodgerblue": true, "firebrick": true, "floralwhite": true, "forestgreen": true, "fuchsia": true, "gainsboro": true, "ghostwhite": true, "gold": true, "goldenrod": true, "gray": true, "green": true, "greenyellow": true, "honeydew": true, "hotpink": true, "indianred ": true, "indigo ": true, "ivory": true, "khaki": true, "lavender": true, "lavenderblush": true, "lawngreen": true, "lemonchiffon": true, "lightblue": true, "lightcoral": true, "lightcyan": true, "lightgoldenrodyellow": true, "lightgrey": true, "lightgreen": true, "lightpink": true, "lightsalmon": true, "lightseagreen": true, "lightskyblue": true, "lightslateblue": true, "lightslategray": true, "lightsteelblue": true, "lightyellow": true, "lime": true, "limegreen": true, "linen": true, "magenta": true, "maroon": true, "mediumaquamarine": true, "mediumblue": true, "mediumorchid": true, "mediumpurple": true, "mediumseagreen": true, "mediumslateblue": true, "mediumspringgreen": true, "mediumturquoise": true, "mediumvioletred": true, "midnightblue": true, "mintcream": true, "mistyrose": true, "moccasin": true, "navajowhite": true, "navy": true, "oldlace": true, "olive": true, "olivedrab": true, "orange": true, "orangered": true, "orchid": true, "palegoldenrod": true, "palegreen": true, "paleturquoise": true, "palevioletred": true, "papayawhip": true, "peachpuff": true, "peru": true, "pink": true, "plum": true, "powderblue": true, "purple": true, "red": true, "rosybrown": true, "royalblue": true, "saddlebrown": true, "salmon": true, "sandybrown": true, "seagreen": true, "seashell": true, "sienna": true, "silver": true, "skyblue": true, "slateblue": true, "slategray": true, "snow": true, "springgreen": true, "steelblue": true, "tan": true, "teal": true, "thistle": true, "tomato": true, "turquoise": true, "violet": true, "violetred": true, "wheat": true, "white": true, "whitesmoke": true, "yellow": true, "yellowgreen": true};

Antville.ColorPickerFactory = function() {
   this.prefix = Antville.prefix + "ColorPicker_";
   this.valuePrefix = Antville.prefix + "ColorValue_";

   this.open = function(name, text, skin) {
      if (skin == "colorpickerExt")
         var cpWindow = window.open("http://blog.austria.info/colorpicker?name=" + name + "&text=" + text + "&skin=" + skin, Antville.ColorPicker.prefix, "toolbar=no,location=no,directories=no,status=no,scrollbars=no,resizable=yes,width=480,height=360");
      else
         var cpWindow = window.open("http://blog.austria.info/colorpicker?name=" + name + "&text=" + text + "&skin=" + skin, Antville.ColorPicker.prefix, "toolbar=no,location=no,directories=no,status=no,scrollbars=no,resizable=yes,width=350,height=320");
   }

   this.set = function(name, color) {
      var prefix = Antville.ColorPicker.prefix;
      var valuePrefix = Antville.ColorPicker.valuePrefix;
      var color = Antville.parseColor(color);
      if (color)
         document.getElementById(prefix + name).style.backgroundColor = color;
      else
         color = Antville.parseColor(document.getElementById(prefix + name).style.backgroundColor);
      if (color.indexOf("#") == 0)
         color = color.substr(1,color.length-1);
      document.getElementById(valuePrefix + name).value = color;
      return;
   }

   return this;
}

Antville.ColorPicker = new Antville.ColorPickerFactory();

Antville.encode = function(str) {
   var chars = ["&", "<", ">", '"'];
   for (var i=0; i < chars.length; i++) {
      var c = chars[i];
      var re = new RegExp(c, "g");
      str = str.replace(re, "&#" + c.charCodeAt() + ";");
   }
   return str;
}

Antville.decode = function(str) {
   return str.replace(/&amp;/g, "&");
}

Antville.parseColor = function(color) {
   var c = color.toLowerCase();
   if (Antville.colors[c])
      return c;
   var rgb = new RegExp("rgb ?\\( ?([0-9^,]*), ?([0-9^,]*), ?([0-9^ \\)]*) ?\\)");
   var result = color.match(rgb);
   if (result) {
      var R = parseInt(result[1], 10).toString(16);
      var G = parseInt(result[2], 10).toString(16);
      var B = parseInt(result[3], 10).toString(16);
      if (R.length == 1) R="0"+R;
      if (G.length == 1) G="0"+G;
      if (B.length == 1) B="0"+B;
      return "#"+R+G+B;
   }
   if (c.indexOf("#") == 0)
      c = c.substr(1,c.length-1);
   if (c.length == 6) {
      var nonhex = new RegExp("[^0-9,a-f]");
      nonhex.ignoreCase = true;
      var found = c.match(nonhex);
      if (!found)
         return "#" + c;
   }
   return;
}

Antville.Referrer = function(url, text, count) {
   this.url = url;
   this.text = text;
   this.count = count;
   return this;
}

Antville.Referrer.prototype.compose = function(key, prefix) {
   var query = new Antville.Query(this.url);
   if (query[key]) {
      if (prefix == null)
         prefix = "";
      return prefix + Antville.encode(query[key]);
   }
   return this.text;
}

Antville.Query = function(str) {
   if (str == undefined)
      var str = location.search.substring(1);
   else if (str.indexOf("?") > -1)
      var str = str.split("?")[1];
   if (str == "")
      return this;
   try {
      var parts = Antville.decode(decodeURIComponent(str)).split("&");
   } catch (e) {
      var parts = Antville.decode(unescape(str)).split("&");
   }
   for (var i = 0; i < parts.length; i++) {
      var pair = parts[i].split("=");
      var key = pair[0];
      if (key) {
         key = key.replace(/\+/g, " ");
         var value = pair[1];
         if (value)
            value = value.replace(/\+/g, " ");
         this[key] = value;
      }
   }
   return this;
}

Antville.Filter = function(def, key) {
   this.key = key;
   if (def == null)
      this.items = [];
   else if (def instanceof Array)
      this.items = def;
   else
      this.items = def.replace(/\r/g, "\n").split("\n");
   return this;
}

Antville.Filter.prototype.test = function(str) {
   if (!str)
      return false;
   for (var n = 0; n < this.items.length; n++) {
      try {
         var re = new RegExp(this.items[n], "i");
         if (re.test(str)) return true;
      } catch (err) {
         ;
      }
   }
   return false;
}
