312 lines
8.4 KiB
JavaScript
312 lines
8.4 KiB
JavaScript
|
|
App.loc = {
|
|
aproxLoc: null,
|
|
realLoc: null,
|
|
range: App.defaultRange,
|
|
loaded: false,
|
|
|
|
// calculate the distance between two points
|
|
distance: function(params) {
|
|
try {
|
|
var R = 6371; // Radius of the earth in km
|
|
var dLat = _toRad(params.to.lat - params.from.lat);
|
|
var dLon = _toRad(params.to.lon - params.from.lon);
|
|
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
|
Math.cos(_toRad(params.from.lat)) * Math.cos(_toRad(params.to.lat)) *
|
|
Math.sin(dLon/2) * Math.sin(dLon/2);
|
|
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
|
var d = R * c; // Distance in km
|
|
return d;
|
|
|
|
} catch(e) {
|
|
App.track('Location Error', {
|
|
lat: App.loc.lat,
|
|
lon: App.loc.lon,
|
|
address: App.loc.address()
|
|
});
|
|
}
|
|
},
|
|
|
|
// get the best posible location
|
|
pos: function() {
|
|
if (!App.loc.realLoc) {
|
|
return App.loc.aproxLoc;
|
|
} else {
|
|
return App.loc.realLoc;
|
|
}
|
|
},
|
|
|
|
// bind for a single event only triggered once
|
|
bind: function(event, fn) {
|
|
$(document).unbind(event)
|
|
$(document).one(event, fn);
|
|
},
|
|
|
|
// get the best posible address
|
|
address: function() {
|
|
return App.loc.pos() ? (App.loc.pos().addressEntered || App.loc.pos().addressReverse || App.loc.pos().addressAlias) : '';
|
|
},
|
|
|
|
// get the location city
|
|
city: function() {
|
|
return (App.loc.pos() && App.loc.pos().city) ? App.loc.pos().city : '';
|
|
},
|
|
|
|
// get the preposition for the location
|
|
prep: function() {
|
|
return (App.loc.pos() && App.loc.pos().prep) ? App.loc.pos().prep : 'in';
|
|
},
|
|
|
|
// get the location from the browsers geolocation
|
|
getLocationByBrowser: function(success, error) {
|
|
if (navigator.geolocation) {
|
|
App.loc.timerId = setTimeout(function() {
|
|
error();
|
|
}, 5000);
|
|
|
|
navigator.geolocation.getCurrentPosition(function(position){
|
|
clearTimeout(App.loc.timerId);
|
|
|
|
App.loc.realLoc = {
|
|
lat: position.coords.latitude,
|
|
lon: position.coords.longitude
|
|
};
|
|
App.track('Locations Shared', {
|
|
lat: position.coords.latitude,
|
|
lon: position.coords.longitude
|
|
});
|
|
App.loc.reverseGeocode(position.coords.latitude, position.coords.longitude, function() {
|
|
success();
|
|
}, error);
|
|
|
|
}, function() {
|
|
clearTimeout(App.loc.timerId);
|
|
error();
|
|
}, {maximumAge: 60000, timeout: 5000, enableHighAccuracy: true});
|
|
|
|
} else {
|
|
error();
|
|
}
|
|
},
|
|
|
|
// parse the city name from the result set
|
|
getCityFromResult: function(results) {
|
|
if (!results) {
|
|
return;
|
|
}
|
|
switch (results[0].types[0]) {
|
|
default:
|
|
case 'administrative_area_level_1':
|
|
App.loc.realLoc.city = results[0].address_components[0].long_name;
|
|
break;
|
|
case 'locality':
|
|
App.loc.realLoc.city = results[0].address_components[0].long_name;
|
|
App.loc.realLoc.region = results[0].address_components[2].short_name;
|
|
break;
|
|
case 'street_address':
|
|
App.loc.realLoc.city = results[0].address_components[2].long_name;
|
|
App.loc.realLoc.region = results[0].address_components[4].short_name;
|
|
break;
|
|
case 'postal_code':
|
|
case 'route':
|
|
App.loc.realLoc.city = results[0].address_components[1].long_name;
|
|
App.loc.realLoc.region = results[0].address_components[3].short_name;
|
|
break;
|
|
}
|
|
|
|
// @todo: do we need this?
|
|
for (var x = 0; x < results.length; x++) {
|
|
for (var i = 0; i < results[x].address_components.length; i++) {
|
|
for (var j = 0; j < results[x].address_components[i].types.length; j++) {
|
|
if (results[x].address_components[i].types[j] == 'locality') {
|
|
App.loc.realLoc.city = results[x].address_components[i].long_name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// get the guessed address
|
|
getAddressFromResult: function(results) {
|
|
if (!results) {
|
|
return;
|
|
}
|
|
App.loc.realLoc.addressReverse = results[0].formatted_address;
|
|
},
|
|
|
|
// set the location from the result set
|
|
setFormattedLocFromResult: function(result) {
|
|
App.loc.getCityFromResult(result);
|
|
App.loc.getAddressFromResult(result);
|
|
$.cookie('location', JSON.stringify(App.loc.realLoc), { expires: App.cookieExpire, path: '/'});
|
|
$('.loc-your-area').html(App.loc.city() || 'your area');
|
|
},
|
|
|
|
// set the location by name
|
|
setFormattedLoc: function(loc) {
|
|
$('.loc-your-area').html(loc);
|
|
},
|
|
|
|
// run in the begining
|
|
init: function() {
|
|
// retrieve the real loc from cookie. ignore googles location
|
|
var lcookie = $.cookie('location') ? JSON.parse($.cookie('location')) : null;
|
|
if (lcookie) {
|
|
App.loc.realLoc = lcookie;
|
|
|
|
} else if (App.config.user.location_lat) {
|
|
// set the realloc to the users position
|
|
App.loc.realLoc = {
|
|
lat: App.config.user.location_lat,
|
|
lon: App.config.user.location_lon,
|
|
addressEntered: App.config.user.address
|
|
};
|
|
}
|
|
google.load('maps', '3', {callback: App.loc.preProcess, other_params: 'sensor=false'});
|
|
},
|
|
|
|
// callback for google location api
|
|
preProcess: function() {
|
|
console.log('preprocessing')
|
|
|
|
var success = function() {
|
|
// browser detection success
|
|
$(document).trigger('location-detected');
|
|
};
|
|
|
|
var error = function() {
|
|
// browser detection error
|
|
};
|
|
|
|
var complete = function(lat, lon, city, region) {
|
|
if (lat) {
|
|
// we have a location! but its just a guess
|
|
App.loc.aproxLoc = {
|
|
lat: lat,
|
|
lon: lon,
|
|
city: city,
|
|
region: region
|
|
};
|
|
} else {
|
|
// if we dont have a location, then lets ask for an address
|
|
App.loc.aproxLoc = null;
|
|
}
|
|
|
|
App.loc.loaded = true;
|
|
$(document).trigger('location-loaded');
|
|
|
|
// if we dont have any real location, then wait for secondary location detection
|
|
if (!App.loc.realLoc) {
|
|
App.loc.getLocationByBrowser(success, error);
|
|
}
|
|
}
|
|
|
|
if (google.loader.ClientLocation) {
|
|
// we got a location back from google. use it
|
|
complete(
|
|
google.loader.ClientLocation.latitude,
|
|
google.loader.ClientLocation.longitude,
|
|
google.loader.ClientLocation.address.city,
|
|
google.loader.ClientLocation.address.country_code == 'US' && google.loader.ClientLocation.address.region ? google.loader.ClientLocation.address.region.toUpperCase() : google.loader.ClientLocation.address.country_code
|
|
);
|
|
|
|
} else if (App.config.loc.lat) {
|
|
// we didnt get a location from google. use maxmind instead
|
|
complete(App.config.loc.lat, App.config.loc.lon, App.config.loc.city, App.config.loc.region);
|
|
} else {
|
|
// we have no location
|
|
complete();
|
|
}
|
|
},
|
|
|
|
// send out a geocode request
|
|
doGeocode: function(address, success, error) {
|
|
address = $.trim(address);
|
|
|
|
// track the entered address to mixpanel
|
|
App.track('Location Entered', {
|
|
address: address
|
|
});
|
|
|
|
// there was an alias. just set it to that
|
|
var rsuccess = function(results) {
|
|
success(results);
|
|
};
|
|
|
|
// there was no alias, do a real geocode
|
|
var rerror = function() {
|
|
// send the request out to google
|
|
var geocoder = new google.maps.Geocoder();
|
|
geocoder.geocode({address: address}, function(results, status) {
|
|
if (status == google.maps.GeocoderStatus.OK) {
|
|
success(results, status);
|
|
} else {
|
|
error(results, status);
|
|
}
|
|
});
|
|
};
|
|
|
|
// Check if the typed address has an alias
|
|
App.routeAlias(address, rsuccess, rerror);
|
|
|
|
// set the bounds of the address to our guessed location
|
|
// var bounds = new google.maps.LatLngBounds(App.config.loc.lat, App.config.loc.lon);
|
|
},
|
|
|
|
// perform a geocode and store the results
|
|
geocode: function(address, success, error) {
|
|
App.loc.doGeocode(address, function(results) {
|
|
if (results.alias) {
|
|
App.loc.realLoc = {
|
|
addressAlias: results.alias.address,
|
|
lat: results.alias.lat,
|
|
lon: results.alias.lon,
|
|
prep: results.alias.prep,
|
|
city: results.alias.city
|
|
};
|
|
App.loc.setFormattedLocFromResult();
|
|
} else {
|
|
App.loc.realLoc = {
|
|
addressEntered: address,
|
|
lat: results[0].geometry.location.lat(),
|
|
lon: results[0].geometry.location.lng()
|
|
};
|
|
App.loc.setFormattedLocFromResult(results);
|
|
}
|
|
success();
|
|
|
|
}, function() {
|
|
App.loc.realLoc = null;
|
|
error();
|
|
});
|
|
},
|
|
|
|
reverseGeocode: function(lat, lon, success, error) {
|
|
App.track('Location Reverse Geocode', {
|
|
lat: lat,
|
|
lon: lon
|
|
});
|
|
|
|
var geocoder = new google.maps.Geocoder();
|
|
var latlng = new google.maps.LatLng(lat, lon);
|
|
|
|
geocoder.geocode({'latLng': latlng}, function(results, status) {
|
|
if (status == google.maps.GeocoderStatus.OK) {
|
|
if (results[1]) {
|
|
App.loc.setFormattedLocFromResult(results);
|
|
success();
|
|
} else {
|
|
$('.location-address').val('Where are you?!');
|
|
}
|
|
} else {
|
|
error();
|
|
}
|
|
});
|
|
},
|
|
km2Miles : function( km ){
|
|
return km * 0.621371;
|
|
},
|
|
Miles2Km : function( miles ){
|
|
return miles * 1.60934;
|
|
}
|
|
} |