82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
|
// License: LGPL-3.0-or-later
|
||
|
const R = require('ramda')
|
||
|
const flyd = require('flyd')
|
||
|
|
||
|
// Stream that has true when google script is loaded
|
||
|
const loaded$ = flyd.stream()
|
||
|
// Stream of autocomplete data
|
||
|
const data$ = flyd.stream()
|
||
|
|
||
|
function initScript() {
|
||
|
// if(document.getElementById('googleAutocomplete')) return
|
||
|
// var script = document.createElement('script')
|
||
|
// script.type = 'text/javascript'
|
||
|
// script.id = 'googleAutocomplete'
|
||
|
// document.body.appendChild(script)
|
||
|
// script.src = `https://maps.googleapis.com/maps/api/js?key=${app.google_api}&libraries=places&callback=initGoogleAutocomplete`
|
||
|
return loaded$
|
||
|
}
|
||
|
|
||
|
window.initGoogleAutocomplete = () => loaded$(true)
|
||
|
|
||
|
function initInput(input) {
|
||
|
var autocomplete = new google.maps.places.Autocomplete(input, {types: ['geocode']})
|
||
|
autocomplete.addListener('place_changed', fillInAddress(autocomplete))
|
||
|
input.addEventListener('focus', geolocate(autocomplete))
|
||
|
input.addEventListener('keydown', e => { if(e.which === 13) e.preventDefault() })
|
||
|
return data$
|
||
|
}
|
||
|
|
||
|
const acceptedTypes = {
|
||
|
street_number: 'short_name'
|
||
|
, route: 'long_name'
|
||
|
, locality: 'long_name'
|
||
|
, administrative_area_level_1: 'short_name'
|
||
|
, country: 'long_name'
|
||
|
, postal_code: 'short_name'
|
||
|
}
|
||
|
|
||
|
const fillInAddress = autocomplete => () => {
|
||
|
var place = { components: autocomplete.getPlace().address_components}
|
||
|
if(!place.components) return
|
||
|
place.types = R.map(x => x.types[0], place.components)
|
||
|
var address = placeData(place, 'street_number')
|
||
|
? placeData(place, 'street_number') + ' ' + placeData(place, 'route')
|
||
|
: ''
|
||
|
|
||
|
var data = {
|
||
|
address: address
|
||
|
, city: placeData(place, 'locality')
|
||
|
, state_code: placeData(place, 'administrative_area_level_1')
|
||
|
, country: placeData(place, 'country')
|
||
|
, zip_code: placeData(place, 'postal_code')
|
||
|
}
|
||
|
data$(data)
|
||
|
}
|
||
|
|
||
|
function placeData(place, key) {
|
||
|
const i = R.findIndex(R.equals(key), place.types)
|
||
|
if(i >= 0) return place.components[i][acceptedTypes[key]]
|
||
|
return ''
|
||
|
}
|
||
|
|
||
|
// Bias the autocomplete object to the user's geographical location,
|
||
|
// as supplied by the browser's 'navigator.geolocation' object.
|
||
|
const geolocate = autocomplete => () => {
|
||
|
if(!navigator || !navigator.geolocation) return
|
||
|
navigator.geolocation.getCurrentPosition(pos => {
|
||
|
var geolocation = {
|
||
|
lat: pos.coords.latitude
|
||
|
, lng: pos.coords.longitude
|
||
|
}
|
||
|
var circle = new google.maps.Circle({
|
||
|
center: geolocation
|
||
|
, radius: pos.coords.accuracy
|
||
|
})
|
||
|
autocomplete.setBounds(circle.getBounds())
|
||
|
})
|
||
|
}
|
||
|
|
||
|
|
||
|
module.exports = {initScript, initInput, data$, loaded$}
|