Skip to content

Instantly share code, notes, and snippets.

@elboletaire
Created May 29, 2014 15:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elboletaire/adbfefa12b22b245869e to your computer and use it in GitHub Desktop.
Save elboletaire/adbfefa12b22b245869e to your computer and use it in GitHub Desktop.
A helper for google maps V3
/**
* 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