(function($){
var geocoder=new google.maps.Geocoder();
function MyOverlay(map){ this.setMap(map); };
MyOverlay.prototype=new google.maps.OverlayView();
MyOverlay.prototype.onAdd=function(){ };
MyOverlay.prototype.onRemove=function(){ };
MyOverlay.prototype.draw=function(){ };
$.goMap={};
$.fn.goMap=function(options){
return this.each(function(){
var goMap=$(this).data('goMap');
if(!goMap){
var goMapBase=$.extend(true, {}, $.goMapBase);
$(this).data('goMap', goMapBase.init(this, options));
$.goMap=goMapBase;
}else{
$.goMap=goMap;
}});
};
$.goMapBase={
defaults: {
draggablemaps:              true,
address:					'',
latitude:					56.9,
longitude:					24.1,
zoom:						4,
delay:						200,
hideByClick:				true,
oneInfoWindow:				true,
prefixId:					'gomarker',
polyId:						'gopoly',
groupId:					'gogroup',
navigationControl:			true,
navigationControlOptions:	{
position:	'TOP_LEFT',
style:		'DEFAULT'
},
mapTypeControl: 			true,
mapTypeControlOptions:		{
position: 	'TOP_RIGHT',
style: 		'DEFAULT'
},
scaleControl: 				false,
scrollwheel:				true,
directions: 				false,
directionsResult: 			null,
disableDoubleClickZoom:		false,
streetViewControl:			false,
markers:					[],
overlays:					[],
polyline:					{
color:		'#FF0000',
opacity:	1.0,
weight:		2
},
polygon:					{
color:			'#FF0000',
opacity:		1.0,
weight:			2,
fillColor:		'#FF0000',
fillOpacity:	0.2
},
circle:						{
color:			'#FF0000',
opacity:		1.0,
weight:			2,
fillColor:		'#FF0000',
fillOpacity:	0.2
},
rectangle:					{
color:			'#FF0000',
opacity:		1.0,
weight:			2,
fillColor:		'#FF0000',
fillOpacity:	0.2
},
maptype:					'HYBRID',
html_prepend:				'<div class=gomapMarker>',
html_append:				'</div>',
addMarker:					false
},
map:			null,
count:			0,
markers:		[],
polylines:		[],
polygons:		[],
circles:		[],
rectangles:		[],
tmpMarkers:		[],
geoMarkers:		[],
lockGeocode:	false,
bounds:			null,
overlays:		null,
overlay:		null,
mapId:			null,
plId:			null,
pgId:			null,
cId:			null,
rId:			null,
opts:			null,
centerLatLng:	null,
init: function(el, options){
var opts=$.extend(true, {}, $.goMapBase.defaults, options);
this.mapId=$(el);
this.opts=opts;
if(opts.address)
this.geocode({address: opts.address, center: true});
else if($.isArray(opts.markers)&&opts.markers.length > 0){
if(opts.markers[0].address)
this.geocode({address: opts.markers[0].address, center: true});
else
this.centerLatLng=new google.maps.LatLng(opts.markers[0].latitude, opts.markers[0].longitude);
}
else
this.centerLatLng=new google.maps.LatLng(opts.latitude, opts.longitude);
var myOptions={
center: 				this.centerLatLng,
disableDoubleClickZoom:	opts.disableDoubleClickZoom,
mapTypeControl:			opts.mapTypeControl,
streetViewControl:		opts.streetViewControl,
mapTypeControlOptions:  {
position:	google.maps.ControlPosition[opts.mapTypeControlOptions.position.toUpperCase()],
style:		google.maps.MapTypeControlStyle[opts.mapTypeControlOptions.style.toUpperCase()]
},
mapTypeId:				google.maps.MapTypeId[opts.maptype.toUpperCase()],
navigationControl:		opts.navigationControl,
navigationControlOptions: {
position:	google.maps.ControlPosition[opts.navigationControlOptions.position.toUpperCase()],
style:		google.maps.NavigationControlStyle[opts.navigationControlOptions.style.toUpperCase()]
},
scaleControl:			opts.scaleControl,
scrollwheel:			opts.scrollwheel,
zoom:					opts.zoom,
draggable: opts.draggablemaps
};
this.map=new google.maps.Map(el, myOptions);
this.overlay=new MyOverlay(this.map);
this.overlays={
polyline:	{ id: 'plId', array: 'polylines', 	create: 'createPolyline' },
polygon:	{ id: 'pgId', array: 'polygons', 	create: 'createPolygon' },
circle:		{ id: 'cId',  array: 'circles',		create: 'createCircle' },
rectangle:	{ id: 'rId',  array: 'rectangles',	create: 'createRectangle' }};
this.plId=$('<div style="display:none;"/>').appendTo(this.mapId);
this.pgId=$('<div style="display:none;"/>').appendTo(this.mapId);
this.cId=$('<div style="display:none;"/>').appendTo(this.mapId);
this.rId=$('<div style="display:none;"/>').appendTo(this.mapId);
for (var j=0, l=opts.markers.length; j < l; j++)
this.createMarker(opts.markers[j]);
for (var j=0, l=opts.overlays.length; j < l; j++)
this[this.overlays[opts.overlays[j].type].create](opts.overlays[j]);
var goMap=this;
if(opts.addMarker==true||opts.addMarker=='multi'){
google.maps.event.addListener(goMap.map, 'click', function(event){
var options={
position:  event.latLng,
draggable: true
};
var marker=goMap.createMarker(options);
google.maps.event.addListener(marker, 'dblclick', function(event){
marker.setMap(null);
goMap.removeMarker(marker.id);
});
});
}
else if(opts.addMarker=='single'){
google.maps.event.addListener(goMap.map, 'click', function(event){
if(!goMap.singleMarker){
var options={
position:  event.latLng,
draggable: true
};
var marker=goMap.createMarker(options);
goMap.singleMarker=true;
google.maps.event.addListener(marker, 'dblclick', function(event){
marker.setMap(null);
goMap.removeMarker(marker.id);
goMap.singleMarker=false;
});
}});
}
delete opts.markers;
delete opts.overlays;
return this;
},
ready: function(f){
google.maps.event.addListenerOnce(this.map, 'bounds_changed', function(){
return f();
});
},
geocode: function(address, options){
var goMap=this;
setTimeout(function(){
geocoder.geocode({'address': address.address}, function(results, status){
if(status==google.maps.GeocoderStatus.OK&&address.center)
goMap.map.setCenter(results[0].geometry.location);
if(status==google.maps.GeocoderStatus.OK&&options&&options.markerId)
options.markerId.setPosition(results[0].geometry.location);
else if(status==google.maps.GeocoderStatus.OK&&options){
if(goMap.lockGeocode){
goMap.lockGeocode=false;
options.position=results[0].geometry.location;
options.geocode=true;
goMap.createMarker(options);
}}
else if(status==google.maps.GeocoderStatus.OVER_QUERY_LIMIT){
goMap.geocode(address, options);
}});
}, this.opts.delay);
},
geoMarker: function(){
if(this.geoMarkers.length > 0&&!this.lockGeocode){
this.lockGeocode=true;
var current=this.geoMarkers.splice(0, 1);
this.geocode({address:current[0].address}, current[0]);
}
else if(this.lockGeocode){
var goMap=this;
setTimeout(function(){
goMap.geoMarker();
}, this.opts.delay);
}},
setMap: function(options){
delete options.mapTypeId;
if(options.address){
this.geocode({address: options.address, center: true});
delete options.address;
}
else if(options.latitude&&options.longitude){
options.center=new google.maps.LatLng(options.latitude, options.longitude);
delete options.longitude;
delete options.latitude;
}
if(options.mapTypeControlOptions&&options.mapTypeControlOptions.position)
options.mapTypeControlOptions.position=google.maps.ControlPosition[options.mapTypeControlOptions.position.toUpperCase()];
if(options.mapTypeControlOptions&&options.mapTypeControlOptions.style)
options.mapTypeControlOptions.style=google.maps.MapTypeControlStyle[options.mapTypeControlOptions.style.toUpperCase()];
if(options.navigationControlOptions&&options.navigationControlOptions.position)
options.navigationControlOptions.position=google.maps.ControlPosition[options.navigationControlOptions.position.toUpperCase()];
if(options.navigationControlOptions&&options.navigationControlOptions.style)
options.navigationControlOptions.style=google.maps.NavigationControlStyle[options.navigationControlOptions.style.toUpperCase()];
this.map.setOptions(options);
},
getMap: function(){
return this.map;
},
createListener: function(type, event, data){
var target;
if(typeof type!='object')
type={type:type};
if(type.type=='map')
target=this.map;
else if(type.type=='marker'&&type.marker)
target=$(this.mapId).data(type.marker);
else if(type.type=='info'&&type.marker)
target=$(this.mapId).data(type.marker + 'info');
if(target)
return google.maps.event.addListener(target, event, data);
else if((type.type=='marker'||type.type=='info')&&this.getMarkerCount()!=this.getTmpMarkerCount())
var goMap=this;
setTimeout(function(){
goMap.createListener(type, event, data);
}, this.opts.delay);
},
removeListener: function(listener){
google.maps.event.removeListener(listener);
},
setInfoWindow: function(marker, html){
var goMap=this;
html.content=goMap.opts.html_prepend + html.content + goMap.opts.html_append;
var infowindow=new google.maps.InfoWindow(html);
infowindow.show=false;
$(goMap.mapId).data(marker.id + 'info',infowindow);
if(html.popup){
goMap.openWindow(infowindow, marker, html);
infowindow.show=true;
}
google.maps.event.addListener(marker, 'click', function(){
if(infowindow.show&&goMap.opts.hideByClick){
infowindow.close();
infowindow.show=false;
}else{
goMap.openWindow(infowindow, marker, html);
infowindow.show=true;
}});
},
openWindow: function(infowindow, marker, html){
if(this.opts.oneInfoWindow)
this.clearInfo();
if(html.ajax){
infowindow.open(this.map, marker);
$.ajax({
url: html.ajax,
success: function(html){
infowindow.setContent(html);
}});
}
else if(html.id){
infowindow.setContent($(html.id).html());
infowindow.open(this.map, marker);
}
else
infowindow.open(this.map, marker);
},
setInfo: function(id, text){
var info=$(this.mapId).data(id + 'info');
if(typeof text=='object')
info.setOptions(text);
else
info.setContent(text);
},
getInfo: function(id, hideDiv){
var info=$(this.mapId).data(id + 'info').getContent();
if(hideDiv)
return $(info).html();
else
return info;
},
clearInfo: function(){
for (var i=0, l=this.markers.length; i < l; i++){
var info=$(this.mapId).data(this.markers[i] + 'info');
if(info){
info.close();
info.show=false;
}}
},
fitBounds: function(type, markers){
var goMap=this;
if(this.getMarkerCount()!=this.getTmpMarkerCount())
setTimeout(function(){
goMap.fitBounds(type, markers);
}, this.opts.delay);
else {
this.bounds=new google.maps.LatLngBounds();
if(!type||(type&&type=='all')){
for (var i=0, l=this.markers.length; i < l; i++){
this.bounds.extend($(this.mapId).data(this.markers[i]).position);
}}
else if(type&&type=='visible'){
for (var i=0, l=this.markers.length; i < l; i++){
if(this.getVisibleMarker(this.markers[i]))
this.bounds.extend($(this.mapId).data(this.markers[i]).position);
}}
else if(type&&type=='markers'&&$.isArray(markers)){
for (var i=0, l=markers.length; i < l; i++){
this.bounds.extend($(this.mapId).data(markers[i]).position);
}}
this.map.fitBounds(this.bounds);
}},
getBounds: function(){
return this.map.getBounds();
},
createPolyline: function(poly){
poly.type='polyline';
return this.createOverlay(poly);
},
createPolygon: function(poly){
poly.type='polygon';
return this.createOverlay(poly);
},
createCircle: function(poly){
poly.type='circle';
return this.createOverlay(poly);
},
createRectangle: function(poly){
poly.type='rectangle';
return this.createOverlay(poly);
},
createOverlay: function(poly){
var overlay=[];
if(!poly.id){
this.count++;
poly.id=this.opts.polyId + this.count;
}
switch(poly.type){
case 'polyline':
if(poly.coords.length > 0){
for (var j=0, l=poly.coords.length; j < l; j++)
overlay.push(new google.maps.LatLng(poly.coords[j].latitude, poly.coords[j].longitude));
overlay=new google.maps.Polyline({
map: this.map,
path: overlay,
strokeColor: 	poly.color ? poly.color:this.opts.polyline.color,
strokeOpacity:	poly.opacity ? poly.opacity:this.opts.polyline.opacity,
strokeWeight:	poly.weight ? poly.weight:this.opts.polyline.weight
});
}
else
return false;
break;
case 'polygon':
if(poly.coords.length > 0){
for (var j=0, l=poly.coords.length; j < l; j++)
overlay.push(new google.maps.LatLng(poly.coords[j].latitude, poly.coords[j].longitude));
overlay=new google.maps.Polygon({
map: this.map,
path: overlay,
strokeColor: poly.color ? poly.color:this.opts.polygon.color,
strokeOpacity: poly.opacity ? poly.opacity:this.opts.polygon.opacity,
strokeWeight: poly.weight ? poly.weight:this.opts.polygon.weight,
fillColor: poly.fillColor ? poly.fillColor:this.opts.polygon.fillColor,
fillOpacity: poly.fillOpacity ? poly.fillOpacity:this.opts.polygon.fillOpacity
});
}
else
return false;
break;
case 'circle':
overlay=new google.maps.Circle({
map: this.map,
center: new google.maps.LatLng(poly.latitude, poly.longitude),
radius: poly.radius,
strokeColor: poly.color ? poly.color:this.opts.circle.color,
strokeOpacity: poly.opacity ? poly.opacity:this.opts.circle.opacity,
strokeWeight: poly.weight ? poly.weight:this.opts.circle.weight,
fillColor: poly.fillColor ? poly.fillColor:this.opts.circle.fillColor,
fillOpacity: poly.fillOpacity ? poly.fillOpacity:this.opts.circle.fillOpacity
});
break;
case 'rectangle':
overlay=new google.maps.Rectangle({
map: this.map,
bounds: new google.maps.LatLngBounds(new google.maps.LatLng(poly.sw.latitude, poly.sw.longitude), new google.maps.LatLng(poly.ne.latitude, poly.ne.longitude)),
strokeColor: poly.color ? poly.color:this.opts.circle.color,
strokeOpacity: poly.opacity ? poly.opacity:this.opts.circle.opacity,
strokeWeight: poly.weight ? poly.weight:this.opts.circle.weight,
fillColor: poly.fillColor ? poly.fillColor:this.opts.circle.fillColor,
fillOpacity: poly.fillOpacity ? poly.fillOpacity:this.opts.circle.fillOpacity
});
break;
default:
return false;
break;
}
this.addOverlay(poly, overlay);
return overlay;
},
addOverlay: function(poly, overlay){
$(this[this.overlays[poly.type].id]).data(poly.id, overlay);
this[this.overlays[poly.type].array].push(poly.id);
},
setOverlay: function(type, overlay, options){
overlay=$(this[this.overlays[type].id]).data(overlay);
if(options.coords&&options.coords.length > 0){
var array=[];
for (var j=0, l=options.coords.length; j < l; j++)
array.push(new google.maps.LatLng(options.coords[j].latitude, options.coords[j].longitude));
options.path=array;
delete options.coords;
}
else if(options.ne&&options.sw){
options.bounds=new google.maps.LatLngBounds(new google.maps.LatLng(options.sw.latitude, options.sw.longitude), new google.maps.LatLng(options.ne.latitude, options.ne.longitude));
delete options.ne;
delete options.sw;
}
else if(options.latitude&&options.longitude){
options.center=new google.maps.LatLng(options.latitude, options.longitude);
delete options.latitude;
delete options.longitude;
}
overlay.setOptions(options);
},
showHideOverlay: function(type, overlay, display){
if(typeof display==='undefined'){
if(this.getVisibleOverlay(type, overlay))
display=false;
else
display=true;
}
if(display)
$(this[this.overlays[type].id]).data(overlay).setMap(this.map);
else
$(this[this.overlays[type].id]).data(overlay).setMap(null);
},
getVisibleOverlay: function(type, overlay){
if($(this[this.overlays[type].id]).data(overlay).getMap())
return true;
else
return false;
},
getOverlaysCount: function(type){
return this[this.overlays[type].array].length;
},
removeOverlay: function(type, overlay){
var index=$.inArray(overlay, this[this.overlays[type].array]), current;
if(index > -1){
current=this[this.overlays[type].array].splice(index, 1);
var markerId=current[0];
$(this[this.overlays[type].id]).data(markerId).setMap(null);
$(this[this.overlays[type].id]).removeData(markerId);
return true;
}
return false;
},
clearOverlays: function(type){
for (var i=0, l=this[this.overlays[type].array].length; i < l; i++){
var markerId=this[this.overlays[type].array][i];
$(this[this.overlays[type].id]).data(markerId).setMap(null);
$(this[this.overlays[type].id]).removeData(markerId);
}
this[this.overlays[type].array]=[];
},
showHideMarker: function(marker, display){
if(typeof display==='undefined'){
if(this.getVisibleMarker(marker)){
$(this.mapId).data(marker).setVisible(false);
var info=$(this.mapId).data(marker + 'info');
if(info&&info.show){
info.close();
info.show=false;
}}
else
$(this.mapId).data(marker).setVisible(true);
}
else
$(this.mapId).data(marker).setVisible(display);
},
showHideMarkerByGroup: function(group, display){
for (var i=0, l=this.markers.length; i < l; i++){
var markerId=this.markers[i];
var marker=$(this.mapId).data(markerId);
if(marker.group==group){
if(typeof display==='undefined'){
if(this.getVisibleMarker(markerId)){
marker.setVisible(false);
var info=$(this.mapId).data(markerId + 'info');
if(info&&info.show){
info.close();
info.show=false;
}}
else
marker.setVisible(true);
}
else
marker.setVisible(display);
}}
},
getVisibleMarker: function(marker){
return $(this.mapId).data(marker).getVisible();
},
getMarkerCount: function(){
return this.markers.length;
},
getTmpMarkerCount: function(){
return this.tmpMarkers.length;
},
getVisibleMarkerCount: function(){
return this.getMarkers('visiblesInMap').length;
},
getMarkerByGroupCount: function(group){
return this.getMarkers('group', group).length;
},
getMarkers: function(type, name){
var array=[];
switch(type){
case "json":
for (var i=0, l=this.markers.length; i < l; i++){
var temp="'" + i + "': '" + $(this.mapId).data(this.markers[i]).getPosition().toUrlValue() + "'";
array.push(temp);
}
array="{'markers':{" + array.join(",") + "}}";
break;
case "data":
for (var i=0, l=this.markers.length; i < l; i++){
var temp="marker[" + i + "]=" + $(this.mapId).data(this.markers[i]).getPosition().toUrlValue();
array.push(temp);
}
array=array.join("&");
break;
case "visiblesInBounds":
for (var i=0, l=this.markers.length; i < l; i++){
if(this.isVisible($(this.mapId).data(this.markers[i]).getPosition()))
array.push(this.markers[i]);
}
break;
case "visiblesInMap":
for (var i=0, l=this.markers.length; i < l; i++){
if(this.getVisibleMarker(this.markers[i]))
array.push(this.markers[i]);
}
break;
case "group":
if(name)
for (var i=0, l=this.markers.length; i < l; i++){
if($(this.mapId).data(this.markers[i]).group==name)
array.push(this.markers[i]);
}
break;
case "markers":
for (var i=0, l=this.markers.length; i < l; i++){
var temp=$(this.mapId).data(this.markers[i]);
array.push(temp);
}
break;
default:
for (var i=0, l=this.markers.length; i < l; i++){
var temp=$(this.mapId).data(this.markers[i]).getPosition().toUrlValue();
array.push(temp);
}
break;
}
return array;
},
getVisibleMarkers: function(){
return this.getMarkers('visiblesInBounds');
},
createMarker: function(marker){
if(!marker.geocode){
this.count++;
if(!marker.id)
marker.id=this.opts.prefixId + this.count;
this.tmpMarkers.push(marker.id);
}
if(marker.address&&!marker.geocode){
this.geoMarkers.push(marker);
this.geoMarker();
}
else if(marker.latitude&&marker.longitude||marker.position){
var options={ map:this.map };
options.id=marker.id;
options.group=marker.group ? marker.group:this.opts.groupId;
options.zIndex=marker.zIndex ? marker.zIndex:0;
options.zIndexOrg=marker.zIndexOrg ? marker.zIndexOrg:0;
if(marker.visible==false)
options.visible=marker.visible;
if(marker.title)
options.title=marker.title;
if(marker.draggable)
options.draggable=marker.draggable;
if(marker.icon&&marker.icon.image){
options.icon=marker.icon.image;
if(marker.icon.shadow)
options.shadow=marker.icon.shadow;
}
else if(marker.icon)
options.icon=marker.icon;
else if(this.opts.icon&&this.opts.icon.image){
options.icon=this.opts.icon.image;
if(this.opts.icon.shadow)
options.shadow=this.opts.icon.shadow;
}
else if(this.opts.icon)
options.icon=this.opts.icon;
options.position=marker.position ? marker.position:new google.maps.LatLng(marker.latitude, marker.longitude);
var cmarker=new google.maps.Marker(options);
if(marker.html){
if(!marker.html.content&&!marker.html.ajax&&!marker.html.id)
marker.html={ content:marker.html };
else if(!marker.html.content)
marker.html.content=null;
this.setInfoWindow(cmarker, marker.html);
}
this.addMarker(cmarker);
return cmarker;
}},
addMarker: function(marker){
$(this.mapId).data(marker.id, marker);
this.markers.push(marker.id);
},
setMarker: function(marker, options){
var tmarker=$(this.mapId).data(marker);
delete options.id;
delete options.visible;
if(options.icon){
var toption=options.icon;
delete options.icon;
if(toption&&toption=='default'){
if(this.opts.icon&&this.opts.icon.image){
options.icon=this.opts.icon.image;
if(this.opts.icon.shadow)
options.shadow=this.opts.icon.shadow;
}
else if(this.opts.icon)
options.icon=this.opts.icon;
}
else if(toption&&toption.image){
options.icon=toption.image;
if(toption.shadow)
options.shadow=toption.shadow;
}
else if(toption)
options.icon=toption;
}
if(options.address){
this.geocode({address: options.address}, {markerId:tmarker});
delete options.address;
delete options.latitude;
delete options.longitude;
delete options.position;
}
else if(options.latitude&&options.longitude||options.position){
if(!options.position)
options.position=new google.maps.LatLng(options.latitude, options.longitude);
}
tmarker.setOptions(options);
},
removeMarker: function(marker){
var index=$.inArray(marker, this.markers), current;
if(index > -1){
this.tmpMarkers.splice(index,1);
current=this.markers.splice(index,1);
var markerId=current[0];
var marker=$(this.mapId).data(markerId);
var info=$(this.mapId).data(markerId + 'info');
marker.setVisible(false);
marker.setMap(null);
$(this.mapId).removeData(markerId);
if(info){
info.close();
info.show=false;
$(this.mapId).removeData(markerId + 'info');
}
return true;
}
return false;
},
clearMarkers: function(){
for (var i=0, l=this.markers.length; i < l; i++){
var markerId=this.markers[i];
var marker=$(this.mapId).data(markerId);
var info=$(this.mapId).data(markerId + 'info');
marker.setVisible(false);
marker.setMap(null);
$(this.mapId).removeData(markerId);
if(info){
info.close();
info.show=false;
$(this.mapId).removeData(markerId + 'info');
}}
this.singleMarker=false;
this.lockGeocode=false;
this.markers=[];
this.tmpMarkers=[];
this.geoMarkers=[];
},
isVisible: function(latlng){
return this.map.getBounds().contains(latlng);
}}
})(jQuery);