allan ebdrup bloghoved ny

Hent dine brugeres geografiske lokation med JavaScript

Prøver at slå din lokation op...
Hvid den ikke dukker op herindenfor kor tid,
kan din ip-adresse ikke findes.


/*
YQL Geo library by Christian Heilmann
Homepage: http://isithackday.com/geo/yql-geo-library
Copyright (c)2010 Christian Heilmann
Code licensed under the BSD License:
http://wait-till-i.com/license.txt
V2 by Allan Ebdrup (simplified, no named functions and fallback to geoPlugin.com if YQL does not return location)
*/
var yqlgeo2 = {
getGeoLocation: function (fnCallback) {
this.mfnCallback = fnCallback;
this.retrieveIp();
},
retrieveIp: function () {
this.createScript('http://jsonip.appspot.com/?callback=yqlgeo2.ipRetrievedCallback');
},
ipRetrievedCallback: function (o) {
this.mstrIp = o.ip;
this.getGeoLocationFromIp(o.ip);
},
createScript: function (src) {
var head = document.getElementsByTagName('head')[0];
var s = document.createElement('script');
s.src = src;
head.appendChild(s);
},
getGeoLocationFromIp2: function (ip) {
//make callback that emulates yql result
window["geoPlugin"] = function (o2) {
var o = {
method: "geoPlugin",
query: {
results: {
ip: ip,
place: {
centroid: { latitude: o2.geoplugin_latitude, longitude: o2.geoplugin_longitude },
country: { content: o2.geoplugin_countryName, code: o2.geoplugin_countryCode },
locality1: {
content: o2.geoplugin_region
},
locality2: {
content: o2.geoplugin_city
}
}
}
}

        };  
        yqlgeo2.geoLocationRetrievedCallback(o);  
    }  
    this.createScript("http://www.geoplugin.net/json.gp?ip=" + ip);  
},  
getGeoLocationFromIp: function (ip) {  
    var yql = 'select * from geo.places where woeid in (' +  

'select place.woeid from flickr.places where (lat,lon) in(' +
'select latitude,longitude from pidgets.geoip' +
' where ip="' + ip + '"))';
this.executeYql(yql, 'yqlgeo2.geoLocationRetrievedCallback');
},
executeYql: function (yql, cb) {
var src = 'http://query.yahooapis.com/v1/public/yql?q=' +
encodeURIComponent(yql) + '&format=json&callback=' + cb + '&' +
'env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
this.createScript(src);
},
geoLocationRetrievedCallback: function (o) {
if (o.query.results) {
if (o.query.results.place) {
o.query.results.ip = this.mstrIp;
this.mfnCallback(o.query.results);
return;
}
}
if (!o.method || o.method != "geoPlugin") {
//Yql gave no result. trying geoPlugin...
this.getGeoLocationFromIp2(this.mstrIp);
}
}
};

span.comment {color:#060; font-weight:normal}
span.oper {color:#006; font-weight:normal}
span.var {color:#600; font-weight:normal}
span.func {color:#606; font-weight:normal}
span.num {color:#300; font-weight:bold}
span.string {color:#066; font-weight:normal}
span.reg {color:#666; font-weight:normal}

    /*  
    YQL Geo library by Christian Heilmann  
    Homepage: http://isithackday.com/geo/yql-geo-library  
    Copyright (c)2010 Christian Heilmann  
    Code licensed under the BSD License:  
    http://wait-till-i.com/license.txt  
    V2 by Allan Ebdrup (simplified, no named functions and fallback to geoPlugin.com if YQL does not return location)  
    */  
    var yqlgeo2 = {  
        getGeoLocation: function (fnCallback) {  
            this.mfnCallback = fnCallback;  
            this.retrieveIp();  
        },  
        retrieveIp: function () {  
            this.createScript('http://jsonip.appspot.com/?callback=yqlgeo2.ipRetrievedCallback');  
        },  
        ipRetrievedCallback: function (o) {  
            this.mstrIp = o.ip;  
            this.getGeoLocationFromIp(o.ip);  
        },  
        createScript: function (src) {  
            var head = document.getElementsByTagName('head')[0];  
            var s = document.createElement('script');  
            s.src = src;  
            head.appendChild(s);  
        },  
        getGeoLocationFromIp2: function (ip) {  
            //make callback that emulates yql result  
            window["geoPlugin"] = function (o2) {  
                var o = {  
                    method: "geoPlugin",  
                    query: {  
                        results: {  
                            ip: ip,  
                            place: {  
                                centroid: { latitude: o2.geoplugin_latitude, longitude: o2.geoplugin_longitude },  
                                country: { content: o2.geoplugin_countryName, code: o2.geoplugin_countryCode },  
                                locality1: {  
                                    content: o2.geoplugin_region  
                                },  
                                locality2: {  
                                    content: o2.geoplugin_city  
                                }  
                            }  
                        }  
                    }

                };  
                yqlgeo2.geoLocationRetrievedCallback(o);  
            }  
            this.createScript("http://www.geoplugin.net/json.gp?ip=" + ip);  
        },  
        getGeoLocationFromIp: function (ip) {  
            var yql = 'select * from geo.places where woeid in (' +  
'select place.woeid from flickr.places where (lat,lon) in(' +  
'select latitude,longitude from pidgets.geoip' +  
' where ip="' + ip + '"))';  
            this.executeYql(yql, 'yqlgeo2.geoLocationRetrievedCallback');  
        },  
        executeYql: function (yql, cb) {  
            var src = 'http://query.yahooapis.com/v1/public/yql?q=' +  
encodeURIComponent(yql) + '&format=json&callback=' + cb + '&' +  
'env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';  
            this.createScript(src);  
        },  
        geoLocationRetrievedCallback: function (o) {  
            if (o.query.results) {  
                if (o.query.results.place) {  
                    o.query.results.ip = this.mstrIp;  
                    this.mfnCallback(o.query.results);  
                    return;  
                }  
            }  
            if (!o.method || o.method != "geoPlugin") {  
                //Yql gave no result. trying geoPlugin...  
                this.getGeoLocationFromIp2(this.mstrIp);  
            }  
        }  
    };  





    yqlgeo2.getGeoLocation(function (o) {  
        var s = "Din lokation er cirka:  

" + o.place.locality2.content + ", " + o.place.locality1.content + ", " + o.place.country.content + "
" +
"Longitude: " + o.place.centroid.longitude + "
Latitude: " + o.place.centroid.latitude + "" +
"Lokationen er ikke præcis, og nogle gange ret forkert.
Hvor præcis er den for dig?
Skriv gerne en kommentar.
Denne kode er lavet med den restriktion, at brugeren ikke må spørges om lov til at opgive sin position.";
document.getElementById("geoLocationOutput").innerHTML = s;
});

Sådan bruges koden

yqlgeo2.getGeoLocation(function (o) {
var s = "Din lokation er cirka:" + o.place.locality2.content + ", " + o.place.locality1.content + ", " + o.place.country.content + "" +
"Longitude: " + o.place.centroid.longitude + ", Latitude: " + o.place.centroid.latitude + "" +
"Lokationen er ikke præcis, og nogle gange ret forkert.";
document.getElementById("geoLocationOutput").innerHTML = s;
});

Gør brug af flere geolokationservices

Løsningen prøver først, at slå brugerens geolokation op via Yahoos data (YQL). Hvis dette ikke giver noget resultat, benyttes geoplugin.com.

Kommentarer (34)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Mads Vibe Rasmussen

Din lokation er cirka:
Solrød, Region Zealand, Denmark
Longitude: 12.183300018311
Latitude: 55.533298492432

Ja det er jo så der jeg er, næsten. Lidt mere ud ved stranden så den har kun kunne slå den offentlige lokalition op på ip adressen

Eneste jeg har set mere præcist er google's database over mobilmaster/wifi access points -den rammer til tider uhyggeligt præcist..

  • 0
  • 0
Erik Jacobsen

Hvor er det nu Randers ligger? I bunden af superligaen, vistnok. Men langt fra hvor jeg bor, Hasselager. I mit tilfælde har de øjensynligt kun adressen på selve udbyderne, og intet på deres interne netværk.

  • 0
  • 0
Allan Ebdrup Blogger

Google Maps placerer mig med et par meters præcision derimod.

Jeg går ud fra at du er på en mobiltelefon?
Metoden i ovenstående kode virker ved at slå din IP-adresses lokation op i en database over serveres geografiske placering.
Jeg vil tro at google maps har adgang til mere data om din position, end man kan få uden at spørge om lov først.
Jeg har lavet ovenstående udfra en restriktion om at brugeren ikke skal spørges om noget. Som sagt kan man finde en meget mere præcis position hvis man er indstillet på at prompte brugeren.

  • 0
  • 0
Klaus Skelbæk Madsen

Google maps har slet ikke en funktion til at finde min position når jeg går ind på den på min stationære computer... Eller også er den gemt meget godt...

Det kan sagtens være det sidste. Det er en lille cirkel oven for streetview manden, som man klikker på, for at få maps til at finde ens nuværende position. Langt fra åbentlyst.

  • 0
  • 0
Jesper Lund Stocholm Blogger

Hej Klaus,

Det kan sagtens være det sidste. Det er en lille cirkel oven for streetview manden, som man klikker på, for at få maps til at finde ens nuværende position

Hvis man klikker på den knap, så promptes man for at give tilladelse til at Chrome (i mit tilfælde) sender data om lokale netværk til Google. Helt konkret forklarer Google mig:

"Hvis du giver Google Chrome tilladelse til at dele din placering med et websted, sender browseren oplysninger om dit lokale netværk til Googles placeringstjenester for at få din omtrentlige placering".

Samme opførsel ses i Safari og Firefox (på Mac).

  • 0
  • 0
Jørn Schou-Rode

Jeg bruger en gratis IP-database fra firmaet MaxMind til et par forskellige webprojekter, og det er mit indtryk at den rammer rimelig præcis.

http://www.maxmind.com/app/locate_my_ip

Når jeg tester denne fra min egen IP er svaret Copenhagen (55.6667/12.5833), hvilket er uendelig meget mere præcist end Istanbul (28.965410/41.018688) som eksemplet her på siden giver mig. Jeg er formentlig bare "uheldig", og det vil ikke overraske mig, om MaxMind har tilsvarende huller.

  • 0
  • 0
Jørn Schou-Rode

Jeg går ud fra at du er på en mobiltelefon?

Chrome til OSX – og formentlig også andre desktopbrowsere – implementerer location API'et, og udregner din position ved at se på listen af tilgængelige wifi access points. De tager så ID'erne herfra og matcher dem mod en database over senest kendte position på disse, og kan så pejle sig ind til din position.

Det fungerer uhyggelig godt mange steder, men kræver som tidligere nævnt brugerens samtykke. Til tjenester hvor brugeren ser en værdi i at oplyse sin position til et website, er dette setup IP-opslag overlegent. Er det ikke åbenlyst for brugeren hvorfor tjenesten har behov for en position, er det nok mere hensigtsmæssigt at holde sig til et IP-opslag bag gardinerne.

  • 0
  • 0
Erik Cederstrand

Din lokation er cirka:
Maribo, Region Zealand, Denmark
Longitude: 11.516699790955
Latitude: 54.766700744629

Spor 26 på Hovedbanen kan til tider godt føles langt væk, men Maribo er nok at strække den. Positionen holder i hvert fald ikke ned til 12. decimal.

  • 0
  • 0
Jacob Larsen

Jeg fik også at vide at jeg var på Amagerbro, København, selvom jeg sad i et tog mellem Hobro og Randers. Er der ikke mulighed for at forbedre nøjagtigheden ved at tage fat i devicens GPS, hvis den er tilgængelig? Ligesom Google gør.

  • 0
  • 0
Jesper Lund Stocholm Blogger

Hej Jacob,

Er der ikke mulighed for at forbedre nøjagtigheden ved at tage fat i devicens GPS, hvis den er tilgængelig? Ligesom Google gør.

Hele pointen med Allans post er (og ret mig endelig, hvis jeg tager fejl) er at vise hvad man kan mht at stedbestemme en bruger - men uden at spørge brugeren om tilladelse til det. I HTML5 er der jo et "geoLocation-API" som kan bruges, der for de fleste browseres tilfælde bruger de omkringliggende WIFIs eller GPS-lokationen, hvis brugeren er online via en telefon.

Problemet med WIFI og GPS er blot, at brugeren bliver spurgt om lov før de kan benyttes. Hvis brugeren derimod giver tilladelse til det, så er det trivielt at finde lokationen med relativt stor nøjagtighed (i de fleste tilfælde).

  • 0
  • 0
Allan Ebdrup Blogger

Jeg har tilføjet en afstemning, så folk kan sige hvor præcis lokationen er. Men det er nok lidt sent, nu er blogindlæget nok røget ud af nyhedsstrømmen...
De må jeg huske næste gang jeg skriver om noget tilsvarende...

  • 0
  • 0
Kasper Grubbe

Virker ikke i Chrome på OSX, og jeg sidder i Ukraine.

Jeg sidder også og roder med GeoLokation som en del af et projekt, jeg er dog gladere for serverside identifikation da du alligevel aldrig får brugeren til at sige 'ja' til at tracke ham. Til at teste præcisionen lavede jeg denne side http://hvorlangterjegfraribe.dk

Den regner afstanden ud fra din gættede position. Og jeg har beskrevet det med kode-eksempler idag, leg gerne videre!

  • 0
  • 0
Allan Ebdrup Blogger

Er det en øvelse i Javascript eller i at finde den bedste data-kilde til IP => geo-lokation?

Måske er det nemmest at jeg forklarer hvor jeg har haft brug for det.

Jeg bruger det på mit fritidsprojekt http://obsurvey hvor folk kan lave spørgeskemaer.

Når folk svarer på et spørgeskema, bruger jeg ovenstående til at logge deres geografiske lokation.

Jeg kan ikke spørge alle der besvarer et spørgeskema om tilladelse til at opgive deres lokation. Samtidigt synes jeg det er super interessant at se hvor i verden folk der svarer på ens spørgeskema kommer fra (Om ikke andet så bare hvilket land)

Der er ingen indtægt på mit fritidsprojekt, så jeg ledte efter en gratis løsning til geo positionering.

Ovenstående er en meget nemt at implementere. Du skal bare copy&paste koden. Det kan bruges uden du har en server selv. Jeg kalder dog min backend og gemmer resultatet, men det behøver man jo ikke gøre.

Så tænkte jeg bare at når nu jeg havde haft gavn af det, så kunne andre måske også. :-)

Det er da meget sjovt at du bare kan paste ovenstående ind på din side og så har du noget geolokation, gratis og hurtigt...

Jeg vidste så ikke at den var så upræcis. Jeg vil tro den er mest præcis i USA hvor firmaerne der har databaserne holder til. Og mange af mine bruger kommer fra USA.

  • 0
  • 0
Jesper Lund

Brugeren kan jo finde på at sige "nej". Jeg bliver næsten hver dag spurgt om min browser må sende min geo location afsted, og det er yderst sjældent, at jeg giver denne tilladelse.

Klogt. Jeg har helt deaktiveret det i about:config.

Men spørgsmålet er om en angriber kan omgå dette, f.eks. med en java applet?

Hvis du sidder bag NAT, kan din private IP adresse afsløres med en usigneret java applet, som de fleste browsere eksekverer uden videre. F.eks. her
http://www.auditmypc.com/anonymous-surfing.asp

Jeg er ikke klar over om det er teknisk muligt, men java appletten skal blot have fat i MAC adressen for dit AP (forudsat at du bruger wifi, men Firefox's geolocation API har samme begrænsning). Så er der en god chance for at denne MAC er i Google's database, og din position kan bestemmes meget præcist (og uden dit vidende).

  • 0
  • 0
Morten Jølnæs Jacobsen

fik som flere andre også

Amagerbro, Copenhagen, Denmark
Longitude: 12.583590
Latitude: 55.666618

Forskellen er måske at jeg faktisk bor kun 1,6km de koordinater, ved amagercentret.

Men når koordinaterne så præcist er det samme tyder det på der er et eller andet der som den ikke kan se forbi...

  • 0
  • 0
Log ind eller Opret konto for at kommentere