/**
* jQuery goMap
*
* @url http://www.pittss.lv/jquery/gomap/
* @author Jevgenijs Shtrauss
* @version 1.3.1 2011.05.01
* This software is released under the MIT License
*/
(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: {
address: '', // Street, City, Country
latitude: 56.9,
longitude: 24.1,
zoom: 4,
delay: 200,
hideByClick: true,
oneInfoWindow: true,
prefixId: 'gomarker',
groupId: 'gogroup',
navigationControl: true, // Show or hide navigation control
navigationControlOptions: {
position: 'TOP_LEFT', // TOP, TOP_LEFT, TOP_RIGHT, BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT, LEFT, RIGHT
style: 'DEFAULT' // DEFAULT, ANDROID, SMALL, ZOOM_PAN
},
mapTypeControl: true, // Show or hide map control
mapTypeControlOptions: {
position: 'TOP_RIGHT', // TOP, TOP_LEFT, TOP_RIGHT, BOTTOM, BOTTOM_LEFT, BOTTOM_RIGHT, LEFT, RIGHT
style: 'DEFAULT' // DEFAULT, DROPDOWN_MENU, HORIZONTAL_BAR
},
scaleControl: false, // Show or hide scale
scrollwheel: true, // Mouse scroll whell
directions: false,
directionsResult: null,
disableDoubleClickZoom: false,
streetViewControl: false,
markers: [],
maptype: 'HYBRID', // Map type - HYBRID, ROADMAP, SATELLITE, TERRAIN
html_prepend: '',
html_append: '
',
addMarker: false
},
map: null,
count: 0,
markers: [],
tmpMarkers: [],
geoMarkers: [],
lockGeocode: false,
bounds: null,
overlay: null,
mapId: null,
opts: null,
centerLatLng: null,
init: function(el, options) {
var opts = $.extend({}, $.goMapBase.defaults, options);
this.mapId = $(el);
this.opts = opts;
if (opts.address)
this.geocode({address: opts.address, center: true});
// else if (opts.latitude != $.goMapBase.defaults.latitude && opts.longitude != $.goMapBase.defaults.longitude)
// this.centerLatLng = new google.maps.LatLng(opts.latitude, opts.longitude);
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()],
styles:
[
{
featureType: "poi.business",
elementType: "labels",
stylers:
[
{
visibility: opts.places
}
]
}
],
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
};
this.map = new google.maps.Map(el, myOptions);
this.overlay = new MyOverlay(this.map);
for (var j = 0, l = opts.markers.length; j < l; j++)
this.createMarker(opts.markers[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;
});
}
});
}
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();
},
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);