/* FUNCTIONS FOR DRAWING GOOGLE MAPS WITH GPS VISUALIZER (http://www.gpsvisualizer.com/) */

gv_api_version = FindGoogleAPIVersion();


// Define parameters of different marker types
if (!self.gv_icons) { gv_icons = new Array(); }
gv_icons['circle'] = { is:[11,11],ia:[5,5],ss:[13,13],iwa:[10,2],isa:[5,9],im:[0,0, 10,0, 10,10, 0,10, 0,0],letters:true };
gv_icons['pin'] = { is:[15,26],ia:[7,25],ss:[30,26],iwa:[7,1],isa:[12,16],im:[5,25, 5,15, 2,13, 1,12, 0,10, 0,5, 1,2, 2,1, 4,0, 10,0, 12,1, 13,2, 14,4, 14,10, 13,12, 12,13, 9,15, 9,25, 5,25 ],letters:true };
gv_icons['square'] = { is:[11,11],ia:[5,5],ss:[13,13],iwa:[10,2],isa:[5,9],im:[0,0, 10,0, 10,10, 0,10, 0,0],letters:true };
gv_icons['triangle'] = { is:[13,13],ia:[6,6],ss:[15,15],iwa:[11,3],isa:[6,10],im:[0,11, 6,0, 12,11, 0,11],letters:false };
gv_icons['diamond'] = { is:[13,13],ia:[6,6],ss:[13,13],iwa:[11,3],isa:[6,10],im:[6,0, 12,6, 6,12, 0,6, 6,0],letters:false };
gv_icons['airport'] = { is:[17,17],ia:[8,8],ss:[19,19],iwa:[13,3],isa:[13,17],im:[6,0, 10,0, 16,6, 16,10, 10,16, 6,16, 0,10, 0,6, 6,0],letters:false };
gv_icons['google'] = { is:[20,34],ia:[9,34],ss:[37,34],iwa:[9,2],isa:[18,25],im:[8,33, 8,23, 1,13, 1,6, 6,1, 13,1, 18,6, 18,13, 11,23, 11,33],letters:true };
gv_icons['googleblank'] = { is:[20,34],ia:[9,34],ss:[37,34],iwa:[9,2],isa:[18,25],im:[8,33, 8,23, 1,13, 1,6, 6,1, 13,1, 18,6, 18,13, 11,23, 11,33],letters:true };
gv_icons['googlemini'] = { is:[12,20],ia:[6,20],ss:[22,20],iwa:[5,1],isa:[10,15],im:[4,19, 4,14, 0,7, 0,3, 4,0, 7,0, 11,3, 11,7, 7,14, 7,19, 4,19],letters:true };
gv_icons['blankcircle'] = { is:[64,64],ia:[31,31],ss:[70,70],iwa:[55,8],isa:[31,63],im:[19,3, 44,3, 60,19, 60,44, 44,60, 19,60, 3,44, 3,19, 19,3],letters:false };

// Make sure defaults have been set; if not, things break. (Some backwards-compatibility (BC) stuff here)
if (!self.gv_marker_icon || !gv_icons[gv_marker_icon]) { gv_marker_icon = (self.default_icon_style) ? default_icon_style : 'pin'; } // BC
if (!self.gv_marker_color) { gv_marker_color = (self.default_icon_color) ? default_icon_color : 'red'; } // BC
if (!self.gv_marker_link_target) { gv_marker_link_target = (self.marker_link_target) ? marker_link_target : '_blank'; } // BC
if (!self.gv_maptypecontrol_style) { gv_maptypecontrol_style = (self.maptypecontrol_style) ? maptypecontrol_style : 'menu'; } // BC
if (self.gv_filter_map_types==null) { gv_filter_map_types = (self.filter_map_types!=null) ? filter_map_types : true; }
if (!self.gv_icon_directory) { gv_icon_directory = 'http://www.gpsvisualizer.com/google_maps/icons/'; }

// Some stuff related to marker lists
var gv_marker_list; var gv_marker_list_html = '';
var gv_marker_array_name; var gv_marker_list_div; var gv_marker_list_div_name; var gv_marker_list_map_name;
if (self.gv_marker_list_options) {
	gv_marker_list = true;
	gv_marker_list_html = '';
	gv_marker_list_map_name = (gv_marker_list_options['map']) ? gv_marker_list_options['map'] : 'gmap';
	gv_marker_array_name = (gv_marker_list_options['array']) ? gv_marker_list_options['array'] : 'wpts';
	if (document.getElementById(gv_marker_list_options['div'])) {
		gv_marker_list_div_name = gv_marker_list_options['div'];
		gv_marker_list_div = document.getElementById(gv_marker_list_div_name);
	} else if (document.getElementById('gv_marker_list')) {
		gv_marker_list_div_name = 'gv_marker_list';
		gv_marker_list_div = document.getElementById(gv_marker_list_div_name);
	} else {
		gv_marker_list = false;
	}
}

// Set up some styles
document.writeln('		<style type="text/css">');
document.writeln('			img.gv_wpt_thumbnail { display:block; text-decoration:none; margin:0px; }');
document.writeln('			img.gv_wpt_photo { display:block; text-decoration:none; margin:0px; }');
document.writeln('			.gv_tooltip {');
document.writeln('				background-color:#FFFFFF; filter:alpha(opacity=100); -moz-opacity:1.0;');
document.writeln('				border:1px solid #666666; padding:2px; text-align:left;');
document.writeln('				font:10px Verdana,sans-serif; color:#000000; white-space: nowrap;');
document.writeln('			}');
document.writeln('			.gv_tooltip img.gv_wpt_thumbnail { display:block; padding-top:3px; }');
document.writeln('			.gv_tooltip img.gv_wpt_photo { display:none; }');
document.writeln('			.gv_wpt { font: 10px Verdana,sans-serif; z-index:999; }');
document.writeln('			.gv_wpt img.gv_wpt_thumbnail { border:1px solid; margin:6px 0px 6px 0px; }');
document.writeln('			.gv_wpt img.gv_wpt_photo { margin:8px 0px 8px 0px; }');
document.writeln('			img.hidden_in_info_window { display:none; }');
document.writeln('			.gv_label {');
document.writeln('				background-color:#333333; filter:alpha(opacity=80); -moz-opacity:0.8;');
document.writeln('				border:1px solid #000000; padding:2px; text-align:left;');
document.writeln('				font:9px Verdana,sans-serif; color:#FFFFFF; white-space: nowrap;');
document.writeln('			}');
document.writeln('			.gv_label img { display:none; }');
document.writeln('			.gv_marker_list {');
document.writeln('				font-family:Verdana,sans-serif;');
document.writeln('			}');
document.writeln('			.gv_marker_list_item {');
document.writeln('				padding:2px 0px 6px 0px;');
document.writeln('				font-family:Verdana,sans-serif;');
document.writeln('				font-size:10px;');
document.writeln('				line-height:1.2em;');
document.writeln('			}');
document.writeln('			.gv_marker_list_item .name { font-size:10px; font-weight:bold; }');
document.writeln('			.gv_marker_list_item .name img { display:none; }');
document.writeln('			.gv_marker_list_item .desc { font-size:9px; filter:alpha(opacity=80); -moz-opacity:0.8; }');
document.writeln('			.gv_maptypelink {');
document.writeln('				background-color:#DDDDDD; color:#000000; text-align:center; white-space: nowrap;');
document.writeln('				border:1px solid; border-color: #999999 #222222 #222222 #999999; padding:1px 2px 1px 2px; margin-bottom:3px;');
document.writeln('				font:9px Verdana,sans-serif; text-decoration:none; cursor:pointer;');
document.writeln('			}');
document.writeln('			.gv_maptypelink_selected { background-color:#FFFFFF; }');
document.writeln('		</style>');
document.writeln('		<style type="text/css" media="print">'); // force icons to print even though Google thinks they shouldn't
document.writeln('			img[src^="http://www.gpsvisualizer.com/"].gmnoprint { display:inline; }');
document.writeln('			img[src$="transparent.png"].gmnoprint { display:none; }');
document.writeln('			img[src$="shadow.png"].gmnoprint { display:none; }');
document.writeln('			img[src$="crosshair.gif"].gmnoprint { display:none; }');
document.writeln('		</style>');

// Create a default icon for all markers
var defaultIcon = new GIcon();
defaultIcon.image = gv_icon_directory+gv_marker_icon+'/'+gv_marker_color+'.png';
defaultIcon.transparent = gv_icon_directory+gv_marker_icon+'/'+gv_marker_color+'-t.png';
defaultIcon.iconSize = new GSize(gv_icons[gv_marker_icon]['is'][0],gv_icons[gv_marker_icon]['is'][1]);
defaultIcon.iconAnchor = new GPoint(gv_icons[gv_marker_icon]['ia'][0],gv_icons[gv_marker_icon]['ia'][1]);
defaultIcon.shadow = (gv_icons[gv_marker_icon]['ss'][0]) ? gv_icon_directory+gv_marker_icon+'/shadow.png' : null;
defaultIcon.shadowSize = (gv_icons[gv_marker_icon]['ss'][0]) ? new GSize(gv_icons[gv_marker_icon]['ss'][0],gv_icons[gv_marker_icon]['ss'][1]) : null;
defaultIcon.infoWindowAnchor = new GPoint(gv_icons[gv_marker_icon]['iwa'][0],gv_icons[gv_marker_icon]['iwa'][1]);
defaultIcon.infoShadowAnchor = new GPoint(gv_icons[gv_marker_icon]['isa'][0],gv_icons[gv_marker_icon]['isa'][1]);
defaultIcon.imageMap = (gv_icons[gv_marker_icon]['im']) ? gv_icons[gv_marker_icon]['im'] : [ 0,0, 0,gv_icons[gv_marker_icon]['is'][1]-1, gv_icons[gv_marker_icon]['is'][0]-1,gv_icons[gv_marker_icon]['is'][1]-1, gv_icons[gv_marker_icon]['is'][0]-1,0, 0,0 ];

var gv_marker_count = 0;
function GV_Marker(map,marker_info,lon,name,desc,url,color,style,width,label_id) {
	// The following variables need to have been defined:
	//   gv_icons (array of icon info), gv_icon_directory (absolute URL)
	//   gv_marker_icon (string), gv_marker_color (string), gv_marker_link_target (string)
	//   gv_api_version (number), gv_marker_list (boolean), gv_marker_list_html (string)
	
	var m = {};
	
	// The old "GV_Marker" function had everything in a particular order; this new one uses more user-friendly named parameters.
	// If the second argment has a 'lat' item INSIDE of it, then it's the new version; otherwise that's just the latitude.
	if (marker_info['lat'] || marker_info['address']) {
		m = marker_info;
		if (m['style'] && !m['icon']) { m['icon'] = m['style']; } // this one changed recently
	} else {
		m['lat'] = marker_info; m['lon'] = lon; m['name'] = name; m['desc'] = desc; m['url'] = url; m['color'] = color; m['icon'] = style; m['width'] = width; m['label_id'] = label_id;
	}
	
	if (marker_info['address'] && !marker_info['lat']) { // allow an "address" field to define the location in a pinch
		var geocoder = new GClientGeocoder();
		geocoder.getLatLng(
			marker_info['address'],
			function(coords){
				if (coords) {
					marker_info['lat'] = coords.lat(); marker_info['lon'] = coords.lng();
					GV_Marker(map,marker_info);
				}
			}
		);
		return;
	}
	
	var tempIcon = new GIcon(defaultIcon);
	var scale = (m['scale'] > 0) ? m['scale'] : 1;
	if (m['icon_url'] || (m['icon'] && m['icon'].substring(0,7) == 'http://')) {
		tempIcon.image = (m['icon_url']) ? m['icon_url'] : m['icon'];
		tempIcon.iconSize = (m['icon_size']) ? new GSize(m['icon_size'][0]*scale,m['icon_size'][1]*scale) : new GSize(32*scale,32*scale);
		tempIcon.iconAnchor = new GPoint(tempIcon.iconSize.width*scale/2,tempIcon.iconSize.height*scale/2);
		tempIcon.infoWindowAnchor = new GPoint(tempIcon.iconSize.width*0.75*scale,0);
		tempIcon.infoShadowAnchor = new GPoint(tempIcon.iconSize.width*0.5*scale,tempIcon.iconSize.height*scale);
		tempIcon.shadow = null; tempIcon.shadowSize = null; tempIcon.imageMap = null;
	} else if (m['icon'] || m['color'] || m['letter'] || m['scale'] > 0) {
		var icon = (m['icon'] && gv_icons[m['icon']]) ? m['icon'] : gv_marker_icon;
		var color = (m['color']) ? m['color'] : gv_marker_color;
		var transparent_icon = color+'-t.png';
		var base_url = (gv_icons[icon]['directory']) ? gv_icons[icon]['directory'] : gv_icon_directory+icon;
		tempIcon.image = base_url+'/'+color+'.png';
		tempIcon.iconSize = new GSize(gv_icons[icon]['is'][0]*scale,gv_icons[icon]['is'][1]*scale);
		tempIcon.iconAnchor = new GPoint(gv_icons[icon]['ia'][0]*scale,gv_icons[icon]['ia'][1]*scale);
		tempIcon.shadow = (gv_icons[icon]['ss']) ? base_url+'/shadow.png' : null;
		tempIcon.shadowSize = (gv_icons[icon]['ss']) ? new GSize(gv_icons[icon]['ss'][0]*scale,gv_icons[icon]['ss'][1]*scale) : null;
		tempIcon.infoWindowAnchor = new GPoint(gv_icons[icon]['iwa'][0]*scale,gv_icons[icon]['iwa'][1]*scale);
		tempIcon.infoShadowAnchor = new GPoint(gv_icons[icon]['isa'][0]*scale,gv_icons[icon]['isa'][1]*scale);
		if (scale != 1) { tempIcon.imageMap = new Array(); for (j=0; j<gv_icons[icon]['im'].length; j++) { tempIcon.imageMap[j] = gv_icons[icon]['im'][j]*scale; } }
		else { tempIcon.imageMap = gv_icons[icon]['im']; }
		if (m['letter']) {
			// tempIcon.label = { url:gv_icon_directory+icon+'/transparent-'+m['letter'].toUpperCase()+'.png', anchor:new GPoint(0,0), size:new GSize(gv_icons[icon]['is'][0],gv_icons[icon]['is'][1]) }; // makes big gray boxes in IE!
			tempIcon.transparent = base_url+'/transparent-'+m['letter'].toUpperCase()+'.png'; // not the most kosher solution, but it seems to work
		} else {
			tempIcon.transparent = base_url+'/'+color+'-t.png';
		}
	}
	var marker = (gv_api_version >= 2) ? new GMarker( new GLatLng(m['lat'],m['lon']), {icon:tempIcon, draggable:false} ) : new GMarker( new GPoint(m['lon'],m['lat']), tempIcon );
	var text = '';
	if (m['name']) {
		if (m['url'] && m['url'] != null) { text = text + '<b><a target="'+gv_marker_link_target+'" href="'+m['url']+'">'+m['name']+'</a></b>'; }
		else { text = text + '<b>'+m['name']+'</b>'; }
	}
	if (m['thumbnail'] && !m['photo']) {
		var thumbnail = '<img class="gv_wpt_thumbnail" src="'+m['thumbnail']+'">';
		if (m['url']) { thumbnail = '<a target="'+gv_marker_link_target+'" href="'+m['url']+'">'+thumbnail+'</A>'; }
		text = text + thumbnail;
	} else if (m['photo']) {
		text = text + '<div><img class="gv_wpt_photo" src="'+m['photo']+'"></div>';
	}
	if (m['desc']) {
		text = text + '<div>' + m['desc'] + '</div>';
	}
	var max_width = (gv_api_version >= 2) ? map.getSize().width - 100 : 600;
	var width = (eval(m['width']) > 200 && eval(m['width']) <= max_width) ? 'width:'+m['width']+'px;' : ''; // apparently you can't make it less than 217 (let's leave 17 for the close box though)
	var info_html = '<DIV style="text-align:left; '+width+'" class="gv_wpt">'+text+'</DIV>';
	if (text) { GEvent.addListener(marker, "click", function(){ marker.openInfoWindowHtml(info_html, {maxWidth:max_width}); }); }
	map.addOverlay(marker);
	
	if (m['name'] || m['thumbnail']) {
		if (m['label'] || m['label_id']) { // draw a permanent label
			var label_text = (m['label']) ? m['label'] : m['name'];
			var label = new ELabel(new GLatLng(m['lat'],m['lon']),label_text,"gv_label",new GSize(tempIcon.iconSize.width/2+1,8),100,false,m['label_id']);
			map.addOverlay(label);
		}
		if (gv_api_version >= 2) {
			// v2 tooltips, adapted from http://www.econym.demon.co.uk/googlemaps/tooltips4.htm
			if (!document.getElementById('gv_tooltip')) { tooltip = GV_Initialize_Marker_Tooltip(map); } // initialize it if it hasn't been done yet
			var tooltip_html = m['name']+' ';
			if (m['thumbnail']) { tooltip_html = tooltip_html + '<img class="gv_wpt_thumbnail" src="'+m['thumbnail']+'">'; }
			if (m['photo']) { tooltip_html = tooltip_html + '<img class="gv_wpt_photo" src="'+m['photo']+'">'; } // photo is hidden in tooltip but gets pre-loaded!
			marker.tooltip = '<div class="gv_tooltip">'+tooltip_html+'</div>';
			GEvent.addListener(marker,'mouseover', function() { GV_Create_Marker_Tooltip(map,marker); });
			GEvent.addListener(marker,'mouseout', function() { tooltip.style.visibility = 'hidden' });
		} else {
			// v1 tooltips, adapted from http://www.econym.demon.co.uk/googlemaps1/tooltips.htm
			var topElement = marker.images[0];
			if (marker.iconImage) { topElement = marker.iconImage; }
			if (marker.transparentIcon) { topElement = marker.transparentIcon; }
			if (marker.imageMap) { topElement = marker.imageMap; }
			topElement.setAttribute("title",m['name']);
		}
	}
	if (gv_api_version >= 2) {
		// This info can be used by other functions, like the "marker list":
		marker.name = (m['name']) ? m['name'] : '[unnamed]';
		marker.desc = (m['desc']) ? m['desc'] : '';
		marker.html = info_html;
		marker.max_width = max_width;
		marker.color = (m['color']) ? m['color'] : gv_marker_color;
		marker.image = tempIcon.image;
		marker.coords = new GLatLng(m['lat'],m['lon']);
		
		gv_marker_count += 1;
		
		if (gv_marker_list && m['type'] != 'tickmark' && !m['nolist']) {
			gv_marker_list_html += GV_Marker_List_Item(marker,gv_marker_list_map_name,gv_marker_array_name+'['+(gv_marker_count-1)+']');
		}
	}
	
	
	return marker;
}

function GV_Initialize_Marker_Tooltip(map) {
	var tt = document.createElement('div');
	map.getPane(G_MAP_FLOAT_PANE).appendChild(tt);
	tt.id = 'gv_tooltip';
	tt.style.visibility = 'hidden';
	return (tt);
}

function GV_Create_Marker_Tooltip(map,marker) {
	// copied almost verbatim from http://www.econym.demon.co.uk/googlemaps/tooltips4.htm
	tooltip.innerHTML = marker.tooltip;
	var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
	var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),map.getZoom());
	var anchor=marker.getIcon().iconAnchor;
	var width=marker.getIcon().iconSize.width;
	var height=tooltip.clientHeight;
	offset.x += -1; offset.y += 4; // a little adjustment
	var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y -height)); 
	pos.apply(tooltip);
	tooltip.style.visibility = 'visible';
}

function GV_Marker_List() {
	if (gv_marker_list) {
		var header = (gv_marker_list_options['header']) ? gv_marker_list_options['header'] : '';
		var footer = (gv_marker_list_options['footer']) ? gv_marker_list_options['footer'] : '';
		gv_marker_list_div.innerHTML = header+gv_marker_list_html+footer;
	}
}

function GV_Marker_List_Item(m,map_name,marker_name) {
	var default_color = (gv_marker_list_options['default_color']) ? gv_marker_list_options['default_color'] : '#000000';
	var color = (gv_marker_list_options['colors']) ? m['color'] : default_color;
	var color_style = 'color:'+color;
	
	var center = (gv_marker_list_options['center']) ? map_name+'.setCenter('+marker_name+'.coords); ' : '';
	var zoom_in = (gv_marker_list_options['zoom']) ? map_name+'.zoomIn(); ' : '';
	var hide_crosshair = (gv_marker_list_options['center'] && document.getElementById('gv_crosshair')) ? "document.getElementById('gv_crosshair').style.display = 'none'; " : '';
	var open_info_window = (gv_marker_list_options['info_window']) ? marker_name+'.openInfoWindowHtml('+marker_name+'.html,{maxWidth:'+marker_name+'.max_width}); ' : '';
	var toggle = 'GV_Toggle_Marker('+map_name+','+marker_name+',this,\''+color+'\');"';
	
	var mouseover = (m.tooltip) ? 'onMouseOver="GV_Create_Marker_Tooltip('+map_name+','+marker_name+');" ' : '';
	var mouseout = (m.tooltip) ? 'onMouseOut="tooltip.style.visibility = \'hidden\';" ' : '';
	
	var text_click = (gv_marker_list_options['toggle']) ? toggle : hide_crosshair+zoom_in+center+open_info_window;
	var icon_click = hide_crosshair+zoom_in+center+open_info_window;
	
	var icon = (gv_marker_list_options['icons']) ? '<img align="top" '+mouseover+mouseout+'onClick="'+icon_click+'" style="cursor:crosshair;" src="'+m['image']+'">&nbsp;' : '';
	var name = '<span '+mouseover+mouseout+'onClick="'+text_click+'" class="name" style="white-space:nowrap; cursor:crosshair; '+color_style+';">'+m['name'] +'<'+'/span>';
	var desc = (gv_marker_list_options['desc'] && m['desc']) ? '<br><span class="desc" style="'+color_style+'">'+m['desc']+'<'+'/span>' : '';
	var first = (gv_marker_count == 1) ? ' gv_marker_list_first_item' : '';
	return ('<div class="gv_marker_list_item'+first+'">' + '<nobr>' + icon + name + '<'+'/nobr>' + desc + '</div>'+"\n");
}

function GV_Toggle_Marker(map,marker,link,link_color,dimmed_color) {
	if (marker.gv_hidden) {
		map.addOverlay(marker);
		marker.gv_hidden = false;
	} else {
		map.removeOverlay(marker);
		marker.gv_hidden = true;
	}
	if (link && link_color) {
		link_color = Color_Hex2CSS(link_color);
		dimmed_color = (dimmed_color) ? Color_Hex2CSS(dimmed_color) : Color_Hex2CSS('#999999');
		var current_color = Color_Hex2CSS(link.style.color);
		if (link.gv_hidden) { link.style.color = link_color; link.gv_hidden = false; }
		else { link.style.color = dimmed_color; link.gv_hidden = true; }
	}
}

function GV_Toggle_Track_And_Label(map,id,color) {
	if (!color) { // older versions of this function only had two parameters
		color = id; id = map; map = gmap;
	} 
	GV_Toggle_Opacity(map,eval(id)); // this one ("trkX") is stored in a variable
	GV_Toggle_Label_Opacity(document.getElementById(id+'_label'),color); // this one ("trkX_label") is a page element
}

function GV_Toggle_Opacity(map,overlay_array) {
	if (gv_api_version >= 2) {
		if (overlay_array.gv_hidden) {
			if (!overlay_array.gv_oor) { // don't turn it on if it's "out of range"
				for (j=0; j<overlay_array.length; j++) { map.addOverlay(overlay_array[j]); }
			}
			overlay_array.gv_hidden = false;
		} else {
			for (j=0; j<overlay_array.length; j++) { map.removeOverlay(overlay_array[j]); }
			overlay_array.gv_hidden = true;
		}
	} else {
		for (j=0; j<overlay_array.length; j++) {
			var item = overlay_array[j];
			if (eval(item.drawElement)) {
				if (item.drawElement.style.display == 'none') { item.drawElement.style.display = ''; }
				else { item.drawElement.style.display = 'none'; }
			} else if (eval(item.images)) {
				for (var i=0; i < item.images.length; i++) {
					if (item.images[i].style.display == 'none') { item.images[i].style.display = ''; }
					else { item.images[i].style.display = 'none'; }
				}
			}
		}
	}
}

function GV_Toggle_Label_Opacity(label,original_color) {
	original_color = Color_Hex2CSS(original_color);
	current_color = Color_Hex2CSS(label.style.color);
	dimmed_color = Color_Hex2CSS('#999999');
//	if (current_color == dimmed_color) { label.style.color = original_color; }
//	else { label.style.color = dimmed_color; }
	if (label.gv_hidden) { label.gv_hidden = false; label.style.color = original_color; }
	else { label.gv_hidden = true; label.style.color = dimmed_color; }
}

function GV_Toggle(id) {
	if (document.getElementById(id).style.display == 'none') {
		document.getElementById(id).style.display = '';
	} else {
		document.getElementById(id).style.display = 'none';
	}
}

function GV_Filter_Tracks (map,info) {
	var min_lat = map.getBounds().getSouthWest().lat();
	var min_lon = map.getBounds().getSouthWest().lng();
	var max_lat = map.getBounds().getNorthEast().lat();
	var max_lon = map.getBounds().getNorthEast().lng();
	if (max_lon < min_lon) { min_lon = -180; max_lon = 180; } // Date Line weirdness
	for (var t in info) {
		if (info[t]['e'] < min_lon || info[t]['w'] > max_lon || info[t]['n'] < min_lat || info[t]['s'] > max_lat) {
			GV_Track_OutOfRange(map,eval(t),true);
		} else {
			GV_Track_OutOfRange(map,eval(t),false);
		}
	}
}
function GV_Track_OutOfRange (map,trk_array,is_oor) {
	if (is_oor) {
		if (!trk_array.gv_hidden) { // if it's already hidden, there's nothing to do
			for (j=0; j<trk_array.length; j++) { map.removeOverlay(trk_array[j]); }
		}
		trk_array.gv_oor = true;
	} else {
		if (trk_array.gv_oor) { // only add it if it was previously out of range
			if (!trk_array.gv_hidden) { // if it's supposed to be hidden, don't show it
				for (j=0; j<trk_array.length; j++) { map.addOverlay(trk_array[j]); }
			}
		}
		trk_array.gv_oor = false;
	}
}
function GV_Filter_Waypoints (map,wpt_array) {
	var min_lat = map.getBounds().getSouthWest().lat();
	var min_lon = map.getBounds().getSouthWest().lng();
	var max_lat = map.getBounds().getNorthEast().lat();
	var max_lon = map.getBounds().getNorthEast().lng();
	if (max_lon < min_lon) { min_lon = -180; max_lon = 180; } // Date Line weirdness
	for (j=0; j<wpt_array.length; j++) {
		var w = wpt_array[j];
		if (w.coords.lng() < min_lon || w.coords.lng() > max_lon || w.coords.lat() < min_lat || w.coords.lat() > max_lat) {
			GV_Marker_OutOfRange(map,w,true);
		} else {
			GV_Marker_OutOfRange(map,w,false);
		}
	}
}
function GV_Marker_OutOfRange (map,marker,is_oor) {
	if (is_oor) {
		if (!marker.gv_hidden) { // if it's already hidden, there's nothing to do
			map.removeOverlay(marker);
		}
		marker.gv_oor = true;
	} else {
		if (marker.gv_oor) { // only add it if it was previously out of range
			if (!marker.gv_hidden) { // if it's supposed to be hidden, don't show it
				map.addOverlay(marker);
			}
		}
		marker.gv_oor = false;
	}
}

function GV_Show_Center_Coordinates(map,id) {
	if (document.getElementById(id)) {
		var lat = map.getCenter().lat().toFixed(5);
		var lng = map.getCenter().lng().toFixed(5);
		document.getElementById(id).innerHTML = "Center: "+lat+","+lng;
	}
}

var gv_map_is_new = true;
function GV_Show_Hidden_Crosshair(map,id) {
	// only do something upon the FIRST movement of the map!
	if (self.gv_map_is_new) {
		document.getElementById(id).style.display = 'block';
		gv_map_is_new = false;
	}
}

function GV_Recenter_Crosshair(map,container_id,crosshair_size) {
	if (document.getElementById(container_id)) {
		document.getElementById(container_id).style.position = 'absolute';
		document.getElementById(container_id).style.top = Math.round(map.getContainer().clientHeight/2-(crosshair_size/2))+'px';
		document.getElementById(container_id).style.left = Math.round(map.getContainer().clientWidth/2-(crosshair_size/2))+'px';
	}
}

function GV_MouseWheel(e) {
	if (e.detail) { // Firefox
		if (e.detail < 0) { gmap.zoomIn(); }
		else if (e.detail > 0) { gmap.zoomOut(); }
	} else if (e.wheelDelta) { // IE
		if (e.wheelDelta > 0) { gmap.zoomIn(); }
		else if (e.wheelDelta < 0) { gmap.zoomOut(); }
	}
}

function Color_Hex2CSS(c) {
	if (c == null) { return null; }
	var rgb = new Array(); rgb = c.match(/([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})/i);
	if (rgb) {
		return ('rgb('+parseInt(rgb[1],16)+','+parseInt(rgb[2],16)+','+parseInt(rgb[3],16)+')');
	} else {
		return (c.replace(/ +/g,''));
	}
}
function Color_Name2Hex(color_name) {
	var c = new Array();
	c['aqua'] = '#00FFFF'; c['black'] = '#000000'; c['blue'] = '#0000FF'; c['brown'] = '#7A4328';
	c['cyan'] = '#00FFFF'; c['default'] = '#FF776B'; c['fuchsia'] = '#FF00FF'; c['gray'] = '#AAAAAA';
	c['green'] = '#009900'; c['grey'] = '#AAAAAA'; c['lime'] = '#00FF00'; c['magenta'] = '#FF00FF';
	c['maroon'] = '#800000'; c['navy'] = '#000080'; c['olive'] = '#808000'; c['orange'] = '#FF6600';
	c['pink'] = '#FF99CC'; c['purple'] = '#990099'; c['red'] = '#FF0000'; c['silver'] = '#808080';
	c['tan'] = '#C1945F'; c['teal'] = '#008080'; c['violet'] = '#6600FF'; c['white'] = '#FFFFFF';
	c['yellow'] = '#FFFF00';
	if (c[color_name]) { return c[color_name]; } else { return ''; }
}



/**************************************************
 * Custom map layers:
 * Adapted from Jef Poskanzer's Acme Mapper
 * (http://mapper.acme.com/)
 **************************************************/
if (gv_api_version >= 2) {
	var USGS_TOPO_TILES = WMSCreateMap('Topo','Topo maps by USGS via terraserver-usa.com','Topo maps unavailable',5,17,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DRG');
	var USGS_AERIAL_TILES = WMSCreateMap('Aerial','Imagery by USGS via terraserver-usa.com','USGS aerial imagery unavailable',7,18,400,'http://terraservice.net/ogcmap6.ashx?version=1.1.1&request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&bgcolor=0xCCCCCC&exceptions=INIMAGE&layers=DOQ');
	var NRCAN_TOPO_TILES = WMSCreateMap('NRCan','Maps by NRCan.gc.ca','NRCan maps unavailable',6,18,600,'http://wms.cits.rncan.gc.ca/cgi-bin/cubeserv.cgi?version=1.1.3&request=GetMap&format=image/png&bgcolor=0xFFFFFF&exceptions=application/vnd.ogc.se_inimage&srs=EPSG:4326&layers=PUB_50K:CARTES_MATRICIELLES/RASTER_MAPS');
	var BLUEMARBLE_TILES = WMSCreateMap('BlueMarble','Map by NASA','OnEarth server unavailable',3,8,128,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=modis');
	var DAILY_TERRA_TILES = WMSCreateMap('"Terra"','Map by NASA','OnEarth server unavailable',3,10,256,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=daily_terra');
	var DAILY_AQUA_TILES = WMSCreateMap('"Aqua"','Map by NASA','OnEarth server unavailable',3,10,256,'http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&styles=&srs=EPSG:4326&format=image/jpeg&layers=daily_aqua');
}

function GV_Add_Custom_Layers(map) {
	map.addMapType(USGS_TOPO_TILES);
	map.addMapType(USGS_AERIAL_TILES);
	map.addMapType(NRCAN_TOPO_TILES);
	map.addMapType(BLUEMARBLE_TILES);
	map.addMapType(DAILY_TERRA_TILES);
	map.addMapType(DAILY_AQUA_TILES);
}

function WMSCreateMap(name,copyright,errorMessage,minResolution,maxResolution,tileSize,baseUrl) {
	var tileLayer = new GTileLayer(new GCopyrightCollection(copyright),minResolution,maxResolution);
	tileLayer.baseUrl = baseUrl;
	tileLayer.tileSize = tileSize;
	tileLayer.getTileUrl = WMSGetTileUrl;
	tileLayer.getCopyright = function() { return { prefix:'',copyrightTexts:[copyright]}; };
	var tileLayers = [tileLayer];
	return new GMapType(tileLayers,G_SATELLITE_MAP.getProjection(),name,{errorMessage:errorMessage,tileSize:tileSize});
}
function WMSGetTileUrl(tile,zoom) {
	var southWestPixel = new GPoint(tile.x*this.tileSize,(tile.y+1)*this.tileSize);
	var northEastPixel = new GPoint((tile.x+1)*this.tileSize,tile.y*this.tileSize);
	var southWestCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(southWestPixel,zoom);
	var northEastCoords = G_SATELLITE_MAP.getProjection().fromPixelToLatLng(northEastPixel,zoom);
	var bbox = southWestCoords.lng()+','+southWestCoords.lat()+','+northEastCoords.lng()+','+northEastCoords.lat();
	return this.baseUrl+'&bbox='+bbox+'&width='+this.tileSize+'&height='+this.tileSize;
}


/**************************************************
 * Custom map-type control:
 * more or less from Google's own documentation
 **************************************************/
function GV_MapTypeControl() {}
if (gv_api_version >= 2) {
	GV_MapTypeControl.prototype = new GControl();
	GV_MapTypeControl.prototype.initialize = function(map) {
		GV_Add_Custom_Layers(map);
		var map_types = [
			{ label:'G. map',type:'G_NORMAL_MAP',title:'Google street map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'G. satellite',type:'G_SATELLITE_MAP',title:'Google satellite map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'G. hybrid',type:'G_HYBRID_MAP',title:'Google "hybrid" map',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'USGS topo',type:'USGS_TOPO_TILES',title:'USGS topographic map',bounds:[-169,18,-66,72],excluded:[] }
			,{ label:'USGS aerial',type:'USGS_AERIAL_TILES',title:'USGS aerial photos (black/white)',bounds:[-152,17,-65,65],excluded:[] }
			,{ label:'Canada topo',type:'NRCAN_TOPO_TILES',title:'NRCan/Toporama maps with contour lines',bounds:[-141,41.7,-52,85],excluded:[-141,41.7,-86,48] }
			,{ label:'Blue Marble',type:'BLUEMARBLE_TILES',title:'NASA "Visible Earth" image',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'Daily "Terra"',type:'DAILY_TERRA_TILES',title:'Daily imagery from "Terra" satellite',bounds:[-180,-90,180,90],excluded:[] }
			,{ label:'Daily "Aqua"',type:'DAILY_AQUA_TILES',title:'Daily imagery from "Aqua" satellite',bounds:[-180,-90,180,90],excluded:[] }
		];
		var center_lat = map.getCenter().lat();
		var center_lng = map.getCenter().lng();
		
		if (gv_maptypecontrol_style == 'menu') {
			var map_selector = document.createElement("select");
			map_selector.id = 'map_selector';
			map_selector.style.font = '10px Verdana';
			map_selector.style.backgroundColor = '#FFFFFF';
			for (j=0; j<map_types.length; j++) {
				if (!gv_filter_map_types || gv_filter_map_types < 0 || ( (center_lng >= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3]) && !(center_lng >= map_types[j]['excluded'][0] && center_lat >= map_types[j]['excluded'][1] && center_lng <= map_types[j]['excluded'][2] && center_lat <= map_types[j]['excluded'][3]) ) ) {
					var opt = document.createElement("option");
					opt.value = map_types[j]['type'];
					opt.appendChild(document.createTextNode(map_types[j]['label']));
					map_selector.appendChild(opt);
					if (map.getCurrentMapType() == eval(opt.value)) { map_selector.selectedIndex = map_selector.length - 1; }
				}
			}
			GEvent.addDomListener(map_selector, "change", function(){map.setMapType(eval(this.value));} );
			map.getContainer().appendChild(map_selector);
			return map_selector;
		} else {
			var map_type_container = document.createElement("div");
			for (j=0; j<map_types.length; j++) {
				if (!gv_filter_map_types || gv_filter_map_types < 0 || ( (center_lng >= map_types[j]['bounds'][0] && center_lat >= map_types[j]['bounds'][1] && center_lng <= map_types[j]['bounds'][2] && center_lat <= map_types[j]['bounds'][3]) && !(center_lng >= map_types[j]['excluded'][0] && center_lat >= map_types[j]['excluded'][1] && center_lng <= map_types[j]['excluded'][2] && center_lat <= map_types[j]['excluded'][3]) ) ) {
					var maplink = document.createElement("div");
					maplink.className = 'gv_maptypelink';
					if (self.gv_maptypecontrol && map.getCurrentMapType() == eval(map_types[j]['type'])) {
						maplink.className = 'gv_maptypelink gv_maptypelink_selected';
					}
					maplink.title = map_types[j]['title'];
					maplink.type = map_types[j]['type'];
					map_type_container.appendChild(maplink);
					maplink.appendChild(document.createTextNode(map_types[j]['label']));
					GEvent.addDomListener(maplink, "click", function(){
						map.setMapType(eval(this.type));
						if (self.gv_maptypecontrol) {
							map.removeControl(gv_maptypecontrol);
							map.addControl(gv_maptypecontrol);
						}
					} );
				}
			}
			map.getContainer().appendChild(map_type_container);
			return map_type_container;
		}
	}
	GV_MapTypeControl.prototype.getDefaultPosition = function() {
		return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,7));
	}
}

// These are here only for backwards compatibilty:
function GPSV_Waypoint(lon,lat,name,desc,url,color,style,width,label_id) { GV_Marker(gmap,lat,lon,name,desc,url,color,style,width,label_id); }
function GPSV_Toggle_Track_And_Label(id,color) { GV_Toggle_Track_And_Label(id,color); } // for backwards compatibility
function GPSV_Toggle_Opacity(overlay_array) { GV_Toggle_Opacity(overlay_array); } // for backwards compatibility
function GPSV_Toggle_Label_Opacity(label,original_color) { GV_Toggle_Label_Opacity(label,original_color); } // for backwards compatibility
function GPSV_MapTypeControl() {}
if (gv_api_version >= 2) { GPSV_MapTypeControl.prototype = GV_MapTypeControl.prototype; }





function GV_Get_Cached_Addresses(map,opts) {
	var SW = map.getBounds().getSouthWest(); var NE = map.getBounds().getNorthEast();
	var lat_center = map.getCenter().lat().toFixed(7);
	var lon_center = map.getCenter().lng().toFixed(7);
	
	var moved_enough = true;
	if (self.gv_last_center && self.gv_last_radius) {
		if (map.getCenter().distanceFrom(gv_last_center) < gv_last_radius*0.4) {
			moved_enough = false;
		}
	}
	if (moved_enough) {
		for (var i = 0; i < gv_dynamic_markers.length; i++) { map.removeOverlay(gv_dynamic_markers[i]); }
		gv_marker_count = 0;
		gv_dynamic_markers.length = 0; // this is important!
		if (gv_marker_list) {
			document.getElementById(gv_marker_list_div_name).innerHTML = 'Loading markers...';
			gv_marker_list_html = '';
		}
		var url = '/google_maps/cached_addresses.cgi?lat_center='+lat_center+'&lon_center='+lon_center+'&lat_min='+SW.lat().toFixed(7)+'&lat_max='+NE.lat().toFixed(7)+'&lon_min='+SW.lng().toFixed(7)+'&lon_max='+NE.lng().toFixed(7)+'&quota='+gv_dynamic_markers_quota;
		GDownloadUrl(url, function(data, responseCode) {
			var xml = GXml.parse(data);
			var marker_tags = xml.documentElement.getElementsByTagName("marker");
			for (var i = 0; i < marker_tags.length; i++) {
				var this_color = (marker_tags[i].getAttribute("color")) ? marker_tags[i].getAttribute("color") : '';
				var this_label = (opts['labels']) ? marker_tags[i].getAttribute("name") : '';
				var m = GV_Marker(map,{
					lat:marker_tags[i].getAttribute("lat"),
					lon:marker_tags[i].getAttribute("lon"),
					name:marker_tags[i].getAttribute("name"),
					desc:marker_tags[i].getAttribute("desc"),
					color:this_color,
					label:this_label
				});
				gv_dynamic_markers.push(m);
			}
			gv_last_radius = 0.7 * map.getCenter().distanceFrom(map.getBounds().getSouthWest()); // in case the XML doesn't have a radius
			if (opts['circle']) {
				var trackpoints = xml.documentElement.getElementsByTagName("trkpt");
				if (trackpoints.length) {
					var tracks = xml.documentElement.getElementsByTagName("trk"); gv_last_radius = tracks[0].getAttribute("radius");
					var pts = new Array();
					for (var i = 0; i < trackpoints.length; i++) {
						pts.push( new GLatLng(trackpoints[i].getAttribute("lat"),trackpoints[i].getAttribute("lon")) );
					}
					var circle_color = (gv_marker_color) ? gv_marker_color : 'white';
					gv_dynamic_markers.push (new GPolyline(pts,Color_Name2Hex(circle_color),2,0.2));
					map.addOverlay(gv_dynamic_markers[gv_dynamic_markers.length-1]);
				}
			}
			if (gv_marker_list) {
				GV_Marker_List();
			}
		});
		gv_last_center = map.getCenter();
	}
}


function GV_Get_Dynamic_Markers(map,opts) {
	if (!self.gv_dynamic_markers || !opts['db']) { return; }
	
	var SW = map.getBounds().getSouthWest(); var NE = map.getBounds().getNorthEast();
	var lat_center = map.getCenter().lat().toFixed(7);
	var lon_center = map.getCenter().lng().toFixed(7);
	
	var moved_enough = true;
	if (self.gv_last_center && self.gv_last_radius) {
		if (map.getCenter().distanceFrom(gv_last_center) < gv_last_radius*0.4) {
			moved_enough = false;
		}
	}
	if (moved_enough) {
		for (var i = 0; i < gv_dynamic_markers.length; i++) { map.removeOverlay(gv_dynamic_markers[i]); }
		gv_marker_count = 0;
		gv_dynamic_markers.length = 0; // this is important!
		if (gv_marker_list) {
			document.getElementById(gv_marker_list_div_name).innerHTML = 'Loading markers...';
			gv_marker_list_html = '';
		}
		var fields = (opts['fields']) ? opts['fields'] : 'name,description,latitude,longitude';
		var sort = (opts['sort']) ? opts['sort'] : '';
		var url = '/google_maps/dynamic_markers.cgi?db='+opts['db']+'&fields='+fields+'&lat_center='+lat_center+'&lon_center='+lon_center+'&lat_min='+SW.lat().toFixed(7)+'&lat_max='+NE.lat().toFixed(7)+'&lon_min='+SW.lng().toFixed(7)+'&lon_max='+NE.lng().toFixed(7)+'&quota='+gv_dynamic_markers_quota+'&sort='+sort;
		GDownloadUrl(url, function(data, responseCode) {
			var xml = GXml.parse(data);
			var marker_tags = xml.documentElement.getElementsByTagName("marker");
			for (var i = 0; i < marker_tags.length; i++) {
				var this_color = (marker_tags[i].getAttribute("color")) ? marker_tags[i].getAttribute("color") : '';
				var this_icon = (marker_tags[i].getAttribute("icon")) ? marker_tags[i].getAttribute("icon") : '';
				var this_label = (marker_tags[i].getAttribute("label")) ? marker_tags[i].getAttribute("label") : marker_tags[i].getAttribute("name");
				this_label = (opts['labels']) ? this_label : '';
				var m = GV_Marker(map,{
					lat:marker_tags[i].getAttribute("lat"),
					lon:marker_tags[i].getAttribute("lon"),
					name:marker_tags[i].getAttribute("name"),
					desc:marker_tags[i].getAttribute("desc"),
					color:this_color,
					icon:this_icon,
					label:this_label
				});
				gv_dynamic_markers.push(m);
			}
			gv_last_radius = 0.7 * map.getCenter().distanceFrom(map.getBounds().getSouthWest()); // in case the XML doesn't have a radius
			if (opts['circle']) {
				var trackpoints = xml.documentElement.getElementsByTagName("trkpt");
				if (trackpoints.length) {
					var tracks = xml.documentElement.getElementsByTagName("trk"); gv_last_radius = tracks[0].getAttribute("radius");
					var pts = new Array();
					for (var i = 0; i < trackpoints.length; i++) {
						pts.push( new GLatLng(trackpoints[i].getAttribute("lat"),trackpoints[i].getAttribute("lon")) );
					}
					var circle_color = (gv_marker_color) ? gv_marker_color : 'white';
					gv_dynamic_markers.push (new GPolyline(pts,Color_Name2Hex(circle_color),2,0.2));
					map.addOverlay(gv_dynamic_markers[gv_dynamic_markers.length-1]);
				}
			}
			if (gv_marker_list) {
				document.getElementById(gv_marker_list_div_name).innerHTML = '';
				GV_Marker_List();
			}
		});
		gv_last_center = map.getCenter();
	}
}





/**************************************************
elabel.js
(adapted from http://www.econym.demon.co.uk/googlemaps/elabel.htm)
(My modification: adding the "label_id" parameter)
**************************************************/

function ELabel(point, html, classname, pixelOffset, percentOpacity, overlap, label_id) {
	// Mandatory parameters
	this.point = point;
	this.html = html;
	
	// Optional parameters
	this.classname = classname || "";
	this.pixelOffset = pixelOffset || new GSize(0,0);
	if (percentOpacity) {
		if (percentOpacity < 0) { percentOpacity = 0; }
		if (percentOpacity > 100) { percentOpacity = 100; }
	}
	this.percentOpacity = percentOpacity;
	this.overlap = overlap || false;
	this.label_id = label_id;
}

if (gv_api_version >= 2) {
	ELabel.prototype = new GOverlay();
	
	ELabel.prototype.initialize = function (map) {
		var div = document.createElement("div");
		div.style.position = "absolute";
		div.innerHTML = '<div id = "' + this.label_id + '" class="' + this.classname + '">' + this.html + '</div>' ;
		map.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(div);
		this.map_ = map;
		this.div_ = div;
		if (this.percentOpacity) {
			if (typeof(div.style.filter) == 'string') { div.style.filter='alpha(opacity:'+this.percentOpacity+')'; }
			if (typeof(div.style.KHTMLOpacity) == 'string') { div.style.KHTMLOpacity=this.percentOpacity/100; }
			if (typeof(div.style.MozOpacity) == 'string') { div.style.MozOpacity=this.percentOpacity/100; }
			if (typeof(div.style.opacity) == 'string') { div.style.opacity=this.percentOpacity/100; }
		}
		if (this.overlap) {
			var z = GOverlay.getZIndex(this.point.lat());
			this.div_.style.zIndex = z;
		}
	}
	
	ELabel.prototype.remove = function() {
		this.div_.parentNode.removeChild(this.div_);
	}
	
	ELabel.prototype.copy = function() {
		return new ELabel(this.point, this.html, this.classname, this.pixelOffset, this.percentOpacity, this.overlap);
	}
	
	ELabel.prototype.redraw = function(force) {
		var p = this.map_.fromLatLngToDivPixel(this.point);
		var h = parseInt(this.div_.clientHeight);
		this.div_.style.left = (p.x + this.pixelOffset.width) + "px";
		this.div_.style.top = (p.y +this.pixelOffset.height - h) + "px";
	}
	
	ELabel.prototype.show = function() {
		this.div_.style.display="";
	}
	
	ELabel.prototype.hide = function() {
		this.div_.style.display="none";
	}
	
	ELabel.prototype.setContents = function(html) {
		this.html = html;
		this.div_.innerHTML = '<div id = "' + this.label_id + '" class="' + this.classname + '">' + this.html + '</div>' ;
		this.redraw(true);
	}
	
	ELabel.prototype.setPoint = function(point) {
		this.point = point;
		if (this.overlap) {
			var z = GOverlay.getZIndex(this.point.lat());
			this.div_.style.zIndex = z;
		}
		this.redraw(true);
	}
	
	ELabel.prototype.setOpacity = function(percentOpacity) {
		if (percentOpacity) {
			if (percentOpacity < 0) { percentOpacity=0; }
			if (percentOpacity > 100) { percentOpacity=100; }
		}
		this.percentOpacity = percentOpacity;
		if (this.percentOpacity) {
			if (typeof(this.div_.style.filter) == 'string') { this.div_.style.filter='alpha(opacity:'+this.percentOpacity+')'; }
			if (typeof(this.div_.style.KHTMLOpacity) == 'string') { this.div_.style.KHTMLOpacity=this.percentOpacity/100; }
			if (typeof(this.div_.style.MozOpacity) == 'string') { this.div_.style.MozOpacity=this.percentOpacity/100; }
			if (typeof(this.div_.style.opacity) == 'string') { this.div_.style.opacity=this.percentOpacity/100; }
		}
	}
}

/**************************************************
 * dom-drag.js
 * 09.25.2001
 * www.youngpup.net
 * Script featured on Dynamic Drive (http://www.dynamicdrive.com) 12.08.2005
 **************************************************
 * 10.28.2001 - fixed minor bug where events
 * sometimes fired off the handle, not the root.
 **************************************************/
var Drag = {

	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
		o.onmousedown	= Drag.start;

		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e) {
		var o = Drag.obj = this;
		e = Drag.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}

		document.onmousemove	= Drag.drag;
		document.onmouseup		= Drag.end;

		return false;
	},

	drag : function(e) {
		e = Drag.fixE(e);
		var o = Drag.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		Drag.obj.lastMouseX	= ex;
		Drag.obj.lastMouseY	= ey;

		Drag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function() {
		document.onmousemove = null;
		document.onmouseup   = null;
		Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
									parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
		Drag.obj = null;
	},

	fixE : function(e) {
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
};



function IE_PNG() { // correctly handle PNG transparency in Win IE 5.5 & 6.
	var arVersion = navigator.appVersion.split("MSIE")
	var version = parseFloat(arVersion[1])
	if ((version >= 5.5) && (document.body.filters)) {
		for(var i=0; i<document.images.length; i++) {
			var img = document.images[i]
			var imgName = img.src.toUpperCase()
			if (imgName.substring(imgName.length-3, imgName.length) == "PNG") {
				var imgID = (img.id) ? "id='" + img.id + "' " : "";
				var imgClass = (img.className) ? "class='" + img.className + "' " : "";
				var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
				var imgStyle = "display:inline-block;" + img.style.cssText;
				if (img.align == "left") { imgStyle = "float:left;" + imgStyle; }
				if (img.align == "right") { imgStyle = "float:right;" + imgStyle; }
				if (img.parentElement.href) { imgStyle = "cursor:hand;" + imgStyle; }
				var strNewHTML = "<span " + imgID + imgClass + imgTitle
				  + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
				  + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
				  + "(src=\'" + img.src + "\', sizingMethod='image');\"></span>" ;
				img.outerHTML = strNewHTML;
				i = i-1;
			}
		}
	}
}


function FindGoogleAPIVersion() {
	var v = 2;
	var scripts = document.getElementsByTagName("script")
	for (var i=0; i<scripts.length; i++) {
		var pattern = /\/maps([0-9])?(\.?[0-9]+)(\.api)?\.js/;
		var m = pattern.exec(scripts[i].src);
		if (m != null) {
			if (m[1] == null) { v = parseFloat('1'+m[2]); }
			else { v = parseFloat(m[1]+m[2]); }
			break;
		}
	}
	return v;
}



