
String.prototype.trim = String.prototype.trim || function() {
    return this.replace(/^\s+/,'').replace(/\s+$/,'');
}


Array.prototype.indexOf = Array.prototype.indexOf || function(item, start) {
    for (var i = (start || 0); i < this.length; i++) {
        if (this[i] == item) {
            return i;
        }
    }
    return -1;
}


Array.prototype.push = Array.prototype.push || function() {
    for (var i = 0; i < arguments.length; i++) {
        this[this.length] = arguments[i];
    }
    return this.length;
}


Array.prototype.splice = Array.prototype.splice || function(start, deleteCount) {
    var beg = this.slice(0, start);
    var del = this.slice(start, start + deleteCount);
    var end = this.slice(start + deleteCount);

    var ins = [];
    for (var i = 2; i < arguments.length; i++) {
    	ins[i-2] = arguments[i];
    }
    
    this.length = 0;
    var tmp = this.concat(beg, ins, end);
    for (var i = 0; i < tmp.length; i++) {
    	this[i] = tmp[i];
    }

    return del;
}


function getClasses(element) {
    return element.className ? element.className.trim().split(/\s+/) : [];
}


function addClass(element, c) {
    var classes = getClasses(element);
    if (classes.indexOf(c) == -1) {
        classes.push(c);
        element.className = classes.join(' ');
    }
}


function removeClass(element, c) {
    var classes = getClasses(element);
    var idx = classes.indexOf(c);
    if (idx != -1) {
        classes.splice(idx, 1);
        element.className = classes.join(' ');
    }
}


function hasClass(element, c) {
    return getClasses(element).indexOf(c) != -1;
}


function Jsslideshow(prefix, msec, max)
// Initialises a slide show - you only need to call this if you want to have more than one on a page, or if you need to change the id-prefix of the elements
{
	this.prefix = prefix ? prefix : "myJsslideshow";
	this.default_interval = msec ? parseInt(msec) : 3500;
	this.selected = 0;
	this.max = max ? parseInt(max) : 12;
	
	this.fadeInDelay = 200; // Setting this to 0 will suppress fade out. Positive values will issue fade in this amount of milliseconds after starting fade out.
	this.opacitySteps = 10; // 5 or 10 steps
	this.fadeInTime = 200; // Total time to fade in in milliseconds
	this.fadeOutTime = 400; // Total time to fade out in milliseconds
	
	this.autoSlide = false;
}

Jsslideshow.prototype.getElem = function(i)
{
	var elem = document.getElementById(this.prefix + ":" + i);
	return elem ? elem : false;
}

Jsslideshow.prototype.getVisible = function()
{
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem && !hasClass(elem, "hidden"))
		{
			return i;
		}
	}
	return false;
}

Jsslideshow.prototype.exists = function()
{
	for (var i = 0; i <= this.max; i++)
	{
		var elem = this.getElem(i);
		if (elem)
			return true;
	}
	return false;
}

Jsslideshow.prototype.autoStart = function(msec)
// Starts the slideshow
// msec (optional) is the interval in milliseconds. Defaults to the value specified at the top
// NOTE: If the slideshow is already started, it will essentially continue, but with the new msec interval
{
	if (!this.exists())
	{
		return;
	}
	this.selected = this.getVisible();
	
	if (this.timer)
		this.autoStop();

	if (msec)
		this.default_interval = msec;
		
	this.autoSlide = true;
	
	//this.autoNext();
	this.showNext();

}

Jsslideshow.prototype.autoNext = function()
{
	if (this.autoSlide)
		this.timer = setTimeout(this.prefix + ".showNext()", this.default_interval);
}

Jsslideshow.prototype.autoStop = function()
// Stops the slideshow
{
	if (this.timer)
		this.timer = clearTimeout(this.timer);
	this.autoSlide = false;
}

Jsslideshow.prototype.autoToggle = function()
// Starts or stops the slideshow
{
	if (this.autoSlide)
		this.autoStop();
	else
		this.autoStart();
}

Jsslideshow.prototype.showPrev = function(i)
// Shows the previous slide
{
	if (i == undefined)
		i = this.selected;
	else if (i == this.selected)
		return;
		
	if (i == 0)
		i = this.max;
	else
		i--;	
	
	if (!this.getElem(i))
		setTimeout(this.prefix + ".showPrev("+i+")", 10); 
	else
		this.show(i);
}

Jsslideshow.prototype.showNext = function(i)
// Shows the next slide
// Rewinds to the beginning when reaching the end
{
	i = 1 + Math.round((this.max - 1) * Math.random());
		
	this.show(i);
}

Jsslideshow.prototype.show = function(i)
// Shows a specific slide (fades in)
{
	if (i == this.selected)
	{
		this.showNext();
		return;
	}
	var elem = this.getElem(i);
	if (elem)
	{	
		if (this.fadeInDelay > 0)
			this.fadeOut(this.selected);
		setTimeout(this.prefix + ".fadeIn("+i+")", this.fadeInDelay);
		
		var nav_elem = document.getElementById("jsslideshow_navbar_select:" + this.selected);
		if (nav_elem)
			removeClass(nav_elem, "selected");
			
		var nav_elem = document.getElementById("jsslideshow_navbar_select:" + i);
		if (nav_elem && !hasClass(nav_elem, "selected"))
			addClass(nav_elem, "selected");
	}
}

Jsslideshow.prototype.hide = function(i)
// Hides a specific slide (immediately)
{
	var elem = this.getElem(i);
	if (elem)
	{	
		if (!hasClass(elem, "hidden"))
			addClass(elem, "hidden");
	}
}

Jsslideshow.prototype.fadeIn = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade in
		{
			addClass(elem, "opacity0");
			removeClass(elem, "hidden");
			addClass(elem, "on_top");
			this.fadeIn(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);

		if (opacity > 90)	// Ending fade in
		{
			this.hide(this.selected);
	 		this.selected = i;
	 		removeClass(elem, opacity_class);
	 		removeClass(elem, "on_top");
	 		this.autoNext();
			return;
		}

		opacity = opacity + parseInt(100 / this.opacitySteps);
		addClass(elem, "opacity" + opacity);
		removeClass(elem, opacity_class);

		setTimeout(this.prefix + ".fadeIn("+i+")", parseInt(this.fadeInTime / this.opacitySteps));
	}			 	
}

Jsslideshow.prototype.fadeOut = function(i)
{
	var elem = this.getElem(i);
	if (elem)
	{
		var opacity_match = elem.className.match(/opacity([^\s]+)/i);

		if (!opacity_match) // Starting fade out
		{
			addClass(elem, "opacity100");
			this.fadeOut(i);
			return;
		}

		var opacity_class = opacity_match[0];
		var opacity = parseInt(opacity_match[1]);
		
		if (opacity < 10)
		{
			removeClass(elem, opacity_class);
			this.hide(i);
			return;
		}

		opacity = opacity - parseInt(100 / this.opacitySteps);
		addClass(elem, "opacity" + opacity);
		removeClass(elem, opacity_class);

		setTimeout(this.prefix + ".fadeOut("+i+")", parseInt(this.fadeOutTime / this.opacitySteps));
	}			 	
}

myJsslideshow = new Jsslideshow("myJsslideshow");