I re-factored my code to be more OO.
Does it have any more room for improvement (naming, readability, oop, etc.)?
I'm importing Gmap.js
in the head tags and the main.js
just before the closing body tag of the HTML document.
Gmap.js
'use strict';
function Gmap(element, options) {
if (!(typeof window.google === 'object' && typeof window.google.maps === 'object')) {
throw Error('The Google Maps JavaScript API v3 library is required.');
}
this.googleMap = new google.maps.Map(element, options), //TODO: make private
this.currentLocation = options.center,
this.markers = []; //TODO: make private
}
Gmap.prototype = {
addMarker: function (location, animateDrop, bounceOnClick) {
animateDrop = (typeof animateDrop === 'undefined') ? true : animateDrop;
bounceOnClick = (typeof bounceOnClick === 'undefined') ? true : bounceOnClick;
var marker = new google.maps.Marker({
map: this.googleMap,
position: location
});
if (animateDrop) {
marker.setAnimation(google.maps.Animation.DROP);
}
if (bounceOnClick) {
google.maps.event.addListener(marker, 'click', function () {
if (marker.getAnimation() !== null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
});
}
this.markers.push(marker);
},
deleteAllMarkers: function () {
for (var i = 0; i < this.markers.length; i++) {
this.markers[i].setMap(null);
}
},
getCenter: function () {
return this.googleMap.getCenter();
},
setCenter: function (latLng) {
this.googleMap.setCenter(latLng);
},
fitBounds: function (latLngBounds) {
this.googleMap.fitBounds(latLngBounds);
},
triggerEvent: function (event) {
google.maps.event.trigger(this.googleMap, event);
}
}
Gmap.geocode = function (geocodeRequest, callback) {
var googleGeocoder = new google.maps.Geocoder();
googleGeocoder.geocode(geocodeRequest, function (results, status) {
callback(results, status);
});
};
Gmap.geocodeStatus = {
OK: google.maps.GeocoderStatus.OK,
ZERO_RESULTS: google.maps.GeocoderStatus.ZERO_RESULTS,
OVER_QUERY_LIMIT: google.maps.GeocoderStatus.OVER_QUERY_LIMIT,
REQUEST_DENIED: google.maps.GeocoderStatus.REQUEST_DENIED,
UNKNOWN_ERROR: google.maps.GeocoderStatus.UNKNOWN_ERROR
};
main.js
'use strict';
(function (window, document, Gmap) {
var MAP_CANVAS_ID = 'map-canvas',
ADDRESS_INPUT_ID = 'address-input',
SEARCH_BUTTON_ID = 'search-button';
var gMap,
mapCanvas = document.getElementById(MAP_CANVAS_ID),
addressInput = document.getElementById(ADDRESS_INPUT_ID);
if (!mapCanvas.hasAttribute('data-default-address')) {
throw new Error('The default address attribute must be present and not empty.');
}
if (!mapCanvas.getAttribute('data-default-address').trim()) {
throw new Error('The default address attribute must not be empty.');
}
Gmap.geocode({ 'address': mapCanvas.getAttribute('data-default-address') }, function (results, status) {
if (status !== Gmap.geocodeStatus.OK) {
if (status === Gmap.geocodeStatus.ZERO_RESULTS) {
throw new Error('The address could not be located.');
}
throw new Error('Geocode was unsuccessful: ' + status);
}
gMap = new Gmap(mapCanvas, {
// required
center: results[0].geometry.location,
zoom: 10,
// disable direct GUI interaction
disableDefaultUI: true,
navigationControl: false,
mapTypeControl: false,
scaleControl: false,
scrollwheel: false,
draggable: false,
zoomControl: false,
disableDoubleClickZoom: true,
suppressInfoWindows: true
});
addressInput.value = results[0].formatted_address;
gMap.addMarker(results[0].geometry.location);
});
// center map responsively
window.addEventListener('resize', function () {
var center = gMap.getCenter();
gMap.triggerEvent('resize');
gMap.setCenter(center);
});
addressInput.onkeydown = function (e) {
if (e.keyCode === 13) {
addressInput.blur();
processAddressInput();
}
};
document.getElementById(SEARCH_BUTTON_ID).onclick = function () {
processAddressInput();
};
function processAddressInput() {
Gmap.geocode({ 'address': addressInput.value }, function (results, status) {
if (status !== Gmap.geocodeStatus.OK) {
if (status === Gmap.geocodeStatus.ZERO_RESULTS) {
return;
}
throw new Error('Geocode was unsuccessful: ' + status);
}
if (results[0].geometry.location.equals(gMap.currentLocation)) {
addressInput.value = results[0].formatted_address;
return;
}
gMap.deleteAllMarkers();
gMap.fitBounds(results[0].geometry.viewport);
gMap.setCenter(results[0].geometry.location);
gMap.addMarker(results[0].geometry.location);
gMap.currentLocation = results[0].geometry.location;
addressInput.value = results[0].formatted_address;
});
}
}(window, document, Gmap));