function s_gmap(param) {
	this.s_marker_icon = typeof param["marker_icon"] == "undefined" ? G_DEFAULT_ICON : param["marker_icon"];
	this.s_id = typeof param["id"] == "undefined" ? null : param["id"];
	this.s_info_id = typeof param["info_id"] == "undefined" ? null : param["info_id"];
	this.s_coord_id = typeof param["coord_id"] == "undefined" ? null : param["coord_id"];
	this.s_loader = typeof param["loader"] == "undefined" ? "" : param["loader"];
	this.s_on_found = typeof param["on_found"] == "undefined" ? null : param["on_found"];
	this.s_on_not_found = typeof param["on_not_found"] == "undefined" ? null : param["on_not_found"];
	this.s_zoom = typeof param["zoom"] == "undefined" ? 15 : param["zoom"];
	this.s_default_coord = typeof param["default_coord"] == "undefined" ? "48.712688|44.513394" : param["default_coord"];
	this.s_type = typeof param["type"] == "undefined" ? G_NORMAL_MAP : param["type"];
	this.s_zoom_control = typeof param["zoom_control"] == "undefined" ? true : param["zoom_control"];
	this.s_type_control = typeof param["type_control"] == "undefined" ? true : param["type_control"];
	this.s_view_marker = typeof param["view_marker"] == "undefined" ? true : param["view_marker"];
	this.s_markerable = typeof param["markerable"] == "undefined" ? false : param["markerable"];
	this.s_areable = typeof param["areable"] == "undefined" ? false : param["areable"];
	this.s_on_not_found = typeof param["on_not_found"] == "undefined" ? "" : param["on_not_found"];
	this.s_on_found = typeof param["on_found"] == "undefined" ? null : param["on_found"];
	this.s_background_color = typeof param["background_color"] == "undefined" ? null : param["background_color"];
	this.s_show_info_callback = typeof param["show_info_callback"] == "undefined" ? null : param["show_info_callback"];

	this.s_area = [0, 0, 0, 0];
	this.s_area_poly = null;
	this.s_coder = null;
	this.s_map = null;
	this.s_coord = null;
	this.s_map_info = "";
	this.s_markered = false;
	this.s_markers = new Array();
	if (this.s_id) this.s_map_frame = document.getElementById(this.s_id);
	if (this.s_coord_id) this.s_coord = document.getElementById(this.s_coord_id);
	if (this.s_info_id) this.s_info = document.getElementById(this.s_info_id);
	else this.s_info = document.createElement("div");
	//this.s_info.id = this.s_id + "_info";
	this.s_info.style.display = "none";
	document.body.appendChild(this.s_info);

	this.s_show = function(coord, zoom, type) {
		coord = typeof coord == "undefined" ? "" : coord;
		if (typeof zoom != "undefined") this.s_zoom = zoom;
		if (typeof type != "undefined") this.s_type = type;
		var x = 0, y = 0, need_marker = true;
		/*if (this.s_is_visible()) {
			this.s_hide();
			return false;
		}*/
		if (coord.length > 0) {
			var coord_arr = this.s_get_coord(coord);
			x = coord_arr[0];
			y = coord_arr[1];
		}
		if (!x || !y) {
			var coord_1 = "";
			try { coord_1 = this.s_coord.value } catch (e) {  };
			if (coord_1.length == 0) try { coord_1 = this.s_coord.innerHTML } catch (e) {  };
			if (coord_1.length > 0) {
				var coord_arr = this.s_get_coord(coord_1);
				x = coord_arr[0];
				y = coord_arr[1];
			}

		}
		if ((!x || !y) && coord.length > 0) {
			this.s_find(coord);
			return false;
		}
		if (!x || !y) {
			var coord_arr = this.s_get_coord(this.s_default_coord);
			x = coord_arr[0];
			y = coord_arr[1];
			need_marker = false;
		}
		this.s_map_frame.style.display = "block";
		this.s_map = new GMap2(this.s_map_frame, {
			draggableCursor: this.s_markerable || this.s_areable ? 'crosshair' : '',
			googleBarOptions:{
				showOnLoad:true
			}/*,
			size: new GSize(
				parseInt(this.s_map_frame.style.width),
				parseInt(this.s_map_frame.style.height)
			)*/
		});
		this.s_map.enableScrollWheelZoom();
		this.s_map.s_marker = null;
		this.s_map.s_obj = this;
		this.s_map.s_mark_clear = function() {
			var obj = typeof this.s_map == "undefined"
				? this
				: this.s_map;
			obj.removeOverlay(obj.s_marker);
			obj.s_marker = null;
			obj.s_clear_map_url();
		};
		this.s_map.s_clear_map_url = function() {
			if (this.s_obj.s_coord) this.s_obj.s_coord.value = "";
		};
		this.s_map.s_update_map_url = function() {
			if (this.s_obj.s_markerable) {
				try { var lat = this.s_marker.getPoint().lat(); lat = lat.toFixed(6); } catch (e) { };
				try { var lng = this.s_marker.getPoint().lng(); lng = lng.toFixed(6); } catch (e) { };
				if (this.s_obj.s_coord) this.s_obj.s_coord.value = lat + "|" + lng;
			}
			if (this.s_obj.s_areable) {
				var lat = this.s_obj.s_area[0].toFixed(6);
				var lng = this.s_obj.s_area[1].toFixed(6);
				var lat_1 = this.s_obj.s_area[2].toFixed(6);
				var lng_1 = this.s_obj.s_area[3].toFixed(6);
				if (this.s_obj.s_coord && lat && lat_1 && lng && lng_1) this.s_obj.s_coord.value = Math.min(lat, lat_1) + "|" + Math.min(lng, lng_1) + "|" + Math.max(lat, lat_1) + "|" + Math.max(lng, lng_1);
			}
		};
		if (this.s_zoom_control == "zoom") this.s_map.addControl(new GSmallZoomControl());
		else if (this.s_zoom_control) this.s_map.addControl(new GLargeMapControl());
		if (this.s_type_control) this.s_map.addControl(new GMapTypeControl());
		this.s_map.setCenter(new GLatLng(x, y), this.s_zoom);
		this.s_map.setMapType(this.s_type);

		if (this.s_markerable) GEvent.addListener(this.s_map, "click", this.s_mark);
		if (this.s_areable) {
			GEvent.addListener(this.s_map, "click", this.s_area_click);
			GEvent.addListener(this.s_map, "mousemove", function(point) {
				this.s_obj.s_area_draw(this, point);
			});
		}
		if (this.s_markerable && x && y && this.s_view_marker && need_marker) this.s_mark(null, new GLatLng(x, y), true);
		if (this.s_areable && coord_arr.length == 4 && this.s_view_marker && need_marker) {
			this.s_area = coord_arr;
			this.s_area_draw(this.s_map);
		}
		return false;
	};
	
	this.s_area_click = function(overlay, point, pp) {
		if (typeof point == 'undefined') point = pp;
		if (this.s_obj.s_area[0] == 0) {
			this.s_obj.s_area[0] = point.lat();
			this.s_obj.s_area[1] = point.lng();
		}
		else if (this.s_obj.s_area[2] == 0) {
			this.s_obj.s_area[2] = point.lat();
			this.s_obj.s_area[3] = point.lng();
		}
		else {
			this.s_obj.s_area = [0, 0, 0, 0];
			if (this.s_obj.s_area_poly) {
				this.removeOverlay(this.s_obj.s_area_poly);
				this.s_obj.s_area_poly = null;
			}
		}
		if (overlay) overlay.s_map.s_update_map_url();
		else this.s_update_map_url();
	};
	
	this.s_area_draw = function(map, point) {
		if ((this.s_area[0] != 0 && this.s_area[2] == 0) || typeof point == 'undefined') {
			if (typeof point == 'undefined') point = new GLatLng(this.s_area[2], this.s_area[3]);
			if (this.s_area_poly) map.removeOverlay(this.s_area_poly);
			this.s_area_poly = new GPolygon(
				[
					new GLatLng(this.s_area[0], this.s_area[1]),
					new GLatLng(this.s_area[0], point.lng()),
					new GLatLng(point.lat(), point.lng()),
					new GLatLng(point.lat(), this.s_area[1]),
					new GLatLng(this.s_area[0], this.s_area[1]),
				],
				"#FF0000",
				1,
				0.5,
				"#FF0000",
				0.2
			);
			this.s_area_poly.s_map = map;
			map.addOverlay(this.s_area_poly);
		}
	};

	this.s_mark = function(overlay, point, dont_mark) {
		dont_mark = typeof dont_mark == "undefined" ? false : dont_mark;
		if (overlay) return false;
		var obj = typeof this.s_marker == "undefined"
			? this.s_map
			: this;
		if (obj.s_marker) obj.s_mark_clear();
		obj.s_marker = new GMarker(point, {
			draggable : obj.s_obj.s_markerable
					? true
					: false,
			bouncy : true,
			dragCrossMove : true,
			icon: this.s_marker_icon
		});
		obj.s_marker.s_map = obj;
		obj.addOverlay(obj.s_marker);
		if (obj.s_obj.s_markerable) {
			if (!dont_mark) obj.s_update_map_url();
			GEvent.addListener(obj.s_marker, "click", obj.s_mark_clear);
			GEvent.addListener(obj.s_marker, "dragend", function() {
				this.s_map.s_update_map_url();
			});
		}
	};

	this.s_set_markers = function(data) {
		this.s_map_info = this.s_info.innerHTML;
		this.s_map.clearOverlays();
		this.s_markers = new Array();
		for (var i = 0; i < data.length; i++) {
			this.s_markers[this.s_markers.length] = new GMarker(new GLatLng(data[i]["x"], data[i]["y"]), {
				draggable : false,
				icon: this.s_marker_icon
			});
			this.s_markers[this.s_markers.length - 1].mid = data[i]["id"];
			this.s_markers[this.s_markers.length - 1].s_obj = this;
			eval("GEvent.addListener(this.s_markers[this.s_markers.length - 1], \"click\", function() { this.s_obj.s_show_info(this); });");
			this.s_map.addOverlay(this.s_markers[this.s_markers.length - 1]);
		}
		this.s_markered = true;
	};

	this.s_show_info = function(mark, no_c_close) {
		no_c_close = typeof no_c_close == 'undefined' ? false : no_c_close;
		this.s_info.innerHTML = this.s_map_info;
		mark.openInfoWindow(document.getElementById(mark.mid), {
			noCloseOnClick : no_c_close
		});
		if (this.s_show_info_callback) this.s_show_info_callback();
		return false
	};

	this.s_find = function(address) {
		//if (this.s_map_frame.style.display == "none") {
			this.s_coder = new GClientGeocoder();
			f = this;
			this.s_coder.getLocations(address, this.s_find_complete);
			this.s_map_frame.innerHTML = this.s_loader;
			this.s_map_frame.style.display = "block";
			this.s_width = this.s_map_frame.style.width;
			this.s_height = this.s_map_frame.style.height;
			/*this.s_map_frame.style.width = */this.s_map_frame.style.height = "";
		//}
		//else this.s_map_frame.display = "none";
	};

	this.s_find_complete = function(response) {
		f.s_hide();
		//f.s_map_frame.style.width = f.s_width;
		f.s_map_frame.style.height = f.s_height;
		if (!response || response.Status.code != 200) {
			try { eval(f.s_on_not_found); } catch (e) { };
			if (f.s_markerable) f.s_show();
		}
		else {
			var place = response.Placemark[0];
			f.s_show(place.Point.coordinates[1] + "|" + place.Point.coordinates[0]);
			var lat = place.Point.coordinates[1];
			var lng = place.Point.coordinates[0]
			try { eval(f.s_on_found); } catch (e) { };
			
		} 
	};

	this.s_get_coord = function(coord) {
		var ret = [];
		if (coord.length > 0) {
		var ln = 0;
			coord += "|";
			for (var i = 0; i < coord.length; i++) {
				if (coord.slice(i, i + 1) == "|") {
					ret[ret.length] = coord.slice(ln, i);
					ln = i + 1;
				}
			}
		}
		return ret;
	};

	this.s_hide = function() {
		if (this.s_map_frame) {
			this.s_map_frame.style.display = "none";
			if (this.s_background_color) this.s_map_frame.style.backgroundColor = this.s_background_color;
		}
		return false;
	};

	this.s_is_visible = function() {
		return this.s_map_frame && this.s_map_frame.style.display == "block";
	};
}

