document.onkeypress = getKey;
var millis_in_3_months =  7948800000;
var millis_in_2_months =  5299200000;
var millis_in_1_month =  2678400000;
var millis_in_1_day =   86400000;
var millis_in_2_days =  172800000;
var millis_in_3_days =  259200000;
var gmap = null;
var first_time = 1;
var points;
var station_list_html = '';
var marker_count = 0;
var requester = null;
var start_dateCtl = null;
var end_dateCtl = null;
var start_hourminCtl = null;
var end_hourminCtl = null;
var stationCtl;
var paramCtl;
var graphic_imgCtl;
var control_titleCtl;
var header_titleCtl;
var delayCtl;
var unitsCtl;
var tzCtl;
var icon;
var start_date, start_hourmin, end_date, end_hourmin, ship, units, tz, param;
var bounds = { min_lat: null, min_lon: null, max_lat: null, max_lon: null};
var waypoints;
var range;
var min_db_val, max_db_val;
var is_track = true;
var plot_thread = null;
var p = 0;
var track_width = 3;
var latest_lon, latest_lat, latest_dt;
var working_thread = null;
var is_working_sign_on = true;
var delay = 0;
var pause_counter = 0;

function blink_working() {
		control_titleCtl.style.visibility = is_working_sign_on ? 'hidden' : 'visible';
		is_working_sign_on  = !is_working_sign_on;
}


// the db_data var will be dynamically loaded using a structure returned by the ajax requester
// all of the cgi scripts called from this file return a db_data structure.
var db_data = null;

function $(element) {
	return typeof(element) == 'object' ? element : document.getElementById(element);
}

var key_stroke_functions = new Array();
key_stroke_functions[32] = check_dates_and_act; //space
key_stroke_functions[112] = pause_plot; // 'p'
//key_stroke_functions[104] = toggle_help_box; // 'h' 
key_stroke_functions[99] = continue_plot; // 'c'
key_stroke_functions[0] = function() {toggle_help_box(true);}; // escape in Firefox, always closes help
key_stroke_functions[27] = function() {toggle_help_box(true);}; // escape in IE, always closes help

function getKey(e) {
	var key = e ? e.which : event.keyCode;
	var f= key_stroke_functions[key];
	if (f) {f();}
	return true;
}

function on_load() {
	
	var check_db_url = "http://hudson.dl.stevens-tech.edu/cgi-bin/db_up.pl";
	ajax_request(check_db_url,"db=atlas");
	if (db_data.status != 'OK') {
		window.location.href = "http://hudson.dl.stevens-tech.edu/maritimeforecast";
	}
	
	set_banner_hide_switch(false);
	Zapatec.Calendar.setup({
		weekNumbers       : false,
		showOthers        : true,
		electric          : false,
		inputField        : "start",
		button            : "start_button",
		ifFormat          : "%Y-%m-%d",
		daFormat          : "%Y-%m-%d" });
	
	Zapatec.Calendar.setup({
		weekNumbers       : false,
		showOthers        : true,
		electric          : false,
		inputField        : "end",
		button            : "end_button",
		ifFormat          : "%Y-%m-%d",
		daFormat          : "%Y-%m/%d" });

	var end_date = new Date();
	var three_days_ago = end_date.getTime() - millis_in_3_days;
	var two_days_ago =  end_date.getTime() - millis_in_2_days;
	var one_day_ago =   end_date.getTime() - millis_in_1_day;
	var start_date = end_date;
	start_dateCtl = $('start');
	start_hourminCtl = $('start_hourmin');
	end_hourminCtl = $('end_hourmin');
	end_dateCtl = $('end');
	start_dateCtl.value = formatDate(start_date,'yyyy-MM-dd');
	end_dateCtl.value = formatDate(end_date,'yyyy-MM-dd');
	stationCtl = $('station');
	paramCtl = $('param');
	unitsCtl=$('units'); 
	tzCtl=$('tz');
	control_titleCtl=$('control_title');
	header_titleCtl=$('header_title');
	delayCtl=$('delay');
	start_hourminCtl.value = '00:00';
	end_hourminCtl.value = '23:59';
	gmap = new GMap2($("gmap"));
	gmap.addMapType(G_PHYSICAL_MAP);	
	gmap.setMapType(G_HYBRID_MAP);	
	gmap.addMapType(G_SATELLITE_MAP);	
	gmap.setMapType(G_SATELLITE_MAP);	
	gmap.addControl(new GSmallMapControl()); // small zoom controls
//	gmap.addControl(new GOverviewMapControl());
//	gmap.addControl(new GLargeMapControl3D()); // large zoom controls
//	gmap.addControl(new GMapTypeControl()); // allow user to control map background
	gmap.addControl(new GScaleControl()); //distance legend
	gmap.addControl(new GMenuMapTypeControl());  // this and below used for dropdown background control
	map_control = new GHierarchicalMapTypeControl();

	gmap.clearOverlays();
	new GKeyboardHandler(gmap); // allow the use of shift-arrow keys to move around

	icon = new GIcon();
	icon.image = defaults.gmarker_icon_name;
	icon.iconSize = new GSize(35,49);
	icon.iconAnchor = new GPoint(18,49);
	icon.infoWindowAnchor = new GPoint(30,30);
	alternate_icon = new GIcon();
	alternate_icon.image = defaults.gmarker_alternate_icon_name;
	alternate_icon.iconSize = new GSize(35,49);
	alternate_icon.iconAnchor = new GPoint(18,49);
	alternate_icon.infoWindowAnchor = new GPoint(30,30);
	banner_load();
	
	set_map_center(defaults.map_center.lat, defaults.map_center.lon, defaults.map_center.zoom);
	load_stations(defaults.station);
	set_params();
	get_inputs();
	ship = defaults.station;
	var current = get_current_location(ship, tz);
	if (db_data.error != 'none') {
		alert(db_data.error);
		return;
	}
	var opts = {title: stationNames[ship],  icon: icon};
	var html = '<div class="mobilemarkertext">' + stationNames[ship] +' Last Location' + '<br>' + '<br>' +
		convert_lat_lon(db_data.lat, db_data.lon) + 
		 '<br>' + db_data.d.substr(0,16) + ' ' + tz + '</div>';
//	marker = create_marker(db_data.lat, db_data.lon, opts, html);
		{
		var lat_lon = new GLatLng(db_data.lat, db_data.lon);
		var marker = new GMarker(lat_lon, opts);
		GEvent.addListener(marker, 'click', function() {
			marker.openInfoWindowHtml(html);});
		}
	gmap.addOverlay(marker);
	set_map_center(db_data.lat, db_data.lon, 14);
	delayCtl.selectedIndex = 0;
	header_titleCtl.innerHTML = "Last Location for the " + stationNames[ship];
}

function get_inputs() {
	start_date = start_dateCtl.value;
	start_hourmin = start_hourminCtl.value;
	end_date = end_dateCtl.value;
	end_hourmin = end_hourminCtl.value;
	param = paramCtl.value;
	ship = stationCtl.value;
	units = unitsCtl.value;
	tz = tzCtl.value;
}

function query_data(action) {

	var x;
	get_inputs();
	if (action == 'download_all') {
		param='all';
		x = $('query_all');
	}
	else {
		x = $('query');
	}
	var url = 'http://hudson.dl.stevens-tech.edu/cgi-bin/queryship.pl?ship=' + ship + 
		'&param=' + param + '&start=' + start_date + '&start_hourmin=' + start_hourmin +
		'&end=' + end_date  + '&end_hourmin=' + end_hourmin + '&units=' + units + '&web=1' +
		'&tz=' + tz ;
	//url = url.toLowerCase();
	x.href=url;
}


function plot() {

	clear_plot();
	gmap.clearOverlays();
	points = null;
	//clear_points();
	points = new Array();
	get_inputs();
	is_track = param == 'TRACK' ? true : false;
	track_width = is_track ? 3 : 4;

	show_colorbar(false);
	get_ship_data(ship, param, start_date, start_hourmin, end_date, end_hourmin, units, tz);
	if (db_data.error != 'none') {
		alert(db_data.error);
		return;
	}

	waypoints = db_data.waypoints;
	max_db_val = db_data.max_val;
	min_db_val = db_data.min_val;
	var min_date, max_date;
	range = max_db_val - min_db_val;
	var counter = 0;
	var which_color = 0;
	var color_counter = 1000000;
	var default_track_color = '#a00000';
	var print_units = '';
	delay = Number(delayCtl.value);

	bounds.min_lat = bounds.max_lat = bounds.min_lon = bounds.max_lon = null;

	if (waypoints.length > 1) {
		$('plot_buttons').style.visibility = 'visible';
		control_titleCtl.innerHTML = "******* WORKING ********";
		control_titleCtl.style.color = "#6E0031";
		working_thread = setInterval('blink_working()', 1000);
		latest_lat = waypoints[waypoints.length-1][1];
		latest_lon = waypoints[waypoints.length-1][2];
		latest_dt = waypoints[waypoints.length-1][0];
		print_units = units_print[param + units];
		min_date = waypoints[0][0];
		max_date = waypoints[waypoints.length-1][0];
		set_bounds_and_center();
		p = 0;
		if (delay) {
			plot_thread = setInterval('make_line()', delay);
		}
		else  { 
			make_line_no_delay();
		}
		if (! is_track) {
			cb_legend('colorbar_numbers', 460, min_db_val, max_db_val, 6, print_units) ;
		}

		header_titleCtl.innerHTML = stationNames[ship] + ' ' + paramNames[param] + 
			print_units + ' from ' +
			min_date.substr(0,16) + ' to ' + max_date.substr(0,16) + ' ' + tz;
		p = 0;
	}
	else { //nothing for this time period, so just show most recent location
		$('points_plotted').innerHTML = '';
		header_titleCtl.innerHTML = 'No ' + paramNames[param] + ' for ' + stationNames[ship] +  
			' from ' + start_date + ' to ' + end_date;
		latest_lat = db_data.latest_lat;
		latest_lon = db_data.latest_lon;
		latest_dt = db_data.latest_dt;
		set_map_center(latest_lat, latest_lon);
		var notice;
		if (db_data.is_today || (!waypoints.length)) {
			notice = 'Most Recent Location:';
		}
		else { 
			notice = 'End Location of:'; 
		}
		var opts = {title: stationNames[ship],  icon: icon};
		var html = '<div class="mobilemarkertext">' + notice + '<br>' + stationNames[ship] + '<br>' +
			convert_lat_lon(latest_lat, latest_lon) + 
			 '<br>' + latest_dt.substr(0,16) + ' ' + tz + '</div>';
		marker = create_marker(latest_lat, latest_lon, opts, html);
		gmap.addOverlay(marker);
	}
}


function set_bounds_and_center() {
	var min_lat, max_lat, min_lon, max_lon;
	var wp = waypoints[0];
	min_lat = wp[1];
	max_lat = wp[1];
	min_lon = wp[2];
	max_lon = wp[2];
	for (var i = 1; i< waypoints.length; i++) {
		wp = waypoints[i];
		var lat = wp[1];
		var lon = wp[2];
		min_lat = lat < min_lat ? lat : min_lat;
		max_lat = lat > max_lat ? lat : max_lat;
		min_lon = lon < min_lon ? lon : min_lon;
		max_lon = lon > max_lon ? lon : max_lon;
	}
	var gbounds = new GLatLngBounds(new GLatLng(min_lat, min_lon),
			new GLatLng(max_lat, max_lon));
		var zoom_level = gmap.getBoundsZoomLevel(gbounds);
		zoom_level = zoom_level < 18 ? zoom_level : 18; // don't get too close on initial load
		var mid_lat = (min_lat + max_lat) / 2;
		var mid_lon = (min_lon + max_lon) / 2;
		set_map_center(mid_lat, mid_lon, zoom_level, true);
}
function create_marker(lat, lon, opts, html) {  //must be in function for closure
		var lat_lon = new GLatLng(lat, lon);
		var marker = new GMarker(lat_lon, opts);
		GEvent.addListener(marker, 'click', function() {
			marker.openInfoWindowHtml(html);});
		return marker;
}


function make_encoded_gpolyline(hex_color, track_width) {	
	
	var points_and_levels = create_encodings();
	var eline = new GPolyline.fromEncoded({
	color: hex_color,
	weight:track_width,
	points: points_and_levels[0],
	levels: points_and_levels[1],
	opacity: 1,
	zoomFactor:32,
	numLevels: 4 });
	gmap.addOverlay(eline);
	//clear_points();
}	

function make_line_no_delay() {
	for (var i = 1; i<= waypoints.length; i++) { //intentional to go 1 too far, see function below
		make_line();
	}
}

function clear_plot() {
	pause_counter = 0;
	clearInterval(plot_thread);
	plot_thread = null;
	$('plot_buttons').style.visibility = 'hidden';
	clearInterval(working_thread);
	control_titleCtl.style.visibility='visible';
	control_titleCtl.innerHTML = "Select Ship and Options";
	control_titleCtl.style.color = "#000099";
	$('points_plotted').innerHTML =  '';
	show_colorbar(false);
	header_titleCtl.innerHTML = "Location for the " + stationNames[ship] + ' at End of Track';
	gmap.clearOverlays();
	if (waypoints && p) {
		var wp = waypoints[waypoints.length-1];
		var opts = {title: stationNames[ship],  icon: icon};
		var html = '<div class="mobilemarkertext">' + 'Location at End of Track:' + '<br>' + stationNames[ship] + 
			'<br>' + convert_lat_lon(wp[1], wp[2]) + 
		 	'<br>' + wp[0].substr(0,16) + ' ' + tz + '</div>';
		marker = create_marker(wp[1], wp[2], opts, html);
		gmap.addOverlay(marker);
		gmap.panTo(new GLatLng(wp[1], wp[2]));
	}
}

function pause_plot() {
	if (!p || !plot_thread) return; //if nothing's happening there's nothing to pause

	clearInterval(plot_thread);
	plot_thread = null;
	var wp = waypoints[p];
	var opts = {title: stationNames[ship],  icon: alternate_icon};
	var print_units = units_print[param + units];
	var param_html = param == 'TRACK' ? '' :
		'<br><br>' + paramNames[param] + ':  ' + wp[3].toFixed(2) + ' ' + print_units;
	var html = '<div class="mobilemarkertext">' + stationNames[ship] +' Location at<br>Pause Point: ' + 
		++pause_counter + 
		'<br>' + '<br>' + convert_lat_lon(wp[1], wp[2]) + 
		'<br>' + wp[0].substr(0,16) + ' ' + tz + param_html + '<br></div>';
	var marker = create_marker(wp[1], wp[2], opts, html);
	gmap.addOverlay(marker);
}

function continue_plot() {
	if (!p || plot_thread) return; // don't start thread if already running or nothing in progress

	delay = Number(delayCtl.value);
	plot_thread = setInterval('make_line()', delay);
}

function make_line() {
	var default_track_color = '#a00000';
	var notice = "End Location of:";
	p++;
	if (p >= waypoints.length) {
		clearInterval(plot_thread);
		plot_thread = null;
		$('plot_buttons').style.visibility = 'hidden';
		var wp = waypoints[p-1];
		var opts = {title: stationNames[ship],  icon: icon};
		var print_units = units_print[param + units];
		var param_html = param == 'TRACK' ? '' :
			'<br><br>' + paramNames[param] + ':  ' + wp[3].toFixed(2) + ' ' + print_units;
		var html = '<div class="mobilemarkertext">' + stationNames[ship] + ' Location at End Point:' + '<br><br>'  + 
			convert_lat_lon(wp[1], wp[2]) + 
		 	'<br>' + wp[0].substr(0,16) + ' ' + tz + param_html + '<br></div>';
		var marker = create_marker(wp[1], wp[2], opts, html);
		gmap.addOverlay(marker);
		clearInterval(working_thread);
		control_titleCtl.style.visibility='visible';
		control_titleCtl.innerHTML = "<em>" + stationNames[ship] + ": " + paramNames[param] + "</em>";
		control_titleCtl.style.color = "#000099";
		working_thread = null;
		$('points_plotted').innerHTML =  '';
		p = 0;
		return;
	}
	
	var waypoint = waypoints[p];
	var wp = waypoints[p];
	var prev_wp = waypoints[p-1];
	var hex_color = is_track ? default_track_color :
	select_color(min_db_val, max_db_val, wp[3], range);
	var pp = new Array();
	pp[0] = new GLatLng(prev_wp[1], prev_wp[2]);
	pp[1] = new GLatLng(wp[1], wp[2]);
	var line = new GPolyline(pp, hex_color, track_width,1);
	gmap.addOverlay(line);
	var dt = wp[0].substring(11,16);
	$('points_plotted').innerHTML =  'Time: ' + dt + '&nbsp;&nbsp;Point: ' + (p+1) + ' (of ' + waypoints.length + ')';

}


function create_plain_marker(lat_lon) {
	var marker = new GMarker(lat_lon);
	return marker;
}

function set_map_center(lat, lon, zoom_level, do_pan_to) {
	if (do_pan_to) {
		gmap.panTo(new GLatLng(lat, lon));
	}
   gmap.setCenter(new GLatLng(lat, lon), zoom_level);

}

function show() {
	var out = ' ';
	var separator = '';
	for (var i = 0; i <  arguments.length; i++) {
		out += separator + arguments[i];
		separator = ', ';
	}
	alert(out);
}

function get_ship_data(ship, param, start, start_hourmin, end, end_hourmin, units, tz) {
	var url = 'http://hudson.dl.stevens-tech.edu/cgi-bin/plotship.pl';
	var params = 'ship=' + ship + 
		'&param=' + param + '&start=' + start + '&start_hourmin=' + start_hourmin +
		'&end=' + end  + '&end_hourmin=' + end_hourmin + '&units=' + units +
		'&tz=' + tz  + '&web=1';
	ajax_request(url,params);
	//alert(url);
}
function get_current_location(ship, tz) {
	var url = 'http://hudson.dl.stevens-tech.edu/cgi-bin/ship_current.pl';
	var params = 'ship=' + ship + '&web=1&tz=' + tz;
	ajax_request(url,params);
}

function ajax_request(url, params) {
	if (!requester) {
		requester = new XMLHttpRequest();
		if (!requester) { alert("can't get requester");}
	}
	var SYNC = false;
	requester.open("POST", url, SYNC);
	requester.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	requester.setRequestHeader('Content-length', params.length);
	requester.setRequestHeader('Connection', 'close');
	requester.send(params);
	var response = requester.responseText;
//	show(url, params);
//	alert(response);
	eval(response);
}

function select_color(min_val, max_val, val, range) {
	var color_choice = Math.floor((val-min_val)* (colors.length-1)/range);
	var rgb = colors[color_choice];
	return rgb_to_hex(rgb);
}

function rgb_to_hex(rgb) {
 	var hex='#';
 	var hex_chars = '0123456789ABCDEF';
	var low = rgb[0] % 16;
	var high = (rgb[0] - low)/16;
	hex+=hex_chars.charAt(high) + hex_chars.charAt(low);
	low = rgb[1] % 16;
	high = (rgb[1] - low)/16;
	hex+=hex_chars.charAt(high) + hex_chars.charAt(low);
	low = rgb[2] % 16;
	high = (rgb[2] - low)/16;
	hex+=hex_chars.charAt(high) + hex_chars.charAt(low);
	return hex;
}

function is_date_bad(input) { //invalid or too early or late

	var msg = null;
	if (! isDate(input.value,'yyyy-MM-dd')) {
			bad_date = true;
			msg = 'Highlighted dates are not valid in form YYYY-MM-DD';
			input.style.color='#ffffff';
			input.style.backgroundColor = '#801143';
			return msg;
	}

	var date_in_millis = getDateFromFormat(input.value,'yyyy-MM-dd');
	if (date_in_millis > ((new Date).getTime() + millis_in_1_day)) {
			msg = 'Dates may not be more than 1 day in the future';
			input.style.color='#ffffff';
			input.style.backgroundColor = '#801143';
			return msg;
	}
	
	if (compareDates('2000-01-01','yyyy-MM-dd', input.value, 'yyyy-MM-dd')) {
			msg = 'Dates prior to the year 2000 are not valid';
			input.style.color='#ffffff';
			input.style.backgroundColor = '#801143';
			return msg;
	}
	input.style.backgroundColor = '#ffffff';
	input.style.color = '#000099';
	return null;
}
	
function show_error(err) {
	alert(err);
}

var hourmin_regexp = /^(\d\d):(\d\d)$/;
function check_hourmin(input) {
	var val = $(input).value;
	if ((!hourmin_regexp.exec(val))  || (RegExp.$1 > 23 || RegExp.$2 > 59)) {
		input.style.color='#ffffff';
		input.style.backgroundColor = '#801143';
		show_error('Invalid hour:min value');
		input.value = val;
		return false;
	}
	input.style.backgroundColor = '#ffffff';
	input.style.color = '#000099';
	return true;
}

function check_date(input) {
	var msg = null;
	msg = is_date_bad(input);
	if (msg) show_error(msg);
	else {
		if (input.id == 'start') {
			$('end').value = input.value;
		}
	}
	return true;
}

function check_dates_and_act(action_in) {
	var action = action_in || 'plot';

	var time_period_exceeded = false;
	var error_msg;

	if ( is_date_bad(end_dateCtl) || is_date_bad(start_dateCtl) ) {
		 show_error( 'There are problems with one or both of the dates');
		 return  null;
	}
	if (compareDates(start_dateCtl.value,'yyyy-MM-dd', end_dateCtl.value, 'yyyy-MM-dd')) {
		show_error('The end date is earlier than the start date');
		return null;
	}
	
	var period_in_millis = getDateFromFormat(end_dateCtl.value,'yyyy-MM-dd') -
								getDateFromFormat(start_dateCtl.value,'yyyy-MM-dd');
	if (action == 'download' && period_in_millis > millis_in_3_months) {
			error_msg = "General parameters may be downloaded for up to 3 months";
			time_period_exceeded = true;
	}
	else if (action == 'download_all' && period_in_millis > millis_in_3_months) {
			error_msg = "All parameters may be downloaded for up to 3 months";
			time_period_exceeded = true;
	}
	else if (action == 'plot' && period_in_millis > millis_in_2_days){
			error_msg = "Parameters may be plotted for up to 2 days per request";
			time_period_exceeded = true;
	}
	if (time_period_exceeded) {
		show_error(error_msg);
		return true; ;
	}
	if (!check_hourmin($('start_hourmin'))) {
		show_error('Bad start_hourmin');
		return true;
	}
	if (!check_hourmin($('end_hourmin'))) {
		show_error('Bad end_hourmin');
		return true;
	}
	action == 'plot' ? plot() :query_data(action);
}
		
function clear_drop_down(ctl) {
	for (var i = ctl.options.length-1; i >= 0; i--) {
		ctl.options[i] = null;
	}
	show_colorbar(false);
}

function load_stations(station) {
	clear_drop_down(stationCtl);
	stationCtl.selectedIndex = 0;
	for(var i = 0;  i < stationNamesList.length ;  i++){
		stationCtl.options[i] = new Option(stationNamesList[i].title, stationNamesList[i].name);
		stationCtl.options[i].className = 'mydrop';
		if (station == stationNamesList[i].name) {
			stationCtl.selectedIndex = i;
		}
	}
}

function set_params() {
	var old_param= null;
	if (paramCtl.length > 0) {
		old_param = paramCtl.value;
	}
	clear_drop_down(paramCtl);
			
	var paramNamesArray = new Array();
	var station = stationCtl.value;
	if(station != null && stationParams[station] != null){	
		for(var i = 0;  i < stationParams[station].length;  i++){
			paramNamesArray[i] = paramNames[stationParams[station][i]] + '#' + stationParams[station][i];
		}
		for(var i = 0;  i < paramNamesArray.length;  i++){
			var splitParam = paramNamesArray[i].split('#');	
			paramCtl.options[i]  = new Option(splitParam[0], splitParam[1]);
			paramCtl.options[i].className = 'mydrop';
			if(splitParam[1] == old_param){
				paramCtl.options[i].selected = true;
			}
		}
	}		 		 
}

function change_param() {
	check_dates_and_act('plot');
}

function show_photos() {
	var url='http://hudson.dl.stevens-tech.edu/mobile/photos/' + stationCtl.value + '_album.shtml'; 
	window.location.href = url;
}

function cb_legend(container_name, container_size, min, max, max_ticks, print_units) {
	var results = nice_numbers(min, max, max_ticks, 1,1);
	var range = max - min;
	var val = results[0];
	var increment = results[1];
	var count = results[2];
	var pos = Math.floor( ((val - min) / range) * container_size) -20;  // starting pos
	pos = -10;
	var pos_inc = Math.floor((container_size-pos-25) / (count-1));
	var cont = $(container_name);
	show_colorbar(true);
	var html = '';
	for (var i = 0; i<count; i++) {
		var out_units = '' + val.toFixed(2);
		if (!i) {out_units += ' ' +print_units;}
		html += '<div style="position:absolute;left:' + pos + 'px">' + out_units + '</div>  ';
		pos += pos_inc;
		val += increment;
	}
	cont.innerHTML = html;
}

function show_colorbar (do_show) {
	$('colorbar_img').style.visibility = do_show ? 'visible' : 'hidden';
	$('colorbar_numbers').innerHTML = '';
}

var is_help_shown = false;
function toggle_help_box(pretend_it_was_this) {
			// 'assume' allows the box to be set open or closed regardless of what it was before
	window.scrollTo(0,0);
	is_help_shown = pretend_it_was_this || is_help_shown;
	if (is_help_shown) {
		$('helpbox').style.display = 'none';
		$('help_box_button').src="images/help_blood.gif";
		$('help_box_button').title="Click for Help";
		is_help_shown = false;
	}
	else {
		$('helpbox').style.display = 'block';
		$('help_box_button').src="images/blue_x_button_down.gif";
		$('help_box_button').title="Click to Close Help";
		//$('helpbox').scrollTop = 0; // can't decide whether to do this!
		is_help_shown = true;
	}
}

function convert_lat_lon(lat, lon) {
	var zero_pad = ['','','.00','00','0','','','.00','00','0','',''];
	var NS = lat > 0 ? "' N" : "' S";
	var EW = lon < 0 ? "' W" : "' E";
	lat = Math.abs(lat);  lon = Math.abs(lon);
	var latmin = Math.floor(lat%1*6000) / 100;
	var latmin_str = latmin < 10 ? '0' + latmin : '' + latmin;
	var orig = latmin_str.length + '';
	latmin_str += zero_pad[latmin_str.length];
	var lonmin = Math.floor(lon%1*6000) / 100 ;
	var lonmin_str = lonmin < 10 ? '0' + lonmin : '' + lonmin;
	var orig = lonmin_str.length + '';
	lonmin_str += zero_pad[lonmin_str.length];
	var latDeg = Math.floor(lat);
	var lonDeg = Math.floor(lon)
	var lat_str = '' + latDeg + '&deg; ' + latmin_str;
	var lon_str = '' + lonDeg + '&deg; ' + lonmin_str;

	return( '<span class="locator">' + lat_str + NS + '<BR>' + lon_str + EW + '</span>');

}
