function Shifter(btnPrevious, btnNext, numOfElements, startElement, continuous, speed, imgBase, btnPreviousEnabled, btnNextEnabled, btnPreviousDisabled, btnNextDisabled) {
	this.btnPrevious = $(btnPrevious);
	this.btnPreviousImg = this.btnPrevious.getElementsByTagName('img')[0];
	this.btnNext = $(btnNext);
	this.btnNextImg = this.btnNext.getElementsByTagName('img')[0];
	this.continuous = continuous;
	this.numOfElements = numOfElements;
	this.currentElement = startElement;
	this.speed = speed;
	this.btnPreviousEnabled = btnPreviousEnabled;
	this.btnPreviousDisabled = btnPreviousDisabled;
	this.btnNextEnabled = btnNextEnabled;
	this.btnNextDisabled = btnNextDisabled;
	this.imgBase = imgBase;
	var o = this;
	if (this.btnPrevious) this.btnPrevious.onclick = function() { o.shiftPrevious(); this.blur(); return false; }
	if (this.btnNext) this.btnNext.onclick = function() { o.shiftNext(); this.blur(); return false; }
	this.panels = new Array();
}

Shifter.prototype.shiftNext = function() {
	if (this.numOfElements < 2) {
		return;
	}
	if (this.currentElement >= this.numOfElements) {
		this.currentElement = 0;
		this.shiftToElementWithoutEffect(this.currentElement);
	}
	if (this.currentElement < this.numOfElements - 1) {
		this.currentElement++;
		this.shiftToElement(this.currentElement);
		this.adjustButtons();
	} else if (this.continuous) {
		// shift to element after the last element (identical with first element)
		this.currentElement++;
		this.shiftToElement(this.numOfElements);
	}
}

Shifter.prototype.shiftPrevious = function() {
	if (this.numOfElements < 2) {
		return;
	}
	if (this.currentElement > 0) {
		this.currentElement--;
		this.shiftToElement(this.currentElement);
		this.adjustButtons();
	} else if (this.continuous) {
		// shift to element after the last element (identical with first element) without effect
		// and from there to the last element
		this.shiftToElementWithoutEffect(this.numOfElements);
		this.currentElement = this.numOfElements - 1;
		this.shiftToElement(this.currentElement);
	}
}

Shifter.prototype.shiftToElement = function (elementNum) {
	for (var i = 0; i < this.panels.length; i++) {
		this.panels[i].shiftToElement(elementNum);
	}
}

Shifter.prototype.shiftToElementWithoutEffect = function (elementNum) {
	for (var i = 0; i < this.panels.length; i++) {
		this.panels[i].shiftToElementWithoutEffect(elementNum);
	}
}

Shifter.prototype.adjustButtons = function() {
	if (!this.continuous) {
		if (this.currentElement == 0) {
			this.btnPreviousImg.src = this.imgBase + this.btnPreviousDisabled;
		} else {
			this.btnPreviousImg.src = this.imgBase + this.btnPreviousEnabled;
		}
		if (this.currentElement == (this.numOfElements - 1)) {
			this.btnNextImg.src = this.imgBase + this.btnNextDisabled;
		} else {
			this.btnNextImg.src = this.imgBase + this.btnNextEnabled;
		}
	}
}

Shifter.prototype.addPanel = function(panel) {
	this.panels.push(panel);
	panel.shifter = this;
}

function ShiftPanel(list, widthOrHeight, horizontal) {
	this.list = list;
	this.widthOrHeight = widthOrHeight;
	this.horizontal = horizontal;
} 

ShiftPanel.prototype.shiftToElement = function(elementNum) {
	var newStyle;
	if (this.horizontal) {
		newStyle = 'left:';
	} else {
		newStyle = 'top:';
	}
	new Effect.Morph(this.list, {
  		style: newStyle + ' -' + this.widthOrHeight * elementNum + 'px',
  		duration: this.shifter.speed
	});
}

ShiftPanel.prototype.shiftToElementWithoutEffect = function(elementNum) {
	var element = $(this.list);
	if (this.horizontal) {
		element.setStyle({left: '-' + this.widthOrHeight * elementNum + 'px'});
	} else {
		element.setStyle({top: '-' + this.widthOrHeight * elementNum + 'px'});
	}
}

function StickerShiftPanel(sticker) {
	this.sticker = sticker;
	this.visible = true;
} 

StickerShiftPanel.prototype.shiftToElement = function(elementNum) {
	if (!this.visible && (elementNum == 0 || elementNum == this.shifter.numOfElements)) {
		Effect.Appear(this.sticker, { duration: this.shifter.speed });
		this.visible = true;
	} else if (this.visible && elementNum != 0 && elementNum != this.shifter.numOfElements){
		Effect.Fade(this.sticker, { duration: this.shifter.speed });
		this.visible = false;
	}
}

StickerShiftPanel.prototype.shiftToElementWithoutEffect = function(elementNum) {
	if (elementNum == 0 || elementNum == this.shifter.numOfElements) {
		$(this.sticker).setStyle({visibility: 'visible'});
		this.visible = true;
	} else {
		$(this.sticker).setStyle({visibility: 'hidden'});
		this.visible = false;
	} 
}
