Ajax.Responders.register(
	{
		onCreate: function() {
			mouseTip.appear();
		},
		onComplete: function() {
			if (Ajax.activeRequestCount == 0) {
				mouseTip.disappear();
			}
		}
	}
);

var mouseTip = Class.create({
	initialize: function () {
		var objMouseTip = document.createElement("div");
		objMouseTip.setAttribute('id', 'mouseTip');
//		objMouseTip.style.display = 'none';
		document.getElementsByTagName('body')[0].appendChild(objMouseTip);
		$('mouseTip').setStyle(
			{
				position: 'absolute',
				width: '100px',
				border: '1px solid #000000',
				backgroundColor: '#FFFFFF',
				padding: '5px',
				zIndex: '2000',
				opacity: '0',
				display: 'none'
			}
		);
		$('mouseTip').innerHTML = '<img src="layout/spinner.gif" style="float: left; margin-right: 5px; margin-bottom: 5px;" /> Daten werden geladen ...';

		// find out if ie runs in quirks mode
		this.docEl = (
		             typeof document.compatMode != "undefined" && 
		             document.compatMode        != "BackCompat"
		            )? "documentElement" : "body";			
		this.init_mousemove();
	},
	
	init_mousemove: function () {
	    if(document.layers) document.captureEvents(Event.MOUSEMOVE);
	    document.onmousemove =	this.dpl_mouse_pos.bind(this);
	},
	
	dpl_mouse_pos: function (e) {
	    // position where mousemove fired
	    //
	    var xPos    =  e? e.pageX : window.event.x;
		var yPos    =  e? e.pageY : window.event.y;
	
		
		// for ie add scroll position
		//
		if (document.all && !document.captureEvents) {
		    xPos    += document[this.docEl].scrollLeft;
		    yPos    += document[this.docEl].scrollTop;
	    }
	    
	    // display position
	    //
	    mouseYPos = yPos;
	    mouseXPos = xPos + 15;
	    $('mouseTip').style.top =  mouseYPos + "px";
	    $('mouseTip').style.left = mouseXPos + "px";
	    
	    // for the dino pass event
	    //
	    if (document.layers) routeEvent(e);
	},
	
	appear: function () {
		$('mouseTip').setStyle(
			{
				display: 'block'
			}
		);
		$('mouseTip').morph(
			{
				opacity: '1'
			}, 
			{
				duration: 0.5
			}
		);
	},
	
	disappear: function () {
		$('mouseTip').setStyle(
			{
				display: 'none'
			}
		);
		$('mouseTip').morph(
			{
				opacity: '0'
			}, 
			{
				duration: 0.5
			}
		);
	}
});

var overlay = Class.create({
	initialize: function(){
		this.overlayOpacity = 0.8; // controls transparency of shadow overlay
		this.overlayDuration = 0.2; // shadow fade in/out duration
		var objOverlay = document.createElement("div");
		objOverlay.setAttribute('id', 'overlay');
		objOverlay.style.display = 'none';
/*
		objOverlay.onclick = function() {
			box.unfocus();
		}
*/
		document.getElementsByTagName('body')[0].appendChild(objOverlay);
		$('overlay')._visible = false;
		$('overlay').setStyle(
			{
				zIndex: '1000'
			}
		);
	},
	
	appear: function () {
		if (!$('overlay')._visible) {
			// Ermitteln der aktuellen Seitengröße
			var arrayPageSize = getPageSize();

			// Overlay auf Dokumentgröße vergrößern und einblenden ------------------
			$('overlay').setStyle({
				height: arrayPageSize[1] + 'px',
				width: arrayPageSize[0] + 'px'
			});
			new Effect.Appear('overlay', {
				duration: this.overlayDuration,
				from: 0.0,
				to: this.overlayOpacity,
				afterFinish: function(){
					$('overlay')._visible = true;
				}
			});
		}
	},
	
	disappear: function () {
		if ($('overlay')._visible) {
			new Effect.Appear('overlay', {
				duration: this.overlayDuration,
				from: this.overlayOpacity,
				to: 0.0,
				afterFinish: function(){
					$('overlay').setStyle({
						display: 'none'
					});
					$('overlay')._visible = false;
				}
			});
		}
	}
	
});

/*
 * Sobald Seite geladen ist, wird automatisch das overlay-Objekt erzeugt
 * (kann nicht vorher stattfinden, da das Body-Objekt vorher vorhanden sein muss).
 * Außerdem werden die Scaleboxes im Quelltext gesucht und vorbereitet.
 */
window.onload = function () {
	mouseTip = new mouseTip();
	overlay = new overlay();
//	box.getScaleboxes();
	 
}

var box = Class.create({
	initialize: function() {
		this.boxIds = new Array();
		this.values = new Object();
		this.values['boxIdFocused'] = false;
		this.values['morphDuration'] = 0.8;
		this.boxDefaults = 	{
								morphTarget: {
							      width: '400px',
							      height: '400px',
								  overflow: 'scroll'
							  	},
								morphOriginal: {
									/* 
									 * Auch wenn es eigentlich sinnlos ist, weil er sowieso überschrieben wird,
									 * muss hier mindestens 1 Default-Wert definiert sein (Funktion object2String erzeugt sonst einen Fehler)
									 */ 
									width: '100px'
								},
								controlbar: {
									show: true
								}
			    			};
		this.scaleboxDivsTemp = {};
							
		/*
		 * Seltsam: Das Objekt "this.boxDefaults" muss als String gespeichert und bei der Verwendung
		 * in der Funktion "getScaleboxes" aus diesem String neu erstellt werden, da es sonst nicht funktioniert.
		 */
		this.boxDefaults = object2String(this.boxDefaults);

		/* 
		 * Das Array, welches alle scaleboxIds und zu jeder scalebox die entsprechenden
		 * Konfigurationsparameter enthält, wird hier erstellt.
		 * Gefüllt wird es nach dem vollständigen Laden der Seite durch die Funktion
		 * getScaleboxes
		 */
		this.scaleboxDivs = new Object();
	},
	
	getScaleboxes: function() {
		// wird die Funktion getElementsByTagName nicht unterstützt, so wird der Vorgang abgebrochen
		if (!document.getElementsByTagName) {
			return;
		}
		  
		if (!box.scaleboxDivs) {
			box.scaleboxDivs = new Object();
		}
		var scaleboxCounter = 0; 
		// Alle Divs auslesen, die mit rel="scalebox" gekennzeichnet sind
		
		/* 
		 * alle Divs durchlaufen, welche im rel-Attribut nicht den Wert "scaleboxlink" enthalten.
		 * Es ist wichtig, dies zu prüfen, damit es möglich ist, einen Link auch auf ein Div zu setzen.
		 * Würde man in der Funktion "getScaleboxes" alle Divs bearbeiten, auch die, die "scaleboxlink" im
		 * rel-Attribut enthalten, würden diese Divs, die eigentlich Links sein sollten, selbst zu
		 * Scaleboxes gemacht.
		 */
		var divs = $$('div:not([rel*=scaleboxlink])');
		for (var i=0; i<divs.length; i++){
			var div = divs[i];
	
			var relAttribute = String(div.getAttribute('rel'));
			if (relAttribute.toLowerCase().match('^scalebox$') || relAttribute.toLowerCase().match('^scalebox.*{.*}.*$')) {
				/* 
				 * Für alle Divs, die mit rel="scalebox" bzw. rel="scalebox({key:value})" gekennzeichnet sind wird die jeweilige ID
				 * in das Array "scaleboxDivs" geschrieben
				 */
				scaleboxCounter ++;
				divId = div.getAttribute('id');
				if (!divId) {
					// Hat ein Div keine ID, so wird dynamisch eine vergeben
					div.setAttribute('id', 'scaleboxId_' + scaleboxCounter);
					divId = div.getAttribute('id')
				}
				
				box.scaleboxDivs[divId] = new Object();
				
				/* Auslesen der übergebenen Parameter
				 * (Parameter muss ein String der Form "{key1: value1, key2: value2}" sein.
				 * Er wird folgendermaßen angegeben: rel="scalebox({key1: value1, key2: value2})".
				 */
				var regexPattern = '{.*}';
				var regex = new RegExp(regexPattern);
				var regexResult = regex.exec(relAttribute);
				var params = false;
				if (regexResult != null) {
					// Die als String vorhandenen Parameter werden zum Objekt konvertiert
					params = string2Object(regexResult[0]);
				}
				
				/* 
				 * Nachdem das "rel"-Attribut ausgewertet wurde und alle Konfigurations-Parameter gespeichert wurden,
				 * wird es durch den Wert "scalebox" überschrieben, um in späteren Schritten einheitlich nach
				 * Scaleboxen suchen zu können.
				 */
				div.setAttribute('rel', 'scalebox');
				
				/* 
				 * Die Konfigurationsparameter für die jeweilige Box werden hier festgelegt.
				 * Es wird dabei das Objekt "this.boxDefaults" als Basis verwendet und es anhand
				 * der für die jeweilige Box angegebenen Konfigurationsparameter angepasst.
				 */
				/*
				 * Seltsam: Das Objekt "this.boxDefaults" muss als String gespeichert und bei der Verwendung
				 * in der Funktion "getScaleboxes" (also hier) aus diesem String neu erstellt werden, da es sonst nicht funktioniert.
				 */
				var boxDefaults = string2Object(this.boxDefaults);
			    this.scaleboxDivs[divId] = extend_multidimensional(boxDefaults, params || { });
				
				/*
				 * Ermitteln und speichern des Ursprungszustandes mittels CSS-Styles
				 */
				this.setOriginalStyles(divId);
			}
		}
		
		this.setScaleboxLinks();
	},
	
	setOriginalStyles: function(boxId) {
		/*
		 * Für alle Werte, die als "morphTarget" angegeben wurden, werden die Ursprungswerte ermittelt
		 * und als Originalzustand für die Box gespeichert
		 */
		var morphTargetStyle = this.scaleboxDivs[boxId]['morphTarget'];

		for (var property in morphTargetStyle) {
			this.scaleboxDivs[boxId]['morphOriginal'][property] = $(boxId).getStyle(property);
		}
	},
	
	setScaleboxLinks: function() {
		// wird die Funktion getElementsByTagName nicht unterstützt, so wird der Vorgang abgebrochen
		if (!document.getElementsByTagName) {
			return;
		}
		
		var links = $$('[rel*=scaleboxlink]');
		for (var i=0; i<links.length; i++) {
			var link = $(links[i]);
			var parentScaleboxId = this.getParentScaleboxId(link);
						
			var linkRel = link.getAttribute('rel');
			
			/* Auslesen der übergebenen Parameter
			 * (Parameter muss ein String der Form "{key1: value1, key2: value2}" sein.
			 * Er wird folgendermaßen angegeben: rel="scalebox({key1: value1, key2: value2})".
			 */
			var regexPattern = '{.*}';
			var regex = new RegExp(regexPattern);
			var regexResult = regex.exec(linkRel);
			var params = {boxId: parentScaleboxId};
			if (regexResult != null) {
				params = extend_multidimensional(params, string2Object('{additionalParams: ' + regexResult[0] + '}'));
			}
			params = object2String(params);
			
			/* 
			 * Da das Attribut "rel" des zu verlinkenden Elementes nun ausgewertet ist,
			 * wird es durch die ID des dazugehörigen scalebox-Divs ersetzt und somit
			 * der Bezug zu dieser scalebox hergestellt. 
			 */
			link.setAttribute('rel', params);

			link.onclick = function() {
				var linkRel = string2Object(this.getAttribute('rel'));
				var boxId = linkRel['boxId'];
				var additionalParams = linkRel['additionalParams'];
				box.focus(boxId, additionalParams);
				return false;
			};
			
			link.setStyle(
				{
					cursor: 'pointer'
				}
			);
	
		}
	},
	
	getParentScaleboxId: function (element) {
		var parentScaleboxId = false;
		var parentElement = element.up();
		if (!parentElement || parentElement == undefined) {
			return;
		}
		var parentRelAttribute = parentElement.getAttribute('rel');
		if (parentRelAttribute && parentRelAttribute.match('^scalebox$') && parentElement.getAttribute('id')) {
			/* 
			 * Wenn das übergeordnete Element mit 'rel="scalebox"' gekennzeichnet ist und eine ID hat
			 * (was auf alle erkannten Scalebox-Divs zutrifft), so wird dessen ID zurückgegeben.
			 */
			parentScaleboxId = parentElement.getAttribute('id');
		} else {
			parentScaleboxId = this.getParentScaleboxId(parentElement);
		}
		return parentScaleboxId;
	},
	
	addBoxId: function (boxId) {
		this.boxIds.push(boxId);
	},
	
	getElementPosition: function (elementId) {
	    element = $(elementId);
	    if (element.getStyle('position') == 'absolute') {
			var top = element.getStyle(top);
			var left = element.getStyle(left);
			var width = element.getStyle(width);
			var height = element.getStyle(height);
		} else {
		    // Position.prepare(); // To be done manually by Scripty when it needs it.
		    var offsets = element.positionedOffset();
		    var top     = offsets[1];
		    var left    = offsets[0];
		    var width   = element.clientWidth - parseFloat(element.getStyle('paddingLeft')) - parseFloat(element.getStyle('paddingRight'));
		    var height  = element.clientHeight - parseFloat(element.getStyle('paddingTop')) - parseFloat(element.getStyle('paddingBottom'));
		}
		var elementPosition = new Object();
		elementPosition['top'] = top + 'px';
		elementPosition['left'] = left + 'px';
		elementPosition['width'] = width + 'px';
		elementPosition['height'] = height + 'px';
		
		return elementPosition;
	},
	
	copyAbsolutized: function (boxId) {
		// ID des Originals temporär ändern
		var originalId = 'original_' + boxId;
		$(boxId).setAttribute('id', originalId);
		
		// Es wird die genaue Positionierung des Originals ermittelt
		var originalPosition = this.getElementPosition(originalId);

		// Kopie des Originals wird erstellt
		var copyBox = $(originalId).cloneNode(true);
		// Der Kopie wird die ursprüngliche ID des Originals zugewiesen
		copyBox.setAttribute('id', boxId);
		
		// Kopie in DOM einhängen als Child von Body
		document.getElementsByTagName('body')[0].appendChild(copyBox);
	
		
		// Position des Originals für Kopie übernehmen	
	    copyBox.style.position = 'absolute';
	    copyBox.style.top    = originalPosition['top'];
	    copyBox.style.left   = originalPosition['left'];
	    copyBox.style.width  = originalPosition['width'];
	    copyBox.style.height = originalPosition['height'];
		
		/* 
		 * Originalposition speichern, um später zurücksetzen zu können.
		 * Die anfänglich zugewiesenen Werte für den Originalzustand der Box
		 * werden hier durch den definitiv aktuellen Stand überschrieben.
		 * Dies ist nötig, um nach einer eventuellen Größenveränderung des
		 * Browserfensters immer noch richtige Werte zu erhalten.
		 */
		this.scaleboxDivs[boxId]['morphOriginal']['width'] = originalPosition['width'];
		this.scaleboxDivs[boxId]['morphOriginal']['height'] = originalPosition['height'];
		this.scaleboxDivs[boxId]['morphOriginal']['left'] = originalPosition['left'];
		this.scaleboxDivs[boxId]['morphOriginal']['top'] = originalPosition['top'];

		// Original ausblenden
		$(originalId).setOpacity(0);
	},
	
	removeCopyAbsolutized: function (boxId) {
		var originalId = 'original_' + boxId;
		// Das Original wird wieder eingeblendet
		$(originalId).setOpacity(1);

		// Ausblenden der Kopie
		$(boxId).morph(
			{
				opacity: '0'
			}, {
				duration: 0.5,
				afterFinish: function() {
					// Kopie wird entfernt
					$(boxId).remove();
					// Das Original bekommt wieder seine ursprüngliche ID zurück
					$(originalId).setAttribute('id', boxId);
				}
			}
		);
		
		// Kennzeichnung der aktuell fokussierten Box entfernen
		this.values['boxIdFocused'] = false;
	},
	
	showControlbar: function(boxId) {
		// Controlbar mit Closebutton erstellen -------------------------------
		var objControlbar = document.createElement("div");
		var controlbarId = boxId + '_controlbar';
		var controlbarCloseButtonId = controlbarId + '_closebutton';
		objControlbar.setAttribute('id', controlbarId);

		var objControlbarCloseButton = document.createElement("img");
		objControlbarCloseButton.setAttribute('src', 'layout/close.gif');
		objControlbarCloseButton.setAttribute('id', controlbarCloseButtonId);
		objControlbarCloseButton.onclick = function() {
			this.unfocus();
		}.bind(this);
		objControlbar.appendChild(objControlbarCloseButton);
		
		document.getElementsByTagName('body')[0].appendChild(objControlbar);
		
		var borderBox = $(boxId).getStyle('border');
		if (borderBox == undefined) {
			borderBox = '0';
		}
		
		var backgroundColorControlbar = '#FFFFFF';

		$(controlbarId).setStyle(
			{
				position: 'absolute',
				top: $(boxId).getStyle('top'),
				left: $(boxId).getStyle('left'),
				border: borderBox,
				borderBottom: 0,
				padding: $(boxId).getStyle('padding'),
				paddingTop: '3px',
				paddingBottom: '3px',
				display: 'block',
				height: '11px',
				width: $(boxId).getStyle('width'),
				backgroundColor: backgroundColorControlbar,
				textAlign: 'right',
				zIndex: '1090'
			}
		);

		$(controlbarCloseButtonId).setStyle(
			{
				cursor: 'pointer'
			}
		);
		
		$(controlbarId).morph(
			{
				top:  parseFloat($(boxId).getStyle('top')) - 17 + 'px'
			},
			{
				duration: 0.5
			}
		);
		
	},
	
	hideControlbar: function(boxId) {
		// Controlbar entfernen
		var controlbarId = boxId + '_controlbar';
		
		if (!$(controlbarId)) {
			return;
		} else {
			$(controlbarId).remove();
		}
	},
	
	doBeforeUpscale: function(boxId) {
		/* 
		 * Ist ein contentBig angegeben, so wird der ursprüngliche Content zunächst entfernt
		 * (es werden hierfür alle ChildNodes gelöscht).
		 */
		if (this.scaleboxDivsTemp[boxId]['contentBig'] != undefined && this.scaleboxDivsTemp[boxId]['contentBig']['contentFile'] != undefined && this.scaleboxDivsTemp[boxId]['contentBig']['contentFile'] != 'none') {
			$(boxId).innerHTML = '<table style="width: 100%; height: 100%;"><tr><td style="width: 100%; height: 100%; vertical-align: middle; text-align: center;"><img src="layout/spinner.gif" /><br /><br />Daten werden geladen ...</td></tr></table>';
		}
	},
	
	doAfterUpscale: function(boxId) {
		// Flag für die aktuell aktive Box setzen
		this.saveBoxIdFocused(boxId);
				
		// Die kompletten Styles des "morphtarget" setzen, um auch die Styles anzuwenden, die im morph nicht durchgeführt werden konnten
		$(boxId).setStyle(this.scaleboxDivsTemp[boxId]['morphTarget']);
		// Einblenden der Controlbar
		if (this.scaleboxDivs[boxId]['controlbar']['show']) {
			this.showControlbar(boxId);
		}
		

		/* 
		 * Ist ein contentBig angegeben, so wird hier der Ajax-Request gestartet,
		 * um den contentBig einzulesen
		 */
		if (this.scaleboxDivsTemp[boxId]['contentBig'] != undefined && this.scaleboxDivsTemp[boxId]['contentBig']['contentFile'] != undefined && this.scaleboxDivsTemp[boxId]['contentBig']['contentFile'] != 'none') {
			
			// Wurden Informationen zu einem Formular übergeben, dessen Daten übermittelt werden sollen, so werden diese hier ausgelesen 
			var formparameters = "";
			if (this.scaleboxDivsTemp[boxId]['form'] != undefined && this.scaleboxDivsTemp[boxId]['form']['id'] != undefined) {
				formparameters = $(this.scaleboxDivsTemp[boxId]['form']['id']).serialize();
			}
			
			// Wurde eine spezielle Übermittlungsmethode angegeben, so wird diese hier mit übergeben. Der Ajax-Wrapper sorgt dann dafür, dass die Daten im entsprechenden Arry ($_GET oder $_POST) zur Verfügung stehen.
			var formmethod = "get";
			if (this.scaleboxDivsTemp[boxId]['form'] != undefined && this.scaleboxDivsTemp[boxId]['form']['method'] != undefined) {
				formmethod = this.scaleboxDivsTemp[boxId]['form']['method'];
			}
			
			this.ajaxObj = new Ajax.Request('ajax_wrapper.php', {
						parameters: {
							wp: this.scaleboxDivsTemp[boxId]['contentBig']['contentFile'],
							formparameters: formparameters,
							formmethod: formmethod
						},
						onSuccess: function (response) {
							if (this.values['boxIdFocused'] == boxId) {
								$(boxId).innerHTML = response.responseText;
							}
						}.bind(this),
						on404: function () {
							if (this.values['boxIdFocused'] == boxId) {
								$(boxId).innerHTML = "<p>Datei wurde nicht gefunden (Error 404)</p>";
							}
						}.bind(this)
					});
		}
	},
	
	doBeforeDownscale: function(boxId) {
		// Ausblenden der Controlbar
		if (this.scaleboxDivs[boxId]['controlbar']['show']) {
			this.hideControlbar(boxId);
		}
		if (this.scaleboxDivs[boxId]['morphOriginal']['overflow']) {
			// Falls für den Originalzustand das CSS-Attribut "overflow" definiert ist, wird es noch vor dem Start des Morphs zurückgesetzt
			$(boxId).setStyle(
				{
					overflow: this.scaleboxDivs[boxId]['morphOriginal']['overflow']
				}
			);
		}
	},
	
	doAfterDownscale: function(boxId) {
		/*
		 * Hier muss der bestehende Ajax-Request abgebrochen werden,
		 * sofern er noch nicht completed ist
		 */
		if (this.ajaxObj && !this.ajaxObj._complete) {
			this.ajaxObj.transport.abort();
		}
		
		// Löschen der scaleboxDivsTemp für diese Box
		delete (this.scaleboxDivsTemp[boxId]);
	},
	
	focus: function(boxId) {
		this.scaleboxDivsTemp[boxId] = copy_object(this.scaleboxDivs[boxId]);
		if (arguments[1] != undefined && typeof(arguments[1]) == 'object') {
			this.scaleboxDivsTemp[boxId] = extend_multidimensional(this.scaleboxDivsTemp[boxId], arguments[1]);
		}
		
		// Ist die Box bereits im Fokus, nichts tun und abbrechen
		if (this.values['boxIdFocused'] || this.values['boxIdFocused'] == 'busy') {
			return;
		}
		
		this.values['boxIdFocused'] = 'busy';

		/* 
		 * Kopie der Box erstellen, welche dann optische verändert (gemorpht - vergrößert usw.) wird.
		 * Das Original bleibt hierbei unberührt und wird nur unsichtbar gemacht (Opacity = 0).
		 * So ist sichergestellt, dass sich bei nicht absolut positionierten Boxen nicht der gesamte
		 * Textfluss verschiebt, sobald die Box verändert wird
		 */ 
		box.copyAbsolutized(boxId);
		
		/*
		 * z-index auf 1100, um definitiv ganz oben zu liegen
		 */
		$(boxId).setStyle(
			{
				zIndex: '1100'
			}
		);


		overlay.appear();

		/* 
		 * Abwarten, bis das Overlay vollständig eingeblendet ist und
		 * noch eine kleine Pause zusätzlich (wie es halt am besten aussieht)
		 * und dann upscale der Box
		 */
		var pause1 = (overlay.overlayDuration + 0.05) * 1000;
		window.setTimeout("box.upscaleBox('" + boxId + "')", pause1);
	},
	
	upscaleBox: function (boxId) {
		// Ermitteln der aktuellen Seitengröße
		var arrayPageSize = getPageSize();
		
		// Ermitteln der aktuellen Scrollposition der Seite
		var arrayPageScroll = getPageScroll();
		
		// Ermitteln der neuen Boxgröße und Position ----------------------
		var viewportWidth = arrayPageSize[2];
		var viewportHeight = arrayPageSize[3];
		
		// Breite und Höhe werden zunächst der Vorgabe entsprechend gesetzt
		var newWidth = parseFloat(this.scaleboxDivsTemp[boxId]['morphTarget']['width']);
		var newHeight = parseFloat(this.scaleboxDivsTemp[boxId]['morphTarget']['height']);
		
		/* 
		 * Sind Breite und Höhe allerdings größer als die Ausmaße des Viewports abzüglich einem Rand,
		 * so werden Breite und Höhe entsprechend verringert, um die Box definitiv ins Sichtfeld zu bekommen
		 */
		if (newWidth > (viewportWidth - 100)) {
			newWidth = viewportWidth - 100;
		}
		if (newHeight > (viewportHeight - 100)) {
			newHeight = viewportHeight - 100;
		}
		
		/*
		 * Die neue Position der Box ist zentriert auf dem Bildschirm.
		 * Um die Position immer zentrieren zu können, muss der aktuelle
		 * Scrollzustand der Seite berücksichtigt werden
		 */
		var newXPos = (viewportWidth - newWidth) / 2 + arrayPageScroll[0];
		var newYPos = (viewportHeight - newHeight) / 2 + arrayPageScroll[1]; 
		// ----------------------------------------------------------------
		
		this.scaleboxDivsTemp[boxId]['morphTarget']['width'] = newWidth + 'px';
		this.scaleboxDivsTemp[boxId]['morphTarget']['height'] = newHeight + 'px';
		this.scaleboxDivsTemp[boxId]['morphTarget']['top'] = Math.round(newYPos) + 'px';
		this.scaleboxDivsTemp[boxId]['morphTarget']['left'] = Math.round(newXPos) + 'px';
		
 		// Box wird nun auf die neue Größe und Position gemorpht
		$(boxId).morph(this.scaleboxDivsTemp[boxId]['morphTarget'],
			{ 
				duration: this.values['morphDuration'],
				beforeStart: function () {
					this.doBeforeUpscale(boxId);
				}.bind(this),
				afterFinish: function(){
					this.doAfterUpscale(boxId)
				}.bind(this)
			}
		);
	},
	
	saveBoxIdFocused: function(boxId) {
		// Speichern der ID der aktuell fokusierten Box
		this.values['boxIdFocused'] = boxId;
	},
	
	unfocus: function() {
		// Ist aktuell keine Box im Fokus, nichts tun und abbrechen
		if (!this.values['boxIdFocused'] || this.values['boxIdFocused'] == 'busy') {
			return;
		}

		boxId = this.values['boxIdFocused'];

		// Kennzeichnung der aktuell fokussierten Box auf Busy
		this.values['boxIdFocused'] = 'busy';

		
		// Downscale der box 
		this.downscaleBox(boxId);
		
		/* 
		 * Abwarten, bis Box komplett herunterskaliert ist
		 * + eine kleine zusätzliche Pause (wie es halt am besten aussieht),
		 * dann Ausblenden des Overlays.
		 */
		window.setTimeout("overlay.disappear()", this.values['morphDuration'] * 1000);
		
		/*
		 * Abwarten, bis Box wieder herunterskaliert und Overlay ausgeblendet ist, dann
		 * Kopie der Originalbox wieder entfernen und die Orginalbox wieder einblenden
		 */
		var pause = (this.values['morphDuration'] + overlay.overlayDuration) * 1000;
		window.setTimeout("box.removeCopyAbsolutized(boxId)", pause);

	},
	
	downscaleBox: function (boxId) {
		/* 
		 * Es wird die genaue Positionierung des Originals ermittelt, um die Kopie wieder an diese Stelle
		 * zurückmorphen zu können. Vorteil dieser Methode: Befindet sich das Original im Textfluss und hat
		 * sich die Position des Originals z. B. durch eine Veränderung der Fenstergröße geändert, so wird
		 * diese neue Position für diesen Morph verwendet.
		 */
		var originalId = 'original_' + boxId;
		var originalPosition = this.getElementPosition(originalId);
		this.scaleboxDivs[boxId]['morphOriginal']['top'] = originalPosition['top'];
		this.scaleboxDivs[boxId]['morphOriginal']['left'] = originalPosition['left'];
		
		// Box wird wieder in den Ursprungszustand zurückgemorpht
		$(boxId).morph(this.scaleboxDivs[boxId]['morphOriginal'],
			{ 
				duration: this.values['morphDuration'],
				beforeStart: function () {
					this.doBeforeDownscale(boxId);
				}.bind(this),
				afterFinish: function(){
					this.doAfterDownscale(boxId)
				}.bind(this)
			}
		);		
	}
});

/* 
 * Instanz der Boxklasse erstellen
 * (Muss auf jeden Fall passieren, bevor die Boxen im Quelltext definiert werden,
 * da es sonst zu Problemen kommt, weil gewisse Objekte noch nicht existieren)
 */

/*
 * Zu Entwicklungszwecken ausschalten
 */
// box = new box();