/** * 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);