| 1 |
/*! jquery-locationpicker - v0.1.16 - 2017-10-02 */ |
| 2 |
(function($) { |
| 3 |
function GMapContext(domElement, options) { |
| 4 |
var _map = new google.maps.Map(domElement, options); |
| 5 |
var _marker = new google.maps.Marker({ |
| 6 |
position: new google.maps.LatLng(54.19335, -3.92695), |
| 7 |
map: _map, |
| 8 |
title: "Drag Me", |
| 9 |
visible: options.markerVisible, |
| 10 |
draggable: options.markerDraggable, |
| 11 |
icon: options.markerIcon !== undefined ? options.markerIcon : undefined |
| 12 |
}); |
| 13 |
return { |
| 14 |
map: _map, |
| 15 |
marker: _marker, |
| 16 |
circle: null, |
| 17 |
location: _marker.position, |
| 18 |
radius: options.radius, |
| 19 |
locationName: options.locationName, |
| 20 |
addressComponents: { |
| 21 |
formatted_address: null, |
| 22 |
addressLine1: null, |
| 23 |
addressLine2: null, |
| 24 |
streetName: null, |
| 25 |
streetNumber: null, |
| 26 |
city: null, |
| 27 |
district: null, |
| 28 |
state: null, |
| 29 |
stateOrProvince: null |
| 30 |
}, |
| 31 |
settings: options.settings, |
| 32 |
domContainer: domElement, |
| 33 |
geodecoder: new google.maps.Geocoder() |
| 34 |
}; |
| 35 |
} |
| 36 |
var GmUtility = { |
| 37 |
drawCircle: function(gmapContext, center, radius, options) { |
| 38 |
if (gmapContext.circle != null) { |
| 39 |
gmapContext.circle.setMap(null); |
| 40 |
} |
| 41 |
if (radius > 0) { |
| 42 |
radius *= 1; |
| 43 |
options = $.extend({ |
| 44 |
strokeColor: "#0000FF", |
| 45 |
strokeOpacity: .35, |
| 46 |
strokeWeight: 2, |
| 47 |
fillColor: "#0000FF", |
| 48 |
fillOpacity: .2 |
| 49 |
}, options); |
| 50 |
options.map = gmapContext.map; |
| 51 |
options.radius = radius; |
| 52 |
options.center = center; |
| 53 |
gmapContext.circle = new google.maps.Circle(options); |
| 54 |
return gmapContext.circle; |
| 55 |
} |
| 56 |
return null; |
| 57 |
}, |
| 58 |
setPosition: function(gMapContext, location, callback) { |
| 59 |
gMapContext.location = location; |
| 60 |
gMapContext.marker.setPosition(location); |
| 61 |
gMapContext.map.panTo(location); |
| 62 |
this.drawCircle(gMapContext, location, gMapContext.radius, {}); |
| 63 |
if (gMapContext.settings.enableReverseGeocode) { |
| 64 |
this.updateLocationName(gMapContext, callback); |
| 65 |
} else { |
| 66 |
if (callback) { |
| 67 |
callback.call(this, gMapContext); |
| 68 |
} |
| 69 |
} |
| 70 |
}, |
| 71 |
locationFromLatLng: function(lnlg) { |
| 72 |
return { |
| 73 |
latitude: lnlg.lat(), |
| 74 |
longitude: lnlg.lng() |
| 75 |
}; |
| 76 |
}, |
| 77 |
addressByFormat: function(addresses, format) { |
| 78 |
var result = null; |
| 79 |
for (var i = addresses.length - 1; i >= 0; i--) { |
| 80 |
if (addresses[i].types.indexOf(format) >= 0) { |
| 81 |
result = addresses[i]; |
| 82 |
} |
| 83 |
} |
| 84 |
return result || addresses[0]; |
| 85 |
}, |
| 86 |
updateLocationName: function(gmapContext, callback) { |
| 87 |
gmapContext.geodecoder.geocode({ |
| 88 |
latLng: gmapContext.marker.position |
| 89 |
}, function(results, status) { |
| 90 |
if (status == google.maps.GeocoderStatus.OK && results.length > 0) { |
| 91 |
var address = GmUtility.addressByFormat(results, gmapContext.settings.addressFormat); |
| 92 |
gmapContext.locationName = address.formatted_address; |
| 93 |
gmapContext.addressComponents = GmUtility.address_component_from_google_geocode(address.address_components); |
| 94 |
} else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { |
| 95 |
return setTimeout(function() { |
| 96 |
GmUtility.updateLocationName(gmapContext, callback); |
| 97 |
}, 1e3); |
| 98 |
} |
| 99 |
if (callback) { |
| 100 |
callback.call(this, gmapContext); |
| 101 |
} |
| 102 |
}); |
| 103 |
}, |
| 104 |
address_component_from_google_geocode: function(address_components) { |
| 105 |
var result = {}; |
| 106 |
for (var i = address_components.length - 1; i >= 0; i--) { |
| 107 |
var component = address_components[i]; |
| 108 |
if (component.types.indexOf("postal_code") >= 0) { |
| 109 |
result.postalCode = component.short_name; |
| 110 |
} else if (component.types.indexOf("street_number") >= 0) { |
| 111 |
result.streetNumber = component.short_name; |
| 112 |
} else if (component.types.indexOf("route") >= 0) { |
| 113 |
result.streetName = component.short_name; |
| 114 |
} else if (component.types.indexOf("locality") >= 0) { |
| 115 |
result.city = component.short_name; |
| 116 |
} else if (component.types.indexOf("sublocality") >= 0) { |
| 117 |
result.district = component.short_name; |
| 118 |
} else if (component.types.indexOf("administrative_area_level_1") >= 0) { |
| 119 |
result.stateOrProvince = component.short_name; |
| 120 |
} else if (component.types.indexOf("country") >= 0) { |
| 121 |
result.country = component.short_name; |
| 122 |
} |
| 123 |
} |
| 124 |
result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim(); |
| 125 |
result.addressLine2 = ""; |
| 126 |
return result; |
| 127 |
} |
| 128 |
}; |
| 129 |
function isPluginApplied(domObj) { |
| 130 |
return getContextForElement(domObj) != undefined; |
| 131 |
} |
| 132 |
function getContextForElement(domObj) { |
| 133 |
return $(domObj).data("locationpicker"); |
| 134 |
} |
| 135 |
function updateInputValues(inputBinding, gmapContext) { |
| 136 |
if (!inputBinding) return; |
| 137 |
var currentLocation = GmUtility.locationFromLatLng(gmapContext.marker.position); |
| 138 |
if (inputBinding.latitudeInput) { |
| 139 |
inputBinding.latitudeInput.val(currentLocation.latitude).change(); |
| 140 |
} |
| 141 |
if (inputBinding.longitudeInput) { |
| 142 |
inputBinding.longitudeInput.val(currentLocation.longitude).change(); |
| 143 |
} |
| 144 |
if (inputBinding.radiusInput) { |
| 145 |
inputBinding.radiusInput.val(gmapContext.radius).change(); |
| 146 |
} |
| 147 |
if (inputBinding.locationNameInput) { |
| 148 |
inputBinding.locationNameInput.val(gmapContext.locationName).change(); |
| 149 |
} |
| 150 |
|
| 151 |
if (inputBinding.zoomInput) { |
| 152 |
inputBinding.zoomInput.val(gmapContext.map.getZoom()).change(); |
| 153 |
} |
| 154 |
} |
| 155 |
function setupInputListenersInput(inputBinding, gmapContext) { |
| 156 |
if (inputBinding) { |
| 157 |
if (inputBinding.radiusInput) { |
| 158 |
inputBinding.radiusInput.on("change", function(e) { |
| 159 |
var radiusInputValue = $(this).val(); |
| 160 |
if (!e.originalEvent || isNaN(radiusInputValue)) { |
| 161 |
return; |
| 162 |
} |
| 163 |
gmapContext.radius = radiusInputValue; |
| 164 |
GmUtility.setPosition(gmapContext, gmapContext.location, function(context) { |
| 165 |
context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); |
| 166 |
}); |
| 167 |
}); |
| 168 |
} |
| 169 |
if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) { |
| 170 |
var blur = false; |
| 171 |
gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0), gmapContext.settings.autocompleteOptions); |
| 172 |
google.maps.event.addListener(gmapContext.autocomplete, "place_changed", function() { |
| 173 |
blur = false; |
| 174 |
var place = gmapContext.autocomplete.getPlace(); |
| 175 |
if (!place.geometry) { |
| 176 |
gmapContext.settings.onlocationnotfound(place.name); |
| 177 |
return; |
| 178 |
} |
| 179 |
GmUtility.setPosition(gmapContext, place.geometry.location, function(context) { |
| 180 |
updateInputValues(inputBinding, context); |
| 181 |
context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); |
| 182 |
}); |
| 183 |
}); |
| 184 |
if (gmapContext.settings.enableAutocompleteBlur) { |
| 185 |
inputBinding.locationNameInput.on("change", function(e) { |
| 186 |
if (!e.originalEvent) { |
| 187 |
return; |
| 188 |
} |
| 189 |
blur = true; |
| 190 |
}); |
| 191 |
inputBinding.locationNameInput.on("blur", function(e) { |
| 192 |
if (!e.originalEvent) { |
| 193 |
return; |
| 194 |
} |
| 195 |
setTimeout(function() { |
| 196 |
var address = $(inputBinding.locationNameInput).val(); |
| 197 |
if (address.length > 5 && blur) { |
| 198 |
blur = false; |
| 199 |
gmapContext.geodecoder.geocode({ |
| 200 |
address: address |
| 201 |
}, function(results, status) { |
| 202 |
if (status == google.maps.GeocoderStatus.OK && results && results.length) { |
| 203 |
GmUtility.setPosition(gmapContext, results[0].geometry.location, function(context) { |
| 204 |
updateInputValues(inputBinding, context); |
| 205 |
context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); |
| 206 |
}); |
| 207 |
} |
| 208 |
}); |
| 209 |
} |
| 210 |
}, 1e3); |
| 211 |
}); |
| 212 |
} |
| 213 |
} |
| 214 |
if (inputBinding.latitudeInput) { |
| 215 |
inputBinding.latitudeInput.on("change", function(e) { |
| 216 |
var latitudeInputValue = $(this).val(); |
| 217 |
if (!e.originalEvent || isNaN(latitudeInputValue)) { |
| 218 |
return; |
| 219 |
} |
| 220 |
GmUtility.setPosition(gmapContext, new google.maps.LatLng(latitudeInputValue, gmapContext.location.lng()), function(context) { |
| 221 |
context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); |
| 222 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 223 |
}); |
| 224 |
}); |
| 225 |
} |
| 226 |
if (inputBinding.longitudeInput) { |
| 227 |
inputBinding.longitudeInput.on("change", function(e) { |
| 228 |
var longitudeInputValue = $(this).val(); |
| 229 |
if (!e.originalEvent || isNaN(longitudeInputValue)) { |
| 230 |
return; |
| 231 |
} |
| 232 |
GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.location.lat(), longitudeInputValue), function(context) { |
| 233 |
context.settings.onchanged.apply(gmapContext.domContainer, [ GmUtility.locationFromLatLng(context.location), context.radius, false ]); |
| 234 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 235 |
}); |
| 236 |
}); |
| 237 |
} |
| 238 |
} |
| 239 |
} |
| 240 |
function autosize(gmapContext) { |
| 241 |
google.maps.event.trigger(gmapContext.map, "resize"); |
| 242 |
setTimeout(function() { |
| 243 |
gmapContext.map.setCenter(gmapContext.marker.position); |
| 244 |
}, 300); |
| 245 |
} |
| 246 |
function updateMap(gmapContext, $target, options) { |
| 247 |
var settings = $.extend({}, $.fn.locationpicker.defaults, options), latNew = settings.location.latitude, lngNew = settings.location.longitude, radiusNew = settings.radius, latOld = gmapContext.settings.location.latitude, lngOld = gmapContext.settings.location.longitude, radiusOld = gmapContext.settings.radius; |
| 248 |
if (latNew == latOld && lngNew == lngOld && radiusNew == radiusOld) return; |
| 249 |
gmapContext.settings.location.latitude = latNew; |
| 250 |
gmapContext.settings.location.longitude = lngNew; |
| 251 |
gmapContext.radius = radiusNew; |
| 252 |
GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.settings.location.latitude, gmapContext.settings.location.longitude), function(context) { |
| 253 |
setupInputListenersInput(gmapContext.settings.inputBinding, gmapContext); |
| 254 |
context.settings.oninitialized($target); |
| 255 |
}); |
| 256 |
} |
| 257 |
$.fn.locationpicker = function(options, params) { |
| 258 |
if (typeof options == "string") { |
| 259 |
var _targetDomElement = this.get(0); |
| 260 |
if (!isPluginApplied(_targetDomElement)) return; |
| 261 |
var gmapContext = getContextForElement(_targetDomElement); |
| 262 |
switch (options) { |
| 263 |
case "location": |
| 264 |
if (params == undefined) { |
| 265 |
var location = GmUtility.locationFromLatLng(gmapContext.location); |
| 266 |
location.radius = gmapContext.radius; |
| 267 |
location.name = gmapContext.locationName; |
| 268 |
return location; |
| 269 |
} else { |
| 270 |
if (params.radius) { |
| 271 |
gmapContext.radius = params.radius; |
| 272 |
} |
| 273 |
GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) { |
| 274 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 275 |
}); |
| 276 |
} |
| 277 |
break; |
| 278 |
|
| 279 |
case "subscribe": |
| 280 |
if (params == undefined) { |
| 281 |
return null; |
| 282 |
} else { |
| 283 |
var event = params.event; |
| 284 |
var callback = params.callback; |
| 285 |
if (!event || !callback) { |
| 286 |
console.error('LocationPicker: Invalid arguments for method "subscribe"'); |
| 287 |
return null; |
| 288 |
} |
| 289 |
google.maps.event.addListener(gmapContext.map, event, callback); |
| 290 |
} |
| 291 |
break; |
| 292 |
|
| 293 |
case "map": |
| 294 |
if (params == undefined) { |
| 295 |
var locationObj = GmUtility.locationFromLatLng(gmapContext.location); |
| 296 |
locationObj.formattedAddress = gmapContext.locationName; |
| 297 |
locationObj.addressComponents = gmapContext.addressComponents; |
| 298 |
return { |
| 299 |
map: gmapContext.map, |
| 300 |
marker: gmapContext.marker, |
| 301 |
location: locationObj |
| 302 |
}; |
| 303 |
} else { |
| 304 |
return null; |
| 305 |
} |
| 306 |
|
| 307 |
case "autosize": |
| 308 |
autosize(gmapContext); |
| 309 |
return this; |
| 310 |
} |
| 311 |
return null; |
| 312 |
} |
| 313 |
return this.each(function() { |
| 314 |
var $target = $(this); |
| 315 |
if (isPluginApplied(this)) { |
| 316 |
updateMap(getContextForElement(this), $(this), options); |
| 317 |
return; |
| 318 |
} |
| 319 |
var settings = $.extend({}, $.fn.locationpicker.defaults, options); |
| 320 |
var gmapContext = new GMapContext(this, $.extend({}, { |
| 321 |
zoom: settings.zoom, |
| 322 |
center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude), |
| 323 |
mapTypeId: settings.mapTypeId, |
| 324 |
mapTypeControl: false, |
| 325 |
styles: settings.styles, |
| 326 |
disableDoubleClickZoom: false, |
| 327 |
scrollwheel: settings.scrollwheel, |
| 328 |
streetViewControl: false, |
| 329 |
radius: settings.radius, |
| 330 |
locationName: settings.locationName, |
| 331 |
settings: settings, |
| 332 |
autocompleteOptions: settings.autocompleteOptions, |
| 333 |
addressFormat: settings.addressFormat, |
| 334 |
draggable: settings.draggable, |
| 335 |
markerIcon: settings.markerIcon, |
| 336 |
markerDraggable: settings.markerDraggable, |
| 337 |
markerVisible: settings.markerVisible |
| 338 |
}, settings.mapOptions)); |
| 339 |
$target.data("locationpicker", gmapContext); |
| 340 |
function displayMarkerWithSelectedArea() { |
| 341 |
GmUtility.setPosition(gmapContext, gmapContext.marker.position, function(context) { |
| 342 |
var currentLocation = GmUtility.locationFromLatLng(gmapContext.location); |
| 343 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 344 |
context.settings.onchanged.apply(gmapContext.domContainer, [ currentLocation, context.radius, true ]); |
| 345 |
}); |
| 346 |
} |
| 347 |
if (settings.markerInCenter) { |
| 348 |
gmapContext.map.addListener("bounds_changed", function() { |
| 349 |
if (!gmapContext.marker.dragging) { |
| 350 |
gmapContext.marker.setPosition(gmapContext.map.center); |
| 351 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 352 |
} |
| 353 |
}); |
| 354 |
//gmapContext.map.addListener("idle", function() { |
| 355 |
gmapContext.map.addListener("dragend", function() { |
| 356 |
if (!gmapContext.marker.dragging) { |
| 357 |
displayMarkerWithSelectedArea(); |
| 358 |
} |
| 359 |
}); |
| 360 |
} |
| 361 |
google.maps.event.addListener(gmapContext.marker, "drag", function(event) { |
| 362 |
updateInputValues(gmapContext.settings.inputBinding, gmapContext); |
| 363 |
}); |
| 364 |
google.maps.event.addListener(gmapContext.marker, "dragend", function(event) { |
| 365 |
displayMarkerWithSelectedArea(); |
| 366 |
}); |
| 367 |
GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(context) { |
| 368 |
updateInputValues(settings.inputBinding, gmapContext); |
| 369 |
setupInputListenersInput(settings.inputBinding, gmapContext); |
| 370 |
context.settings.oninitialized($target); |
| 371 |
}); |
| 372 |
}); |
| 373 |
}; |
| 374 |
$.fn.locationpicker.defaults = { |
| 375 |
location: { |
| 376 |
latitude: 40.7324319, |
| 377 |
longitude: -73.82480777777776 |
| 378 |
}, |
| 379 |
locationName: "", |
| 380 |
radius: 500, |
| 381 |
zoom: 15, |
| 382 |
mapTypeId: google.maps.MapTypeId.ROADMAP, |
| 383 |
styles: [], |
| 384 |
mapOptions: {}, |
| 385 |
scrollwheel: true, |
| 386 |
inputBinding: { |
| 387 |
latitudeInput: null, |
| 388 |
longitudeInput: null, |
| 389 |
radiusInput: null, |
| 390 |
locationNameInput: null, |
| 391 |
zoomInput:null |
| 392 |
}, |
| 393 |
enableAutocomplete: false, |
| 394 |
enableAutocompleteBlur: false, |
| 395 |
autocompleteOptions: null, |
| 396 |
addressFormat: "postal_code", |
| 397 |
enableReverseGeocode: true, |
| 398 |
draggable: true, |
| 399 |
onchanged: function(currentLocation, radius, isMarkerDropped) {}, |
| 400 |
onlocationnotfound: function(locationName) {}, |
| 401 |
oninitialized: function(component) {}, |
| 402 |
markerIcon: undefined, |
| 403 |
markerDraggable: true, |
| 404 |
markerVisible: true |
| 405 |
}; |
| 406 |
})(jQuery); |