Last active
May 17, 2017 14:45
-
-
Save japboy/efb780beaf7088902d95 to your computer and use it in GitHub Desktop.
Vue.js sample using Google Maps API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Vue.js sample using Google Maps API</title> | |
<style> | |
.v-transition { | |
height: auto; | |
opacity: 1; | |
transition-duration: 0.2s; | |
transition-property: height, opacity; | |
} | |
.v-enter, .v-leave { | |
height: 0; | |
opacity: 0; | |
} | |
.suggested { | |
background-color: #fff; | |
font-family: sans-serif; | |
margin: 0; | |
position: relative; | |
width: 100%; | |
} | |
.suggested > dt { | |
color: rgb(200,200,200); | |
font-size: smaller; | |
padding: 3px; | |
} | |
.suggested > dd { | |
margin: 0; | |
padding: 3px 6px; | |
} | |
.suggested > dd:hover { | |
background-color: rgb(240,240,240); | |
color: rgb(100,100,100); | |
} | |
#nav { | |
box-sizing: border-box; | |
left: 0; | |
padding: 0.3rem; | |
position: absolute; | |
top: 0; | |
width: 100%; | |
z-index: 1; | |
} | |
#map-canvas { | |
height: 100%; | |
left: 0; | |
position: absolute; | |
top: 0; | |
width: 100%; | |
z-index: 0; | |
} | |
</style> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script> | |
<script src="//maps.googleapis.com/maps/api/js?key=AIzaSyAbz4NWK8NfeybeMGfBqQyablVMv2Xm0Lw"></script> | |
<script type="x-template" id="tmpl-form"> | |
<input type="text" placeholder="Put anything." autofocus v-model="text" v-bind:style="styleText"> | |
<dl class="suggested" v-if="suggested" v-transition> | |
<dt>Suggested Countries</dt> | |
<dd v-for="country in countries">{{country.name.common}} / {{country.name.official}}</dd> | |
</dl> | |
</script> | |
<script defer> | |
(function (w, d, n, _, $, Vue, GM) { | |
/** jQuery functions */ | |
var documentLoaded = function () { | |
var dfr = new $.Deferred(); | |
$(d).ready(dfr.resolve); | |
dfr.promise(); | |
}; | |
/** Vue ViewModels */ | |
Vue.component('autocomplete-input-box', { | |
replace: true, | |
template: '#tmpl-form', | |
data: function () { | |
return { | |
text: '', | |
styleText: { | |
boxSizing: 'border-box', | |
fontSize: '1.2rem', | |
padding: '3px', | |
position: 'relative', | |
width: '100%' | |
}, | |
countries: [] | |
}; | |
}, | |
computed: { | |
suggested: function () { | |
return 0 < this.countries.length && 0 < this.text.length; | |
} | |
}, | |
watch: { | |
text: function (val, old) { | |
if (val === old || 2 > val.length) return; | |
this.$dispatch('lookup:dispatch', val); | |
} | |
}, | |
events: { | |
'lookup:broadcast': function (suggestedCountries) { | |
this.$set('countries', suggestedCountries); | |
} | |
} | |
}); | |
var nav = new Vue({ | |
data: { | |
countries: [] | |
}, | |
events: { | |
'lookup:dispatch': function (text) { | |
var countries = this.$get('countries'); | |
var countryNames = _.chain(countries).pluck('name'); | |
var textMatched = function (val) { | |
var re = new w.RegExp('.*' + text + '.*', 'i'); | |
return re.test(val); | |
}; | |
var suggestedCommonNames = countryNames | |
.pluck('common') | |
.filter(textMatched) | |
.value(); | |
var suggestedOfficialNames = countryNames | |
.pluck('official') | |
.filter(textMatched) | |
.value(); | |
var suggestedNames = _.union(suggestedCommonNames, suggestedOfficialNames); | |
var suggestedCountries = _.chain(suggestedNames) | |
.map(function (suggestedName) { | |
var index = countryNames | |
.findIndex(function (name) { | |
return name.common === suggestedName || name.official === suggestedName; | |
}) | |
.value(); | |
return countries[index]; | |
}) | |
.value(); | |
this.$broadcast('lookup:broadcast', suggestedCountries); | |
this.$emit('lookup', suggestedCountries); | |
} | |
} | |
}); | |
/** Google Maps */ | |
var mapCanvas = d.createElement('div'); | |
mapCanvas.setAttribute('id', 'map-canvas'); | |
var latLng = new GM.LatLng(35.6833, 139.6833); | |
var map = new GM.Map(mapCanvas, { center: latLng, zoom: 10 }); | |
var mapReset = function (center, zoom) { | |
GM.event.trigger(map, 'resize'); | |
map.setCenter(center || map.getCenter()); | |
map.setZoom(zoom || map.getZoom()); | |
}; | |
/** JSON datas */ | |
var countriesLoaded = $.get('//cdn.rawgit.com/mledoze/countries/master/dist/countries.json'); | |
var activeCountryLoaded = function (code) { | |
var url = '//cdn.rawgit.com/mledoze/countries/master/data/' + code + '.geo.json'; | |
return $.get(url); | |
}; | |
/** Main process */ | |
var polygon = function (coordinates) { | |
var polygons = _.map(coordinates, function (coords) { | |
var paths = _.chain(coords) | |
.map(function (coord) { return new GM.LatLng(coord[1], coord[0]); }) | |
.value(); | |
var polygon = new GM.Polygon({ | |
paths: paths, | |
strokeColor: '#FF0000', | |
strokeWeight: 3, | |
fillColor: '#FF0000', | |
fillOpacity: 0.35 | |
}); | |
return polygon; | |
}); | |
return polygons; | |
}; | |
var geojsonToPolygons = function (data) { | |
var features = _.chain(data.features) | |
.map(function (feature) { | |
var geometry = feature.geometry, polygons = []; | |
if (_.isEmpty(geometry) || !geometry.type) { | |
console.warn('Invalid data.'); | |
} else if ('MultiPolygon' === geometry.type) { | |
polygons = polygon(geometry.coordinates); | |
} else if ('Polygon' === geometry.type) { | |
polygons = polygon(geometry.coordinates); | |
} | |
return polygons; | |
}) | |
.value(); | |
return features[0]; | |
}; | |
var main = function (doc, countries) { | |
nav.$mount('#nav'); | |
nav.$set('countries', countries[0]); | |
var ___polygons = []; | |
nav.$on('lookup', function (countries) { | |
_.each(___polygons, function (polygon) { polygon.setMap(null); }); | |
___polygons = []; | |
_.each(countries, function (country) { | |
activeCountryLoaded(country.cca3.toLowerCase()).then(function (resp) { | |
___polygons = geojsonToPolygons(resp); | |
_.each(___polygons, function (polygon) { polygon.setMap(map); }); | |
}, error); | |
}); | |
var firstCountry = _.first(countries); | |
if (!_.isEmpty(firstCountry)) { | |
var latLng = new GM.LatLng(firstCountry.latlng[0], firstCountry.latlng[1]); | |
map.panTo(latLng); | |
} | |
}); | |
d.body.appendChild(mapCanvas); | |
mapCanvas.style.position = 'absolute'; | |
mapReset(latLng, 3); | |
}; | |
var error = function (err) { | |
console.error(err.message); | |
}; | |
var promises = [ | |
documentLoaded(), | |
countriesLoaded | |
]; | |
$.when.apply(undefined, promises).then(main, error); | |
})(window, document, navigator, _, jQuery, Vue, google.maps); | |
</script> | |
</head> | |
<body> | |
<nav id="nav"> | |
<autocomplete-input-box></autocomplete-input-box> | |
</nav> | |
</body> | |
</html> |
Looks like the API key is expired; console shows:
Google Maps API error: ExpiredKeyMapError https://developers.google.com/maps/documentation/javascript/error-messages#expired-key-map-error js?key=AIzaSyDCkYB76QzhTAx26dDiRP2l6pe2cqVZ3PY:34
_.kb @ js?key=AIzaSyDCkYB76QzhTAx26dDiRP2l6pe2cqVZ3PY:34
(anonymous function) @ common.js:50
(anonymous function) @ common.js:200
c @ common.js:44
(anonymous function) @ AuthenticationService.Authenticate?1shttp%3A%2F%2Fbl.ocks.org%2Fjapboy%2Fraw%2Fefb780b……:1
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Preview http://bl.ocks.org/efb780beaf7088902d95