Skip to content
Snippets Groups Projects
Commit 5209a600 authored by Nikolaus Krismer's avatar Nikolaus Krismer
Browse files

reworked geolocator (locate user by ip)

parent 7bcdcbfe
No related branches found
No related tags found
No related merge requests found
...@@ -4,16 +4,23 @@ ...@@ -4,16 +4,23 @@
<head> <head>
<title>ISOGA New: Using Isochrones for Geospatial Analysis</title> <title>ISOGA New: Using Isochrones for Geospatial Analysis</title>
<link type="text/css" rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" /> <link type="text/css" rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" />
<link type="text/css" rel="stylesheet" href="http://domoritz.de/leaflet-locatecontrol/src/L.Control.Locate.css" />
<link type="text/css" rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css"> <link type="text/css" rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<link type="text/css" rel="stylesheet" href="css_new/jquery-ui-timepicker-addon.css" /> <link type="text/css" rel="stylesheet" href="css_new/jquery-ui-timepicker-addon.css" />
<link type="text/css" rel="stylesheet" href="css_new/geosearch.css" /> <link type="text/css" rel="stylesheet" href="css_new/geosearch.css" />
<link type="text/css" rel="stylesheet" href="css_new/isoga.css" /> <link type="text/css" rel="stylesheet" href="css_new/isoga.css" />
<!--[if lt IE 9]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.ie.css" />
<link type="text/css" rel="stylesheet" href="http://domoritz.de/leaflet-locatecontrol/src/L.Control.Locate.ie.css" />
<![endif]-->
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&amp;sensor=false"></script> <script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&amp;sensor=false"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script> <script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script> <script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>
<script type="text/javascript" src="http://maps.stamen.com/js/tile.stamen.js"></script> <script type="text/javascript" src="http://maps.stamen.com/js/tile.stamen.js"></script>
<script type="text/javascript" src="http://domoritz.de/leaflet-locatecontrol/src/L.Control.Locate.js"></script>
<script type="text/javascript" src="js_new/locatebyip.js"></script>
<script type="text/javascript" src="js_new/jquery-ui-timepicker-addon.js"></script> <script type="text/javascript" src="js_new/jquery-ui-timepicker-addon.js"></script>
<script type="text/javascript" src="js_new/console.js"></script> <script type="text/javascript" src="js_new/console.js"></script>
<script type="text/javascript" src="js_new/geosearch.js"></script> <script type="text/javascript" src="js_new/geosearch.js"></script>
...@@ -21,7 +28,6 @@ ...@@ -21,7 +28,6 @@
<script type="text/javascript" src="js_new/controls.js"></script> <script type="text/javascript" src="js_new/controls.js"></script>
<script type="text/javascript" src="js_new/bing.js"></script> <script type="text/javascript" src="js_new/bing.js"></script>
<script type="text/javascript" src="js_new/google.js"></script> <script type="text/javascript" src="js_new/google.js"></script>
<script type="text/javascript" src="js_new/geolocator.js"></script>
<script type="text/javascript" src="js_new/map.js"></script> <script type="text/javascript" src="js_new/map.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
......
/*jslint browser:true, nomen:true */
//for jsLint implied variable warnings:
/*global google:false */
/*
* Geolocator Javascript Lib
* version: 1.1
* author: Onur YILDIRIM
* contact: onur@cutepilot.com
* project page: https://github.com/onury/geolocator
* copyright: © 2012. MIT License.
*/
var geolocator = (function () {
'use strict';
/*-------- PRIVATE PROPERTIES & FIELDS --------*/
/* Storage for the callback function to be executed when the location is successfully fetched. */
var onSuccess,
/* Storage for the callback function to be executed when the location could not be fetched due to an error. */
onError,
/* HTML element ID for the Google Maps. */
mCanvasId,
/* Google Maps URL. */
googleLoaderURL = 'https://www.google.com/jsapi',
/* Array of source services that provide location-by-IP information. */
ipGeoSources = [
{url: 'http://freegeoip.net/json/', cbParam: 'callback'}, // 0
{url: 'http://www.geoplugin.net/json.gp', cbParam: 'jsoncallback'}, // 1
{url: 'http://geoiplookup.wikimedia.org/', cbParam: ''} // 2
//,{url: 'http://j.maxmind.com/app/geoip.js', cbParam: ''} // Not implemented. Requires attribution. See http://dev.maxmind.com/geoip/javascript
],
/* The index of the current IP source service. */
ipGeoSourceIndex = 0; // default (freegeoip)
/*-------- PRIVATE METHODS --------*/
/* Non-blocking method for loading scripts dynamically.
*/
function loadScript(url, callback, type) {
var script = document.createElement('script');
script.type = (type === undefined) ? 'text/javascript' : type;
if (typeof callback === 'function') {
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = function () { callback(); };
}
}
script.src = url;
//document.body.appendChild(script);
document.getElementsByTagName('head')[0].appendChild(script);
}
/* Loads Google Maps API and executes the callback function when done.
*/
function loadGoogleMaps(callback) {
function loadMaps() {
if (geolocator.__glcb) { delete geolocator.__glcb; }
google.load('maps', '3', {other_params: 'sensor=false', callback: callback});
}
if (window.google !== undefined && google.maps !== undefined) {
if (callback) { callback(); }
} else {
if (window.google !== undefined && google.loader !== undefined) {
loadMaps();
} else {
geolocator.__glcb = loadMaps;
loadScript(googleLoaderURL + '?callback=geolocator.__glcb');
}
}
}
/* Draws the map from the fetched geo information.
*/
function drawMap(elemId, mapOptions, infoContent) {
var map, marker, infowindow,
elem = document.getElementById(elemId);
if (elem) {
map = new google.maps.Map(elem, mapOptions);
marker = new google.maps.Marker({
position: mapOptions.center,
map: map
});
infowindow = new google.maps.InfoWindow();
infowindow.setContent(infoContent);
//infowindow.open(map, marker);
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
geolocator.location.map = {
canvas: elem,
map: map,
options: mapOptions,
marker: marker,
infoWindow: infowindow
};
} else {
geolocator.location.map = null;
}
}
/* Runs a reverse-geo lookup for the specified lat-lon coords.
*/
function reverseGeoLookup(latlng, callback) {
var geocoder = new google.maps.Geocoder();
function onReverseGeo(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (callback) { callback(results); }
}
}
geocoder.geocode({'latLng': latlng}, onReverseGeo);
}
/* Fetches additional details (from the reverse-geo result) for the address property of the location object.
*/
function fetchDetailsFromLookup(data) {
if (data.length > 0) {
var i, comp, comps = data[0].address_components;
geolocator.location.formattedAddress = data[0].formatted_address;
for (i = 0; i < comps.length; i += 1) {
comp = comps[i];
if (comp.types.indexOf('route') >= 0) {
geolocator.location.address.street = comp.long_name;
} else if (comp.types.indexOf('neighborhood') >= 0) {
geolocator.location.address.neighborhood = comp.long_name;
} else if (comp.types.indexOf('sublocality') >= 0) {
geolocator.location.address.town = comp.long_name;
} else if (comp.types.indexOf('locality') >= 0) {
geolocator.location.address.city = comp.long_name;
} else if (comp.types.indexOf('administrative_area_level_1') >= 0) {
geolocator.location.address.region = comp.long_name;
} else if (comp.types.indexOf('country') >= 0) {
geolocator.location.address.country = comp.long_name;
geolocator.location.address.countryCode = comp.short_name;
} else if (comp.types.indexOf('postal_code') >= 0) {
geolocator.location.address.postalCode = comp.long_name;
} else if (comp.types.indexOf('street_number') >= 0) {
geolocator.location.address.streetNumber = comp.long_name;
}
}
}
}
/* Finalizes the location object via reverse-geocoding and draws the map (if required).
*/
function finalize(coords) {
var latlng = new google.maps.LatLng(coords.latitude, coords.longitude);
function onGeoLookup(data) {
if (data.length > 0) {
fetchDetailsFromLookup(data);
}
var zoom = geolocator.location.ipGeoSource === null ? 14 : 7, //zoom out if we got the lcoation from IP.
mapOptions = {
zoom: zoom,
center: latlng,
mapTypeId: 'roadmap'
};
drawMap(mCanvasId, mapOptions, data[0].formatted_address);
if (onSuccess) { onSuccess.call(null, geolocator.location); }
}
reverseGeoLookup(latlng, onGeoLookup);
}
/* Gets the geo-position via HTML5 geolocation (if supported).
*/
function getPosition(fallbackToIP, html5Options) {
geolocator.location = null;
function fallback(errMsg) {
var ipsIndex = fallbackToIP === true ? 0 : (typeof fallbackToIP === 'number' ? fallbackToIP : -1);
if (ipsIndex >= 0) {
geolocator.locateByIP(onSuccess, onError, ipsIndex, mCanvasId);
} else {
if (onError) { onError.call(null, errMsg); }
}
}
function geoSuccess(position) {
geolocator.location = {
ipGeoSource: null,
coords: position.coords,
timestamp: (new Date()).getTime(), //overwrite timestamp (Safari-Mac and iOS devices use different epoch; so better use this).
address: {}
};
finalize(geolocator.location.coords);
}
function geoError(error) {
// switch (error.code) {
// case error.PERMISSION_DENIED:
// break;
// case error.POSITION_UNAVAILABLE:
// break;
// case error.TIMEOUT:
// break;
// case error.UNKNOWN_ERROR:
// break;
// }
fallback(error.message);
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, html5Options);
} else { // not supported
fallback('geolocation is not supported.');
}
}
/* Builds the location object from the source data.
*/
function buildLocation(sourceIndex, data) {
switch (sourceIndex) {
case 0: // freegeoip
geolocator.location = {
coords: {
latitude: data.latitude,
longitude: data.longitude
},
address: {
city: data.city,
country: data.country_name,
countryCode: data.country_code,
region: data.region_name
}
};
break;
case 1: // geoplugin
geolocator.location = {
coords: {
latitude: data.geoplugin_latitude,
longitude: data.geoplugin_longitude
},
address: {
city: data.geoplugin_city,
country: data.geoplugin_countryName,
countryCode: data.geoplugin_countryCode,
region: data.geoplugin_regionName
}
};
break;
case 2: // Wikimedia
geolocator.location = {
coords: {
latitude: data.lat,
longitude: data.lon
},
address: {
city: data.city,
country: '',
countryCode: data.country,
region: ''
}
};
break;
}
if (geolocator.location) {
geolocator.location.coords.accuracy = null;
geolocator.location.coords.altitude = null;
geolocator.location.coords.altitudeAccuracy = null;
geolocator.location.coords.heading = null;
geolocator.location.coords.speed = null;
geolocator.location.timestamp = new Date().getTime();
geolocator.location.ipGeoSource = ipGeoSources[sourceIndex];
geolocator.location.ipGeoSource.data = data;
}
}
/* The callback that is executed when the location data is fetched from the source.
*/
function onGeoSourceCallback(data) {
var initialized = false;
geolocator.location = null;
delete geolocator.__ipscb;
function gLoadCallback() {
if (ipGeoSourceIndex === 2) { // Wikimedia
if (window.Geo !== undefined) {
buildLocation(ipGeoSourceIndex, window.Geo);
delete window.Geo;
initialized = true;
}
} else {
if (data !== undefined) {
buildLocation(ipGeoSourceIndex, data);
initialized = true;
}
}
if (initialized === true) {
finalize(geolocator.location.coords);
} else {
if (onError) { onError('Could not get location.'); }
}
}
loadGoogleMaps(gLoadCallback);
}
/* Loads the (jsonp) source. If the source does not support json-callbacks;
* the callback is executed dynamically when the source is loaded completely.
*/
function loadIpGeoSource(source) {
if (source.cbParam === undefined || source.cbParam === null || source.cbParam === '') {
loadScript(source.url, onGeoSourceCallback);
} else {
loadScript(source.url + '?' + source.cbParam + '=geolocator.__ipscb'); //ip source callback
}
}
return {
/*-------- PUBLIC PROPERTIES --------*/
/* The recent location information fetched as an object.
*/
location: null,
/*-------- PUBLIC METHODS --------*/
/* Gets the geo-location by requesting user's permission.
*/
locate: function (successCallback, errorCallback, fallbackToIP, html5Options, mapCanvasId) {
onSuccess = successCallback;
onError = errorCallback;
mCanvasId = mapCanvasId;
function gLoadCallback() { getPosition(fallbackToIP, html5Options); }
loadGoogleMaps(gLoadCallback);
},
/* Gets the geo-location from the user's IP.
*/
locateByIP: function (successCallback, errorCallback, sourceIndex, mapCanvasId) {
ipGeoSourceIndex = (sourceIndex === undefined ||
(sourceIndex < 0 || sourceIndex >= ipGeoSources.length)) ? 0 : sourceIndex;
onSuccess = successCallback;
onError = errorCallback;
mCanvasId = mapCanvasId;
geolocator.__ipscb = onGeoSourceCallback;
loadIpGeoSource(ipGeoSources[ipGeoSourceIndex]);
}
};
}());
/*
* Provides L.Map with convenient shortcuts for using ip based geolocation features.
*/
L.IpProvider = {};
L.IpProvider.None = null;
L.IpProvider.FreeGeoIp = {
url: 'http://freegeoip.net/json/',
cbParam: 'callback',
buildLocationObject: function (data) {
if (!data) {
return null;
}
return {
coords: {
accuracy: 10000,
latitude: parseFloat(data.latitude),
longitude: parseFloat(data.longitude)
},
timestamp: new Date().getTime()
};
}
};
L.IpProvider.GeoPlugin = {
url: 'http://www.geoplugin.net/json.gp',
cbParam: 'jsoncallback',
buildLocationObject: function (data) {
if (!data) {
return null;
}
return {
coords: {
accuracy: 10000,
/* jshint ignore:start */
latitude: parseFloat(data.geoplugin_latitude),
longitude: parseFloat(data.geoplugin_longitude)
/* jshint ignore:end */
},
timestamp: new Date().getTime()
};
}
};
L.IpProvider.Wikimedia = {
url: 'http://geoiplookup.wikimedia.org/',
cbParam: '',
buildLocationObject: function () {
var data = window.Geo,
result = {
coords: {
accuracy: 10000,
latitude: parseFloat(data.lat),
longitude: parseFloat(data.lon)
},
timestamp: new Date().getTime()
};
delete window.Geo;
return result;
}
};
L.IpLocator = L.Class.extend({
locateByIp: function (source, responseCallback, errorCallback) {
var handlerFn = L.bind(function (data) {
this._handleIpResponse(source, data, responseCallback, errorCallback);
}, this);
if (source.cbParam === undefined || source.cbParam === null || source.cbParam === '') {
this._loadScript(source.url, handlerFn);
return;
}
window.cbObject = {};
window.cbObject.fn = handlerFn;
this._loadScript(source.url + '?' + source.cbParam + '= window.cbObject.fn');
},
_handleIpResponse: function (source, data, responseCallback, errorCallback) {
window.cbObject = null;
delete window.cbObject;
var pos = source.buildLocationObject(data);
if (pos === null) {
if (errorCallback) { errorCallback('Could not get location.'); }
} else if (responseCallback) {
responseCallback(pos);
}
},
_loadScript: function (url, callback, type) {
var script = document.createElement('script');
script.type = (type === undefined) ? 'text/javascript' : type;
if (typeof callback === 'function') {
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = function () { callback(); };
}
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
});
L.Map.include({
_defaultLocateOptions: {
ipProvider: L.IpProvider.Wikimedia,
timeout: 10000,
watch: false
// setView: false
// maxZoom: <Number>
// maximumAge: 0
// enableHighAccuracy: false
},
locate: function (/*Object*/ options) {
options = this._locateOptions = L.extend(this._defaultLocateOptions, options);
if (!navigator.geolocation && !options.ipProvider) {
this._handleGeolocationError({
code: 0,
message: 'Geolocation not supported.'
});
return this;
}
var onResponse = L.bind(this._handleGeolocationResponse, this),
onError = L.bind((options.ipProvider) ? this._fallbackToIp : this._handleGeolocationError, this);
if (options.watch) {
this._locationWatchId =
navigator.geolocation.watchPosition(onResponse, onError, options);
} else {
navigator.geolocation.getCurrentPosition(onResponse, onError, options);
}
return this;
},
_fallbackToIp: function (errMsg) {
if (!this._locateOptions.ipProvider) {
this._handleGeolocationError(errMsg);
return;
}
var onResponse = L.bind(this._handleGeolocationResponse, this),
onError = L.bind(this._handleGeolocationError, this);
(new L.IpLocator()).locateByIp(this._locateOptions.ipProvider, onResponse, onError);
}
});
var INNSBRUCK = [47.265718, 11.391342],
VIENNA = [48.186312, 16.317615];
function createMap() { function createMap() {
var defaultCenter = [47.265718, 11.391342], // set center to innsbruck, tyrol, austria var defaultCenter = INNSBRUCK,
// var defaultCenter = [48.186312, 16.317615], // set center to vienna, austria
mapOptions, mapOptions,
zoom = 12; zoom = 12;
...@@ -12,6 +14,7 @@ function createMap() { ...@@ -12,6 +14,7 @@ function createMap() {
mapOptions = { mapOptions = {
attributionControl: false, attributionControl: false,
center: defaultCenter, center: defaultCenter,
ipProvider: L.IpProvider.Wikimedia,
zoomControl: false, // hide default zoom control, so we can create a bottomright one zoomControl: false, // hide default zoom control, so we can create a bottomright one
zoom: zoom zoom: zoom
}; };
...@@ -22,7 +25,7 @@ function createMap() { ...@@ -22,7 +25,7 @@ function createMap() {
} }
function drawMap(mapOptions) { function drawMap(mapOptions) {
var layerControl = L.control.layers(), var layerControl = L.control.layers({position: 'topright'}),
map = null, map = null,
zoomControl = L.control.zoom({position: 'bottomright'}); zoomControl = L.control.zoom({position: 'bottomright'});
...@@ -42,11 +45,12 @@ function drawMap(mapOptions) { ...@@ -42,11 +45,12 @@ function drawMap(mapOptions) {
// Map creation and control assignment // Map creation and control assignment
map = L.map('map', mapOptions); map = L.map('map', mapOptions);
map.addControl(new SettingsControl()); map.addControl(new SettingsControl({position: 'bottomright'}));
map.addControl(new HelpControl()); map.addControl(new HelpControl({position: 'bottomright'}));
map.addControl(layerControl); map.addControl(layerControl);
map.addControl(zoomControl); map.addControl(zoomControl);
map.addControl(L.control.scale()); map.addControl(L.control.locate({position: 'bottomright'}));
map.addControl(L.control.scale({position: 'bottomleft'}));
map.addControl(new L.Control.GeoSearch({ map.addControl(new L.Control.GeoSearch({
doReverseLookup: true, doReverseLookup: true,
position: 'topleft', position: 'topleft',
...@@ -179,9 +183,9 @@ function addBingLayers(c) { ...@@ -179,9 +183,9 @@ function addBingLayers(c) {
function locateAndDraw(mapOptions) { function locateAndDraw(mapOptions) {
var fnSuccess = function(location) { onLocationSuccess(mapOptions, location); }, var fnSuccess = function(location) { onLocationSuccess(mapOptions, location); },
fnError = function(message) { onLocationError(mapOptions, message); }, fnError = function(message) { onLocationError(mapOptions, message); },
html5Options = { enableHighAccuracy: true, timeout: 3000, maximumAge: 0 }; locator = new L.IpLocator();
geolocator.locate(fnSuccess, fnError, true, html5Options); locator.locateByIp(mapOptions.ipProvider, fnSuccess, fnError);
} }
function onLocationSuccess(mapOptions, location) { function onLocationSuccess(mapOptions, location) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment