Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Berezovsky committed Jan 2, 2014
1 parent c02347e commit 147fe27
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,15 @@ jquery-locationpicker-plugin
============================

JQuery Location Picker plugin

This plug-in allows to easily find and select location on the Google map. Except of single point it allows to choose some area by providing center of the area and some radius. All the date can be saved to any html input element automatically as well as processed with javascript (callback support).

The other feature of the plug-in is automatical address resoulver wich allows to get address line from the selected latitude and longitude. Also plug-in supports search by address typed into the binded input element which uses autocomplete feature from Google API to make search process easier. In this case marker will be automatically positioned on the map after successull address resolution.

Currently plug-in uses JQuery and Google Maps. Integration is pretty simple:

```
$('mycontainer').locationpicker();
```


249 changes: 249 additions & 0 deletions locationpicker.jquery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
(function ( $ ) {

/**
* Holds google map object and related utility entities.
* @constructor
*/
function GMapContext(domElement, options) {
var _map = new google.maps.Map(domElement, options);
var _marker = new google.maps.Marker({
position: new google.maps.LatLng(54.19335, -3.92695),
map: _map,
title: "Drag Me",
draggable: true
});
return {
map: _map,
marker: _marker,
circle: null,
location: _marker.position,
radius: options.radius,
locationName: options.locationName,
settings: options.settings,
domContainer: domElement,
geodecoder: new google.maps.Geocoder()
}
}

// Utility functions for Google Map Manipulations
var GmUtility = {
/**
* Draw a circle over the the map. Returns circle object.
* Also writes new circle object in gmapContext.
*
* @param center - LatLng of the center of the circle
* @param radius - radius in meters
* @param gmapContext - context
* @param options
*/
drawCircle: function(gmapContext, center, radius, options) {
if (gmapContext.circle != null) {
gmapContext.circle.setMap(null);
}
if (radius > 0) {
radius *= 1;
options = $.extend({
strokeColor: "#0000FF",
strokeOpacity: 0.35,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.20
}, options);
options.map = gmapContext.map;
options.radius = radius;
options.center = center;
gmapContext.circle = new google.maps.Circle(options);
return gmapContext.circle;
}
return null;
},
/**
*
* @param gMapContext
* @param location
* @param callback
*/
setPosition: function(gMapContext, location, callback) {
gMapContext.location = location;
gMapContext.marker.setPosition(location);
gMapContext.map.panTo(location);
this.drawCircle(gMapContext, location, gMapContext.radius, {});
if (gMapContext.settings.enableReverseGeocode) {
gMapContext.geodecoder.geocode({latLng: gMapContext.location}, function(results, status){
if (status == google.maps.GeocoderStatus.OK && results.length > 0){
gMapContext.locationName = results[0].formatted_address;
}
if (callback) {
callback.call(this, gMapContext);
}
});
} else {
if (callback) {
callback.call(this, gmapContext);
}
}

},
locationFromLatLng: function(lnlg) {
return {latitude: lnlg.lat(), longitude: lnlg.lng()}
}
}

function isPluginApplied(domObj) {
return getContextForElement(domObj) != undefined;
}

function getContextForElement(domObj) {
return $(domObj).data("locationpicker");
}

function updateInputValues(inputBinding, gmapContext){
if (!inputBinding) return;
var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
if (inputBinding.latitudeInput) {
inputBinding.latitudeInput.val(currentLocation.latitude);
}
if (inputBinding.longitudeInput) {
inputBinding.longitudeInput.val(currentLocation.longitude);
}
if (inputBinding.radiusInput) {
inputBinding.radiusInput.val(gmapContext.radius);
}
if (inputBinding.locationNameInput) {
inputBinding.locationNameInput.val(gmapContext.locationName);
}
}

function setupInputListenersInput(inputBinding, gmapContext) {
if (inputBinding) {
inputBinding.radiusInput.on("change", function() {
gmapContext.radius = $(this).val();
GmUtility.setPosition(gmapContext, gmapContext.location);
});
if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) {
gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0));
google.maps.event.addListener(gmapContext.autocomplete, 'place_changed', function() {
var place = gmapContext.autocomplete.getPlace();
if (!place.geometry) {
gmapContext.onlocationnotfound();
return;
}
GmUtility.setPosition(gmapContext, place.geometry.location, function() {
updateInputValues(inputBinding, gmapContext);
});
});
}
}
}

/**
* Initialization:
* $("#myMap").locationpicker(options);
* @param options
* @param params
* @returns {*}
*/
$.fn.locationpicker = function( options, params ) {
if (typeof options == 'string') { // Command provided
var _targetDomElement = this.get(0);
// Plug-in is not applied - nothing to do.
if (!isPluginApplied(_targetDomElement)) return;
var gmapContext = getContextForElement(_targetDomElement);
switch (options) {
case "location":
if (params == undefined) { // Getter
var location = GmUtility.locationFromLatLng(gmapContext.location);
location.radius = gmapContext.radius;
location.name = gmapContext.locationName;
return location;
} else { // Setter
if (params.radius) {
gmapContext.radius = params.radius;
}
GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) {
updateInputValues(gmapContext.settings.inputBinding, gmapContext);
});
}
break;
case "subscribe":
/**
* Provides interface for subscribing for GoogleMap events.
* See Google API documentation for details.
* Parameters:
* - event: string, name of the event
* - callback: function, callback function to be invoked
*/
if (options == undefined) { // Getter is not available
return null;
} else {
var event = params.event;
var callback = params.callback;
if (!event || ! callback) {
console.error("LocationPicker: Invalid arguments for method \"subscribe\"")
return null;
}
google.maps.event.addListener(gmapContext.map, event, callback);
}

break;
}
return null;
}
return this.each(function() {
var $target = $(this);
// If plug-in hasn't been applied before - initialize, otherwise - skip
if (isPluginApplied(this)) return;
// Plug-in initialization is required
// Defaults
var settings = $.extend($.fn.locationpicker.defaults, options );
// Initialize
var gmapContext = new GMapContext(this, {
zoom: settings.zoom,
center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude),
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
disableDoubleClickZoom: false,
scrollwheel: settings.scrollwheel,
streetViewControl: false,
radius: settings.radius,
locationName: settings.locationName,
settings: settings
});
$(this).data("locationpicker", gmapContext);
// Subscribe GMap events
google.maps.event.addListener(gmapContext.marker, "dragend", function(event) {
GmUtility.setPosition(gmapContext, gmapContext.marker.position, function(){
var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
settings.onchanged(currentLocation, gmapContext.radius, true);
updateInputValues(settings.inputBinding, gmapContext);
});
});
GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(){
updateInputValues(settings.inputBinding, gmapContext);
settings.oninitialized($target);
});
// Set up input bindings if needed
setupInputListenersInput(settings.inputBinding, gmapContext);
});
};
$.fn.locationpicker.defaults = {
location: {latitude: 40.7324319, longitude: -73.82480799999996},
locationName: "",
radius: 500,
zoom: 15,
scrollwheel: true,
inputBinding: {
latitudeInput: null,
longitudeInput: null,
radiusInput: null,
locationNameInput: null
},
enableAutocomplete: false,
enableReverseGeocode: true,
onchanged: function(currentLocation, radius, isMarkerDropped) {},
onlocationnotfound: function(locationName) {},
oninitialized: function (component) {}

}

}( jQuery ));

0 comments on commit 147fe27

Please sign in to comment.