Skip to content

Instantly share code, notes, and snippets.

@ChrisLTD
Last active November 21, 2016 14:55
Show Gist options
  • Save ChrisLTD/263f46a54b240fd9bafc93fbc6fa1f3f to your computer and use it in GitHub Desktop.
Save ChrisLTD/263f46a54b240fd9bafc93fbc6fa1f3f to your computer and use it in GitHub Desktop.
Pull latitude and longitude from the HTML5 geolocation API with a fallback to Freegeoip. ES6.
'use strict';
const GEOLOCATION_TYPE = {
GEOPOSITION: 'GEOPOSITION',
FREEGEOIP: 'FREEGEOIP'
};
class Localizer {
constructor() {
// Let's get the ball rolling
this.getPositionViaGeolocationAPI();
}
getPositionViaGeolocationAPI() {
// check if this browser supports the geolocation API
var geolocation = null;
if (window.navigator && window.navigator.geolocation) {
geolocation = window.navigator.geolocation;
}
if (geolocation) {
// this browser supports geolocation,
// ask for permission to get the users info
// if they deny us, we'll try freegeoip instead
geolocation.getCurrentPosition((position) => {
this.foundPosition(position, GEOLOCATION_TYPE.GEOPOSITION);
}, this.getPositionViaFreegeoip.bind(this));
} else {
// this browser doesn't support geolocation
// try freegeoip instead
this.getPositionViaFreegeoip();
}
}
getPositionViaFreegeoip() {
// Request geolocation from freegeoip using JSONP
// Using JSONP instead of XMLHttpRequest let's us get around CORS
this.jsonpSend('https://freegeoip.net/json?callback=handleJSONP', {
callbackName: 'handleJSONP',
onSuccess: (json) => {
if(json && typeof json.latitude !== 'undefined'){
this.foundPosition(json, GEOLOCATION_TYPE.FREEGEOIP);
} else {
this.noPositionAvailable();
console.log(err);
}
},
onTimeout: () => {
this.noPositionAvailable();
},
timeout: 5
});
}
foundPosition(position, positionType) {
var latitude, longitude;
// FREEGEOIP and the geolocation API return differently formatted data
// this maps between the different return types
if (positionType == GEOLOCATION_TYPE.GEOPOSITION) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
} else if (positionType == GEOLOCATION_TYPE.FREEGEOIP) {
latitude = position.latitude;
longitude = position.longitude;
} else {
return;
}
console.log(`latitude: ${latitude} longitude: ${longitude}`);
// calculate distance from Yankee Stadium
const ys = { latitude: 40.829658, longitude: -73.926187 };
const distanceFromYS = this.distanceInMetersBetween(latitude, longitude, ys.latitude, ys.longitude);
console.log(`You are currently ${distanceFromYS} meters from Yankee Stadium`);
}
noPositionAvailable() {
console.log('No position information available.');
}
// http://stackoverflow.com/a/13045312/648844
//
// Sample Usage:
//
// jsonpSend('some_url?callback=handleStuff', {
// callbackName: 'handleStuff',
// onSuccess: function(json){
// console.log('success!', json);
// },
// onTimeout: function(){
// console.log('timeout!');
// },
// timeout: 5
// });
jsonpSend(src, options) {
var callback_name = options.callbackName || 'callback',
on_success = options.onSuccess || function(){},
on_timeout = options.onTimeout || function(){},
timeout = options.timeout || 10; // sec
var timeout_trigger = window.setTimeout(function(){
window[callback_name] = function(){};
on_timeout();
}, timeout * 1000);
window[callback_name] = function(data){
window.clearTimeout(timeout_trigger);
on_success(data);
};
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = src;
document.getElementsByTagName('head')[0].appendChild(script);
}
// http://stackoverflow.com/a/28543001/648844
distanceInMetersBetween(latitude, longitude, latitude2, longitude2) {
const dLatitude = (latitude - latitude2) * Math.PI / 180;
const dLongitude = (longitude - longitude2) * Math.PI / 180;
const a = 0.5 - Math.cos(dLatitude) / 2 + Math.cos(latitude2 * Math.PI / 180) *
Math.cos(latitude * Math.PI / 180) * (1 - Math.cos(dLongitude)) / 2;
return Math.round(6371000 * 2 * Math.asin(Math.sqrt(a)));
}
}
// Instantiate object
var localizer = new Localizer();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment