Created
May 29, 2014 15:54
-
-
Save elboletaire/adbfefa12b22b245869e to your computer and use it in GitHub Desktop.
A helper for google maps V3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* MapManager helper class for google maps api V3 | |
* | |
* @author Òscar Casajuana <elboletaire@underave.net> | |
* @param {object} options Default options to pass to the map manager | |
* { | |
* id: "map", // your canvas id | |
* multiple_select: true, // set to true to show a multiple select when there are multiple results | |
* max_points: 23, // max number of points allowed into the map (false to disable) | |
* limit_alert: "You reached the limit!", // The alert showed when trying to add more points than allowed | |
* not_found_alert: "Could not find", // displayed when the address or location can't be reached | |
* add_zoom: 16, // set this zoom when adding a mark | |
* map: {} // map options, | |
* marker: {} // marker default options (can be overriden), | |
* label_style: {} // the label style (displayed when a point can be dragged) | |
* } | |
*/ | |
google.maps.Marker.prototype.animate = function(latlng, delay) { | |
delay = typeof delay === 'undefined' ? 5 : delay; | |
var numDeltas = 100, | |
i = 0, | |
deltaLat, | |
deltaLng, | |
marker = this, | |
initial_position = [this.position.lat(), this.position.lng()], | |
final_position = latlng; | |
if (final_position instanceof google.maps.LatLng) { | |
final_position = [latlng.lat(), latlng.lng()]; | |
} | |
function transition() { | |
i = 0; | |
deltaLat = (final_position[0] - initial_position[0]) / numDeltas; | |
deltaLng = (final_position[1] - initial_position[1]) / numDeltas; | |
move(); | |
} | |
function move() { | |
initial_position[0] += deltaLat; | |
initial_position[1] += deltaLng; | |
marker.setPosition(new google.maps.LatLng(initial_position[0], initial_position[1])); | |
if (i != numDeltas) { | |
i++; | |
setTimeout(move, delay); | |
} | |
} | |
transition(); | |
}; | |
var MapManager = function (options) { | |
var InfoWindow = function(map, marker, values) { | |
var content = typeof values !== 'string' ? fill(values) : values; | |
if (typeof marker.html !== 'undefined') { | |
content = fill(values, marker.html); | |
} | |
var infowindow = new google.maps.InfoWindow({ | |
content: content | |
}); | |
infowindows.push(this); | |
bindClick(map, marker); | |
function bindClick(map, marker) { | |
map.addListener(marker, 'click', function() { | |
infowindows.close(); | |
infowindow.open(map.getMap(), marker); | |
}); | |
} | |
function fill(values, layout) { | |
var result = options.infowindow.layout; | |
if (typeof layout !== 'undefined') { | |
result = layout; | |
} | |
for (var k in values) { | |
result = result.replace(':' + k, values[k]); | |
} | |
return result; | |
} | |
this.close = function() { | |
infowindow.close(); | |
}; | |
}, | |
InfoWindows = function() { | |
var infowindows = []; | |
this.push = function(infowindow) { | |
infowindows.push(infowindow); | |
}; | |
this.close = function(which) { | |
infowindows.forEach(function(infowindow, k) { | |
if (typeof which !== 'undefined') { | |
if (which === k) { | |
infowindow.close(); | |
return true; | |
} | |
} else { | |
infowindow.close(); | |
} | |
}); | |
}; | |
}, | |
mm = this, | |
markers = [], marker = null, infowindows = new InfoWindows(), bounds = new google.maps.LatLngBounds(), | |
map = { | |
layer: document.getElementById(options.id), | |
map: null, | |
geocoder: null | |
}, | |
defaults = { | |
multiple_select : false, | |
max_points : false, // disabled by default | |
limit_alert: "You have reached the points limit. Remove one to add more", | |
not_found_alert: "Could not find specified location", | |
add_zoom: 16, | |
map: { | |
center: new google.maps.LatLng(-34.397, 150.644), | |
zoom: 8, | |
mapTypeId: google.maps.MapTypeId.ROADMAP | |
}, | |
marker: { | |
draggable: true, | |
set_center: false, | |
set_zoom: false | |
}, | |
infowindow: { | |
show: false, | |
layout: '<div class="infowindow"><h4>:name</h4><p>:address</p></div>' | |
}, | |
label_style: { | |
border: "1px solid black", | |
textAlign: "center", | |
fontSize: "11px", | |
width: "150px", | |
backgroundColor: "rgba(255, 255, 255, .8)" | |
} | |
}; | |
// Merge options.. | |
options = jQuery.extend(true, defaults, options); | |
// TODO... | |
var multiple_select = { | |
show: function(results) { | |
console.log(results); | |
} | |
}; | |
// Finds a location by given address | |
this.find = function(address, callback) { | |
var geocode = {}; | |
if (typeof address === 'object') { | |
if (address instanceof google.maps.LatLng) { | |
geocode = {latLng: address}; | |
} else { | |
if (typeof address.lat === 'undefined') { | |
if (typeof address.latitude === 'undefined') { | |
address.lat = address[0]; | |
address.lng = address[1]; | |
} else { | |
address.lat = address.latitude; | |
address.lng = address.longitude; | |
} | |
} | |
geocode = {latLng: new google.maps.LatLng(address.lat, address.lng)}; | |
} | |
} else { | |
geocode = {address: address}; | |
} | |
map.geocoder.geocode(geocode, function(data, status) { | |
if (status == google.maps.GeocoderStatus.OK) { | |
callback(data); | |
} else { | |
geocode_error(status); | |
} | |
}); | |
}; | |
// Error displayed when no location has been found | |
function geocode_error(status) { | |
alert(options.not_found_alert); | |
} | |
this.getCenter = function() { | |
return map.map.getCenter(); | |
}; | |
this.getMap = function() { | |
return map.map; | |
}; | |
this.getMarker = function(k) { | |
return markers[k]; | |
}; | |
this.getMarkers = function() { | |
return markers; | |
}; | |
this.getZoom = function() { | |
return map.map.getZoom(); | |
}; | |
// Center map... | |
this.setCenter = function(geolocation) { | |
if (typeof geolocation === 'undefined') { | |
return false; | |
} | |
if (!(geolocation instanceof google.maps.LatLng)) { | |
if (typeof geolocation.lat === 'undefined') { | |
if (typeof geolocation.latitude === 'undefined') { | |
geolocation.lat = geolocation[0]; | |
geolocation.lng = geolocation[0]; | |
} else { | |
geolocation.lat = geolocation.latitude; | |
geolocation.lng = geolocation.longitude; | |
} | |
} | |
geolocation = new google.maps.LatLng(geolocation.lat, geolocation.lng); | |
} | |
map.map.setCenter(geolocation); | |
return this; | |
}; | |
this.setCenterAndZoom = function(geolocation) { | |
this.setCenter(geolocation); | |
this.setZoom(options.add_zoom); | |
}; | |
// Zoom map... | |
this.setZoom = function(zoom) { | |
if (typeof zoom !== "number") { | |
zoom = parseInt(zoom, 10); | |
} | |
map.map.setZoom(zoom); | |
return this; | |
}; | |
// Get a unique counter (also counts removed marks) | |
this.getCount = function() { | |
return markers.length; | |
}; | |
// Get the real number of marks added | |
this.getRealCount = function() { | |
var count = 0; | |
for (var i in markers) { | |
if (typeof markers[i] !== "function" && markers[i] !== null) { | |
count++; | |
} | |
} | |
return count; | |
}; | |
// Shortcut for adding listeners | |
this.addListener = function(object, event, callback) { | |
google.maps.event.addListener(object, event, callback); | |
return this; | |
}; | |
// Removes a point, given a marker or it's unique identifier | |
this.removePoint = function(marker) { | |
if (typeof marker !== 'object') { | |
markers[marker].setMap(null); | |
markers[marker] = null; | |
return true; | |
} | |
// If it's the google marker.. | |
for (var i in markers) { | |
if (marker === markers[i]) { | |
mm.removePoint(i); | |
} | |
} | |
}; | |
function draggable_label(marker) { | |
var infobox = new InfoBox({ | |
content: "Drag point to reposition", | |
disableAutoPan: true, | |
boxStyle: options.label_style, | |
pixelOffset: new google.maps.Size(-80, -35), | |
alignBottom: true | |
}); | |
var close = infobox.close; | |
infobox.close = function() { | |
var _this = this; | |
jQuery(infobox.div_).fadeOut("slow", function(){ | |
close.apply(_this); | |
}); | |
}; | |
infobox.open(map.map, marker); | |
setTimeout(function(){ | |
infobox.close(); | |
}, 2000); | |
mm.addListener(marker, "dragstart", function(){ | |
infobox.close(); | |
}); | |
} | |
this.addPoint = function(opts, callback) { | |
if (options.max_points === false || options.max_points > this.getRealCount()) { | |
this.find(opts.position, function(results) { | |
if (results.length > 1 && options.multiple_select) { | |
multiple_select.show(results, callback); | |
} | |
if (!options.multiple_select) { | |
mm.addMarker(jQuery.extend(true, opts, {position: results[0].geometry.location}), callback); | |
} | |
}); | |
} else { | |
alert(options.limit_alert); | |
return false; | |
} | |
}; | |
this.addMarker = function(opts, callback) { | |
var _opts = {}; | |
if (options.max_points !== false && options.max_points <= this.getRealCount()) { | |
alert(options.limit_alert); | |
return false; | |
} | |
if ( !(opts.position instanceof google.maps.LatLng) ) { | |
opts.position = new google.maps.LatLng(opts.position.lat, opts.position.lng); | |
} | |
jQuery.extend(true, _opts, options.marker, opts, {map: map.map}); | |
if (_opts.set_center) { | |
mm.setCenter(opts.position); | |
} | |
if (_opts.set_zoom) { | |
mm.setZoom(options.add_zoom); | |
} | |
marker = new google.maps.Marker(_opts); | |
if (_opts.draggable) { | |
draggable_label(marker); | |
} | |
markers.push(marker); | |
bounds.extend(opts.position); | |
if (options.infowindow.show && (_opts.values || _opts.html)) { | |
var infowindow = new InfoWindow(mm, marker, _opts.values ? _opts.values : null); | |
} | |
callback && callback(marker, infowindow); | |
}; | |
this.fitBounds = function() { | |
map.map.fitBounds(bounds); | |
}; | |
function init() { | |
map.map = new google.maps.Map(map.layer, options.map); | |
map.geocoder = new google.maps.Geocoder(); | |
} | |
init(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment