
/**
 * HoverMap ein ein Script zur Erzeugung von Bild-Hovern unter zu Hilfenahme von
 * HTML-Imagemaps, um polygonale Reaktionsflaechen zu ermoeglichen. Es arbeitet
 * komplett eigenstaendig und benoetigt lediglich ein Basis-Bild, ein leeres Gif
 * und die Konfigurationsdaten fuer die Hover-Bereiche (siehe dazu die Beispiel-
 * Konfiguration in der Datei maplocations.js).
 * Das Script baut dann aus dem Basis-Bild und den konfigurierten Hover-Bildern
 * drei Schichten auf:
 * - Ein relativ positioniertes Div mit der Groesse des Basis-Bildes, welches das
 *   Ausgangsbild als Hintergrundbild hat
 * - die Bilder zur Anzeige beim beruehren der Hover-Bereiche, welche an die
 *   konfigurierten Positionen gesetzt und ausgeblendet werden
 * - ein das ganze ueberdeckendes, durchsichtiges Bild, welches eine auf Basis
 *   der Hover-Bereichskoordinaten zusammengebaute Imagemap verwendet, welche
 *   wiederum mittels onmouseover und onmouseout auf den Bereichen die
 *   dazugehoerigen Hover-Bilder einblendet.
 *
 * Vollstaendige Kompatibilitaet getestet in:
 *   - Opera ab 7.5
 *   - Firefox ab 1.0
 *   - Internet Explorer ab 5.5
 *
 * @version: 0.2
 * @author: Kristian Kriehl
 */

/**
 * Konstruktor fuer das HoverMap-Objekt. Benoetigt als Parameter die Dom-ID des
 * Basisbilds und das Hover-Bereichskonfigurations-Objekt
 *
 * @param {String} baseIMG Dom-ID des Basis-Bildes
 * @param {Object} mapLocations Konfigurationsobjekt fuer die Hover-Bereiche
 * @return {HoverMap} Neue HoverMap Instanz
 */
function HoverMap(baseIMG, mapLocations) {
	this.activeLocation = "";
	this.pointCache = new Array();
	this.baseImageID = baseIMG;
	this.mapLocations = mapLocations;
	this.locationEvents = new Object();
	this.overlayImage = "img/blank.gif";
	this.container = null;

	this.setOverlayImage = function(image) {
		this.overlayImage = image;
	}

	this.getContainer = function() {
		return this.container;
	}
}

/**
 * Microsoft IE Versionsermittlung
 * Gefunden im Microsoft Developers Network:
 * http://msdn.microsoft.com/en-us/library/ms537509(VS.85).aspx
 *
 * @return {Float} IE-Versionsnummer (-1 wenn kein IE)
 */
HoverMap.prototype.getInternetExplorerVersion = function() {
	var version = -1;

	if (navigator.appName == "Microsoft Internet Explorer" && !window.opera) {
		var usrAgent = navigator.userAgent;
		var regex = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
		
		if (regex.exec(usrAgent) != null) {
			version = parseFloat( RegExp.$1 );
		}
	}
	
	return version;
};

HoverMap.prototype.addLocationEvent = function(locationName, event, func, args) {
	if(typeof this.mapLocations[locationName] == "object" && this.mapLocations[locationName] != null) {
		if(typeof this.locationEvents[locationName] != "object") {
			this.locationEvents[locationName] = new Object();
		}
		this.locationEvents[locationName][event] = func;
	}
};

/**
 * Initialisiert das HoverMap-Objekt:
 * Erzeugt die drei Schichten, setzt die Events und ersetzt das vorherige Bild
 * durch die HoverMap
 */
HoverMap.prototype.init = function() {

	var baseImageObj = document.getElementById(this.baseImageID);

	if(baseImageObj.width == 0) {
		baseImageObj.onload = function() { alert("image has loaded"); };
		baseImageObj.style.display = "block";
	}

	// Erzeugen des Container-Elements
	this.container = document.createElement("div");
	this.container.id = "hovermap_" + this.baseImageID;

	// Style festlegen. Ganz wichtig: Position relative!
	with(this.container.style) {
		position = "relative";
		width = baseImageObj.width + "px";
		height = baseImageObj.height + "px";
		backgroundImage = "url('" + baseImageObj.src + "')";
		backgroundColor = "#FFFFFF";
		backgroundRepeat = "no-repeat";
		backgroundPosition = "top left";
	}

	// ImageMap erzeugen und in den Container einfuegen
	var imageMap = this.createImageMap();
	this.container.appendChild(imageMap);

	// Fuer alle Locations die Hover-Ereignisse erzeugen
	var imgLocation = null;

	for(loc in this.mapLocations) {
		imgLocation = this.createHoverImage(loc);
		if(imgLocation != null) this.container.appendChild(imgLocation);
	}

	// Das transparente Bild welches die ImageMap verwendet erzeugen
	var mapOverlayImage = this.createMapOverlayImage();
	this.container.appendChild(mapOverlayImage);

	// Das alte Bild durch die erzeugte HoverMap ersetzen
	baseImageObj.parentNode.replaceChild(this.container, baseImageObj);
};

/**
 * Erzeugt ein Hover-Bild an der passenden Position anhand der zum Namen gehoerigen
 * Konfigurationsdaten
 *
 * @param {String} loc Name der Map-Location
 * @return {Object} Img-Element oder Span-Element im IE ab 5.5 bis 6.X
 */
HoverMap.prototype.createHoverImage = function(loc) {
	// Ueberpruefen, ob ein Hover-Bild angegeben wurde
	if(
		this.mapLocations[loc]["hover"] == undefined  ||
		typeof this.mapLocations[loc]["hover"] != "object" ||
		this.mapLocations[loc]["hover"] == null
	) {
		return null;
	}

	// Konfiguration des zugehoerigen Hover-Bildes in der Variable hover
	// referenzieren
	var hover = this.mapLocations[loc]["hover"];

	// Neues Bild erzeugen
	var imgLocation = document.createElement("img");
	// ID und URL des Bildes setzen
	imgLocation.id = "blend_" + loc;
	imgLocation.src = hover["image"];

	// Position aus der Konfiguration lesen
	var imgLeft = hover["location"][0] + "px";
	var imgTop  = hover["location"][1] + "px";

	// Falls vorhanden den Offset-Wert aus der Konfiguration hinzuaddieren
	if(this.mapLocations[loc].offset != undefined) {
		imgLeft = this.mapLocations[loc].offset[0] + hover["location"][0] + "px";
		imgTop  = this.mapLocations[loc].offset[1] + hover["location"][1] + "px";
	}

	// Style des Bildes setzen
	with(imgLocation.style) {
		position = "absolute"; // Absolute Positionierung in Relation zum Elternelement
		left = imgLeft;        // die zuvor ermittelte X-Koordinate im Bild
		top = imgTop;          // die zuvor ermittelte Y-Koordinate im Bild
		display = "none";      // Versteckt erzeugen
	}

	// IE-Version ermitteln (-1 wenn kein IE verwendet wird)
	var ieVersion = this.getInternetExplorerVersion();

	// Falls ein IE ab Version 5.5 und unterhalb von 7.0 verwendet wird,
	// muss das Bild durch ein IE-taugliches Pendant ersetzt werden, falls
	// Alhpa-Transparenz unterstützt werden soll
	if(ieVersion >= 5.5 && ieVersion < 7) {
		return this.createIEImage(imgLocation);
	}

	return imgLocation;
};

/**
 * Erzeugt die ImageMap auf Basis der Konfigurationdaten
 */
HoverMap.prototype.createImageMap = function() {
	// Map-Element erzeugen
	var imageMap = document.createElement("map");
	// ID und Name setzen (ID um missverstaendnisse zu vermeiden ;))
	imageMap.name = this.baseImageID + "_hovermap";
	imageMap.id = this.baseImageID + "_hovermap";

	// Area-Element-Variable leer initialisieren
	var newArea = null;

	// Area-Elemente erzeugen und an die ImageMap anhaengen
	for(loc in this.mapLocations) {
		newArea = null;
		newArea = this.createLocationAreaElement(loc);
		imageMap.appendChild(newArea);
	}

	// ImageMap zurueckgeben
	return imageMap;
};

HoverMap.prototype.createMapOverlayImage = function() {
	var baseImageObj = document.getElementById(this.baseImageID);
	var mapOverlayImg = document.createElement("img");
	
	mapOverlayImg.border = "0";
	mapOverlayImg.src = this.overlayImage;
	mapOverlayImg.alt = baseImageObj.alt;
	mapOverlayImg.title = baseImageObj.title;
	mapOverlayImg.useMap = "#" + this.baseImageID + "_hovermap";

	with(mapOverlayImg.style) {
		position = "absolute";
		top = "0px";
		left = "0px";
		width = baseImageObj.width + "px";
		height = baseImageObj.height + "px";
		zIndex = 50;
	}

	return mapOverlayImg;
};

/**
 * Correctly handle PNG transparency in Win IE 5.5 & 6.
 * http://homepage.ntlworld.com/bobosola. Updated 18-Jan-2006.
 */
HoverMap.prototype.createIEImage = function(img) {
	var imgName = img.src.toUpperCase();

	// Testen ob es sich um ein PNG handelt
	if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
	{
		// Falls es ein verlinktes Bild ist, einen Handcursor verwenden
		if (img.parentElement && img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;

		// neues HTML-Element erzeugen
		var span = document.createElement("span");
		span.id = (img.id) ? img.id : "";
		span.className = (img.className) ? img.className : "";
		span.title = (img.title) ? img.title : img.alt;
		span.style.cssText = img.style.cssText;

		if(img.align == "left") {
			span.styleFloat = "left";
		} if (img.align == "right") {
			span.styleFloat = "right";
		}

		with(span.style) {
			width = img.style.width || img.width;
			height = img.style.height || img.height;
			filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + img.src + "', sizingMethod='scale')";
		}

		return span;
	}

	return img;
}

HoverMap.prototype.createLocationAreaElement = function(loc) {
	var instance = this;
	var c = this.mapLocations[loc];
	var newArea = document.createElement("area");
	
	if(c.href)   newArea.href = c.href;
	if(c.target) newArea.target = c.target;
	
	newArea.shape = "poly";

	if(c.title)  {
		newArea.alt = c.title;
		newArea.title = c.title;
	}
	
	newArea.onmouseover = function(l) {
		return function() {
			instance.showLocation(l,true);
			instance.execEvent("onmouseover", null, l);
		}
	}(loc);
	newArea.onmouseout = function(l) {
		return function() {
			instance.hideActiveLocation();
			instance.execEvent("onmouseout", null, l);
		}
	}(loc);

	newArea.onclick = function(l) {
		return function() {
			instance.execEvent("onclick", null, l);
		}
	}(loc);

	newArea.onmousemove = function(l) {
		return function() {
			instance.execEvent("onmousemove", null, l);
		}
	}(loc);

	var isX = true;
	var coords = "";

	for(cIndex in c.coords) {
		if(isX) {
			if(c.offset != undefined) {
				coords += (c.offset[0] + c.coords[cIndex]) + ",";
			} else {
				coords += c.coords[cIndex] + ",";
			}
			isX = false;
		} else {
			if(c.offset != undefined) {
				coords += (c.offset[1] + c.coords[cIndex]) + ",";
			} else {
				coords += c.coords[cIndex] + ",";
			}
			isX = true;
		}
	}

	newArea.coords = coords.substr(0, coords.length - 1);

	return newArea;
};

HoverMap.prototype.showLocation = function(country, updateActiveLocation) {
	var blend = document.getElementById("blend_" + country);

	if(typeof blend == "object" && blend != null) {
		blend.style.display = "block";
	}

	if(updateActiveLocation) this.activeLocation = country;
};

HoverMap.prototype.hideLocation = function(country) {
	var blend = document.getElementById("blend_" + country);

	if(typeof blend == "object" && blend != null) {
		blend.style.display = "none";
	}

	if(this.activeLocation == country)  this.activeLocation = "";
};

HoverMap.prototype.hideActiveLocation = function() {
	var blend = document.getElementById("blend_" + this.activeLocation);

	if(typeof blend == "object" && blend != null) {
		blend.style.display = "none";
	}

	this.activeLocation = "";
};

HoverMap.prototype.execEvent = function(eventName, eventObj, loc) {
	if(typeof this.locationEvents[loc] == "object") {
		if(typeof this.locationEvents[loc][eventName] == "function") {
			var func = this.locationEvents[loc][eventName];
			func.call(null, eventObj, loc);
		}
	}
}