function Browser(id, wrapperEl, root, params, async, method) {
	Browser.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
Browser.inheritsFrom(Widget);function OpenFlashChart(id, wrapperEl, root, params, async, method) {
	OpenFlashChart.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
OpenFlashChart.inheritsFrom(Widget);
OpenFlashChart.prototype.callBack = function(response, context) {
	var dataFile = (context.params.dataSource + "?widgetId=" + context.id).escape() + context.params.extra;
	swfobject.embedSWF("./Framework/Extensions/OC2/open-flash-chart.swf", "ofc_" + context.id, context.params.width, context.params.height, "9.0.0", "./Framework/Extensions/OC2/expressInstall.swf", {"data-file":dataFile}, {"wmode": "transparent"} );
};function CMSInfo(id, wrapperEl, root, params, async, method) {
	CMSInfo.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
CMSInfo.inheritsFrom(Widget);function DatePicker(id, wrapperEl, root, params, async, method) {
	DatePicker.superConstructor.call(this, id, wrapperEl, root, params, async, method);
	this.handlers = [];
}
DatePicker.inheritsFrom(Widget);
DatePicker.prototype.addHandler = function(func) {
	this.handlers.add(func);
	return this;
};
DatePicker.prototype.clearHandlers = function() {
	return this;
};
DatePicker.prototype.callBack = function(response, context) {
	if (context.params.update) {
		$(context.params.update).$().value = context.params.date;
	}
	if (context.params.wrapper) {
		$(context.params.wrapper).hide();
	}
	var handlers = context.handlers;
	for (var i = 0; i < context.handlers.length; i++) {
		context.handlers[i].call(this, context.params);
	}
};
DatePicker.prototype.selectDate = function(date) {
	this.params.date = date;
	this.refresh();
};function ColorPicker(id, wrapperEl, root, params, async, method) {
	ColorPicker.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
ColorPicker.inheritsFrom(Widget);
ColorPicker.prototype.callBack = function(response, context) {
	if (context.params.update) {
		$(context.params.update).$().value = context.params.color;
	}
};
ColorPicker.prototype.selectColor = function(color) {
	this.params.color = color;
	this.refresh();
};Widget.addCallBack("VisitorInfo", function(params) {
	widgets = params.widgets.split("_");
	Widget.addCallBack("DatePicker", new function(params) {
		Widget.getClass("DatePicker").addHandler(params.widgets[3], function(date) {
			new Widget($(params.widgetId).$().parentNode).refresh("widgetId=" + params.widgetId + "&date=" + date);
		});
	});
});
function VisitorInfo() {}
VisitorInfo.minHeight 		= 0;
VisitorInfo.maxHeight 		= 350;
VisitorInfo.duration 		= 750;
VisitorInfo.tweenType 		= Tween.ease;
VisitorInfo.fps 			= 30;
VisitorInfo.suffix 		= "px";
VisitorInfo.selectedBlock 	= null;
VisitorInfo.selectBlock = function(id) {
	var block = $(id);
	if (this.selectedBlock != null) {
		if (this.selectedBlock.$().id == id) {
			block.resizeHeight(this.maxHeight, this.minHeight, this.duration, this.tweenType, this.fps, this.suffix);
			this.selectedBlock = null
			return;
		}
		this.selectedBlock.resizeHeight(this.maxHeight, this.minHeight, this.duration, this.tweenType, this.fps, this.suffix);
	}
	block.resizeHeight(this.minHeight, this.maxHeight, this.duration, this.tweenType, this.fps, this.suffix);
	this.selectedBlock = block;
};
Widget.addClass("VisitorInfo", VisitorInfo);function Console(id, wrapperEl, root, params, async, method) {
	Console.superConstructor.call(this, id, wrapperEl, root, params, async, method);
	this.commandIndex = 0;
	this.commands = [];
}
Console.inheritsFrom(Widget);
Console.prototype.handleKey = function(source, event) {
	if (event.keyCode == 13) {
		this.submit(source);
	} else if (event.keyCode == 38 && this.commands.length > 0) {
		if (this.commandIndex > 0) {
			this.commandIndex--;
		}
		source.value = this.commands[this.commandIndex];
	} else if (event.keyCode == 40 && this.commands.length > 0) {
		if (this.commandIndex < this.commands.length - 1) {
			this.commandIndex++;
		}
		source.value = this.commands[this.commandIndex];
	}
	return event.keyCode;
};
Console.prototype.storeCommand = function(command) {
	if (this.commands[this.commands.length - 1] == command) {
		this.commandIndex = this.commands.length;
		return this.commands.length;
	}
	this.commands.add(command);
	this.commandIndex = this.commands.length;
	this.max = false;
	return this.commands.length;
};
Console.prototype.submit = function(source) {
	if (source.value.length == 0) {
		return;
	}
	this.storeCommand(source.value);
	var chain = $(this.id + "_history");
	var ajax = new Ajax(null, "./Framework/Widgets/Console/ajaxconsole.php?widgetId=" + this.id + "&command=" + source.value);
	ajax.onSuccess = function(response) {
		response = JSON.parse(response);
		chain.append(response.html);
		chain.$().scrollTop = chain.$().scrollHeight;
		eval(response.code);
	};
	ajax.request();
	source.value = "";;
};
Console.prototype.toggle = function(button) {
	if (this.max) {
		$(button.parentNode.parentNode).css({
				position: "relative",
				left: "auto",
				top: "auto",
				width: "auto",
				height: "auto"
			});
		$(this.id + "_history").setStyle("height", "200px");
		$(button.parentNode).setStyle("margin", "0 0 0 0");
	} else {
		$(button.parentNode.parentNode).css({
				position: "fixed",
				left: 0,
				top: 0,
				width: "100%",
				height: "100%"
			});
		$(this.id + "_history").setStyle("height", "100%");
		$(button.parentNode).setStyle("margin", "-30px 0 0 0");
	}
	this.max = !this.max;
};function SuperGrid(id, wrapperEl, root, params, async, method) {
	SuperGrid.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
SuperGrid.inheritsFrom(Widget);
SuperGrid.selectedColumn = null;
SuperGrid.pressedKey = null;
SuperGrid.grids = [];
SuperGrid.refresh = function(id, url) {
	$(id).hide();
	$(id + "_loader").show();
	$(id).request(url, function() {
			$(id + "_loader").hide();
			$(id).show();
		});
};
SuperGrid.selectColumn = function(column) {
	SuperGrid.selectedColumn = column;
};
SuperGrid.toggleRow = function(id, url, row) {
	var tempDiv = document.createElement("DIV");
	tempDiv.id = id + "_temp";
	document.body.appendChild(tempDiv);
	SuperGrid.refresh(tempDiv.id, url + "?grid=" + id + "&row=" + row);
};
SuperGrid.placeOperand = function(operand) {
	if (SuperGrid.selectedColumn != null) {
		SuperGrid.selectedColumn.value += operand;
		SuperGrid.selectedColumn.focus();
	}
};
SuperGrid.setFilter = function(id, column, filter) {
	for (var i = 0; i < SuperGrid.grids.length; i++) {
		if (SuperGrid.grids[i].id == id) {
			break;
		}
	}
	i = (i >= SuperGrid.grids.length) ? -1 : i;
	if (i == -1) {
		SuperGrid.grids.add({ "id": id, "columns": [ { "column": column, "filter": filter } ] });
		i = SuperGrid.grids.length;
	} else {
		for (var c = 0; c < SuperGrid.grids[i].columns.length; c++) {
			if (SuperGrid.grids[i].columns[c].column == column) {
				SuperGrid.grids[i].columns[c].filter = filter;
				return;
			}
		}
		SuperGrid.grids[i].columns.add({ "column": column, "filter": filter });
	}
};
SuperGrid.applyFilters = function(id, url) {
	url += "?grid=" + id + "&filters=";
	for (var i = 0; i < SuperGrid.grids.length; i++) {
		if (SuperGrid.grids[i].id == id) {
			break;
		}
	}
	if (i >= SuperGrid.grids.length) {
		return;
	}
	var grid = SuperGrid.grids[i];
	var columns = [];
	for (var i = 0; i < grid.columns.length; i++) {
		columns.add({ "column": grid.columns[i].column, "filter": grid.columns[i].filter.escape() });
	}
	var json = JSON.stringify(columns).escape();
	SuperGrid.refresh(id, url + json);
};
SuperGrid.clearFilters = function(id) {
	for (var i = 0; i < SuperGrid.grids.length; i++) {
		if (SuperGrid.grids[i].id == id) {
			break;
		}
	}
	if (i >= SuperGrid.grids.length) {
		return;
	}
	SuperGrid.grids.removeByIndex(i);
};
SuperGrid.parseDistinctValues = function(id, url, e, column, selected) {
	$(e).setBColor("#ffdddd");
	new Ajax(null, url + "?grid=" + id + "&distinctColumn=" + column, null, null, function(response) {
		var values = JSON.parse(response);
		for (var i = e.options.length; i >= 0; i--) {
			e.options[i] = null;
		}
		e.selectedIndex = 0;
		e.options[0] = new Option("", "");
		for (var i = 0; i < values.length; i++) {
			e.options[i + 1] = new Option(values[i], values[i]);
			if (values[i] == selected) {
				e.selectedIndex = i + 1;
			}
		}
		e.disabled = false;
		$(e).setBColor("#ddffdd");
	}).request();
};
SuperGrid.setSkin = function(id, url, graphicsPath, skin) {
	$(id).$().parentNode.parentNode.children[0].children[0].src = graphicsPath + "/Skins/" + skin + "/small_logo.png";
	$(id + "_loader").$().children[0].src = graphicsPath + "/Skins/" + skin + "/logo.png";
	SuperGrid.refresh(id, url + "?grid=" + id + "&skin=" + skin);
};
SuperGrid.clickRow = function(element, id, url, row) {
	if (SuperGrid.pressedKey == 17) {
		$(element).toggleClass("selected");
		SuperGrid.toggleRow(id, url, row);
		return false;
	}
	return true;
};
SuperGrid.handleRowData = function(id, url, action, row) {
	if (action == null) {
		Debugger.write("Handling row data is not possible when no action is set!");
		return;
	}
	row = (row != null) ? row : "";
	SuperGrid.refresh(id, url + "?grid=" + id + "&handleRowData=" + action + "," + row);
};
Widget.addClass("SuperGrid", SuperGrid);
$(document).on("keydown", function(e) {
	var keyCode = (window.event) ? window.event.keyCode : e.which;
	SuperGrid.pressedKey = keyCode;
}).on("keyup", function(e) {
	var keyCode = (window.event) ? window.event.keyCode : e.which;
	SuperGrid.pressedKey = null;
});function UltraGrid(id, wrapperEl, root, params, async, method) {
	UltraGrid.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
UltraGrid.inheritsFrom(Widget);
UltraGrid.pressedKey = null;
function UltraGrid_Action(id, path) {
	if (id == null || path == null) {
		alert("When an UltraGrid_Action-instance is created, an ID & path must be given!");
	}
	this.id = id;
	this.path = path;
	this.actions = [];
	this.selectedColumn = null;
};
UltraGrid_Action._instances = [];
UltraGrid_Action.instance = function(id, path) {
	var index = -1;
	for (var i = 0; index < 0 && i < UltraGrid_Action._instances.length; i++) {
		if (UltraGrid_Action._instances[i].id == id) {
			index = i;
		}
	}
	if (index < 0) {
		index = UltraGrid_Action._instances.length;
		UltraGrid_Action._instances.add(new UltraGrid_Action(id, path));		
	} else if (path != null) {
		UltraGrid_Action._instances[index].path = path;
	}
	return UltraGrid_Action._instances[index];
};
UltraGrid_Action.prototype.loader = function(show) {
	if (show && this.interval == null) {
		var chain = $(this.id + "_loader");
		this.interval = setInterval(function() { chain.getElementsByTagName("span").append("."); }, 1000);
		$(this.id + "_holder").hide();
		$(this.id + "_loader").show();
	} else if (!show && this.interval != null) {
		this.interval = clearInterval(this.interval);
		this.interval = null;
	}
};
UltraGrid_Action.prototype.toggleRow = function(row) {
	row = row ? row : "";
	this.actions.add({ "toggleRow": { "row": row } });
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.actions.clear();
	new Ajax(null, url).request();
	return this;
};
UltraGrid_Action.prototype.click = function(e, row) {
	if (UltraGrid.pressedKey == 17) {
		$(e).toggleClass("selected");
		this.toggleRow(row);
		return false;
	}
	return true;
};
UltraGrid_Action.prototype.setPage = function(page) {
	this.actions.add({ "currentPage": { "page": page } });
	return this;
};
UltraGrid_Action.prototype.setRowsPerPage = function(rows) {
	this.actions.add({ "rowsPerPage": { "rows": rows } });
	return this;
};
UltraGrid_Action.prototype.sort = function(column, sort) {
	this.actions.add({ "sort": { "column": column, "sort": sort } });
	return this;
};
UltraGrid_Action.prototype.move = function(column, move) {
	this.actions.add({ "move": { "column": column, "move": move } });
	return this;
};
UltraGrid_Action.prototype.selectColumn = function(el) {
	this.selectedColumn = el;
	return this;
};
UltraGrid_Action.prototype.filter = function(column, filter) {
	var index = -1;
	for (var i = 0; index < 0 && i < this.actions.length; i++) {
		if (this.actions[i].filter) {
			index = i;
		}
	}
	if (index < 0) {
		index = this.actions.length;
		this.actions.add({ "filter": [] });
	}
	var columnIndex = -1;
	for (var i = 0; columnIndex < 0 && i < this.actions[index].filter.length; i++) {
		if (this.actions[index].filter[i].column == column) {
			columnIndex = i;
		}
	}
	if (columnIndex < 0) {
		this.actions[index].filter.add({ "column": column, "filter": filter });
	} else {
		this.actions[index].filter[columnIndex].filter = filter;
	}
	return this;
};
UltraGrid_Action.prototype.getOptions = function(e, column, selected) {
	this.actions.add({ "getOptions": { "column": column } });
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.actions.clear();
	new Ajax(null, url, null, null, function(response) {
		var values = JSON.parse(response);
		for (var i = e.options.length; i >= 0; i--) {
			e.options[i] = null;
		}
		e.selectedIndex = 0;
		e.options[0] = new Option("", "");
		for (var i = 0; i < values.length; i++) {
			e.options[i + 1] = new Option(values[i], values[i]);
			if (values[i] == selected) {
				e.selectedIndex = i + 1;
			}
		}
		e.disabled = false;
		$(e).setBColor("#ddffdd");
	}).request();
	return this;
};
UltraGrid_Action.prototype.search = function(search) {
	this.actions.add({ "search": { "value": search } });
	return this;
};
UltraGrid_Action.prototype.setSkin = function(skin) {
	this.actions.add({ "setSkin": { "skin": skin } });
	return this;
};
UltraGrid_Action.prototype.placeOperand = function(operand) {
	if (this.selectedColumn) {
		this.selectedColumn.value += operand;
		this.selectedColumn.focus();
	}
	return this;
};
UltraGrid_Action.prototype.exportTo = function(type, scope) {
	this.actions.add({ "export": { "type": type, "scope": scope } });
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.actions.clear();
	document.location=url;
	return this;
};
UltraGrid_Action.prototype.save = function(name, title, txtLoading, txtChoose, txtDefault) {
	if (name == null) {
		name = prompt(txtChoose, txtDefault);
		if (name == null) {
			return this;
		}
	}
	this.actions.add({ "config": { "action": "save", "name": name } });
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.actions.clear();
	var chain = $("popup");
	if (title) { chain.setTitle(title); }
	if (txtLoading) { chain.update(txtLoading); }
	chain.request(url).show();
	return this;
};
UltraGrid_Action.prototype.load = function(name, title, txtLoading) {
	this.actions.add({ "config": { "action": "load", "name": name } });
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.actions.clear();
	var chain = $("popup");
	if (title) { chain.setTitle(title); }
	if (txtLoading) { chain.update(txtLoading); }
	if (name) {
		chain.request(url, function(response, context) { context.refresh(); }, null, null, null, null, null, this).show();
	} else {
		chain.request(url).show();
	}
	return this;
};
UltraGrid_Action.prototype.request = function(path) {
	if (path != null) {
		this.path = path;
	}
	var url = this.path + "?gridId=" + this.id + "&actions=" + JSON.stringify(this.actions).escape();
	this.loader(true);
	$(this.id).request(url, function(response, context) { context.loader(false); }, null, null, null, null, null, this);
	this.actions.clear();
	return this;
};
UltraGrid_Action.prototype.refresh = function(path) {
	return this.request(path);
};
$(document).on("keydown", function(e) {
	var keyCode = (window.event) ? window.event.keyCode : e.which;
	UltraGrid.pressedKey = keyCode;
}).on("keyup", function(e) {
	var keyCode = (window.event) ? window.event.keyCode : e.which;
	UltraGrid.pressedKey = null;
});Widget.addCallBack("SWFUploader", function(params) {
	alert(params.uploadHandler);
	var settings = {
			debug: params.debug,
			upload_url: "./Framework/Widgets/SWFUploader/uploader.php",
			flash_url: "./Framework/Extensions/SWFUpload/swfupload.swf",
			flash9_url: "./Framework/Extensions/SWFUpload/swfupload_fp9.swf",
			post_params: { "uploadDir": params.uploadDir, "PHPSESSID": params.sessionId },
			file_types: params.fileTypes,
			file_types_description: params.fileDescription,
			file_size_limit: params.sizeLimit,
			file_upload_limit: params.maxFiles,
			file_queue_limit: 0,
			button_image_url: params.btnSprite,
			button_width: params.btnWidth,
			button_height: params.btnHeight,
			button_placeholder_id: params.widgetId + "_button",
			swfupload_preload_handler: function() {
					if (!this.support.loading) {
						alert("You need the Flash Player 9.028 or above to use SWFUpload.");
						return false;
					}
				},
			swfupload_load_failed_handler: function() {
					alert("Something went wrong while loading SWFUpload. If this were a real application we'd clean up and then give you an alternative");
				},
			file_queue_error_handler: function(file, errorCode, message) {
					alert("File queue error handler message: '" + message + "' (code: " + errorCode + ")!");
				},
			file_dialog_complete_handler: function(numFilesSelected, numFilesQueued) {
					try {
						this.startUpload();
					} catch (ex)  {
						Debugger.write(ex);
					}
				},
			upload_start_handler: function(file) {
					return true;
				},
			upload_error_handler: function(file, errorCode, message) {
					alert("File upload error message: '" + message + "' (code: " + errorCode + ")!");	
				},
			upload_success_handler: function(file, serverData) {
					alert("File " + file.name + " uploaded...");
				}
		};
	SWFUploader.createInstance(params.widgetId, settings);
});
function SWFUploader() {}
SWFUploader.widgets = [];
SWFUploader.createInstance = function(widgetId, settings) {
	var swfu = new SWFUpload(settings);
	SWFUploader.widgets[widgetId] = swfu;
	return swfu;
};function SHOUTcast(id, wrapperEl, root, params, async, method) {
	SHOUTcast.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
SHOUTcast.inheritsFrom(Widget);
SHOUTcast.prototype.callBack = function(response, context) {
	var dt = new Date();
	var tm = dt.getTime();
	var fileToLoad = "http://o.aolcdn.com/shoutcast/widget/radio/ShoutcastV1.swf" + "?random=" + tm;
	var frameSwf = new SWFTag("miniagmmodule.swf", fileToLoad , context.params.width, context.params.height, SWFTag.V9);
	frameSwf.setAttribute("wmode", SWFTag.TRANSPARENT);
	frameSwf.setAllowScriptAccess(SWFTag.ALWAYS);
	$(context.id).update(frameSwf.toString());
};function LanguageSelector(id, wrapperEl, root, params, async, method) {
	LanguageSelector.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
LanguageSelector.inheritsFrom(Widget);
LanguageSelector.prototype.show = function(e, element) {
	e = e ? e : window.event;
	var chain = $(element.children[1]);
	var pos = GlobalKit.mousePos(e);
	var scroll = GlobalKit.scrollPos(e);
	pos.x -= scroll.x + 4;
	pos.y -= scroll.y + 4;
	var old = chain.getStyle("position");
	var box = chain.setStyle("position", "absolute").show().getBox();
	chain.setStyle("position", old);
	if (pos.x < 0) {
		pos.x = 20;
	} else if ((pos.x + box.w) > GlobalKit.screenWidth()) {
		pos.x = GlobalKit.screenWidth() - box.w - 20;
	}
	if (pos.y < 0) {
		pos.y = 20;
	} else if ((pos.y + box.h) > GlobalKit.screenHeight()) {
		pos.y = GlobalKit.screenHeight() - box.h - 20;
	}
	chain.setPos(pos);
};Widget.addCallBack("Tetris", function(params) {
	var tetris = new Tetris();
	tetris.unit = 14;
	tetris.areaX = 12;
	tetris.areaY = 22;
});
function Tetris() {
	var self = this;
	this.stats = new Stats();
	this.puzzle = null;
	this.area = null;
	this.unit  = 20; 
	this.areaX = 20; 
	this.areaY = 20; 
	this.highscores = new Highscores(10);
	this.paused = false;
	this.start = function()
	{
		if (self.puzzle && !confirm('Are you sure you want to start a new game ?')) return;
		self.reset();
		self.stats.start();
		document.getElementById("tetris-nextpuzzle").style.display = "block";
		document.getElementById("tetris-keys").style.display = "none";
		self.area = new Area(self.unit, self.areaX, self.areaY, "tetris-area");
		self.puzzle = new Puzzle(self, self.area);
		if (self.puzzle.mayPlace()) {
			self.puzzle.place();
		} else {
			self.gameOver();
		}
	};
	this.reset = function()
	{
		if (self.puzzle) {
			self.puzzle.destroy();
			self.puzzle = null;
		}
		if (self.area) {
			self.area.destroy();
			self.area = null;
		}
		document.getElementById("tetris-gameover").style.display = "none";
		document.getElementById("tetris-nextpuzzle").style.display = "none";
		document.getElementById("tetris-keys").style.display = "block";
		self.stats.reset();
		self.paused = false;
		document.getElementById('tetris-pause').style.display = 'block';
		document.getElementById('tetris-resume').style.display = 'none';
	};
	this.pause = function()
	{
		if (self.puzzle == null) return;
		if (self.paused) {
			self.puzzle.running = true;
			self.puzzle.fallDownID = setTimeout(self.puzzle.fallDown, self.puzzle.speed);
			document.getElementById('tetris-pause').style.display = 'block';
			document.getElementById('tetris-resume').style.display = 'none';
			self.stats.timerId = setInterval(self.stats.incTime, 1000);
			self.paused = false;
		} else {
			if (!self.puzzle.isRunning()) return;
			if (self.puzzle.fallDownID) clearTimeout(self.puzzle.fallDownID);
			document.getElementById('tetris-pause').style.display = 'none';
			document.getElementById('tetris-resume').style.display = 'block';
			clearTimeout(self.stats.timerId);
			self.paused = true;
			self.puzzle.running = false;
		}
	};
	this.gameOver = function()
	{
		self.stats.stop();
		self.puzzle.stop();
		document.getElementById("tetris-nextpuzzle").style.display = "none";
		document.getElementById("tetris-gameover").style.display = "block";
		if (this.highscores.mayAdd(this.stats.getScore())) {
			var name = prompt("Game Over !\nEnter your name:", "");
			if (name && name.trim().length) {
				this.highscores.add(name, this.stats.getScore());
			}
		}
	};
	this.up = function()
	{
		if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {
			if (self.puzzle.mayRotate()) {
				self.puzzle.rotate();
				self.stats.setActions(self.stats.getActions() + 1);
			}
		}
	};
	this.down = function()
	{
		if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {
			if (self.puzzle.mayMoveDown()) {
				self.stats.setScore(self.stats.getScore() + 5 + self.stats.getLevel());
				self.puzzle.moveDown();
				self.stats.setActions(self.stats.getActions() + 1);
			}
		}
	};
	this.left = function()
	{
		if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {
			if (self.puzzle.mayMoveLeft()) {
				self.puzzle.moveLeft();
				self.stats.setActions(self.stats.getActions() + 1);
			}
		}
	};
	this.right = function()
	{
		if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {
			if (self.puzzle.mayMoveRight()) {
				self.puzzle.moveRight();
				self.stats.setActions(self.stats.getActions() + 1);
			}
		}
	};
	this.space = function()
	{
		if (self.puzzle && self.puzzle.isRunning() && !self.puzzle.isStopped()) {
			self.puzzle.stop();
			self.puzzle.forceMoveDown();
		}
	};
	var helpwindow = new Window("tetris-help");
	var highscores = new Window("tetris-highscores");
	document.getElementById("tetris-menu-start").onclick = function() { helpwindow.close(); highscores.close(); self.start(); this.blur(); };
	document.getElementById("tetris-menu-pause").onclick = function() { self.pause(); this.blur(); };
	document.getElementById("tetris-menu-resume").onclick = function() { self.pause(); this.blur(); };
	document.getElementById("tetris-menu-help").onclick = function() { highscores.close(); helpwindow.activate(); this.blur(); };
	document.getElementById("tetris-help-close").onclick = helpwindow.close;
	document.getElementById("tetris-menu-highscores").onclick = function()
	{
		helpwindow.close();
		document.getElementById("tetris-highscores-content").innerHTML = self.highscores.toHtml();
		highscores.activate();
		this.blur();
	};
	document.getElementById("tetris-highscores-close").onclick = highscores.close;
	var keyboard = new Keyboard();
	keyboard.set(keyboard.n, this.start);
	keyboard.set(keyboard.p, this.pause);
	keyboard.set(keyboard.up, this.up);
	keyboard.set(keyboard.down, this.down);
	keyboard.set(keyboard.left, this.left);
	keyboard.set(keyboard.right, this.right);
	keyboard.set(keyboard.space, this.space);
	document.onkeydown = keyboard.event;
	function Window(id)
	{
		this.id = id;
		this.el = document.getElementById(this.id);
		var self = this;
		this.activate = function()
		{
			self.el.style.display = (self.el.style.display == "block" ? "none" : "block");
		};
		this.close = function()
		{
			self.el.style.display = "none";
		};
		this.isActive = function()
		{
			return (self.el.style.display == "block");
		};
	}
	function Keyboard()
	{
		this.up = 38;
		this.down = 40;
		this.left = 37;
		this.right = 39;
		this.n = 78;
		this.p = 80;
		this.r = 82;
		this.space = 32;
		this.f12 = 123;
		this.escape = 27;
		this.keys = [];
		this.funcs = [];
		var self = this;
		this.set = function(key, func)
		{
			this.keys.push(key);
			this.funcs.push(func);
		};
		this.event = function(e)
		{
			if (!e) { e = window.event; }
			for (var i = 0; i < self.keys.length; i++) {
				if (e.keyCode == self.keys[i]) {
					self.funcs[i]();
				}
			}
		};
	}
	function Stats()
	{
		this.level;
		this.time;
		this.apm;
		this.lines;
		this.score;
		this.puzzles; 
		this.actions;
		this.el = {
			"level": document.getElementById("tetris-stats-level"),
			"time":  document.getElementById("tetris-stats-time"),
			"apm":  document.getElementById("tetris-stats-apm"),
			"lines": document.getElementById("tetris-stats-lines"),
			"score": document.getElementById("tetris-stats-score")
		}
		this.timerId = null;
		var self = this;
		this.start = function()
		{
			this.reset();
			this.timerId = setInterval(this.incTime, 1000);
		};
		this.stop = function()
		{
			if (this.timerId) {
				clearInterval(this.timerId);
			}
		};
		this.reset = function()
		{
			this.stop();
			this.level = 1;
			this.time  = 0;
			this.apm   = 0;
			this.lines = 0;
			this.score = 0;
			this.puzzles = 0;
			this.actions = 0;
			this.el.level.innerHTML = this.level;
			this.el.time.innerHTML = this.time;
			this.el.apm.innerHTML = this.apm;
			this.el.lines.innerHTML = this.lines;
			this.el.score.innerHTML = this.score;
		};
		this.incTime = function()
		{
			self.time++;
			self.el.time.innerHTML = self.time;
			self.apm = parseInt((self.actions / self.time) * 60);
			self.el.apm.innerHTML = self.apm;
		};
		/**
		 * Set score - update html
		 * @param int i
		 * @return void
		 * @access public
		 */
		this.setScore = function(i)
		{
			this.score = i;
			this.el.score.innerHTML = this.score;
		};
		/**
		 * Set level - update html
		 * @param int i
		 * @return void
		 * @access public
		 */
		this.setLevel = function(i)
		{
			this.level = i;
			this.el.level.innerHTML = this.level;
		};
		/**
		 * Set lines - update html
		 * @param int i
		 * @return void
		 * @access public
		 */
		this.setLines = function(i)
		{
			this.lines = i;
			this.el.lines.innerHTML = this.lines;
		};
		/**
		 * Number of puzzles created on current level
		 * @param int i
		 * @return void
		 * @access public
		 */
		this.setPuzzles = function(i)
		{
			this.puzzles = i;
		};
		/**
		 * @param int i
		 * @return void
		 * @access public
		 */
		this.setActions = function(i)
		{
			this.actions = i;
		};
		/**
		 * @return int
		 * @access public
		 */
		this.getScore = function()
		{
			return this.score;
		};
		/**
		 * @return int
		 * @access public
		 */
		this.getLevel = function()
		{
			return this.level;
		};
		/**
		 * @return int
		 * @access public
		 */
		this.getLines = function()
		{
			return this.lines;
		};
		/**
		 * Number of puzzles created on current level
		 * @return int
		 * @access public
		 */
		this.getPuzzles = function()
		{
			return this.puzzles;
		};
		/**
		 * @return int
		 * @access public
		 */
		this.getActions = function()
		{
			return this.actions;
		};
	}
	/**
	 * Area consists of blocks (2 dimensional board).
	 * Block contains "0" (if empty) or Html Object.
	 * @param int x
	 * @param int y
	 * @param string id
	 */
	function Area(unit, x, y, id)
	{
		this.unit = unit;
		this.x = x;
		this.y = y;
		this.el = document.getElementById(id);
		this.board = [];
		// create 2-dimensional board
		for (var y = 0; y < this.y; y++) {
			this.board.push(new Array());
			for (var x = 0; x < this.x; x++) {
				this.board[y].push(0);
			}
		}
		this.destroy = function()
		{
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						this.el.removeChild(this.board[y][x]);
						this.board[y][x] = 0;
					}
				}
			}
		};
		this.removeFullLines = function()
		{
			var lines = 0;
			for (var y = this.y - 1; y > 0; y--) {
				if (this.isLineFull(y)) {
					this.removeLine(y);
					lines++;
					y++;
				}
			}
			return lines;
		};
		this.isLineFull = function(y)
		{
			for (var x = 0; x < this.x; x++) {
				if (!this.board[y][x]) { return false; }
			}
			return true;
		};
		this.removeLine = function(y)
		{
			for (var x = 0; x < this.x; x++) {
				this.el.removeChild(this.board[y][x]);
				this.board[y][x] = 0;
			}
			y--;
			for (; y > 0; y--) {
				for (var x = 0; x < this.x; x++) {
					if (this.board[y][x]) {
						var el = this.board[y][x];
						el.style.top = el.offsetTop + this.unit + "px";
						this.board[y+1][x] = el;
						this.board[y][x] = 0;
					}
				}
			}
		};
		this.getBlock = function(y, x)
		{
			if (y < 0) { return 0; }
			if (y < this.y && x < this.x) {
				return this.board[y][x];
			} else {
				throw "Area.getBlock("+y+", "+x+") failed";
			}
		};
		this.addElement = function(el)
		{
			var x = parseInt(el.offsetLeft / this.unit);
			var y = parseInt(el.offsetTop / this.unit);
			if (y >= 0 && y < this.y && x >= 0 && x < this.x) {
				this.board[y][x] = el;
			} else {
			}
		};
	}
	function Puzzle(tetris, area)
	{
		var self = this;
		this.tetris = tetris;
		this.area = area;
		this.fallDownID = null;
		this.forceMoveDownID = null;
		this.type = null; 
		this.nextType = null; 
		this.position = null; 
		this.speed = null;
		this.running = null;
		this.stopped = null;
		this.board = []; 
		this.elements = [];
		this.nextElements = []; 
		this.x = null;
		this.y = null;
		this.puzzles = [
			[
				[0,0,1],
				[1,1,1],
				[0,0,0]
			],
			[
				[1,0,0],
				[1,1,1],
				[0,0,0]
			],
			[
				[0,1,1],
				[1,1,0],
				[0,0,0]
			],
			[
				[1,1,0],
				[0,1,1],
				[0,0,0]
			],
			[
				[0,1,0],
				[1,1,1],
				[0,0,0]
			],
			[
				[1,1],
				[1,1]
			],
			[
				[0,0,0,0],
				[1,1,1,1],
				[0,0,0,0],
				[0,0,0,0]
			]
		];
		this.reset = function()
		{
			if (this.fallDownID) {
				clearTimeout(this.fallDownID);
			}
			if (this.forceMoveDownID) {
				clearTimeout(this.forceMoveDownID);
			}
			this.type = this.nextType;
			this.nextType = random(this.puzzles.length);
			this.position = 0;
			this.speed = 80 + (700 / this.tetris.stats.getLevel());
			this.running = false;
			this.stopped = false;
			this.board = [];
			this.elements = [];
			for (var i = 0; i < this.nextElements.length; i++) {
				document.getElementById("tetris-nextpuzzle").removeChild(this.nextElements[i]);
			}
			this.nextElements = [];
			this.x = null;
			this.y = null;
		};
		this.nextType = random(this.puzzles.length);
		this.reset();
		/**
		 * Check whether puzzle is running.
		 * @return bool
		 * @access public
		 */
		this.isRunning = function()
		{
			return this.running;
		};
		/**
		 * Check whether puzzle has been stopped by user. It happens when user clicks
		 * "down" when puzzle is already at the bottom of area. The puzzle may still
		 * be running with event fallDown(). When puzzle is stopped, no actions will be
		 * performed when user press a key.
		 * @return bool
		 * @access public
		 */
		this.isStopped = function()
		{
			return this.stopped;
		};
		/**
		 * Get X position of puzzle (top-left)
		 * @return int
		 * @access public
		 */
		this.getX = function()
		{
			return this.x;
		};
		/**
		 * Get Y position of puzzle (top-left)
		 * @return int
		 * @access public
		 */
		this.getY = function()
		{
			return this.y;
		};
		/**
		 * Check whether new puzzle may be placed on the area.
		 * Find (x,y) in area where beginning of the puzzle will be placed.
		 * Check if first puzzle line (checking from the bottom) can be placed on the area.
		 * @return bool
		 * @access public
		 */
		this.mayPlace = function()
		{
			var puzzle = this.puzzles[this.type];
			var areaStartX = parseInt((this.area.x - puzzle[0].length) / 2);
			var areaStartY = 1;
			var lineFound = false;
			var lines = 0;
			for (var y = puzzle.length - 1; y >= 0; y--) {
				for (var x = 0; x < puzzle[y].length; x++) {
					if (puzzle[y][x]) {
						lineFound = true;
						if (this.area.getBlock(areaStartY, areaStartX + x)) { return false; }
					}
				}
				if (lineFound) {
					lines++;
				}
				if (areaStartY - lines < 0) {
					break;
				}
			}
			return true;
		};
		this.place = function()
		{
			this.tetris.stats.setPuzzles(this.tetris.stats.getPuzzles() + 1);
			if (this.tetris.stats.getPuzzles() >= (10 + this.tetris.stats.getLevel() * 2)) {
				this.tetris.stats.setLevel(this.tetris.stats.getLevel() + 1);
				this.tetris.stats.setPuzzles(0);
			}
			var puzzle = this.puzzles[this.type];
			var areaStartX = parseInt((this.area.x - puzzle[0].length) / 2);
			var areaStartY = 1;
			var lineFound = false;
			var lines = 0;
			this.x = areaStartX;
			this.y = 1;
			this.board = this.createEmptyPuzzle(puzzle.length, puzzle[0].length);
			// create puzzle
			for (var y = puzzle.length - 1; y >= 0; y--) {
				for (var x = 0; x < puzzle[y].length; x++) {
					if (puzzle[y][x]) {
						lineFound = true;
						var el = document.createElement("div");
						el.className = "block" + this.type;
						el.style.left = (areaStartX + x) * this.area.unit + "px";
						el.style.top = (areaStartY - lines) * this.area.unit + "px";
						this.area.el.appendChild(el);
						this.board[y][x] = el;
						this.elements.push(el);
					}
				}
				if (lines) {
					this.y--;
				}
				if (lineFound) {
					lines++;
				}
			}
			this.running = true;
			this.fallDownID = setTimeout(this.fallDown, this.speed);
			var nextPuzzle = this.puzzles[this.nextType];
			for (var y = 0; y < nextPuzzle.length; y++) {
				for (var x = 0; x < nextPuzzle[y].length; x++) {
					if (nextPuzzle[y][x]) {
						var el = document.createElement("div");
						el.className = "block" + this.nextType;
						el.style.left = (x * this.area.unit) + "px";
						el.style.top = (y * this.area.unit) + "px";
						document.getElementById("tetris-nextpuzzle").appendChild(el);
						this.nextElements.push(el);
					}
				}
			}
		};
		this.destroy = function()
		{
			for (var i = 0; i < this.elements.length; i++) {
				this.area.el.removeChild(this.elements[i]);
			}
			this.elements = [];
			this.board = [];
			this.reset();
		};
		this.createEmptyPuzzle = function(y, x)
		{
			var puzzle = [];
			for (var y2 = 0; y2 < y; y2++) {
				puzzle.push(new Array());
				for (var x2 = 0; x2 < x; x2++) {
					puzzle[y2].push(0);
				}
			}
			return puzzle;
		};
		this.fallDown = function()
		{
			if (self.isRunning()) {
				if (self.mayMoveDown()) {
					self.moveDown();
					self.fallDownID = setTimeout(self.fallDown, self.speed);
				} else {
					for (var i = 0; i < self.elements.length; i++) {
						self.area.addElement(self.elements[i]);
					}
					var lines = self.area.removeFullLines();
					if (lines) {
						self.tetris.stats.setLines(self.tetris.stats.getLines() + lines);
						self.tetris.stats.setScore(self.tetris.stats.getScore() + (1000 * self.tetris.stats.getLevel() * lines));
					}
					self.reset();
					if (self.mayPlace()) {
						self.place();
					} else {
						self.tetris.gameOver();
					}
				}
			}
		};
		this.forceMoveDown = function()
		{
			if (!self.isRunning() && !self.isStopped()) {
				if (self.mayMoveDown()) {
					self.tetris.stats.setScore(self.tetris.stats.getScore() + 5 + self.tetris.stats.getLevel());
					self.tetris.stats.setActions(self.tetris.stats.getActions() + 1);
					self.moveDown();
					self.forceMoveDownID = setTimeout(self.forceMoveDown, 30);
				} else {
					for (var i = 0; i < self.elements.length; i++) {
						self.area.addElement(self.elements[i]);
					}
					var lines = self.area.removeFullLines();
					if (lines) {
						self.tetris.stats.setLines(self.tetris.stats.getLines() + lines);
						self.tetris.stats.setScore(self.tetris.stats.getScore() + (1000 * self.tetris.stats.getLevel() * lines));
					}
					self.reset();
					if (self.mayPlace()) {
						self.place();
					} else {
						self.tetris.gameOver();
					}
				}
			}
		};
		this.stop = function()
		{
			this.running = false;
		};
		this.mayRotate = function()
		{
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						var newY = this.getY() + this.board.length - 1 - x;
						var newX = this.getX() + y;
						if (newY >= this.area.y) { return false; }
						if (newX < 0) { return false; }
						if (newX >= this.area.x) { return false; }
						if (this.area.getBlock(newY, newX)) { return false; }
					}
				}
			}
			return true;
		};
		this.rotate = function()
		{
			var puzzle = this.createEmptyPuzzle(this.board.length, this.board[0].length);
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						var newY = puzzle.length - 1 - x;
						var newX = y;
						var el = this.board[y][x];
						var moveY = newY - y;
						var moveX = newX - x;
						el.style.left = el.offsetLeft + (moveX * this.area.unit) + "px";
						el.style.top = el.offsetTop + (moveY * this.area.unit) + "px";
						puzzle[newY][newX] = el;
					}
				}
			}
			this.board = puzzle;
		};
		this.mayMoveDown = function()
		{
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						if (this.getY() + y + 1 >= this.area.y) { this.stopped = true; return false; }
						if (this.area.getBlock(this.getY() + y + 1, this.getX() + x)) { this.stopped = true; return false; }
					}
				}
			}
			return true;
		};
		this.moveDown = function()
		{
			for (var i = 0; i < this.elements.length; i++) {
				this.elements[i].style.top = this.elements[i].offsetTop + this.area.unit + "px";
			}
			this.y++;
		};
		this.mayMoveLeft = function()
		{
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						if (this.getX() + x - 1 < 0) { return false; }
						if (this.area.getBlock(this.getY() + y, this.getX() + x - 1)) { return false; }
					}
				}
			}
			return true;
		};
		this.moveLeft = function()
		{
			for (var i = 0; i < this.elements.length; i++) {
				this.elements[i].style.left = this.elements[i].offsetLeft - this.area.unit + "px";
			}
			this.x--;
		};
		this.mayMoveRight = function()
		{
			for (var y = 0; y < this.board.length; y++) {
				for (var x = 0; x < this.board[y].length; x++) {
					if (this.board[y][x]) {
						if (this.getX() + x + 1 >= this.area.x) { return false; }
						if (this.area.getBlock(this.getY() + y, this.getX() + x + 1)) { return false; }
					}
				}
			}
			return true;
		};
		this.moveRight = function()
		{
			for (var i = 0; i < this.elements.length; i++) {
				this.elements[i].style.left = this.elements[i].offsetLeft + this.area.unit + "px";
			}
			this.x++;
		};
	}
	function random(i)
	{
		return Math.floor(Math.random() * i);
	}
	function Highscores(maxscores)
	{
		this.maxscores = maxscores;
		this.scores = [];
		this.load = function()
		{
			var cookie = new Cookie();
			var s = cookie.get("tetris-highscores");
			this.scores = [];
			if (s.length) {
				var scores = s.split("|");
				for (var i = 0; i < scores.length; ++i) {
					var a = scores[i].split(":");
					this.scores.push(new Score(a[0], Number(a[1])));
				}
			}
		};
		this.save = function()
		{
			var cookie = new Cookie();
			var a = [];
			for (var i = 0; i < this.scores.length; ++i) {
				a.push(this.scores[i].name+":"+this.scores[i].score);
			}
			var s = a.join("|");
			cookie.set("tetris-highscores", s, 3600*24*1000);
		};
		this.mayAdd = function(score)
		{
			if (this.scores.length < this.maxscores) { return true; }
			for (var i = this.scores.length - 1; i >= 0; --i) {
				if (this.scores[i].score < score) { return true; }
			}
			return false;
		};
		this.add = function(name, score)
		{
			name = name.replace(/[;=:|]/g, "?");
			name = name.replace(/</g, "&lt;").replace(/>/g, "&gt;");
			if (this.scores.length < this.maxscores) {
				this.scores.push(new Score(name, score));
			} else {
				for (var i = this.scores.length - 1; i >= 0; --i) {
					if (this.scores[i].score < score) {
						this.scores.removeByIndex(i);
						this.scores.push(new Score(name, score));
						break;
					}
				}
			}
			this.sort();
			this.save();
		};
		this.getScores = function()
		{
			return this.scores;
		};
		this.toHtml = function()
		{
			var s = '<table cellspacing="0" cellpadding="2"><tr><th></th><th>Name</th><th>Score</th></tr>';
			for (var i = 0; i < this.scores.length; ++i) {
				s += '<tr><td>?.</td><td>?</td><td>?</td></tr>'.format(i+1, this.scores[i].name, this.scores[i].score);
			}
			s += '</table>';
			return s;
		};
		this.sort = function()
		{
			var scores = this.scores;
			var len = scores.length;
			this.scores = [];
			for (var i = 0; i < len; ++i) {
				var el = null, index = null;
				for (var j = 0; j < scores.length; ++j) {
					if (!el || (scores[j].score > el.score)) {
						el = scores[j];
						index = j;
					}
				}
				scores.removeByIndex(index);
				this.scores.push(el);
			}
		};
		function Score(name, score)
		{
			this.name = name;
			this.score = score;
		}
		this.load();
	}
	function Cookie()
	{
		this.get = function(name)
		{
			var cookies = document.cookie.split(";");
			for (var i = 0; i < cookies.length; ++i) {
				var a = cookies[i].split("=");
				if (a.length == 2) {
					a[0] = a[0].trim();
					a[1] = a[1].trim();
					if (a[0] == name) {
						return unescape(a[1]);
					}
				}
			}
			return "";
		};
		this.set = function(name, value, seconds, path, domain, secure)
		{
			this.del(name);
			if (!path) path = '/';
			var cookie = (name + "=" + escape(value));
			if (seconds) {
				var date = new Date(new Date().getTime()+seconds*1000);
				cookie += ("; expires="+date.toGMTString());
			}
			cookie += (path    ? "; path="+path : "");
			cookie += (domain  ? "; domain="+domain : "");
			cookie += (secure  ? "; secure" : "");
			document.cookie = cookie;
		};
		this.del = function(name)
		{
			document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT";
		};
	}
}
if (!String.prototype.trim) {
	String.prototype.trim = function() {
		return this.replace(/^\s*|\s*$/g, "");
	};
}
if (!Array.prototype.removeByIndex) {
	Array.prototype.removeByIndex = function(index) {
		this.splice(index, 1);
	};
}
if (!String.prototype.format) {
	String.prototype.format = function() {
		if (!arguments.length) { throw "String.format() failed, no arguments passed, this = "+this; }
		var tokens = this.split("?");
		if (arguments.length != (tokens.length - 1)) { throw "String.format() failed, tokens != arguments, this = "+this; }
		var s = tokens[0];
		for (var i = 0; i < arguments.length; ++i) {
			s += (arguments[i] + tokens[i + 1]);
		}
		return s;
	};
}
Widget.addClass("Tetris", Tetris);Widget.addCallBack("MultiUploader", function(params) {
});
function MultiUploader() {}
MultiUploader.iframes = [];
MultiUploader.uploadFile = function(widgetId) {
	var iframe = $(widgetId + "_frame").$();
	if (!MultiUploader.iframes.contains(iframe)) {
		$(iframe).on("load", function() { MultiUploader.onLoad(widgetId); });
		MultiUploader.iframes.add(iframe);
	}
	$(widgetId + "_form").$().submit();
	$(widgetId + "_file").$().disabled = "disabled";
};
MultiUploader.onLoad = function(widgetId) {
	var result = frames[$(widgetId + "_frame").$().id].document.getElementsByTagName("body")[0].innerHTML;
	result = JSON.parse(result);
	if (result.success) {
		var filesBlock = $(widgetId + "_files").$();
		for (var i = 0; i < result.files.length; i++) {
			var div = document.createElement("DIV");
			div.id = widgetId + "_file_" + result.files[i].tmp_name;
			div.innerHTML = result.files[i].name + " (" + result.files[i].size + ") <a href='Javascript:void(0);' onclick='MultiUploader.removeFile(\"" + widgetId + "\", \"" + result.files[i].tmp_name + "\");'>X</a>";
			filesBlock.insertBefore(div, filesBlock.firstChild);
		}
	} else {
		alert(result.exception);
	}
	$(widgetId + "_file").$().disabled = null;
};
MultiUploader.removeFile = function(widgetId, tmpName) {
	$(widgetId + "_file_" + tmpName).destroy();
	var handler = $(widgetId + "_form").$().action;
	var result = document.createElement("DIV");
	new Ajax(result, handler + "&remove=" + tmpName, function() { alert(result.innerHTML); }).request();
};Widget.addCallBack("SuperChat", function(params) {
	Widget.getClass("SuperChat").refresh(params.widgetId, params.chatService, params.refresh);
	Widget.getClass("SuperChat").updateColors(params.widgetId);
});
function SuperChat() {}
SuperChat.ajax = null;
SuperChat.aborts = 0;
SuperChat.updateColors = function(widget) {
	$(widget + "_name", widget + "_input").setColor("#" + $(widget + "_color").$().value);
	setTimeout(function() { SuperChat.updateColors(widget); }, 1000);
};
SuperChat.toggleDisplay = function(widget) {
	var chain = $(widget + "_history");
	if (chain.getStyle("height") == "300px") {
		chain.stopTweens().resizeHeight(300, 100, 500, Tween.ease);
	} else {
		chain.stopTweens().resizeHeight(100, 300, 500, Tween.ease);
	}
	setTimeout(function() { chain.$().scrollTop = chain.$().scrollHeight; }, 500);
};
SuperChat.refresh = function(widget, chatService, refresh) {
	var history = $(widget + "_history");
	if (SuperChat.ajax) {
		if (SuperChat.aborts < 5) {
			SuperChat.ajax.abort();
			SuperChat.aborts++;
		}
	}
	SuperChat.ajax = new Ajax(null, chatService + "?widgetId=" + widget);
	SuperChat.ajax.onSuccess = function(response) {
		var bottom = (history.$().scrollTop == history.$().scrollHeight);
		history.update(response);
		if (bottom) {
			history.$().scrollTop = history.$().scrollHeight;
		}
		SuperChat.aborts = 0;
	};
	SuperChat.ajax.request();
	setTimeout(function() { SuperChat.refresh(widget, chatService, refresh); }, refresh);
};
SuperChat.say = function(widget, chatService) {
	var name = $(widget + "_name");
	var color = $(widget + "_color");
	var msg = $(widget + "_input");
	var history = $(widget + "_history");
	if (SuperChat.ajax) {
		if (SuperChat.aborts < 5) {
			SuperChat.ajax.abort();
			SuperChat.aborts++;
		}
	}
	var url = chatService + "?widgetId=" + widget;
	url += "&msg=" + escape(msg.$().value.replace("+", "%2B"));
	url += "&name=" + escape(name.$().value.replace("+", "%2B"));
	url += "&color=" + color.$().value;
	SuperChat.ajax = new Ajax(null, url);
	SuperChat.ajax.onSuccess = function(response) {
		history.update(response);
		history.$().scrollTop = history.$().scrollHeight;
		SuperChat.aborts = 0;
	};
	SuperChat.ajax.request();
	msg.$().value = "";
};
Widget.addClass("SuperChat", SuperChat);function Login(id, wrapperEl, root, params, async, method) {
	Login.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
Login.inheritsFrom(Widget);
Login.prototype.submit = function(values) {
	var params = "widgetId=" + this.id + "&" + $(this.id).getValues("INPUT", "URL");
	this.refresh(params);
};
Login.prototype.callBack = function(response, context) {
	var code = $(context.id + "_code").$().value;
	if (code.length > 0) {
		eval(code);
	}
};function SocialMedia(id, wrapperEl, root, params, async, method) {
	SocialMedia.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
SocialMedia.inheritsFrom(Widget);function ImageFader(id, wrapperEl, root, params, async, method) {
	ImageFader.superConstructor.call(this, id, wrapperEl, root, params, async, method);
	this.slides = [];
	this.currentIndex = this.retrieveCurrentIndex();
	this.slideTime = parseInt(params.duration);
	this.pause = parseInt(params.pause);
	this.fps = params.fps;
	this.tween = eval("Tween." + params.tween);
	this.timer = null;
}
ImageFader.inheritsFrom(Widget);
ImageFader.prototype.callBack = function(response, context) {
	context.init();
};
ImageFader.prototype.init = function() {
	this.slides = document.getElementsByClassName("image", $(this.id).$());
	var key = this.id;
	var index = this.currentIndex;
	var next = (index == this.slides.length - 1) ? 0 : index + 1;
	this.timer = setTimeout(function() { Widget.getInstance(key).slide(index, next); }, this.pause);
};
ImageFader.prototype.slideTo = function(index) {
	this.slide(this.currentIndex, index);
};
ImageFader.prototype.slide = function(from, to) {
	if (this.timer != null) {
		clearTimeout(this.timer);
	}
	for (var i = 0; i < this.slides.length; i++) {
		if (i == from) {
			$(this.slides[i]).css({"zIndex":5});
		} else if (i == to) {
			$(this.slides[i]).setTransparency(100).css({"zIndex":10});
		} else {
			$(this.slides[i]).css({"zIndex":0});
		}
	}
	var navs = document.getElementsByClassName("nav", $(this.id).$(), "A");
	$(navs[from]).removeClass("selected");
	$(navs[to]).addClass("selected");
	$(this.slides[to]).fade(100, 0, this.slideTime, this.tween, this.fps);
	var key = this.id;
	var next = (to == this.slides.length - 1) ? 0 : to + 1;
	this.timer = setTimeout(function() { Widget.getInstance(key).slide(to, next); }, this.slideTime + this.pause);
	this.currentIndex = to;
	this.storeCurrentIndex();
};
ImageFader.prototype.storeCurrentIndex = function() {
	Cookie.save(this.id + "_cookie_index", this.currentIndex);
};
ImageFader.prototype.retrieveCurrentIndex = function() {
	var index = parseInt(Cookie.get(this.id + "_cookie_index"));
	return (isNaN(index)) ? 0 : index;
};Widget.addCallBack("ImageGroupFader", function(params) {
	ImageGroupFader.getInstance(params.widgetId, params.duration, params.pause, params.fps, eval("Tween." + params.tween), params.credits).init();
});
function ImageGroupFader(widgetId, duration, pause, fps, tween, credits) {
	this.widgetId = widgetId;
	this.slides = [];
	this.currentIndex = 0;
	this.slideTime = parseInt(duration);
	this.pause = parseInt(pause);
	this.fps = fps;
	this.tween = tween;
	this.credits = credits;
	this.timer = null;
};
ImageGroupFader.instances = {};
ImageGroupFader.getInstance = function(widgetId, duration, pause, fps, tween, credits) {
	if (!(widgetId in ImageGroupFader.instances)) {
		ImageGroupFader.instances[widgetId] = new ImageGroupFader(widgetId, duration, pause, fps, tween, credits);
	}
	return ImageGroupFader.instances[widgetId];
};
ImageGroupFader.prototype.init = function() {
	this.slides = document.getElementsByClassName("group", $(this.widgetId).$(), "DIV");
	var key = this.widgetId;
	var index = this.currentIndex;
	this.timer = setTimeout(function() { ImageGroupFader.getInstance(key).slide(index, 1); }, this.pause);
};
ImageGroupFader.prototype.slideTo = function(index) {
	this.slide(this.currentIndex, index);
};
ImageGroupFader.prototype.slide = function(from, to) {
	if (this.timer != null) {
		clearTimeout(this.timer);
	}
	for (var i = 0; i < this.slides.length; i++) {
		if (i == from) {
			$(this.slides[i]).css({"zIndex":5});
		} else if (i == to) {
			$(this.slides[i]).setTransparency(100).css({"zIndex":10});
		} else {
			$(this.slides[i]).css({"zIndex":0});
		}
	}
	var navs = document.getElementsByClassName("nav", $(this.widgetId).$(), "A");
	$(navs[from]).removeClass("selected");
	$(navs[to]).addClass("selected");
	$(this.slides[to]).fade(100, 0, this.slideTime, this.tween, this.fps);
	var key = this.widgetId;
	var next = (to == this.slides.length - 1) ? 0 : to + 1;
	this.timer = setTimeout(function() { ImageGroupFader.getInstance(key).slide(to, next); }, this.slideTime + this.pause);
	this.currentIndex = to;
};function TagCloud(id, wrapperEl, root, params, async, method) {
	TagCloud.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
TagCloud.inheritsFrom(Widget);function NewWidget(id, wrapperEl, root, params, async, method) {
	NewWidget.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
NewWidget.inheritsFrom(Widget);
NewWidget.prototype.callBack = function(response, context) {
	Debugger.write("NewWidget '" + context.id + "' CallBack :-D");
	Debugger.write("RESPONSE: " + response.length);
	$(context.id).setBColor("yellow");
	Widget.replaceAll(document.getElementsByName("widget"), true);
};
NewWidget.prototype.onLoad = function(context) {
	$(context.id).setBColor("red");
	Debugger.write("NewWidget '" + context.id + "' OnLoad :-P");
};
NewWidget.prototype.test = function() {
	alert("test: " + this.id + " - " + this.params.param2);
};function NewWidget2(id, wrapperEl, root, params, async, method) {
	NewWidget2.superConstructor.call(this, id, wrapperEl, root, params, async, method);
	this.extra = "Een extra JS-var";
}
NewWidget2.inheritsFrom(Widget);
NewWidget2.prototype.callBack = function(response, context) {
	Debugger.write("NewWidget2 '" + context.id + "' CallBack :-D met extra var: " + context.extra);
	Debugger.write("RESPONSE: " + response.length);
	$(context.id).setBColor("blue");
	Widget.replaceAll(document.getElementsByName("widget"), true);
};
NewWidget2.prototype.onLoad = function(context) {
	$(context.id).setBColor("cyan");
	Debugger.write("NewWidget2 '" + context.id + "' OnLoad :-P met extra var: " + context.extra);
};
NewWidget2.prototype.test = function() {
	alert("test: " + this.id + " - " + this.params);
};function NewWidget3(id, wrapperEl, root, params, async, method) {
	NewWidget3.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
NewWidget3.inheritsFrom(Widget);
NewWidget3.prototype.callBack = function(response, context) {
	Debugger.write("NewWidget3 '" + context.id + "' CallBack :-D");
	Debugger.write("RESPONSE: " + response.length);
	$(context.id).setBColor("magenta");
};
NewWidget3.prototype.onLoad = function(context) {
	$(context.id).setBColor("white");
	Debugger.write("NewWidget3 '" + context.id + "' OnLoad :-P");
};
NewWidget3.prototype.test = function() {
	alert("test: " + this.id + " - " + this.params);
};function FontChanger(id, wrapperEl, root, params, async, method) {
	FontChanger.superConstructor.call(this, id, wrapperEl, root, params, async, method);
	this.timer = null;
}
FontChanger.inheritsFrom(Widget);
FontChanger.prototype.changeSize = function(change) {
	var element = this.params.element;
	if (element == "" || element == null) {
		element = document.body;
	}
	var size = $(element).getStyle("fontSize");
	size = parseInt(size);
	size = isNaN(size) ? 100 : size;
	size = (change == null) ? 100 : size + change;
	$(element).setStyle("fontSize", size + "%");
	if (change != null) {
		var widget = this;
	}
};
FontChanger.prototype.stop = function() {
	if (this.timer != null) {
		this.timer = null;
	}
};
FontChanger.prototype.changeFont = function(font) {
	var element = this.params.element;
	if (element == "" || element == null) {
		element = document.body;
	}
	$(element).setStyle("fontFamily", font);
};function BrowserChecker(id, wrapperEl, root, params, async, method) {
	BrowserChecker.superConstructor.call(this, id, wrapperEl, root, params, async, method);
}
BrowserChecker.inheritsFrom(Widget);
