function LocalElevationLookup() {
	if (document.getElementById('single_point_coords') && document.getElementById('single_point_coords').value.match(/\w/)) {
		var coords = document.getElementById('single_point_coords').value;
		local_elevation_script = new JSONscriptRequest( 'elevation_data/elev.js?' + 'coords=' + uri_escape(coords) );
		local_elevation_script.buildScriptTag(); // Build the dynamic script tag
		local_elevation_script.addScriptTag(); // Add the script tag to the page, let it do its thing
		
	} else {
		return false;
	}
}

function LocalElevationCallback(meters,source) {
	if (document.getElementById('single_point_elevation')) {
		if (meters != null) {
			var feet = null;
			if (meters == 0) {
				feet = 0;
			} else {
				feet = Math.round((1/meters)*3.28084);
				meters = Math.round((1/meters)*1);
			}
			document.getElementById('single_point_elevation').innerHTML = meters+' meters ('+feet+' feet) [data source: '+source+']';
		} else {
			document.getElementById('single_point_elevation').innerHTML = 'no data found';
		}
	}
	local_elevation_script.removeScriptTag(); // Clean it up
}


function InitializeElevationFinder() {
	elevationCallback = function(d) { ElevationCallback(d); }
	base_url = []; elevation_variable = [];
	base_url['srtm3'] = 'http://ws5.geonames.org/srtm3JSON?callback=elevationCallback';
	elevation_variable['srtm3'] = 'srtm3';
	base_url['gtopo30'] = 'http://ws5.geonames.org/gtopo30JSON?callback=elevationCallback';
	elevation_variable['gtopo30'] = 'gtopo30';
	
	source_menu = document.getElementById('source') || null;
	units_menu = document.getElementById('units') || null;
	separator_menu = document.getElementById('separator') || null;
	progress_indicator = document.getElementById('progress') || null;
	no_elevation_box = document.getElementById('no_elevation') || null;
	start_button = document.getElementById('start') || null;
	start_button_parent = (start_button) ? start_button.parentNode : null;
	start_button_onclick = (start_button) ? start_button.getAttribute('onclick') : '';
}

function StartButton(processing_now,process_name) {
	if (!process_name) { process_name = 'elevation lookup'; }
	if (processing_now) {
		var style = 'color:#666666; font-weight:normal; background-color:#CCFFCC;';
		var text = 'Cancel '+process_name;
		var onclick = "continue_processing=false; StartButton(false,'"+process_name+"');";
		start_button_parent.innerHTML = '<input id="start" type="button" style="'+style+'" value="'+text+'" onclick="'+onclick+'">';
	} else {
		var style='color:#000000; font-weight:bold; background-color:#CCFFCC;';
		var text = 'Start '+process_name;
		var onclick = "LookupMultipleElevations('elevation_input','elevation_results');";
		start_button_parent.innerHTML = '<input id="start" type="button" style="'+style+'" value="'+text+'" onclick="'+onclick+'">';
		FinishedProcessing(process_name);
	}
}

function FinishedProcessing(process_name) {
	if (!process_name) { process_name = 'elevation lookup'; }
	if (process_name.match(/elevation/)) {
		var finished = new Image();
		finished.src = 'http://maps.gpsvisualizer.com/geocoder/finished.png?source='+source+'&count='+location_counter+'/'+input_locations.length+'&page='+uri_escape(document.location)+'&key=ELEVATION&time='+(new Date()).getTime();
		return true;
	} else {
		return false;
	}
}

function LookupMultipleElevations(input_id,output_id) {
	// globals:
	input_textarea = document.getElementById(input_id) || null;
	results_textarea = document.getElementById(output_id) || null;
	source = (source_menu) ? source_menu.value : 'srtm3';
	units = (units_menu) ? units_menu.value : 'metric';
	units_tag = (units == 'us') ? '(feet)' : '';
	sep = ','; if (separator_menu && separator_menu.value) { sep = (separator_menu.value == 'tab') ? "\t" : separator_menu.value; }
	no_elevation = (no_elevation_box && no_elevation_box.checked) ? true : false;
	
	if (!input_textarea || !results_textarea) { return false; }
	var input_data = input_textarea.value;
	input_data = input_data.replace(/(^\s+|\s+$)/g,""); // delete leading and trailing white space
	input_data = input_data.replace(/\r/,'\n'); // just in case there are weird line breaks
	input_lines = input_data.split(/\n/);
	input_locations = [];
	input_elevations = [];
	
	if (!input_data.match(/\w/)) { return false; }
	
	if (!input_lines[0].match(/(^|\t|,) *(lati?|latt?itude)\b/i) || !input_lines[0].match(/(^|\t|,) *(long?|lng|long?t?itude)\b/i)) {
		alert ("It looks like your data doesn't have a header row that defines the 'latitude' and 'longitude' columns.  Without a header, the program doesn't know what order your data fields are in, and it can't continue.");
		return false;
	}
	
	var result = ParseTabularData();
	if (!result) { return false; }
	
	StartButton(true,'elevation lookup');
	continue_processing = true;
	
	location_counter = 0;
	actual_limit = (self.limit && limit[source] && limit[source] < input_locations.length) ? limit[source] : input_locations.length;
	if (input_locations[location_counter].match(/\d.*,.*\d/) && (!input_elevations[location_counter] || input_elevations[location_counter] == 0)) {
		ElevationLookup();
	} else {
		ElevationCallback(null);
	}
}

function ParseTabularData() { // input_locations[] and input_lines[] are global
	
	if (input_lines.length < 2) { return false; }
	
	input_header = input_lines.shift();
	input_delimiter = ',';
	if (input_header.match(/\t/)) { input_delimiter = '\t'; }
	else if (input_header.match(/;/) && !input_header.match(/,/)) { input_delimiter = ';'; }
	input_fields = input_header.split(input_delimiter);
	
	input_field_index = new Array;
	for (var j=0; j<input_fields.length; j++) {
		input_fields[j] = input_fields[j].replace(/(^\s+|\s+$)/g,""); // delete leading and trailing white space
		input_fields[j] = input_fields[j].replace(/,$/g,""); // delete trailing commas
		if (input_fields[j].match(/^(alti?|altitude|elev?|elevation)\b/i) && input_field_index['altitude'] == null) {
			input_field_index['altitude'] = j;
			input_fields[j] = input_fields[j].replace(/ *\([^\)]*\)/i,''); // remove parens
			input_fields[j] += units_tag;
		}
		else if (input_fields[j].match(/^(lati?|latt?itude)\b/i) && input_field_index['latitude'] == null) { input_field_index['latitude'] = j; }
		else if (input_fields[j].match(/^(long?|lng|long?t?itude)\b/i) && input_field_index['longitude'] == null) { input_field_index['longitude'] = j; }
	}
	
	var field_count = 0; for (var i in input_field_index) { field_count++; }
	if (field_count == 0) { return false; }
	
	for (var j=0; j<input_lines.length; j++) {
		var parts = input_lines[j].split(input_delimiter);
		var location = '';
		if (input_field_index['latitude'] != null && parts[input_field_index['latitude']] != '' && parts[input_field_index['latitude']] != undefined && input_field_index['longitude'] != null && parts[input_field_index['longitude']] != '' && parts[input_field_index['longitude']] != undefined) {
			location = ParseCoordinate(parts[input_field_index['latitude']])+','+ParseCoordinate(parts[input_field_index['longitude']]);
		}
		location = location.replace(/^[\s,;]+|[\s,;]+$|\s+([,;])/g,"$1"); // delete leading and trailing white space and commas
		location = location.replace(/[\s][\s]+/g," "); // compress white space
		input_locations[j] = location;
		
		var alt = '';
		if (input_field_index['altitude'] != null && parts[input_field_index['altitude']] != '' && parts[input_field_index['altitude']] != undefined) { alt = parts[input_field_index['altitude']]; }
		if (!alt.match(/\d/)) { alt = ''; }
		input_elevations[j] = alt;
	}
	
	// Prepare results box for output
	if (!results_textarea.value.match(/\w/)) {
		for (var j=0; j<input_fields.length; j++) {
			if (j > 0) { results_textarea.value = results_textarea.value + sep; }
			results_textarea.value = results_textarea.value + input_fields[j];
		}
		if (input_field_index['altitude'] == null && !no_elevation) {
			results_textarea.value = results_textarea.value + sep+'altitude'+units_tag;
		}
		results_textarea.value = results_textarea.value + '\n';
	}
	return true;
}



function ElevationLookup() {
	if (!no_elevation) {
		var lat_lon = input_locations[location_counter].split(/,/);
		elevation_script = new JSONscriptRequest( base_url[source] + '&lat=' + uri_escape(lat_lon[0]) + '&lng=' + uri_escape(lat_lon[1]) );
		elevation_script.buildScriptTag(); // Build the dynamic script tag
		elevation_script.addScriptTag(); // Add the script tag to the page
	} else {
		ElevationCallback(null);
	}
}

function ElevationCallback(data) {
	var d= {};
	if (data) {
		if (data && data[elevation_variable[source]] != null && data[elevation_variable[source]] > -32000) {
			d['altitude'] = data[elevation_variable[source]];
			if (units == 'us') { d['altitude'] = Math.round(d['altitude']*3.28084); }
		}
		elevation_script.removeScriptTag();
	}
	OutputRowWithElevation(d);
	
	location_counter += 1;
	if (location_counter < actual_limit && continue_processing) {
		if (input_locations[location_counter].match(/\d.*,.*\d/) && (!input_elevations[location_counter] || input_elevations[location_counter] ==0)) {
			var pause = (no_elevation) ? 0 : 1000*delay[source];
			window.setTimeout("ElevationLookup()",pause);
		} else {
			ElevationCallback(null);
		}
	} else if (limit[source] && location_counter >= limit[source] && limit[source] < input_locations.length) {
		StartButton(false,'elevation lookup');
		var msg = "Sorry, you're only allowed to send "+limit[source]+" addresses at once to the server with this form.";
		alert (msg);
	} else if (location_counter == input_locations.length) { // all done, no limit issues
		StartButton(false,'elevation lookup');
	}
}

function OutputRowWithElevation(d) {
	if (!input_lines[location_counter].match(/\w/)) {
		results_textarea.value = results_textarea.value + '\n';
	} else {
		var parts = input_lines[location_counter].split(input_delimiter);
		for (var j=0; j<input_fields.length; j++) {
			var p = (parts[j]) ? parts[j].replace(/(^[\s]*|[\s]*$)/g,'') : '';
			if (j == input_field_index['altitude']) {
				if (!input_elevations[location_counter] || input_elevations[location_counter] == 0) { p = d['altitude']; }
			} else if (j == input_field_index['latitude'] || j == input_field_index['longitude']) {
				p = ParseCoordinate(p);
			}
			if (j > 0) { results_textarea.value = results_textarea.value + sep; }
			results_textarea.value = results_textarea.value + qd(p);
		}
		if (input_field_index['altitude'] == null && !no_elevation) {
			results_textarea.value = results_textarea.value + sep+qd(d['altitude']);
		}
		results_textarea.value = results_textarea.value + '\n';
	}
	results_textarea.scrollTop = results_textarea.scrollHeight;
	
	if (progress_indicator) { progress_indicator.innerHTML = '('+(location_counter+1)+' of '+input_locations.length+' lines processed)'; }
}

function ParseCoordinate(coordinate) {
	coordinate = coordinate.toString();
	coordinate = coordinate.replace(/[^NESW0-9\.\- ]/gi,' '); // only a few characters are useful; delete the rest
	var neg = 0; if (coordinate.match(/(^\s*-|[WS])/i)) { neg = 1; }
	coordinate = coordinate.replace(/[NESW\-]/gi,' ');
	if (!coordinate.match(/[0-9]/i)) { return ''; }
	parts = coordinate.match(/([0-9\.\-]+)[^0-9\.]*([0-9\.]+)?[^0-9\.]*([0-9\.]+)?/);
	if (!parts || parts[1] == null) {
		return '';
	} else {
		n = parseFloat(parts[1]);
		if (parts[2]) { n = n + parseFloat(parts[2])/60; }
		if (parts[3]) { n = n + parseFloat(parts[3])/3600; }
		if (neg && n >= 0) { n = 0 - n; }
		n = Math.round(10000000 * n) / 10000000;
		if (n == Math.floor(n)) { n = n + '.0'; }
		n = n+''; // force number into a string context
		n = n.replace(/,/g,'.'); // in case some foreign systems created a number with a comma in it
		return n;
	}
}

function comma2point (number) {
	number = number+''; // force number into a string context
	return (number.replace(/,/g,'.'));
}

function tag_to_string(xml_text,tag_name) { // read tags out of an XML string
	var pattern = new RegExp('<'+tag_name+'>\\s*([^<]*)\\s*<\/'+tag_name+'>','i');
	var m = pattern.exec(xml_text);
	m = (m) ? m[1] : '';
	return (m)
}

function qd(text) { // qd = quote delimiters
	if (text == undefined) { return ''; }
	text = text.toString();
	if (text == '') { return ''; }
	var dl = (sep) ? sep : ',';
	var pattern = (dl == '|') ? '\\'+dl : dl;
	if (text.toString().match(pattern)) {
		return '"'+text.replace(/(^\s*|\s*$)/g,'')+'"';
	} else {
		return text.replace(/(^\s*|\s*$)/g,'');
	}
}

function uri_escape(text) {
	text = escape(text);
	text = text.replace(/\//g,"%2F");
	text = text.replace(/\?/g,"%3F");
	text = text.replace(/=/g,"%3D");
	text = text.replace(/&/g,"%26");
	text = text.replace(/@/g,"%40");
	return (text);
}







// JSONscriptRequest -- a simple class for accessing Yahoo! Web Services
// using dynamically generated script tags and JSON
//
// Author: Jason Levitt
// Date: December 7th, 2005
//
// Constructor -- pass a REST request URL to the constructor
//

function JSONscriptRequest(fullUrl) {
	// REST request path
	this.fullUrl = fullUrl; 
	// Keep IE from caching requests
	this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
	// Get the DOM location to put the script tag
	this.headLoc = document.getElementsByTagName("head").item(0);
	// Generate a unique script tag id
	this.scriptId = 'YJscriptId' + JSONscriptRequest.scriptCounter++;
}

// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {

	// Create the script tag
	this.scriptObj = document.createElement("script");
	
	// Add script object attributes
	this.scriptObj.setAttribute("type", "text/javascript");
	this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
	this.scriptObj.setAttribute("id", this.scriptId);
}
 
// removeScriptTag method
// 
JSONscriptRequest.prototype.removeScriptTag = function () {
	// Destroy the script tag
	if (this.scriptObj) {
		this.headLoc.removeChild(this.scriptObj);
	}
}

// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
	// Create the script tag
	this.headLoc.appendChild(this.scriptObj);
}




/*	This work is licensed under Creative Commons GNU LGPL License.
	License: http://creativecommons.org/licenses/LGPL/2.1/
	Version: 0.9
	Author:  Stefan Goessner/2006
	Web:	 http://goessner.net/ 
*/
function json2xml(o, tab) {
	var toXml = function(v, name, ind) {
		var xml = "";
		if (v instanceof Array) {
			for (var i=0, n=v.length; i<n; i++)
				xml += ind + toXml(v[i], name, ind+"\t") + '\n';
		}
		else if (typeof(v) == "object") {
			var hasChild = false;
			xml += ind + "<" + name;
			for (var m in v) {
				if (m.charAt(0) == "@")
					xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
				else
					hasChild = true;
			}
			xml += hasChild ? ">" : "/>";
			if (hasChild) {
				for (var m in v) {
					if (m == "#text")
						xml += v[m];
					else if (m == "#cdata")
						xml += "<![CDATA[" + v[m] + "]]>";
					else if (m.charAt(0) != "@")
						xml += toXml(v[m], m, ind+"\t");
				}
				xml += (xml.charAt(xml.length-1)=='\n'?ind:"") + "</" + name + ">";
			}
		}
		else {
			xml += ind + "<" + name + ">" + v.toString() +  "</" + name + ">";
		}
		return xml;
	}, xml="";
	for (var m in o)
		xml += toXml(o[m], m, "");
	return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
}


