/*
Script Name: vCard Supermap
Description: Turns static hCards addresses into dynamic Google Maps.
Version: 1.5.1
Author: Ashley Kyd
Author URI: http://kyd.com.au/
*/
var xmlDoc;
var map;
var geocoder;
var mapParent;
var mapText;
var mapLoaded = false;

/*
 * Initial function. Makes vCards clickable, instantiates
 * the elements we need to display a map, and loads the Maps API.
 */
function makeClickableVcards(){
	
	// Let's make all vCard elements clickable. It'll be great.
	
	var vcards = document.getElementsByTagName('div');
	vCardHasAtLeastOne = false; // Flag to let us know if we found any vCards.
	
	// Loop through every div on the page, then check if it's a vCard.
	for(i=0;i<vcards.length;i++){
	
		// We found one. That was easy.
		if(vcards[i].className=='vcard'){
			vCardHasAddress = false; // Another flag, this time for the address.
			var properties = vcards[i].getElementsByTagName('span');
			
			// Loop through all of the child elements, looking for the adr.
			for(j=0;j<properties.length;j++){

				// We've found a locality element, this will do.
				if(properties[j].className=='locality'){
					vCardHasAddress = true;
				}

			}
			
			// So now we make the address clickable.
			if(vCardHasAddress == true){
				var properties = vcards[i].getElementsByTagName('div');
				
				// first we've got to find it.
				for(j=0;j<properties.length;j++){
					classes = properties[j].className;
					
					// We've found (what looks like) it. Proceed blindly.
					if(classes.match('adr')){
						properties[j].onclick = makeMap;
						properties[j].onmouseout = function(){this.style.borderColor='#b5011c';this.style.cursor='pointer';}
						properties[j].onmouseover = function(){this.style.borderColor='#000';this.style.cursor='pointer';}
						vCardHasAtLeastOne = true;
					}
				}
				
			
			}
		}
	}
	
	// If we found a vCard previously, let's go.
	if(vCardHasAtLeastOne==true){

		// Since the Maps API is enormous, we only load it now we're sure we need it.
		loadApi();

		// Let's now instantiate the elements we need to make a map window.
				
		inlineWindow = document.createElement('div');
		inlineWindow.setAttribute('id','map_canvas_wrap');
		
		inlineWindowDocument = document.createElement('div');
		inlineWindowDocument.setAttribute('id','map_canvas');
		
		inlineWindowClose = document.createElement('a');
		inlineWindowClose.setAttribute('href','#');
		inlineWindowClose.setAttribute('class','closelink');
		inlineWindowClose.onclick=function(){this.parentNode.style.display='none';return false;}
		
		inlineWindowTitle = document.createElement('p');
		inlineWindowTitle.setAttribute('id','map_title');
		inlineWindowTitle.innerHTML = 'Loading a Map...';
		
		inlineWindow.appendChild(inlineWindowTitle);
		inlineWindow.appendChild(inlineWindowClose);
		inlineWindow.appendChild(inlineWindowDocument);
		document.getElementById('footer').appendChild(inlineWindow);
		
	}

}

/*
 * API Loading function.
 * The variable "key" needs to be defined already.
 */
function loadApi(){
	// Load the Google Maps API, now that we need it.
	
	// Here's our url.
	googleApiSrc = "http://www.google.com/jsapi?callback=apiLoadedEvent&key="+key;

	// Now we can create a script element to insert into the <head>
	var script = document.createElement("script");
	script.src = googleApiSrc;
	script.type = "text/javascript";
	document.getElementsByTagName("head")[0].appendChild(script);
}

/*
 * API Loaded.
 * This is a callback function to let us know the API has been loaded.
 */
function apiLoadedEvent(){
	// Load the Maps API now.
	google.load("maps", "2", {"callback" : mapsLoadedEvent});
}

/*
 * Maps Loaded.
 * This is a callback function to let us know the maps API has been loaded.
 */
function mapsLoadedEvent(){
	// Mark the API as completely loaded. Now everything will be clickable.
	mapLoaded = true;
}


/*
 * Find Address
 * Create a textual address from the referenced hCard.
 */
function findAdr(vcard){
	
	var spans = vcard.getElementsByTagName('span');
	
	var address = new Array();
	var addressValid = false;
	
	// Loop through all the elements. They must be <span>s.
	for(i=0;i<spans.length;i++){
		className = spans[i].className;

		// Pick which piece of the address we've found.
		switch(className){
			case 'street-address':
				address[0] = spans[i].childNodes[0].nodeValue;
				break;
			case 'locality':
				address[1] = spans[i].childNodes[0].nodeValue;
				addressValid = true;
				break;
			case 'region':
				address[2] = spans[i].childNodes[0].nodeValue;
				break;
			case 'postal-code':
				address[3] = spans[i].childNodes[0].nodeValue;
				break;
			case 'country-name':
				address[3] = spans[i].childNodes[0].nodeValue;
				break;
			
		}
		
	}
	
	// Join the address brutally into one piece.
	// Note, the extended-address attribute has been left out.
	address = address.join(', ');
	
	return address;
	
	
}



/*
 * Make Map
 * Function to glue everything together. Gets the address from a vCard, 
 * and then geocodes it to the addAddressToMap() callback.
 */
function makeMap(){
	
	// If the API hasn't been fully loaded yet, give up.
	if(mapLoaded==false){
		return false;
	}
	
	// Show the map element(s). :-)
	mapParent = document.getElementById('map_canvas_wrap');	
	mapText = document.getElementById('map_title');
	mapText.innerHTML = 'Loading Map.';
	mapParent.style.display = 'block';
	
	// Get the address from the vCard.
	address = findAdr(this);
	
	if(address){
		
		// We've found an address. Make a map. :-)
		map = new GMap2(document.getElementById("map_canvas"));
		mapText.innerHTML = 'Loading Map..';
		
		// Initialise our map defaults
		map.setCenter(new GLatLng(34, 0), 16);
		geocoder = new GClientGeocoder();
		geocoder.getLocations(address, addAddressToMap);
		
		
	}else{
		
		// No hcard/address address found
		
	}
	
}



/*
 * addAddressToMap
 * addAddressToMap() is called when the geocoder returns an
 * answer.  It adds a marker to the map with an open info window
 * showing the nicely formatted version of the address and the country code.
 */
function addAddressToMap(response) {
	// Reset some things.
	mapText.innerHTML = 'Loading Map...';
	map.clearOverlays();

	if (!response || response.Status.code != 200) {
		// Address couldn't be geocoded. :-(
		mapText.innerHTML = 'Loading Map Failed';
		return false;

	} else {
		// Set a marker, and move the map to the geocoded location.
		mapText.innerHTML = 'Map View';
		place = response.Placemark[0];
		point = new GLatLng(place.Point.coordinates[1],	place.Point.coordinates[0]);
						
		map.setCenter(point);	
		marker = new GMarker(point);
		map.addOverlay(marker);
		map.setCenter(point);
		map.addControl(new GSmallMapControl());
		
	}
}

window.onload = makeClickableVcards;
