function Slideshow(timeout, parentId)
{
  this.parent   = document.getElementById(parentId);
  this.images   = [];
  this.timeout  = timeout || 5000;
  this.current  = 0;
  this.firstrun = true;
  this.callback = null;

  this.parent.className = "slideshow";

  while(this.parent.firstChild)
    this.parent.removeChild(this.parent.firstChild);

  var a = document.createElement("a");
  a.target = "_blank";
  this.parent.appendChild(a);

  return this;
}

Slideshow.prototype = {

  // public methods:

  AddElement: function(imageSrc, caption, link)
  {
    var l = this.images.length;

    var imag = this.images[l] = new Object;
    imag.src = imageSrc;
	imag.alt = caption;

    var img = imag.obj = document.createElement("img");
    img.src = imageSrc;
	
    img.id  = "slide_img_" + this.parent.id + "_" + String(l);
	img.url = link;

    this.parent.firstChild.appendChild(img);

    var s           = imag.cap = document.createElement("span");
    s.id            = "slide_cap_" + this.parent.id + "_" + String(l);
	s.innerHTML     = '';
	s.style.zIndex  = 10;
    s.style.opacity = 0;
	s.style.cursor  = link ? "pointer" : "default";
    s.style.filter  = "alpha(opacity=0)";

    this.parent.firstChild.appendChild(s);

    var is = img.style;
	is.zIndex   = 1;
	is.position = "absolute"
	is.top      = "0px";
	is.left     = "0px";
    is.border   = "0";
    is.opacity  = 0;
    is.filter   = "alpha(opacity=0)";

    return l;
  },

  AddCallback: function(func, param)
  {
	this.callback = this._delegate(null, func, param);
  },

  start: function()
  {
    this._showslide();
  },

  // support methods follow:

  _delegate: function(obj, func, param)
  {
    param = param || null;
    return function() { func.call(obj, param); };
  },

  _showslide: function()
  {
    var cur = this.current;

	if(!this.firstrun)
	{
	  var img = this.images[cur];

	  this._fade(img.obj.id, 0, 50, 10, true);
	  this._fade(img.cap.id, 0, 50, 10, false);
	}

    var l = this.images.length, cur = this.current = (((cur == l - 1) || this.firstrun) ? 0 : (cur + 1));

    var img = this.images[cur];
    this._fade(img.obj.id, 100, 50, 10, true, this.callback);
    this._fade(img.cap.id, 100, 50, 10, false);

	this.firstrun = false;
	setTimeout(this._delegate(this, this._showslide), this.timeout + 500);
  },

  _fade: function(id, destOp, rate, delta, affectParent, callback)
  {
    var obj = document.getElementById(id);

    if(obj.timer)
	{
		clearTimeout(obj.timer);
	}

    var curOp = obj.filters ? obj.filters.alpha.opacity : (obj.style.opacity * 100.0);
    var direction = (curOp <= destOp) ? 1 : -1;

	if((curOp == 0) && (destOp == 100))
	{
		obj.style.display = "block";
	}

	if(affectParent)
	{
		if((curOp >= 50) && (destOp == 100))
		{
			if(obj.url)
			{
				obj.parentNode.href = obj.url || "";
			}
			else
			{
				obj.parentNode.removeAttribute("href");
			}
		}
	}

    delta  = Math.min(direction * (destOp - curOp), delta);
    curOp += direction * delta;

	if((curOp == 0) && (destOp == 0))
	{
		obj.style.display = "none";
	}

    if(obj.filters)
	{
		obj.filters.alpha.opacity = curOp;
	}
    else
	{
		obj.style.opacity = curOp / 100.0;
	}

    if(curOp != destOp)
	{
		obj.timer = setTimeout(function() { Slideshow.prototype._fade(id, destOp, rate, delta, affectParent, callback); }, rate);
	}
	else
	{
		if((destOp == 100) && callback)
		{
			callback();
		}
	}
  }
};