/*
  This file is part of Groops. All rights reserved. No rights granted to
  use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software or parts of the Software without prior written and
  signed permission.
  
  Location map

  Author:: Guillaume Dufloux
  Copyright:: Copyright (c) 2006, 2007 by Groops GmbH
  License:: No rights granted for any use of the Software or parts of it
*/

/**
 * Location map. 
 *
 * Manage a map of areas and flags with scriptaculous effects
 *
 * Parameters
 *
 * [location_codes] Array of location codes, e.g. ['de','at','ch']
 *
 * Options
 *
 * [map_id] Id of the map element you want to grant mouseevents
 * [min_opacity] Minimum opacity an element might reach when "hide" (default to 0.3)
 * [duration] Show-hide effects duration in seconds
 *
 * Usage
 *
 *   1. Build a map with areas (optional). Area ids must be like "area_{code}"
 * 		<map name="map_europe" id="map_europe">
 * 		<area id="area_de" shape="poly" coords="0 0 100 100" alt="Germany" /></map>
 *
 *   2. Include your main map image and related flags. Flags ids must be like "flag_{code}"
 * 		<div style="position:relative;">
 * 		<img src="/images/map_europe.png" alt="Europe" usemap="#map_europe" />	
 * 		<a id="flag_de" style="position:absolute; left:50px; top:50px;">
 * 		<img src="/images/maps/flag_de.gif" alt="Germany" /></a></div>
 *
 *   3. Intanciate the javascript locationMap object, and specify map_id if one
 *		var map = new locationMap(['de'], {map_id:'map_europe'});
 *
 * Requirements
 *
 * Scriptaculous Effects (http://script.aculo.us)
 *
 * Compatibility
 *
 * Tested on Firefox 2.0.0.9, Safari 2.0.4, Camino 1.5.3 and IE6
 * Note that on Camino, no errors happen but effects doesn't work (opacity doesn't change)
 *
 * Development notes
 *
 * Code has been split in two part, one to handle hide-show effects,
 * and the second to dynamicaly set elements 'on-mouse-events'. 
 * 
 */
function locationMap(location_codes, options){
	
	// Array of location codes as keys for handle elements
	this.codes = location_codes; 
	
	// Minimum opacity an element might reach when "hide"
	if( options['min_opacity'] != null){
		// must be > 0 to not totally undisplay elements
		this.min_opacity = options['min_opacity'] + 0.01;
	} else {
		this.min_opacity = 0.3;
	};
	
	// Show-hide effects duration in seconds
	if( options['duration'] != null){
		this.duration = options['duration'];
	} else {
		this.duration = 0.5;
	};
	
	// Set a dynamic lock variable to know if mouse is over a location
	// Usefull to not restore all flags to normal opacity
	this.locked = false;
	
	// Set a timer and a timeout in seconds before restoring all flags to normal opacity
	// Usefull to wait a few when user is switching from an area to another
	this.timer = null;
	this.timeout = 0.5;

	/**
	 * Following functions handle hide-show effects
	 * Only location_codes parameter is needed for this part
	 */

	// Action onmouseover a location
	this.overLocation = function(code){
		this.locked = true;
		this.showLocation(code);
		var other_codes = this.codes.without(code);
		for(var i = 0; i < other_codes.length; i++){
			this.hideLocation(other_codes[i]); 
		}
	};

	// Action onmouseout a location
	this.outLocation = function(code){
		this.locked = false;
		this.outMap();
	};

	// Action onmouseout map area
	this.outMap = function(){	
		// wait few time if switching countries
		clearTimeout(this.timer);
		var obj = this;
		this.timer = setTimeout( function(){obj.showAllCountries();} , this.timeout * 1000);
	};

	// Show all countries
	this.showAllCountries = function(){
		if (this.locked == false){
			for(var i = 0; i < this.codes.length; i++){
				this.showLocation(this.codes[i]); 
			}
		}
	};

	// Show a location 
	this.showLocation = function(code){
		var element = $('flag_' + code);
		var current_opacity = element.getOpacity();
		new Effect.Opacity(element, {duration:this.duration, from:current_opacity, to:1.0});
	};

	// Hide a location 
	this.hideLocation = function(code){
		var element = $('flag_' + code);
		var current_opacity = element.getOpacity();
		new Effect.Opacity(element, {duration:this.duration, from:current_opacity, to:this.min_opacity});
	};
	
	/**
	 * Following functions dynamicaly set elements 'on-mouse-events'
	 * Parameter map_id is optional, so each setting has a sample html code
	 * if you want to do it by yourself.
	 */
	
	var self = this;
	
	// <a id="flag_code" onmouseover="map.overLocation('code');" 
	// 	onmouseout="map.outLocation('code');">
	for(var i = 0; i < this.codes.length; i++){
		var code = this.codes[i];
		var flag_element = $('flag_' + code);
		flag_element.code = code
		flag_element.onmouseover = function(){
			self.overLocation(this.code); 
		};
		flag_element.onmouseout = function(){
			self.outLocation(this.code); 
		};
	};
	
	if ( options['map_id'] ){
		
		// <map id="map_id" onmouseout="map.outMap();">
		var map_element = $(options['map_id']);
		map_element.onmouseout = function(){
			self.outMap();
		};
		
		// <area id="area_code" onmouseover="map.overLocation('code');" 
		// 	onmouseout="map.outLocation('code');" />
		for(var i = 0; i < this.codes.length; i++){
			var code = this.codes[i];
			var area_element = $('area_' + code);
			area_element.code = code
			area_element.onmouseover = function(){
				self.overLocation(this.code); 
			};
			area_element.onmouseout = function(){
				self.outLocation(this.code); 
			};
		};
		
	}
}