if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    }
}

var SJJS = {
	parent:true,
	using: function(ns) {
		var _namespacearray = ns.split(".");
		var x, _namespacepointer = SJJS;

		for (x = 1; x < _namespacearray.length; x++)
		{
			_namespacepointer = _namespacepointer[_namespacearray[x]];
		}
		if (!_namespacepointer.parent)
		{
			eval(_namespacearray[_namespacearray.length - 1] + " = " + ns + ";");
		} else {
			for (x in _namespacepointer)
			{
				eval(x + " = " + ns + "." + x + ";");
			}
		}
	},
	init: function() {
		SJJS.GMap.Overlays.GeoLabel.prototype = new google.maps.Overlay();
		SJJS.GMap.Controls.Label.prototype = new google.maps.Overlay();
		SJJS.GMap.Controls.GLegend.prototype = new google.maps.Control();
		SJJS.GMap.Controls.GList.prototype = new google.maps.Control();
		SJJS.GMap.Controls.GMenuBar.prototype = new google.maps.Control();
		if (SJJS.pageInstance && SJJS.pageInstance.onLoad) {
			SJJS.pageInstance.onLoad();
		}
	},
	util:{
		parent:true,
		getBodyHeight: function() {
			return window.innerHeight || (document.documentElement.clientHeight || document.body.clientHeight);
		},
		getBodyWidth: function() {
			return window.innerWidth || (document.documentElement.clientWidth || document.body.clientWidth);
		},
		encodeUrl: function(postdata) {
			var _newdata = "";

			for (var x = 0; x < postdata.length; x++) {
				var _char = postdata.charCodeAt(x);
				if (!((_char > 47 && _char < 58) || (_char > 64 && _char < 91) || (_char > 96 && _char < 123))) {
					h = _char.toString(16);
					_newdata += "%" + h.toUpperCase();
				} else {
					_newdata += postdata.charAt(x);
				}
			}

			return _newdata;
		},
		download: function(url, onload, postdata, contenttype) {
			var r;
			if (typeof ActiveXObject != 'undefined') {
				r = new ActiveXObject('Microsoft.XMLHTTP');
			} else if (window["XMLHttpRequest"]) {
				r = new XMLHttpRequest();
			}

			if (r)
			{
				if (r.overrideMimeType) {
					//r.overrideMimeType("text/html");
				}
				r.onreadystatechange = function() {
					if (r.readyState === 4) {
						if (r.status === 200) {
							onload(r.responseText, r.status);
							delete r.onreadystatechange;
						}
					}
				}
				if (postdata) {
					r.open("POST", url, true);
					if (contenttype) {
						r.setRequestHeader("Content-Type", contenttype);		
					} else {
						r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					}
					r.send(postdata);
				} else {
					r.open("GET", url, true);
					r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
					r.send("");
				}
			}
		},
		getCookie: function(name) {
			var _cs, _ce, _ct, _ar = [];
			if (document.cookie.length > 0) {
				var _cs = document.cookie.indexOf(name + "=");
				if (_cs != -1) {
					_cs += name.length + 1; 
					_ce = document.cookie.indexOf(";",_cs);
					if (_ce === -1) {
						_cd = document.cookie.length;
					}
					_ct = document.cookie.substring(_cs, _ce);
		  			_ar = _ct.split("|");
				} 
			}
			return _ar;
		},
		setCookie: function(name, values) {
			var _ct = name + "=";
			var _d = new Date();
			for (var x = 0; x < values.length; x++) {
				_ct += values[x] + "|";
			}
			_d.setDate(_d.getDate()+356);
			_ct += ";expires=" + _d.toGMTString();
			document.cookie = _ct;
		}
	},
	dom:{
		parent:true,
		controls:{parent:true}
	},
	map:{
		parent:true,
		getType: function() {
			return "Gv2";
		},
		createMap: function(type, divname, options) {
			var _map;
			var _type = SJJS.map.getType();

			if (!options) {
				options = {};
			}
			switch (type) {
				case "VE":
					break;
				case "GE":
					break;
				case "Gv2":
					if (google.maps.BrowserIsCompatible()) {
						_map = new google.maps.Map2(document.getElementById(divname));
						if (!options.center) {
							options.center = new google.maps.LatLng(37.313477473067, -121.880502070713);
						}
						if (!options.zoom) {
							options.zoom = 11;
						}
						_map.setCenter(options.center, options.zoom);
						_type = type;
						return _map;
					} else {
						return null;
					}
					break;
				case "Gv3":
					break;
			}

			SJJS.map.getType = function () { return _type; };
		},
		createIcon: function(opts) {
			//Altered version of function originally created by Pamela Fox of Google, http://gmaps-utility-library.googlecode.com/svn/trunk/mapiconmaker/1.1/src/mapiconmaker.js
			var width = opts.width || 32;
			var height = opts.height || 32;
			var primaryColor = opts.primaryColor || "#ff0000";
			var strokeColor = opts.strokeColor || "#000000";
			var cornerColor = opts.cornerColor || "#ffffff";
			var icon;
			   
			var baseUrl = "http://chart.apis.google.com/chart?cht=mm";
			var iconUrl = baseUrl + "&chs=" + width + "x" + height + 
				"&chco=" + cornerColor.replace("#", "") + "," + 
				primaryColor.replace("#", "") + "," + 
				strokeColor.replace("#", "");

			if (SJJS.map.getType && SJJS.map.getType() === "Gv2") {
				icon = new google.maps.Icon(G_DEFAULT_ICON);
	
				icon.image = iconUrl + "&ext=.png";
				icon.iconSize = new google.maps.Size(width, height);
				icon.shadowSize = new google.maps.Size(Math.floor(width * 1.6), height);
				icon.iconAnchor = new google.maps.Point(width / 2, height);
				icon.infoWindowAnchor = new google.maps.Point(width / 2, Math.floor(height / 12));
				icon.printImage = iconUrl + "&chof=gif";
				icon.mozPrintImage = iconUrl + "&chf=bg,s,ECECD8" + "&chof=gif";
				iconUrl = baseUrl + "&chs=" + width + "x" + height + 
					"&chco=" + cornerColor.replace("#", "") + "," + 
					primaryColor.replace("#", "") + "," + 
					strokeColor.replace("#", "");
				icon.transparent = iconUrl + "&chf=a,s,ffffff11&ext=.png";
				
				icon.imageMap = [
					width / 2, height,
					(7 / 16) * width, (5 / 8) * height,
					(5 / 16) * width, (7 / 16) * height,
					(7 / 32) * width, (5 / 16) * height,
					(5 / 16) * width, (1 / 8) * height,
					(1 / 2) * width, 0,
					(11 / 16) * width, (1 / 8) * height,
					(25 / 32) * width, (5 / 16) * height,
					(11 / 16) * width, (7 / 16) * height,
					(9 / 16) * width, (5 / 8) * height
				];
				for (var i = 0; i < icon.imageMap.length; i++) {
					icon.imageMap[i] = parseInt(icon.imageMap[i]);
				}
			} else if (SJJS.map.getType && SJJS.map.getType() === "Gv3") {
				icon = new google.maps.MarkerImage(iconUrl + "&ext=.png", new google.maps.Size(width, height));
			}
			
			return icon;
		},
		createCircle: function(lat, lng, options) {
			if (!options.color) {
				options.color = "#007700";
			}
			if (!options.width) {
				options.width = 3;
			}
			if (!options.transparency) {
				options.transparency = 0.4;
			}
			if (!options.sides) {
				options.sides = 36;
			}
			var _d2r = Math.PI/180;
			var _r2d = 180/Math.PI;
			var _start = 0;

			if (options.sides%2 == 1) { 
				_start = (0.5 - 2/options.sides) * Math.PI; 
			} else { 
				_start = (0.5 - 1/options.sides) * Math.PI; 
			}
			var _lat = (options.miles/3963)*_r2d;	 // using 3963 miles as earth's radius 
			var _lng = _lat/Math.cos(lat*_d2r); 
			var _points = []; 
			var _theta;
			var i;
			for (i = -1; i < options.sides; i++) { 
				_theta = 2*i*Math.PI/options.sides + _start; 
				x = lng + (_lng * Math.cos(_theta)); 
				y = lat + (_lat * Math.sin(_theta)); 
				_points.push(new google.maps.Point(x,y)); 
			};
			return new google.maps.Polyline(_points,options.color,options.width,options.transparency);
		},
		createMarker: function(latlng, style, opts) {
			
		}
	},
	GMap:{
		parent:true,
		Overlays:{parent:true},
		Controls:{parent:true},
		createCircle: function(lat, lng, options) {
			if (!options.miles) {
				options.miles = 2;
			}
			if (!options.color) {
				options.color = "#007700";
			}
			if (!options.width) {
				options.width = 3;
			}
			if (!options.transparency) {
				options.transparency = 0.4;
			}
			if (!options.sides) {
				options.sides = 36;
			}
			var _d2r = Math.PI/180;
			var _r2d = 180/Math.PI;
			var _start = 0;

			if (options.sides%2 == 1) { 
				_start = (0.5 - 2/options.sides) * Math.PI; 
			} else { 
				_start = (0.5 - 1/options.sides) * Math.PI; 
			}
			var _lat = (options.miles/3963)*_r2d;	 // using 3963 miles as earth's radius 
			var _lng = _lat/Math.cos(lat*_d2r); 
			var _points = []; 
			var _theta;
			var i;
			for (i = -1; i < options.sides; i++) { 
				_theta = 2*i*Math.PI/options.sides + _start; 
				x = lng + (_lng * Math.cos(_theta)); 
				y = lat + (_lat * Math.sin(_theta)); 
				_points.push(new google.maps.Point(x,y)); 
			};
			return new google.maps.Polyline(_points,options.color,options.width,options.transparency);
		}
	}
};

//Event class

SJJS.util.Event = (function() {
	var _listeners = [];
	var _listenerReturns = [];

	return {
		addDomListener: function(element, eventName, listener) {
			if (element.addEventListener) // most browsers
				element.addEventListener(eventName, listener, true);
			else if (element.attachEvent) // IE
				element.attachEvent('on' + eventName, listener);
			_listeners.push({type:"DOM", element: element, name: eventName, listener: listener});
			_listenerReturns.push({});
			return _listenerReturns[_listenerReturns.length - 1];
		},
		addListener: function(element, eventName, listener) {
			_listeners.push({type:"DOM", element: element, name: eventName, listener: listener});
			_listenerReturns.push({});
			return _listenerReturns[_listenerReturns.length - 1];
		},
		trigger: function(element, eventName) {
			var x;
			var _args = [];
			var _eventindex = -1;
	
			for (x = 0; x < _listeners.length; x++)
			{
				if (_listeners[x].element === element && _listeners[x].name === eventName)
				{
					_eventindex = x;
				}
			}
			if (_eventindex > -1)
			{
				if (arguments.length > 2)
				{
					for (x = 2; x < arguments.length; x++) {
						_args.push(arguments[x]);
					}
					_listeners[_eventindex].listener.apply(_listeners[_eventindex].element, _args);
				}
				else
				{
					_listeners[_eventindex].listener.apply(_listeners[_eventindex].element, []);
				}
			}
		},
		removeListener: function(eventlistener) {
			var x;
			var _eventindex = _listenerReturns.indexOf(eventlistener);
	
			if (_eventindex > -1)
			{
				if (eventlistener.type === "DOM")
				{
					if (eventlistener.element.removeEventListener) // most browsers
						eventlistener.element.removeEventListener(eventlistener.name, eventlistener.listener, false);
					else if (eventlistener.element.detachEvent) // IE
						eventlistener.element.detachEvent('on' + eventlistener.name, eventlistener.listener);
				}
				_listeners[_eventindex] = undefined;
				_listeners.splice(_eventindex, 1);
				_listenerReturns[_eventindex] = undefined;
				_listenerReturns.splice(_eventindex, 1);
			}
		}
	}
})();

SJJS.util.Event.addDomListener(window, "load", SJJS.init);

//Color class, provides various functionality for creating and manipulating colors
SJJS.util.Color = (function(){
	var _color = function() {
		var me = this;
		var _r = 0;
		var _g = 0;
		var _b = 0;
		var _hex = 0;
		var _h = 0;
		var _s = 0;
		var _l = 0;
	
		function _d2h(d) {
			var h2r = d.toString(16).toUpperCase();
			if (h2r.length === 1) {
				h2r = "0" + h2r;
			}
			return h2r;
		}
	
		function _h2d(h) {return parseInt(h,16);} 
	
		function _RGBToHSL()
		{
			//Normalize rgb values
			var r = _r / 255;
			var g = _g / 255;
			var b = _b / 255;
		
			//Determine the minimum and maximum values from the normalized rgb values
			var min = Math.min(r, Math.min(g, b)), max = Math.max(r, Math.max(g, b));
		
			//Determine the hue value
			if (max === min)
			{
				_h = 0;
			}
			else if (max === r && g >= b)
			{
				_h = 60 * ((g - b) / (max - min)) + 0;
			}
			else if (max === r && g < b)
			{
				_h = 60 * ((g - b) / (max - min)) + 360;
			}
			else if (max === g)
			{
				_h = 60 * ((b - r) / (max - min)) + 120;
			}
			else if (max === b)
			{
				_h = 60 * ((r - g) / (max - min)) + 240;
			}
		
			//Determine light value
			_l = (1/2) * (max + min);
		
			//Determine saturation
			if (max === min) {
				_s = 0.0;
			}
			else if (_l <= (1/2)) {
				_s = (max - min) / (2 * _l);
			}
			else if (_l > (1/2)) {
				_s = (max - min) / (2 - (2 * _l));
			}
		
			//Clamp hsl values to [0,1] (or [0,360] for the h value)
			_h = Math.max(0, Math.min(_h, 360));
			_s = Math.max(0, Math.min(_s, 1));
			_l = Math.max(0, Math.min(_l, 1));
		}
		
		function _HexToRGB()
		{
			var hexparse = _hex.replace(/#/, "");
			var hr = hexparse.substr(0, 2);
			var hg = hexparse.substr(2, 2);
			var hb = hexparse.substr(4, 2);
		
			_r = _h2d("0x" + hr);
			_g = _h2d("0x" + hg);
			_b = _h2d("0x" + hb);
		}
		
		function _HSLToRGB()
		{
			var q;
			if (_l < 0.5)
			{
				q = _l * (1 + _s);
			}
			if (_l >= 0.5)
			{
				q = _l + _s - (_l * _s);
			}
		
			var p = 2 * _l - q;
		
			var hk = _h / 360;
		
			var colors = [];
			colors[0] = hk + (1/3);
			colors[1] = hk;
			colors[2] = hk - (1/3);
		
			for (var i = 0; i < colors.length; i++)
			{
				if (colors[i] < 0.0) {
					colors[i] += 1.0;
				}
				if (colors[i] > 1.0) {
					colors[i] -= 1.0;
				}
		
				if (colors[i] < (1/6))
				{
					colors[i] = p + ((q - p) * 6 * colors[i]);
				}
				else if (colors[i] <= (1/6) || colors[i] < (1/2))
				{
					colors[i] = q;
				}
				else if (colors[i] <= (1/2) || colors[i] < (2/3))
				{
					colors[i] = p + ((q - p) * 6 * ((2/3) - colors[i]));
				}
				else
				{
					colors[i] = p;
				}
			}
		
			_r = Math.ceil(colors[0] * 255);
			_g = Math.ceil(colors[1] * 255);
			_b = Math.ceil(colors[2] * 255);
		}
	
		function _RGBToHex()
		{
			var hr = _d2h(_r);
			var hg = _d2h(_g);
			var hb = _d2h(_b);
		
			if (hr.length === 0) {
				hr = "0" + hr;
			}
			if (hg.length === 0) {
				hg = "0" + hg;
			}
			if (hb.length === 0) {
				hb = "0" + hb;
			}
		
			_hex = "#" + hr + hg + hb;
		}
		
		me.setRGB = function(r, g, b)
		{
			_r = r;
			_g = g;
			_b = b;
	
			_RGBToHex();
			_RGBToHSL();
		};
		me.setR = function(r)
		{
			_r = r;
		
			_RGBToHex();
			_RGBToHSL();
		};
		
		me.getR = function()
		{
			return _r;
		};
		
		me.setG = function(g)
		{
			_g = g;
		
			_RGBToHex();
			_RGBToHSL();
		};
		
		me.getG = function()
		{
			return _g;
		};
		
		me.setB = function(b)
		{
			_b = b;
		
			_RGBToHex();
			_RGBToHSL();
		};
		
		me.getB = function()
		{
			return _b;
		};
		
		me.setHex = function(hex)
		{
			_hex = hex;
		
			_HexToRGB();
			_RGBToHSL();
		};
		
		me.getHex = function()
		{
			return _hex;
		};
	
		me.setHSL = function(h, s, l)
		{
			_h = h;
			_s = s;
			_l = l;
	
			_HSLToRGB();
			_RGBToHex();
		};
		
		me.setH = function(h)
		{
			_h = h;
		
			_HSLToRGB();
			_RGBToHex();
		};
		
		me.getH = function()
		{
		 	return _h;
		};
		
		me.setS = function(s)
		{
			_s = s;
		
			_HSLToRGB();
			_RGBToHex();
		};
		
		me.getS = function()
		{
			return _s;
		};
		
		me.setL = function(l)
		{
			_l = l;
		
			_HSLToRGB();
			_RGBToHex();
		};
		
		me.getL = function()
		{
			return _l;
		};
	
		me.copy = function() {
			var _returncolor = new SJJS.util.Color();
			_returncolor.setHex(_hex);
	
			return _returncolor;
		};
	};
	return {
		FromRGB:function(r, g, b)
		{
			var _returncolor = new _color();
			_returncolor.setRGB(r, g, b);
		
			return _returncolor;
		},
		FromHex:function(hex)
		{
			var _returncolor = new _color();
			_returncolor.setHex(hex);
		
			return _returncolor;
		},
		FromHSL:function(h, s, l)
		{
			var _h = h, _s = s, _l = l;
			//Clamp hsl values to [0,1]
			if (_h > 360) {
				_h = 360;
			}
			if (_h < 0) {
				_h = 0;
			}
			if (_s > 1.0) {
				_s = 1.0;
			}
			if (_s < 0) {
				_s = 0;
			}
			if (_l > 1.0) {
				_l = 1.0;
			}
			if (_l < 0) {
				_l = 0;
			}
			var _returncolor = new _color();
			_returncolor.setHSL(_h, _s, _l);
		
			return _returncolor;
		},
		FromColor:function(colortocopy)
		{
			var _returncolor = new _color();
			_returncolor.setHex(colortocopy.getHex());
			return _returncolor;
		}
	}
})();

//Data provides a way to retrieve information from a database
SJJS.GMap.Overlays.Data = function() {
	var me = this;
	var _jdata, _currenturl, _currentpostdata, _delete = false;

	this.type = "Data";

	function objectSetTimeout_(object, argument1, command, milliseconds) {
		return window.setTimeout(function() {
			command.call(object, argument1);
		}, milliseconds);
	}

	function _parsedata(data) {
		var _uniqueid, _stylecontent, _featureref, _hidefound = false, _tempbounds;

		if (!_delete) {
			_featuredata = [];

			_jdata = eval('(' + data + ')');

			for (x = 0; x < _jdata.length; x++) {
				SJJS.util.Event.trigger(me, "rowadded", x);
			}

			SJJS.util.Event.trigger(me, "enddownload");
		}
	}
	function _downloaddata(dataurl, postdata) {
		_delete = false;
		SJJS.util.Event.trigger(me, "begindownload");

		if (postdata) {
			SJJS.util.download(dataurl, function(data, responseCode) {
				if ((dataurl === _currenturl && postdata === _currentpostdata)) {
					_parsedata(data);
				}
			}, postdata);
		} else {
			SJJS.util.download(dataurl, function(data, responseCode) {
				if ((dataurl === _currenturl)) {
					_parsedata(data);
				}
			});
		}
	}

	me.getFieldById = function(id, field) {
		return _jdata[id][field];
	};

	me.getRowsByField = function(field, value) {
		var x, i;
		var _returnarray = [];

		for (x = 0; x < _jdata.length; x++) {
			if (_jdata[x][field] === value) {
				_returnarray.push(_jdata[x]);
			}
		}

		return _returnarray;
	};

	me.getRows = function() {
		return _jdata;
	};

	me.removeData = function() {
		SJJS.util.Event.trigger(me, "dataremoved");
		_delete = true;
		delete _jdata;
	};

	me.setData = function(dataurl, postdata) {
		_currenturl = dataurl;
		_currentpostdata = postdata;

		me.removeData();

		window.setTimeout(function() {
			_downloaddata(dataurl, postdata);
		}, 20);
	};
};

//SJCityOverlay provides a way to add city data to the map
SJJS.GMap.Overlays.GISOverlay = function(_map) {
	var me = this;
	var _sjplacemarks = [];
	var _events = [];
	var _hidefeatures = [];
	var _featuredata, _jdata, _map, _currenturl, _currentpostdata, _bounds, _delete = false;
	var _error;

	this.type = "GISOverlay";

	function objectSetTimeout_(object, argument1, command, milliseconds) {
		return window.setTimeout(function() {
			command.call(object, argument1);
		}, milliseconds);
	}

	function _pusheventfunction(dindex, findex, fhandle) {
		var _tempf = function() {
			var x, _args = [];
			_args.push(_jdata[dindex].features[findex].uid);
			for (x = 0; x < arguments.length; x++)
			{
				_args.push(arguments[x]);
			}
			_events[fhandle].eventfunction.apply(_jdata[dindex].features[findex].feature, _args);
		}
		_jdata[dindex].eventhandles[findex].push(GEvent.addListener(_jdata[dindex].features[findex].feature, _events[fhandle].name, _tempf));
		_tempf = null;
	}

	function _updatestyle(id, style) {
		var x, _icon;
		var _dindex = _featuredata[id].dataindex, _findex = _featuredata[id].featureindex;
		_featureref = _jdata[_dindex].features[_findex];

		if (_featuredata[id].type === "point") {
			_icon = SJJS.map.createIcon({ width: style.width, height: style.height, primaryColor: style.color, cornerColor: style.color, strokeColor: "#000000" });
			if (_featuredata[id].style.width !== style.width || _featuredata[id].style.height !== style.height) {
				for (x = 0; x < _jdata[_dindex].eventhandles[_findex].length; x++) {
					GEvent.removeListener(_jdata[_dindex].eventhandles[_findex][x]);
					_jdata[_dindex].eventhandles[_findex][x] = null;
				}
				_map.removeOverlay(_featureref.feature);
				_featureref.glatlng = new google.maps.LatLng(_featureref.lat, _jdata[_dindex].features[_findex].lng);
				_featureref.feature = new google.maps.Marker(_featureref.glatlng, _icon);
				_map.addFeature(_featureref.feature);
				for (x = 0; x < _events.length; x++) {
					if (_events[j].type === _featureref.type) {
						_pusheventfunction(_dindex, _findex, x);
					}
					else if (_events[j].type === "Features") {
						_pusheventfunction(_dindex, _findex, x);
					}
				}
				_featureref = null;
			} else {
				_featureref.feature.setImage(_icon.image);
			}
			_featureref.style = style;
		} else if (_featuredata[id].type === "linestring") {
			_featureref.feature.setStrokeStyle(style);
			_featuredata[id].style = style;
		} else if (_featuredata[id].type === "polygon") {
			_featureref.feature.setStrokeStyle(style);
			if (style.fill) {
				_featureref.feature.setFillStyle({color:style.fillcolor, opacity:style.fillopacity, weight:style.weight});
			}
			_featuredata[id].style = style;
		}
	}

	function _removefeatures() {
		var x, i, j, _featureref;

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				if (_jdata[x].features) {
					for (i = 0; i < _jdata[x].features.length; i++) {
						_featureref = _jdata[x].features[i];
						if (_featureref.feature) {
							for (j = 0; j < _jdata[x].eventhandles[i].length; j++) {
								GEvent.removeListener(_jdata[x].eventhandles[i][j]);
								delete _jdata[x].eventhandles[i][j];
							}
							_map.removeOverlay(_featureref.feature);
							SJJS.util.Event.trigger(me, "featureremoved", _featureref.feature.sjextensions.id);
							delete _featureref.feature;
							delete _featureref.glatlng;
						}
						_featureref = null;
						_jdata[x].features[i] = null;
					}
				}
			}
			_jdata = null;
			_featuredata = null;
		}
	}


	function _parsedata(data, applystyle) {
		var _uniqueid, _stylecontent, _featureref, _hidefound = false, _tempbounds;

		if (data.charAt(0) === "<") {
			_error = true;
		}
		if (!_delete && !_error) {
			_featuredata = [];

			_jdata = eval('(' + data + ')');
			for (x = 0; x < _jdata.length; x++) {
				_jdata[x].eventhandles = [];
				for (j = 0; j < _hidefeatures.length; j++) {
					if (_hidefeatures[j].value === _jdata[x][_hidefeatures[j].attribute]) {
						_hidefound = true;
						break;
					}
				}

	  		for (i = 0; i < _jdata[x].features.length; i++) {
					_featureref = _jdata[x].features[i];

					_jdata[x].eventhandles[i] = [];
					_featuredata.push({ dataindex: x, featureindex: i });
					_uniqueid = _featuredata.length - 1;
					_featureref.uid = _uniqueid;

					_stylecontent = applystyle(_uniqueid);

					_featuredata[_uniqueid].style = _stylecontent;
					_featuredata[_uniqueid].type = _featureref.type;

					if (_featureref.type === "Point" || _featureref.type === "point") {
						_featureref.glatlng = new google.maps.LatLng(_featureref.lat, _featureref.lng);
						_featureref.feature = new google.maps.Marker(_featureref.glatlng, SJJS.map.createIcon({ width: _stylecontent.width, height: _stylecontent.height, primaryColor: _stylecontent.color, cornerColor: _stylecontent.color, strokeColor: "#000000" }));
						_bounds.extend(_featureref.glatlng);
					}
					if (_featureref.type === "Polyline" || _featureref.type === "linestring") {
						_featureref.feature = new google.maps.Polyline.fromEncoded({ color: _stylecontent.color, weight: _stylecontent.weight, opacity: _stylecontent.opacity, points: _featureref.polylines[0].points, levels: _featureref.polylines[0].levels, numLevels: _featureref.polylines[0].numLevels, zoomFactor: _featureref.polylines[0].zoomFactor });
						_tempbounds = _featureref.feature.getBounds();
						_bounds.extend(_tempbounds.getSouthWest());
						_bounds.extend(_tempbounds.getNorthEast());
					}
					if (_featureref.type === "Polygon" || _featureref.type === "polygon") {
						_featureref.feature = new google.maps.Polygon.fromEncoded({ polylines: [{ color: _stylecontent.color, weight: _stylecontent.weight, opacity: _stylecontent.opacity, points: _featureref.polylines[0].points, levels: _featureref.polylines[0].levels, numLevels: _featureref.polylines[0].numLevels, zoomFactor: _featureref.polylines[0].zoomFactor}], color: _stylecontent.fillcolor, opacity: _stylecontent.fillopacity, fill: _stylecontent.fill, outline: true });
						_tempbounds = _featureref.feature.getBounds();
						_bounds.extend(_tempbounds.getSouthWest());
						_bounds.extend(_tempbounds.getNorthEast());
					}

					_featureref.feature.sjextensions = { dataindex: x, featureindex: i, id: _uniqueid };
					if (!_hidefound) {
						_map.addOverlay(_featureref.feature);
						SJJS.util.Event.trigger(me, "featureadded", _uniqueid);
					}

					for (j = 0; j < _events.length; j++) {
						if (_events[j].type === _featureref.type) {
							_pusheventfunction(x, i, j);
						}
						else if (_events[j].type === "Features") {
							_pusheventfunction(x, i, j);
						}
					}
		}
				_hidefound = false;
			}

			delete _stylecontent;
			delete _featureref;
			SJJS.util.Event.trigger(me, "enddownload");
		}
	}
	function _downloaddata(dataurl, stylefunction, postdata) {
		_delete = false;
		SJJS.util.Event.trigger(me, "begindownload");

		if (postdata) {
			SJJS.util.download(dataurl, function(data, responseCode) {
				if ((dataurl === _currenturl && postdata === _currentpostdata)) {
					_parsedata(data, stylefunction);
				}
			}, postdata);
		} else {
			SJJS.util.download(dataurl, function(data, responseCode) {
				if ((dataurl === _currenturl)) {
					_parsedata(data, stylefunction);
				}
			});
		}
	}

	function _pusheventfunctiontofeatures(fhandle) {
		var x, i;

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				for (i = 0; i < _jdata[x].features.length; i++) {
					if (_jdata[x].features[i].feature) {
						if (_events[fhandle].type === _jdata[x].features[i].type) {
							_pusheventfunction(x, i, fhandle);
						}
						else if (_events[fhandle].type === "Features") {
							_pusheventfunction(x, i, fhandle);
						}
					}
				}
			}
		}
	}

	me.getBounds = function() {
		return _bounds;
	};

	me.getStyleById = function(id) {
		return _featuredata[id].style;
	};

	me.getGeometryTypeById = function(id) {
		return _featuredata[id].type;
	};

	me.getAttributeById = function(id, attribute) {
		return _jdata[_featuredata[id].dataindex][attribute];
	};

	me.getAttribute = function(feature, attribute) {
		if (feature.sjextensions !== undefined && feature.sjextensions !== null) {
			return _jdata[feature.sjextensions.dataindex][attribute];
		}
	};

	me.getFeatureId = function(feature) {
		if (feature.sjextensions !== undefined && feature.sjextensions !== null) {
			return feature.sjextensions.id;
		}
	};

	me.getFeaturesByAttribute = function(attribute, value) {
		var x, i;
		var _returnarray = [];

		for (x = 0; x < _jdata.length; x++) {
			if (_jdata[x][attribute] === value) {
				for (i = 0; i < _jdata[x].features.length; i++) {
					_returnarray.push(_jdata[x].features[i].feature);
				}
			}
		}

		return _returnarray;
	};

	me.hideFeaturesByAttribute = function(attribute, value) {
		var x, i;

		_hidefeatures.push({ attribute: attribute, value: value });

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				if (_jdata[x][attribute] === value) {
					for (i = 0; i < _jdata[x].features.length; i++) {
						if (_jdata[x].features[i].feature) {
							_map.removeOverlay(_jdata[x].features[i].feature);
							SJJS.util.Event.trigger(me, "featureremoved", _jdata[x].features[i].feature.sjextensions.id);
						}
					}
				}
			}
		}
		SJJS.util.Event.trigger(me, "featureshidden");
	};

	me.showFeaturesByAttribute = function(attribute, value) {
		var x, i, _found, _hideindex;

		for (x = 0; x < _hidefeatures.length; x++) {
			if (_hidefeatures[x].attribute === attribute && _hidefeatures[x].value === value) {
				_hideindex = x;
			}
		}
		if (_hideindex) {
			if (_jdata) {
				for (x = 0; x < _jdata.length; x++) {
					if (_jdata[x][attribute] === value) {
						for (i = 0; i < _jdata[x].features.length; i++) {
							if (_jdata[x].features[i].feature) {
								_map.addOverlay(_jdata[x].features[i].feature);
								SJJS.util.Event.trigger(me, "featureadded", _jdata[x].features[i].feature.sjextensions.id);
							}
						}
					}
				}
			}
			delete _hidefeatures[_hideindex];
			_hidefeatures.splice(_hideindex, 1);
		}
		SJJS.util.Event.trigger(me, "featuresshown");
	};

	me.addEventsByAttribute = function(attribute, value, eventname, eventfunction) {
		var x, i;

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				if (_jdata[x][attribute] === value) {
					for (i = 0; i < _jdata[x].features.length; i++) {
						if (_jdata[x].features[i].feature) {
							_pusheventfunction(x, i, fhandle);
						}
					}
				}
			}
		}
	};

	me.addEventToMarkers = function(eventname, eventfunction) {
		var _returnhandler;

		_events.push({ type: "point", eventfunction: eventfunction, name: eventname });
		_returnhandler = _events.length - 1;

		_pusheventfunctiontofeatures(_returnhandler);
	};

	me.addEventToPolylines = function(eventname, eventfunction) {
		var _returnhandler;

		_events.push({ type: "linestring", eventfunction: eventfunction, name: eventname });
		_returnhandler = _events.length - 1;

		_pusheventfunctiontofeatures(_returnhandler);
	};

	me.addEventToPolygons = function(eventname, eventfunction) {
		var _returnhandler;

		_events.push({ type: "polygon", eventfunction: eventfunction, name: eventname });
		_returnhandler = _events.length - 1;

		_pusheventfunctiontofeatures(_returnhandler);
	};

	me.addEventToFeatures = function(eventname, eventfunction) {
		var _returnhandler;

		_events.push({ type: "Features", eventfunction: eventfunction, name: eventname });
		_returnhandler = _events.length - 1;

		_pusheventfunctiontofeatures(_returnhandler);
	};

	me.setStyleById = function(id, style) {
		_updatestyle(id, style);
	};

	me.setStyleByAttribute = function(attribute, value, style) {
		var x, i;

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				if (_jdata[x][attribute] === value) {
					for (i = 0; i < _jdata[x].features.length; i++) {
						_updatestyle(_jdata[x].features[i].uid, style);
					}
				}
			}
		}
	};

	me.setStyle = function(style) {
		var x, i;

		if (_jdata) {
			for (x = 0; x < _jdata.length; x++) {
				for (i = 0; i < _jdata[x].features.length; i++) {
					_updatestyle(_jdata[x].features[i].uid, style);
				}
			}
		}
	};

	me.removeData = function() {
		_delete = true;
		_removefeatures();
		SJJS.util.Event.trigger(me, "dataremoved");
	};

	me.setData = function(dataurl, stylefunction, postdata) {
		delete _bounds;
		_bounds = new google.maps.LatLngBounds();

		_currenturl = dataurl;
		_currentpostdata = postdata;

		_removefeatures();
		window.setTimeout(function() {
			_downloaddata(dataurl, stylefunction, postdata);
		}, 20);
		if (_error) {
			return false;
		}
		return true;
	};
};

SJJS.util.states = function() {
	var _states = {};
	var me = this;

	me.add = function(name, current) {
		_states[name] = {current:current};
	};
	me.setCurrent = function(name) {
		_states[name].current = true;
		SJJS.util.Event.trigger(me, "statechange", name);
	};
	me.getCurrent = function() {
		for (var x in _states) {
			if (_states[x].current) {
				return x;
			}
		}
		return null;
	};
};

SJJS.GMap.Overlays.GISOverlayManager = function(map) {
	var _overlays = {};
	var me = this;

	me.add = function(name, overlay) {
		_overlays[name] = overlay;
	};

	me.get = function(name) {
		return _overlays[name];
	};

	me.remove = function(name, del) {
		if (_overlays[name].removeData) {
			_overlays[name].removeData();
		} else {
			map.removeOverlay(_overlays[name]);
		}
		if (del) {
			_overlays[name] = null;
		}
	};

	me.removeAll = function() {
		var x;
		for (x in _overlays) {
			if (_overlays[x].removeData) {
				_overlays[x].removeData();
			} else {
				map.removeOverlay(_overlays[x]);
			}
		}
	};

	me.removeAllBut = function() {
		var x, y, _found;
		for (x in _overlays) {
			_found = false;
			for (y = 0; y <= arguments.length; y++) {
				if (arguments[y] === x) {
					_found = true;
				}
			}
			if (!_found) {
				if (_overlays[x]) {
					if (_overlays[x].removeData) {
						_overlays[x].removeData();
					} else {
						map.removeOverlay(_overlays[x]);
					}
				}
			}
		}
	};
};


//LabelOverlay class provides a way to display the name of the marker when hovered over
SJJS.GMap.Overlays.GeoLabel = function(latlng, text, color, fontsize, fontfamily) {
	var me = this;
	var _map;

	var _div;

	if (!fontfamily) {
		fontfamily = "Arial";
	}
	if (!fontsize) {
		fontsize = 24;
	}
	if (!color) {
		color = "#000000";
	}
	
	me.initialize = function(map) {
		_map = map;

		_div = document.createElement("div");

		_div.innerHTML = text;
		_div.style.color = color;
		_div.style.fontSize = fontsize + "pt";
		_div.style.fontFamily = fontfamily;

		_div.style.position = "absolute";
		_div.style.top = (_map.fromLatLngToDivPixel(latlng).y - (fontsize / 2)) + "px";
		_div.style.left = (_map.fromLatLngToDivPixel(latlng).x - (fontsize / 2)) + "px";

		_map.getPane(G_MAP_MAP_PANE).appendChild(_div);
	};
	
	me.remove = function() {
		_map.getPane(G_MAP_MAP_PANE).removeChild(_div);
	};
	
	me.copy = function() {
		return new SJJS.GMap.Overlays.GeoLabel(latlng, color, fontsize, fontfamily);
	};
	
	me.redraw = function(force) {
		if (!force) {
			return;
		}

		_div.style.top = (_map.fromLatLngToDivPixel(latlng).y - (fontsize / 2)) + "px";
		_div.style.left = (_map.fromLatLngToDivPixel(latlng).x - (fontsize / 2)) + "px";
	};
};

//Window

SJJS.GMap.Controls.GWindow = function(windowoptions) {
	var me = this;

	var _container = document.createElement("div");
	var _titlebar = document.createElement("div");
	var _close = document.createElement("div");
	var _title = document.createElement("span");
	var _window = document.createElement("div");
	var _windowshadow = document.createElement("div");

	if (windowoptions.titlebackgroundcolor === undefined || windowoptions.titlebackgroundcolor === null) {
		windowoptions.titlebackgroundcolor = "#7AA9DD";
	}
	if (windowoptions.titlecolor === undefined || windowoptions.titlecolor === null) {
		windowoptions.titlecolor = "#FFFFFF";
	}
	if (windowoptions.width === undefined || windowoptions.width === null) {
		windowoptions.width = 200;
	}
	if (windowoptions.height === undefined || windowoptions.height === null) {
		windowoptions.height = 200;
	}
	if (windowoptions.hidden === undefined || windowoptions.hidden === null) {
		windowoptions.hidden = false;
	}
	windowoptions.border = "1px solid black";
	if (windowoptions.top === undefined || windowoptions.top === null) {
		windowoptions.top = ((SJJS.util.getBodyHeight() / 2) - 10);
	}
	if (windowoptions.left === undefined || windowoptions.left === null) {
		windowoptions.left = ((SJJS.util.getBodyWidth() / 2) - (windowoptions.width / 2));
	}

	var _hidden = windowoptions.hidden;

	_windowshadow.style.width = (windowoptions.width + 16) + "px";
	_windowshadow.style.height = (windowoptions.height + 22) + "px";
	_windowshadow.style.position = "absolute";
	_windowshadow.style.top = (windowoptions.top + 5) + "px";
	_windowshadow.style.left = (windowoptions.left + 5) + "px";
	_windowshadow.style.backgroundColor = "#000000";
	_windowshadow.style.filter = "alpha(opacity=20)";
	_windowshadow.style.opacity = ".2";
	_container.appendChild(_windowshadow);

	_titlebar.style.borderTop = windowoptions.border;
	_titlebar.style.borderLeft = windowoptions.border;
	_titlebar.style.borderRight = windowoptions.border;
	_titlebar.style.padding = "0px 7px 0px 7px";
	_titlebar.style.position = "absolute";
	_titlebar.style.left = windowoptions.left + "px";
	_titlebar.style.top = windowoptions.top + "px";
	_titlebar.style.width = windowoptions.width + "px";
	_titlebar.style.height = "20px";
	_titlebar.style.backgroundColor = windowoptions.titlebackgroundcolor;
	_titlebar.style.color = windowoptions.titlecolor;
	if (windowoptions.title !== undefined && windowoptions.title !== null) {
		_title.innerHTML = windowoptions.title;
	}
	_title.style.cssFloat = "left";
	_titlebar.appendChild(_title);
	_container.appendChild(_titlebar);

	_close.innerHTML = "X";
	_close.style.width = "10px";
	_close.style.height = "20px";
	_close.style.position = "absolute";
	_close.style.top = 0;
	_close.style.right = "7px";
	_close.style.cursor = "pointer";
	//_close.style.cssFloat = "right";
	_close.style.color = windowoptions.titlecolor;
	_titlebar.appendChild(_close);

	_window.style.height = windowoptions.height + "px";
	_window.style.position = "absolute";
	_window.style.borderBottom = windowoptions.border;
	_window.style.borderLeft = windowoptions.border;
	_window.style.borderRight = windowoptions.border;
	_window.style.left = windowoptions.left + "px";
	_window.style.top = (windowoptions.top + 20) + "px";
	_window.style.width = windowoptions.width + "px";
	_window.style.backgroundColor = "#FFFFFF";
	_window.style.padding = "0px 7px 0px 7px";
	_window.innerHTML = "";
	if (windowoptions.backgroundrepeat !== undefined && windowoptions.backgroundrepeat !== null) {
		_window.style.backgroundRepeat = windowoptions.backgroundrepeat;
	}
	if (windowoptions.backgroundposition !== undefined && windowoptions.backgroundposition !== null) {
		_window.style.backgroundPosition = windowoptions.backgroundposition;
	}
	if (windowoptions.backgroundimage !== undefined && windowoptions.backgroundimage !== null) {
		_window.style.backgroundImage = windowoptions.backgroundimage;
	}

	_container.appendChild(_window);

	document.getElementsByTagName("body")[0].appendChild(_container);

	var _drag = new google.maps.DraggableObject(_titlebar);

	google.maps.Event.addListener(_drag, "drag", function() {
		_windowshadow.style.top = (_drag.top + 5) + "px";
		_windowshadow.style.left = (_drag.left + 5) + "px";
		_window.style.top = (_drag.top + 20) + "px";
		_window.style.left = _drag.left + "px";
		//_close.style.top = _titlebar.style.top;
		//_close.style.left = (_drag.left + (windowoptions.width - 3)) + "px";
	});

	me.hide = function() {
		_titlebar.style.visibility = "hidden";
		_window.style.visibility = "hidden";
		_close.style.visibility = "hidden";
		_windowshadow.style.visibility = "hidden";
		_hidden = true;
		SJJS.util.Event.trigger(me, "windowclosed");
	};
	me.show = function() {
		_titlebar.style.visibility = "visible";
		_window.style.visibility = "visible";
		_close.style.visibility = "visible";
		_windowshadow.style.visibility = "visible";
		_hidden = false;
	};
	me.isHidden = function() {
		return _hidden;
	};

	SJJS.util.Event.addDomListener(_close, "click", function() {
		me.hide();
	});

	if (_hidden) {
		me.hide();
	} else {
		me.show();
	}

	me.addContentDom = function(domcontent) {
		_window.appendChild(domcontent);
	};
	me.addContentHtml = function(htmlcontent) {
		_window.innerHTML += htmlcontent;
	};
	me.addPage = function(page) {
		SJJS.util.download(page, function(data, responseCode) {
			var _ar;
			if (responseCode === 200) {
				_ar = data.split("|||||||");
				eval(_ar[0]);
				_window.innerHTML += _ar[1];
			}
		});
	};

	me.getWidth = function() {
		return parseInt(_window.style.width.replace("px", ""), 10);
	};
	me.getHeight = function() {
		return parseInt(_window.style.height.replace("px", ""), 10);
	};
	me.setWidth = function(newwidth) {
		_window.style.width =  newwidth + "px";
		_titlebar.style.width = newwidth + "px";
		_windowshadow.style.width = newwidth + "px";
		windowoptions.width = newwidth;
		_close.style.right = "3px";
	};
	me.setHeight = function(newheight) {
		_window.style.height = newheight + "px";
		_windowshadow.style.height = newheight + "px";
	};
	me.setTitle = function(newtitle) {
		_title.innerHTML = newtitle;
	};
};

//LabelOverlay class provides a way to display the name of the marker when hovered over
SJJS.GMap.Controls.Label = function(name, latlng) {
	var me = this;
	var _map;
	var _div = document.createElement("div");
	
	me.initialize = function(map) {
		_map = map;

		_div.style.border = "1px solid black";
		_div.style.position = "absolute";
		//_div.style.height = "50px";
		_div.style.width = "150px";
		_div.style.color = "#003366";
		_div.style.fontFamily = "Arial";
		_div.style.fontSize = "7pt";
		_div.style.textAlign = "center";
		_div.style.backgroundImage = "url('http://www.sanjoseca.gov/images/leftnav_bg.gif')";
		_div.innerHTML = "<table style='width:100%;height:100%;'><tr><td valign='center' align='center'><span style='font-size:9pt;'>" + name + "</span></td></tr></table>";
	
		map.getPane(G_MAP_FLOAT_PANE).appendChild(_div);
	};
	
	me.remove = function() {
		_div.parentNode.removeChild(_div);
		_div = null;
	};
	
	me.copy = function() {
		return new LabelOverlay(name, latlng);
	};
	
	me.redraw = function(force) {
		if (!force) {
			return;
		}
	
		_div.style.left = (_map.fromLatLngToDivPixel(latlng).x + 7) + "px";
		_div.style.top = (_map.fromLatLngToDivPixel(latlng).y - 80) + "px";
	};
};

//Legend provides a legend for the map

SJJS.GMap.Controls.GLegend = function(title, legendwidth) {
	var me = this;
	var _container = document.createElement("div");
	var _legenddiv = document.createElement("div");
	var _newtable = document.createElement("table");
	var _newtablebody = document.createElement("tbody");
	var _entries = [];
	var _titlespan = document.createElement("div");

	this.type = "GLegend";
	
	this.AddEntry = function(id, entry)
	{
		_entries[id] = {iconhtml: entry.iconhtml, name: entry.name, hascheck: entry.hascheck, checked: entry.hascheck};
		//entry (iconhtml, name, hascheck, checked)
		_entries[id].newrow = document.createElement("tr");
		_entries[id].newselectcol = document.createElement("td");
		_entries[id].newimagecol = document.createElement("td");
		_entries[id].newnamecol = document.createElement("td");
	
		_entries[id].newrow.style.width = "100%";
		if (_entries[id].hascheck) {
			_entries[id].newcheck = document.createElement("input");
			_entries[id].newcheck.id = _entries[id].name + "check";
			_entries[id].newcheck.type = "checkbox";
			_entries[id].newselectcol.appendChild(_entries[id].newcheck);

			if (_entries[id].checked === undefined || _entries[id].checked === null) {
				_entries[id].newcheck.checked = true;
			}
			else {
				_entries[id].newcheck.checked = true; //entry.checked;
			}

			SJJS.util.Event.addDomListener(_entries[id].newcheck, "click", function() {
				SJJS.util.Event.trigger(me, "entrycheck", _entries[id].newcheck.checked, _entries[id].name);
			});
		}

		_entries[id].newimagecol.innerHTML = _entries[id].iconhtml;
	
		_entries[id].newnamecol.style.textAlign = "left";
		_entries[id].newnamecol.style.color = "#3B6AA0";
		_entries[id].newnamecol.innerHTML += _entries[id].name;
		_entries[id].newrow.appendChild(_entries[id].newselectcol);
		_entries[id].newrow.appendChild(_entries[id].newimagecol);
		_entries[id].newrow.appendChild(_entries[id].newnamecol);
		_newtablebody.appendChild(_entries[id].newrow);
	};

	this.removeEntry = function(id)
	{
		_entries[id].newrow.removeChild(_entries[id].newselectcol);
		_entries[id].newrow.removeChild(_entries[id].newimagecol);
		_entries[id].newrow.removeChild(_entries[id].newnamecol);
		_newtablebody.removeChild(_entries[id].newrow);
		_entries[id].newrow = null;
		_entries[id].newselectcol = null;
		_entries[id].newimagecol = null;
		_entries[id].newnamecol = null;
		_entries[id] = null;
	};
	
	this.show = function()
	{
		_legenddiv.style.visibility = "visible";
		_legenddiv.style.height = null;
	};

	this.hide = function()
	{
		_legenddiv.style.visibility = "hidden";
		_legenddiv.style.height = 0;
	};
	
	this.initialize = function(map) {
		_legenddiv.id = "GLegend";

		_legenddiv.style.width = legendwidth;
		_legenddiv.style.backgroundColor = "#FFFFFF";
		_legenddiv.style.textAlign = "center";
		_legenddiv.style.fontFamily = "Arial";
		_legenddiv.style.fontSize = "9pt";
		_legenddiv.style.border = "1px solid gray";
		_legenddiv.style.padding = "0px 0px 0px 0px";

		_titlespan.id = "GLegendTitle";
		_titlespan.style.color = "#FFFFFF";
		_titlespan.style.textAlign = "center";
		_titlespan.style.fontWeight = "bold";
		_titlespan.style.width = "100%";
		_titlespan.style.backgroundColor = "#7AA9DD";
		if (title !== undefined && title !== null)
		{
			_titlespan.innerHTML = title + "<br />";
		}
		_legenddiv.appendChild(_titlespan);
	
		_newtablebody.id = "legendtbody";
		_newtable.style.width = "100%";
		_newtable.appendChild(_newtablebody);
		_legenddiv.appendChild(_newtable);
	
		_container.appendChild(_legenddiv);

		map.getContainer().appendChild(_container);
		return _container;
	};
	
	this.getDefaultPosition = function() {
		return new google.maps.ControlPosition(G_ANCHOR_BOTTOM_LEFT, new google.maps.Size(2, 32));
	};

	this.printable = function() {
		return true;
	}
}

SJJS.GMap.Controls.DivList = function(listoptions) {
	var me = this;
	var _listdiv = document.createElement("div");
	var _listsections = [];
	var _listentries = [];
	var _listheight;
	var _haseveryother = true;
	var _otherbordercolor;

	if (!listoptions) {
		listoptions = {};
	}
	if (!listoptions.width) {
		listoptions.width = 200;
	}
	if(!listoptions.height) {
		listoptions.height = 200;
	}
	if (!listoptions.color) {
		listoptions.color = SJJS.util.Color.FromHex("#000000");
	}
	if (!listoptions.backcolor) {
		listoptions.backcolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!listoptions.highlightcolor) {
		listoptions.highlightcolor = SJJS.util.Color.FromHex("#000000");
	}
	if (!listoptions.highlightbackcolor) {
		listoptions.highlightbackcolor = SJJS.util.Color.FromHex("#FBEC5D");
	}
	if (!listoptions.selectcolor) {
		listoptions.selectcolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!listoptions.selectbackcolor) {
		listoptions.selectbackcolor = SJJS.util.Color.FromHex("#7AA9DD");
	}
	if (!listoptions.sectioncolor) {
		listoptions.sectioncolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!listoptions.sectionbackcolor) {
		listoptions.sectionbackcolor = SJJS.util.Color.FromHex("#7AA9DD");
	}
	if (!listoptions.everyothercolor && !listoptions.everyotherbackcolor) {
		_haseveryother = false;
	} else if (!listoptions.everyotherbackcolor) {
		listoptions.everyotherbackcolor = SJJS.util.Color.FromHex("#7AA9DD");
		listoptions.everyotherbackcolor.setL(listoptions.everyothercolor.getL() + 0.25);
	} else if (!listoptions.everyothercolor) {
		listoptions.everyothercolor = SJJS.util.Color.FromHex("#000000");
	}

	if (listoptions.hasdividers) {
		if (_haseveryother) {
			_otherbordercolor = SJJS.util.Color.FromHSL(listoptions.everyotherbackcolor.getH(), listoptions.everyotherbackcolor.getS(), listoptions.everyotherbackcolor.getL() - 0.25);
			if (_otherbordercolor.getL() < 0.25) {
				_otherbordercolor.setL(listoptions.everyotherbackcolor.getL() + 0.25);
			}
		} else {
			_otherbordercolor = SJJS.util.Color.FromHSL(listoptions.backcolor.getH(), listoptions.backcolor.getS(), listoptions.backcolor.getL() - 0.25);
			if (_otherbordercolor.getL() < 0.25) {
				_otherbordercolor.setL(listoptions.backcolor.getL() + 0.25);
			}
		}
	}

	_listsections.push(listoptions);
	_listsections[0].name = "_default";
	_listsections[0].div = document.createElement("div");
	_listsections[0].entries = [];
	_listsections[0].everyother = false;

	_listdiv.id = listoptions.name + "divId";
	
	if (listoptions.width) {
		_listdiv.style.width = listoptions.width + "px";
	}
	if (listoptions.height) {
		_listheight = listoptions.height;
	}

	if (!listoptions.visible) {
		_listdiv.style.visibility = "hidden";
		_listdiv.style.height = "0px";
	} else {
		_listdiv.style.visibility = "visible";
		if (_listheight) {
			_listdiv.style.height = _listheight + "px";
		} else {
			_listdiv.style.height = null;
		}
	}
	_listdiv.style.overflow = "auto";
	_listdiv.style.fontFamily = "Arial";
	_listdiv.style.fontSize = "8pt";
	_listdiv.style.color = listoptions.color.getHex();
	_listdiv.style.backgroundColor = listoptions.backcolor.getHex();
	_listdiv.style.border = "1px solid gray";
	_listdiv.style.textAlign = "left";
	_listdiv.style.cursor = "pointer";
	_listdiv.style.overflow = "auto";
	
	_listdiv.innerHTML = "";

	_listdiv.appendChild(_listsections[0].div);

	function _deleteentry(sectionindex, nameindex) {
		if (nameindex === (_listsections[sectionindex].entries.length + 1)) {
			_listsections[sectionindex].everyother = !_listsections[sectionindex].everyother;
		}
		_listsections[sectionindex].div.removeChild(_listsections[sectionindex].entries[nameindex].div);
		_listsections[sectionindex].entries[nameindex].div = null;
		SJJS.util.Event.removeListener(_listsections[sectionindex].entries[nameindex].click);
		SJJS.util.Event.removeListener(_listsections[sectionindex].entries[nameindex].mouseover);
		SJJS.util.Event.removeListener(_listsections[sectionindex].entries[nameindex].mouseout);
		_listsections[sectionindex].entries[nameindex].clickfunction = null;
		_listsections[sectionindex].entries[nameindex].mouseoverfunction = null;
		_listsections[sectionindex].entries[nameindex].mouseoutfunction = null;
		_listsections[sectionindex].entries[nameindex].click = null;
		_listsections[sectionindex].entries[nameindex].mouseover = null;
		_listsections[sectionindex].entries[nameindex].mouseout = null;
		_listsections[sectionindex].entries[nameindex] = null;
		_listsections[sectionindex].entries.splice(nameindex, 1);
	}

	function _selectentry(sectionindex, nameindex)
	{
		_listsections[sectionindex].entries[nameindex].div.style.color = _listsections[sectionindex].selectcolor.getHex();
		_listsections[sectionindex].entries[nameindex].div.style.backgroundColor = _listsections[sectionindex].selectbackcolor.getHex();
		_listsections[sectionindex].entries[nameindex].selected = true;
	}

	function _deselectentry(sectionindex, nameindex)
	{
		_listsections[sectionindex].entries[nameindex].div.style.color = _listsections[sectionindex].color.getHex();
		_listsections[sectionindex].entries[nameindex].div.style.backgroundColor = _listsections[sectionindex].backcolor.getHex();
		_listsections[sectionindex].entries[nameindex].selected = false;
	}

	function _setbackground(sectionindex, nameindex)
	{
		if (_haseveryother && _listsections[sectionindex].everyother) {
			_listsections[sectionindex].entries[nameindex].div.style.color = _listsections[sectionindex].everyothercolor.getHex();
			_listsections[sectionindex].entries[nameindex].div.style.backgroundColor = _listsections[sectionindex].everyotherbackcolor.getHex();
			_listsections[sectionindex].everyother = false;
		} else {
			_listsections[sectionindex].entries[nameindex].div.style.color = _listsections[sectionindex].color.getHex();
			_listsections[sectionindex].entries[nameindex].div.style.backgroundColor = _listsections[sectionindex].backcolor.getHex();
			_listsections[sectionindex].everyother = true;
		}
	}

	function _listsort(l, r) {
		if (l.sort < r.sort) {
			return -1;
		}
		if (l.sort === r.sort) {
			return 0;
		}
		return 1;
	}
	
	function _dlistsort(l, r) {
		if (l.sort > r.sort) {
			return -1;
		}
		if (l.sort === r.sort) {
			return 0;
		}
			return 1;
	}

	function _findsectionindex(section) {
		var x, _index = 0;
	
		for (x = 0; x < _listsections.length; x++) {
			if (_listsections[x].name === section) {
				return x;
			}
		}
	
		return _index;
	}
	
	function _findgroupindex(sectionindex, group) {
		var x, _index = -1;
	
		if (_listsections[sectionindex]) {
			for (x = 0; x < _listsections[sectionindex].entries.length; x++) {
				if (_listsections[sectionindex].entries[x].group === group) {
					return x;
				}
			}
		}
	
		return _index;
	}
	
	this.hide = function() {
		_listdiv.style.visibility = "hidden";
		_listdiv.style.height = "0px";
	};
	
	this.show = function() {
		_listdiv.style.visibility = "visible";
		_listdiv.style.height = _listheight + "px";
	};

	this.addSection = function(text, name, options) {
		_listsections.push({text: text, name: name, headerdiv: document.createElement("div"), div:document.createElement("div"), container:document.createElement("div"), entries:[], everyother:false});
		var _index = _listsections.length - 1;

		if (!options) {
			options = {};
		}
		_listsections[_index].color = options.color || listoptions.color;
		_listsections[_index].backcolor = options.backcolor || listoptions.backcolor;
		_listsections[_index].highlightcolor = options.highlightcolor || listoptions.highlightcolor;
		_listsections[_index].highlightbackcolor = options.highlightbackcolor || listoptions.highlightbackcolor;
		_listsections[_index].selectcolor = options.selectcolor || listoptions.selectcolor;
		_listsections[_index].selectbackcolor = options.selectbackcolor || listoptions.selectbackcolor;
		_listsections[_index].sectioncolor = options.sectioncolor || listoptions.sectioncolor;
		_listsections[_index].sectionbackcolor = options.sectionbackcolor || listoptions.sectionbackcolor;
		_listsections[_index].everyothercolor = options.everyothercolor || listoptions.everyothercolor;
		_listsections[_index].everyotherbackcolor = options.everyotherbackcolor || listoptions.everyotherbackcolor;

		_listsections[_index].headerdiv.style.padding = "3px 2px 3px 2px";
		_listsections[_index].headerdiv.style.fontWeight = "bold";
		_listsections[_index].headerdiv.style.border = "3px ridge " + _listsections[_index].sectionbackcolor.getHex();
		_listsections[_index].headerdiv.style.color = _listsections[_index].sectioncolor.getHex();
		_listsections[_index].headerdiv.style.backgroundColor = _listsections[_index].sectionbackcolor.getHex();

		_listsections[_index].headerdiv.innerHTML = "-  " + text;

		_listsections[_index].clickfunction = function() {
			if (_listsections[_index].isCollapsed) {
				_listsections[_index].container.appendChild(_listsections[_index].div);
				_listsections[_index].headerdiv.innerHTML = "-  " + _listsections[_index].text;
				_listsections[_index].isCollapsed = false;
			} else {
				_listsections[_index].container.removeChild(_listsections[_index].div);
				_listsections[_index].headerdiv.innerHTML = "+  " + _listsections[_index].text;
				_listsections[_index].isCollapsed = true;

			}
		};
		_listsections[_index].click = SJJS.util.Event.addDomListener(_listsections[_index].headerdiv, "click", _listsections[_index].clickfunction);

		_listsections[_index].container.appendChild(_listsections[_index].headerdiv);
		_listsections[_index].container.appendChild(_listsections[_index].div);
		_listdiv.appendChild(_listsections[_index].container);
	};
	
	this.addEntry = function(text, group, options) {
		var _index;
		
		if (!options.section) {
			options.section = "_default";
		}
		var _sectionindex = _findsectionindex(options.section);
		var _groupindex = _findgroupindex(_sectionindex, group);
		var w;
		
		if (_groupindex === -1) {
			_listsections[_sectionindex].entries.push({div: document.createElement("div")});
			_index = _listsections[_sectionindex].entries.length - 1;
			if (listoptions.hasdividers) {
				_listsections[_sectionindex].entries[_index].div.style.borderBottom = "1px solid " + _otherbordercolor.getHex();
			}

			_setbackground(_sectionindex, _index);
			_listsections[_sectionindex].entries[_index].div.style.padding = "2px 0px 2px 4px";
			_listsections[_sectionindex].entries[_index].div.innerHTML = text;
			_listsections[_sectionindex].entries[_index].div.id = group + "GListItem";

			_listsections[_sectionindex].entries[_index].text = text;
			_listsections[_sectionindex].entries[_index].group = group;
			_listsections[_sectionindex].entries[_index].sort = name;
			_listsections[_sectionindex].entries[_index].entries = 1;
			_listsections[_sectionindex].entries[_index].index = _index;

			_listsections[_sectionindex].div.appendChild(_listsections[_sectionindex].entries[_index].div);

			_listsections[_sectionindex].entries[_index].clickfunction = function() {
				if (options.selectable) {
					if (!listoptions.multiselect) {
						for (w = 0; w < _listsections[_sectionindex].entries.length; w++) {
							if (_listsections[_sectionindex].entries[w].selected && _listsections[_sectionindex].entries[w] !== _listsections[_sectionindex].entries[_index]) {
								_deselectentry(_sectionindex, w);
							} else if (_listsections[_sectionindex].entries[w] === _listsections[_sectionindex].entries[_index]) {
								if (_listsections[_sectionindex].entries[w].selected) {
									_deselectentry(_sectionindex, w);
								} else {
									_selectentry(_sectionindex, w);
								}
							}
						}
					} else {
						if (_listsections[_sectionindex].entries[_index].selected) {
							_deselectentry(_sectionindex, _index);
						} else {
							_selectentry(_sectionindex, _index);
						}
					}
					_listsections[_sectionindex].entries[_index].oldcolor = _listsections[_sectionindex].selectcolor.getHex();
					_listsections[_sectionindex].entries[_index].oldbackcolor = _listsections[_sectionindex].selectbackcolor.getHex();
				}

				SJJS.util.Event.trigger(me, "clickitem", group, options.section);
			};
			_listsections[_sectionindex].entries[_index].click = SJJS.util.Event.addDomListener(_listsections[_sectionindex].entries[_index].div, "click", _listsections[_sectionindex].entries[_index].clickfunction);

			_listsections[_sectionindex].entries[_index].mouseoverfunction = function() {
				me.highlightByGroup(group, options.section);

				SJJS.util.Event.trigger(me, "mouseoveritem", group, options.section);
			};
			_listsections[_sectionindex].entries[_index].mouseover = SJJS.util.Event.addDomListener(_listsections[_sectionindex].entries[_index].div, "mouseover", _listsections[_sectionindex].entries[_index].mouseoverfunction);

			_listsections[_sectionindex].entries[_index].mouseoutfunction = function() {
				me.unhighlightByGroup(group, options.section);

				SJJS.util.Event.trigger(me, "mouseoutitem", group, options.section);
			};
			_listsections[_sectionindex].entries[_index].mouseout = SJJS.util.Event.addDomListener(_listsections[_sectionindex].entries[_index].div, "mouseout", _listsections[_sectionindex].entries[_index].mouseoutfunction);
		} else {
			_listsections[_sectionindex].entries[_groupindex].entries++;
		}
	};
	
	this.removeEntry = function(group, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);
		
		if (_groupindex !== -1) {
			_deleteentry(_sectionindex, _groupindex);
		} else {
			if (_listsections[_sectionindex].entries[_groupindex]) {
				_listsections[_sectionindex].entries[_groupindex].entries--;
				if (_listsections[_sectionindex].entries[_groupindex].entries <= 0) {
					_deleteentry(_sectionindex, _groupindex);
				}
			}
		}
	};

	this.highlightByGroup = function(group, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);

		if (!_listsections[_sectionindex].isCollapsed && _groupindex !== -1) {
			if (!_listsections[_sectionindex].entries[_groupindex].oldcolor) {
				_listsections[_sectionindex].entries[_groupindex].oldcolor = _listsections[_sectionindex].entries[_groupindex].div.style.color;
				_listsections[_sectionindex].entries[_groupindex].div.style.color = _listsections[_sectionindex].highlightcolor.getHex();
			}
			if (!_listsections[_sectionindex].entries[_groupindex].oldbackcolor) {
				_listsections[_sectionindex].entries[_groupindex].oldbackcolor = _listsections[_sectionindex].entries[_groupindex].div.style.backgroundColor;
				_listsections[_sectionindex].entries[_groupindex].div.style.backgroundColor = _listsections[_sectionindex].highlightbackcolor.getHex();
			}
		}
	};

	this.unhighlightByGroup = function(group, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);

		if (!_listsections[_sectionindex].isCollapsed && _groupindex !== -1) {
			if (_listsections[_sectionindex].entries[_groupindex].oldcolor) {
				_listsections[_sectionindex].entries[_groupindex].div.style.color = _listsections[_sectionindex].entries[_groupindex].oldcolor;
				_listsections[_sectionindex].entries[_groupindex].oldcolor = null;
			}
			if (_listsections[_sectionindex].entries[_groupindex].oldbackcolor) {
				_listsections[_sectionindex].entries[_groupindex].div.style.backgroundColor = _listsections[_sectionindex].entries[_groupindex].oldbackcolor;
				_listsections[_sectionindex].entries[_groupindex].oldbackcolor = null;
			}
		}
	};
	
	this.getDivByGroup = function(group, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);
	
		if (_groupindex !== -1) {
			return _listsections[_sectionindex].entries[_groupindex].div;
		}
		return undefined;
	};
	
	this.setSortByGroup = function(group, sort, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);
	
		if (_groupindex !== -1) {
			_listsections[_sectionindex].entries[_groupindex].sort = sort;
		}
	};
	
	this.sortListBySection = function(descending, section) {
		var x, i = 0;
		var _sectionindex = _findsectionindex(section);
	
		if (descending) {
	 		_listsections[_sectionindex].entries.sort(_dlistsort);
		}
		else {
			_listsections[_sectionindex].entries.sort(_listsort);
		}
		for (x = 0; x < _listsections[_sectionindex].entries.length; x++) {
			_listsections[_sectionindex].div.removeChild(_listsections[_sectionindex].entries[x].div);
		}

		_listsections[_sectionindex].everyother = false;
		for (x = 0; x < _listsections[_sectionindex].entries.length; x++) {
			_setbackground(_sectionindex, x);
			_listsections[_sectionindex].div.appendChild(_listsections[_sectionindex].entries[x].div);
		}
	};

	this.sortList = function(descending) {
		var x, s, i = 0;
		for (s = 0; s < _listsections.length; s++) {
			if (descending) {
		 		_listsections[s].entries.sort(_dlistsort);
			}
			else {
				_listsections[s].entries.sort(_listsort);
			}
			for (x = 0; x < _listsections[s].entries.length; x++) {
				_listsections[s].div.removeChild(_listsections[s].entries[x].div);
			}
	
			_listsections[s].everyother = false;
			for (x = 0; x < _listsections[s].entries.length; x++) {
				_setbackground(s, x);
				_listsections[s].div.appendChild(_listsections[s].entries[x].div);
			}
		}
	};

	this.setTextForGroup = function(text, section) {
		var _sectionindex = _findsectionindex(section);

		_listsections[_sectionindex].text = text;
		if (_listsections[_sectionindex].isCollapsed) {
			_listsections[_sectionindex].headerdiv.innerHTML = "+  " + text;
		} else {
			_listsections[_sectionindex].headerdiv.innerHTML = "-  " + text;
		}
	};

	this.getNumberOfEntries = function() {
		var x, w = 0;
		for (x = 0; x < _listsections.length; x++) {
			w += _listsections[x].entries.length;
		}
		return w;
	};

	this.getNumberOfEntriesForSection = function(section) {
		var _sectionindex = _findsectionindex(section);
		return _listsections[_sectionindex].entries.length;
	};

	this.getNumberOfEntriesForGroup = function(group, section) {
		var _sectionindex = _findsectionindex(section);
		var _groupindex = _findgroupindex(_sectionindex, group);
	
		if (_groupindex !== -1) {
			return _listsections[_sectionindex].entries[_groupindex].entries;
		}
		return 0;
	};

	this.getTextByIndex = function(index, section) {
		var _sectionindex = section || 0;
		return _listsections[_sectionindex].entries[index].text;
	};

	this.getGroupByIndex = function(index, section) {
		var _sectionindex = section || 0;
		return _listsections[_sectionindex].entries[index].group;
	};

	this.getSectionName = function(section) {
		return _listsections[section].name;
	};

	this.getSelected = function() {
		var x, y, _selected = [];

		for (x = 0; x < _listsections.length; x++) {
			for (y = 0; y < _listsections[x].entries.length; y++) {
				if (_listsections[x].entries[y].selected) {
					_selected.push({section: x, group: y});
				}
			}
		}
		return _selected;
	};
	
	this.Groups = function(section) {
		var _groupsarray = [];
		var x;
		var _sectionindex = _findsectionindex(section);
	
		for (x = 0; x < _listsections[_sectionindex].entries.length; x++) {
			_groupsarray.push(_listsections[_sectionindex].entries[x].group);
		}
	
		return _groupsarray;
	};

	this.setHeight = function(height) {
		_listheight = height;
		if (_listdiv.style.visibility === "visible") {
			_listdiv.style.height = _listheight + "px";
		}
	};

	this.getMainDiv = function() {
		return _listdiv;
	};
};

SJJS.GMap.Controls.AddressWindow = function(windowoptions, callback) {
	var me = this;

	var _addresswindow;
	var _addressoptionswindow;

	var _atable;
	var _atbody;
	var _atr1;
	var _atd1;
	var _atr2;
	var _atd2;
	var _asearch;
	var _aOk;
	var _aCancel;

	var _aotable;
	var _aotbody;
	var _aotr1;
	var _aotd1;
	var _aotr2;
	var _aotd2;
	var _highlightcolor;
	var _aolist;
	var _aoOk;
	var _aoCancel;

	var _listevents = {};

	var _highlightcolor = SJJS.util.Color.FromHex("#6789CC");
	_highlightcolor.setL(_highlightcolor.getL() + .07);
	var _selectcolor = SJJS.util.Color.FromHex("#6789CC");

	var _selectedname;

	function _removeentries() {
		var _names = _aolist.Groups();
		for (var w = 0; w < _names.length; w++) {
			_aolist.removeEntry(_names[w]);
		}
	}

	function _addresssearch(searchaddress, gowithfirst) {
		var gcoder = new google.maps.ClientGeocoder();
		gcoder.setViewport(new google.maps.LatLngBounds(new google.maps.LatLng(37.12473880841236, -122.34031677246094), new google.maps.LatLng(37.50209991181568, -121.4208984375)));
		if (!searchaddress) {
			searchaddress = document.getElementById("searchaddresstextid").value;
		}
		gcoder.getLocations(searchaddress, function(response) {
			var point;
			if (!response || response.Status.code !== 200) {
				alert(searchaddress + " not found");
			} else {
				if (gowithfirst)
				{
					point = new google.maps.LatLng(response.Placemark[0].Point.coordinates[1], response.Placemark[0].Point.coordinates[0]);
					callback(point);
				}
				else if (response.Placemark.length > 1)
				{
					for (var x = 0; x < response.Placemark.length; x++)
					{
						_aolist.addEntry(response.Placemark[x].address, response.Placemark[x].address, {selectable:true});
					}
					_addressoptionswindow.show();
					_aolist.show();
				} else {
					point = new google.maps.LatLng(response.Placemark[0].Point.coordinates[1], response.Placemark[0].Point.coordinates[0]);
					callback(point);
				}
			}
		});
		_addresswindow.hide();
	}

	_atable = document.createElement("table");
	_atable.style.height = "100%";
	_atable.style.width = "100%";
	_atable.style.fontSize = "10pt";
	_atable.id = "addresswindowtable";

	_atbody = document.createElement("tbody");
	_atable.appendChild(_atbody);

	_atr1 = document.createElement("tr");
	_atr1.style.height = "70%";
	_atbody.appendChild(_atr1);

	_atd1 = document.createElement("td");
	_atd1.style.width = "100%";
	_atd1.valign = "top";
	_atd1.innerHTML = 'Within distance of address<br />Examples:<br />Address: 200 E Santa Clara, San Jose, CA<br />Cross Streets (Enter streets seperated by ampersand(&): E Santa Clara & 10th St, San Jose, CA<br />';
	_atr1.appendChild(_atd1);

	_asearch = document.createElement("input");
	_asearch.id = "searchaddresstextid";
	_asearch.type = "text";
	_asearch.style.width = "90%";
	_atd1.appendChild(_asearch);

	_atr2 = document.createElement("tr");
	_atr2.style.height = "20%";
	_atbody.appendChild(_atr2);

	_atd2 = document.createElement("td");
	_atd2.style.width = "100%";
	_atd2.valign = "middle";
	_atd2.align = "center";
	_atr2.appendChild(_atd2);

	_aOk = document.createElement("input");
	_aOk.type = "button";
	_aOk.id = "addressOk";
	_aOk.style.height = "20px";
	_aOk.style.width = "50px";
	_aOk.value = "OK";
	_atd2.appendChild(_aOk);

	_aCancel = document.createElement("input");
	_aCancel.type = "button";
	_aCancel.id = "addressCancel";
	_aCancel.style.height = "20px";
	_aCancel.style.width = "70px";
	_aCancel.value = "Cancel";
	_atd2.appendChild(_aCancel);



	_aotable = document.createElement("table");
	_aotable.style.height = "100%";
	_aotable.style.width = "100%";
	_aotable.style.fontSize = "10pt";
	_aotable.id = "addressoptionswindowtable";

	_aotbody = document.createElement("tbody");
	_aotable.appendChild(_aotbody);

	_aotr1 = document.createElement("tr");
	_aotr1.style.height = "70%";
	_aotbody.appendChild(_aotr1);

	_aotd1 = document.createElement("td");
	_aotd1.style.width = "100%";
	_aotd1.valign = "top";
	_aotr1.appendChild(_aotd1);

	_highlightcolor = SJJS.util.Color.FromHex("#7AA9DD");
	_highlightcolor.setL(_highlightcolor.getL() + 0.15);
	_aolist = new SJJS.GMap.Controls.DivList({visible: false, highlightbackcolor: _highlightcolor, name:"addressoptionsList", width:340});
	_aotd1.appendChild(_aolist.getMainDiv());

	_aotr2 = document.createElement("tr");
	_aotr2.style.height = "20%";
	_aotbody.appendChild(_aotr2);

	_aotd2 = document.createElement("td");
	_aotd2.style.width = "100%";
	_aotd2.valign = "middle";
	_aotd2.align = "center";
	_aotr2.appendChild(_aotd2);

	_aoOk = document.createElement("input");
	_aoOk.type = "button";
	_aoOk.id = "addressoptionsOk";
	_aoOk.style.height = "20px";
	_aoOk.style.width = "50px";
	_aoOk.value = "OK";
	_aotd2.appendChild(_aoOk);

	_aoCancel = document.createElement("input");
	_aoCancel.type = "button";
	_aoCancel.id = "addressoptionsCancel";
	_aoCancel.style.height = "20px";
	_aoCancel.style.width = "70px";
	_aoCancel.value = "Cancel";
	_aotd2.appendChild(_aoCancel);

	windowoptions.width = 400;
	windowoptions.height = 150;

	_addresswindow = new SJJS.GMap.Controls.GWindow(windowoptions);
	_addressoptionswindow = new SJJS.GMap.Controls.GWindow(windowoptions);

	_addressoptionswindow.setHeight(300);
	_addressoptionswindow.setWidth(350);
	_addressoptionswindow.setTitle("Did you mean...");

	SJJS.util.Event.addListener(_addressoptionswindow, "windowclosed", function() {
		_removeentries();
		_aolist.hide();
	});

	SJJS.util.Event.addDomListener(_asearch, "keypress", function(event) {
		var keycode = event.which || event.keyCode;

		if (keycode === 13) {
			_addresssearch();
		}
	});

	SJJS.util.Event.addDomListener(_aOk, "click", function() {
		_addresssearch();
	});
	SJJS.util.Event.addDomListener(_aCancel, "click", function() {
		_addresswindow.hide();
	});
	SJJS.util.Event.addDomListener(_aoOk, "click", function() {
		var _selected = _aolist.getSelected();
		if (_selected.length > 0) {
			_addresssearch(_aolist.getGroupByIndex(_selected[0].group), true);
			_addressoptionswindow.hide();
		}
	});
	SJJS.util.Event.addDomListener(_aoCancel, "click", function() {
		_addressoptionswindow.hide();
	});

	_addresswindow.addContentDom(_atable);
	_addressoptionswindow.addContentDom(_aotable);

	me.show = function() {
		_addresswindow.show();
		_asearch.focus();
	};
	me.hide = function() {
		_addresswindow.hide();
		_addressoptionswindow.hide();
	};
};

//GList provides a list of markers added to the map

SJJS.GMap.Controls.GList = function(list) {
	var me = this;
	var _container = document.createElement("div");

	this.initialize = function(map) {
		list.setHeight(parseInt(map.getContainer().style.height.replace("px", ""), 10) - 20);
		_container.appendChild(list.getMainDiv());

		map.getContainer().appendChild(_container);

		google.maps.Event.addDomListener(map, "resize", function() {
			list.setHeight(parseInt(map.getContainer().style.height.replace("px", ""), 10) - 20);
		});

		return _container;
	};

	this.printable = function() {
		return true;
	};

	this.getDefaultPosition = function() {
		return new google.maps.ControlPosition(G_ANCHOR_TOP_RIGHT, new google.maps.Size(0, 0));
	};
}

//GMenuBar

SJJS.GMap.Controls.GMenuBar = function(menuoptions) {
	var me = this;

	if (!menuoptions) {
		menuoptions = {};
	}
	if (!menuoptions.color) {
		menuoptions.color = SJJS.util.Color.FromHex("#6789CC");
	}
	if (!menuoptions.backcolor) {
		menuoptions.backcolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!menuoptions.selectcolor) {
		menuoptions.selectcolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!menuoptions.selectbackcolor) {
		menuoptions.selectbackcolor = SJJS.util.Color.FromHex("#6789CC");
		menuoptions.selectbackcolor.setL(menuoptions.selectbackcolor.getL() + .07);
	}
	if (!menuoptions.highlightcolor) {
		menuoptions.highlightcolor = SJJS.util.Color.FromHex("#FFFFFF");
	}
	if (!menuoptions.highlightbackcolor) {
		menuoptions.highlightbackcolor = SJJS.util.Color.FromHex("#6789CC");
	}
	if (!menuoptions.bordercolor) {
		menuoptions.bordercolor = SJJS.util.Color.FromHex("#999999");
	}
	var _startx = 0;
	var _starty = 0;

	var _items = [];

	var _previousid;

	var _numspans = 0;
	var _itemwidth = 50;

	var container = document.createElement("div");

	var _map;

	var _menuopen = false;


	function _hideallexcept(menuid) {
		var x;

		for (x in _items)
		{
			if (x !== menuid)
			{
				if (!_items[x].parentid && _items[x].type === "menu") {
					_items[x].menuwindow.style.visibility = "hidden";
					_defaultid(x);
					_items[x].checked = false;
				}
			}
		}
	}

	function _hideall() {
		var x;

		for (x in _items)
		{
			if (!_items[x].parentid && _items[x].type === "menu") {
				_menuopen = false;
				_items[x].menuwindow.style.visibility = "hidden";
				_defaultid(x);
				_items[x].checked = false;
			}
		}
	}

	function _selectid(id) {
		_items[id].container.style.backgroundColor = menuoptions.selectbackcolor.getHex();
		_items[id].container.style.color = menuoptions.selectcolor.getHex();
	}

	function _highlightid(id) {
		_items[id].container.style.backgroundColor = menuoptions.highlightbackcolor.getHex();
		_items[id].container.style.color = menuoptions.highlightcolor.getHex();
	}

	function _defaultid(id) {
		_items[id].container.style.backgroundColor = menuoptions.backcolor.getHex();
		_items[id].container.style.color = menuoptions.color.getHex();
	}

	function _uncheckitem(itemid) {
		_items[itemid].checked = false;
		document.getElementById("chk" + itemid).checked = false;
		SJJS.util.Event.trigger(me, "itemunchecked", itemid);
	}

	function _checkitem(itemid) {
		_items[itemid].checked = true;
		document.getElementById("chk" + itemid).checked = true;
		SJJS.util.Event.trigger(me, "itemchecked", itemid);
	}

	function _removesubitems(menuid)
	{
		var x;
		if (_items[menuid])
		{	
			for (x in _items)
			{
				if (_items[x].parentid === menuid) {
					_items[menuid].menuwindow.removeChild(_items[x].container);
					delete _items[x].container;
					delete _items[x];
				}
			}
		}
	}

	function _addmaptypes() {
		var x, _maptypearray, _tempbool;

		if (!_items.MapTypeID)
		{
			me.addMenuItem("MapTypeID", "Map", {type:"menu"});
		} else {
			_removesubitems("MapTypeID");
		}

		_maptypearray = _map.getMapTypes();
		for (x = 0; x < _maptypearray.length; x++)
		{
			if (_maptypearray[x].getName(false) === _map.getCurrentMapType().getName(false)) {
				_tempbool = true;
			} else {
				_tempbool = false;
			}
			me.addMenuItem(_maptypearray[x].getName(false) + "ID", _maptypearray[x].getName(false), {parentid: "MapTypeID", checked: _tempbool, type: "option", group:"MapTypes"});

			_items[_maptypearray[x].getName(false) + "ID"].maptype = _maptypearray[x];
		}
	}

	me.addMenuItem = function(id, text, itemoptions) {
		var _templeft;
		var _boxwidth = 21;

		var checkprop = "";

		_items[id] = {text: text, type: itemoptions.type};
		if (!itemoptions.parentid) {
			if (!itemoptions.itemwidth) {
				itemoptions.itemwidth = _itemwidth;
			}
			if (!itemoptions.menuwidth) {
				itemoptions.menuwidth = 75;
			}

			_items[id].checked = false;
			_items[id].spannum = _numspans;
			_items[id].spanwidth = itemoptions.itemwidth;
			_items[id].menuposition = _startx;
			for (var x in _items)
			{
				if (_items[x].spannum < _numspans) {
					_items[id].menuposition += _items[x].spanwidth;
				}
			}

			_items[id].container = document.createElement("span");
			_items[id].container.style.position = "absolute";
			_items[id].container.style.width = itemoptions.itemwidth + "px";
			_items[id].container.style.height = "18px";
			_items[id].container.style.top = _starty + "px";
			_items[id].container.style.left = _items[id].menuposition + "px";
			_items[id].container.style.margin = "2px 0px 0px 0px";
			_items[id].container.style.padding = "0px 0px 0px 0px";
			_items[id].container.style.fontWeight = "bold";
			_items[id].container.style.textAlign = "center";
			_items[id].container.style.fontSize = "10pt";

			_items[id].container.style.borderBottom = "1px solid " + menuoptions.bordercolor.getHex();
			_items[id].container.style.borderTop = "1px solid " + menuoptions.bordercolor.getHex();
			if (_numspans === 0) {
				_items[id].container.style.borderLeft = "1px solid " + menuoptions.bordercolor.getHex();
				_items[id].container.style.borderRight = "1px solid " + menuoptions.bordercolor.getHex();
			} else {
				_items[_previousid].container.style.borderRight = "0px";
				_items[id].container.style.borderRight = "1px solid " + menuoptions.bordercolor.getHex();
			}
		} else {
			_items[id].parentid = itemoptions.parentid;
			_items[id].container = document.createElement("div");
			_items[id].container.style.fontSize = "8pt";
			_items[id].container.style.height = "18px";
			_items[id].container.style.width = "100%";
		}
		if ((itemoptions.type === "check" || itemoptions.type === "option") && itemoptions.checked)
		{
			_items[id].checked = true;
			checkprop = "checked='checked'";
		}
		if (itemoptions.type === "check")
		{
			_items[id].ischeck = true;
			_items[id].container.innerHTML = "<span style='float:left;height:100%;width:" + _boxwidth + "px;border-right:1px solid " + menuoptions.color.getHex() + "'><input type='checkbox' id='chk" + id + "' " + checkprop + "></input></span><span style='padding:0px 0px 0px 4px;'>" + text + "</span>";
		} else if (itemoptions.type === "option") {
			_items[id].isoption = true;
			_items[id].group = itemoptions.group;
			_items[id].container.innerHTML = "<span style='float:left;height:100%;width:" + _boxwidth + "px;border-right:1px solid " + menuoptions.color.getHex() + "'><input type='radio' id='chk" + id + "' " + checkprop + "></input></span><span style='padding:0px 0px 0px 4px;'>" + text + "</span>";
		} else if (itemoptions.parentid) {
			_items[id].container.innerHTML = "<span style='float:left;height:100%;width:" + _boxwidth + "px;border-right:1px solid " + menuoptions.color.getHex() + "'>&nbsp;</span><span style='padding:0px 0px 0px 4px;'>" + text + "</span>";
		} else {
			_items[id].container.innerHTML = _items[id].text;
		}
		_items[id].container.style.cursor = "pointer";
		_items[id].container.style.fontFamily = "Arial";
		_items[id].container.style.color = menuoptions.color.getHex();
		_items[id].container.style.backgroundColor = menuoptions.backcolor.getHex();
		_items[id].container.classid = "SJJSMenuItem";

		if (itemoptions.type === "menu")
		{
			_items[id].menuwindow = document.createElement("div");

			_items[id].menuwindow.style.position = "absolute";
			_items[id].menuwindow.style.top = (_starty + 21) + "px";
			_items[id].menuwindow.style.left = _items[id].menuposition + "px";
			_items[id].menuwindow.style.width = itemoptions.menuwidth + _boxwidth + 4 + "px";

			_items[id].menuwindow.style.position = "absolute";
			_items[id].menuwindow.style.fontFamily = "Arial";
			_items[id].menuwindow.style.fontSize = "8pt";
			_items[id].menuwindow.style.backgroundColor = menuoptions.backcolor.getHex();
			_items[id].menuwindow.style.border = "1px solid " + menuoptions.bordercolor.getHex();
			_items[id].menuwindow.style.margin = "0px 0px 0px 0px";
			_items[id].menuwindow.style.visibility = "hidden";

			container.appendChild(_items[id].menuwindow);
		}

		SJJS.util.Event.addDomListener(_items[id].container, "mouseover", function() {
			if (_menuopen && !itemoptions.parentid) {
				_hideallexcept(id);
				if (itemoptions.type === "menu") {
					_items[id].menuwindow.style.visibility = "visible";
					_items[id].checked = true;
				}
			}
			_highlightid(id);
		});
		SJJS.util.Event.addDomListener(_items[id].container, "mouseout", function() {
			if (_items[id].checked && _items[id].type === "menu") {
				_selectid(id);
			} else {
				_defaultid(id);
			}
		});

		SJJS.util.Event.addDomListener(_items[id].container, "click", function(e) {
			var x;

			if (!itemoptions.parentid) {
				if (!_items[id].checked && _items[id].type === "menu")
				{
					_hideall();
					_menuopen = true;
					_items[id].menuwindow.style.visibility = "visible";
					_items[id].checked = true;
					_highlightid(id);
				} else {
					_hideall();
				}
			}
			else {
				if (_items[id].type === "check")
				{
					if (_items[id].checked) {
						_uncheckitem(id);
					} else {
						_checkitem(id);
					}
				} else if (_items[id].type === "option") {
					me.checkItem(id);
					if (_items[id].parentid === "MapTypeID") {
						_map.setMapType(_items[id].maptype);
					}
				}
				_hideall();
			}
			SJJS.util.Event.trigger(me, "itemclicked", id);
		});

		if (!_items[id].parentid) {
			container.appendChild(_items[id].container);

			_numspans++;
			_previousid = id;
		} else {
			_items[_items[id].parentid].menuwindow.appendChild(_items[id].container);
		}
	}

	me.checkItem = function(itemid) {
		if (_items[itemid].ischeck) {
			_checkitem(itemid);
		}
		if (_items[itemid].isoption) {
			if (!_items[itemid].checked) {
				for (x in _items) {
					if (_items[x].group === _items[itemid].group && _items[itemid].group) {
						_uncheckitem(x);
					}
					_checkitem(itemid);
				}
			}
		}
	}

	me.uncheckItem = function(itemid) {
		if (_items[itemid].ischeck) {
			_uncheckitem(itemid);
		}
	}


	me.initialize = function(map) {
		_map = map;

		menuoptions.color.setL(menuoptions.color.getL() - 0.1);
	
		map.getContainer().appendChild(container);

		container.style.width = "100%";


		_addmaptypes();

		GEvent.addListener(_map, "addmaptype", function(maptype) {
			_addmaptypes();
		});
		GEvent.addListener(_map, "removemaptype", function(maptype) {
			_addmaptypes();
		});
		GEvent.addListener(_map, "maptypechanged", function() {
			me.checkItem(_map.getCurrentMapType().getName(false) + "ID");
		});

		return container;
	};
	
	me.getDefaultPosition = function() {
		return new google.maps.ControlPosition(G_ANCHOR_TOP_LEFT, new google.maps.Size(70, 10));
	};
}
