Christian Heilmann

Posts Tagged ‘hack’

TTMMHTM: Braille body mods, Tesco hack, Placemaker talk video, old superheroes, steampunk, accessible Opera and cat control

Tuesday, July 14th, 2009

Things that made me happy this morning:

Geo this! Geolocate WordPress posts with Greasemonkey and Yahoo Placemaker

Monday, June 22nd, 2009

Geolocating content on the web is a great idea. By embedding latitude and longitude and real place names in your document you allow data mining for location or easy display on a map.

The problem up to now was that it is quite a job to find out the correct geo information from a text or a document and it is quite a pain to enter the information by hand.

Yahoo Placemaker is a web service that helps you with that – you give it some text or a document URL and it returns you all the things it found in there that resemble a geographical location back. The issue with doing that on a live site is that you slow down your site immensely as you need to look up every time.

The more logical place to do the lookup with Placemaker is when you edit your document. I thought this would be cool to have for this WordPress install here and wrote a small GreaseMonkey script that injects a new “Geo this!” button in the main WP form:

Geo this - button by  you.

When I hit the button the script does an Ajax request using the Placemaker open YQL table to get the information for the currently edited text.

Once it found the information it adds it at the end of the document as a GEO microformat. Each found entry starts with a comment that tells you what Placemaker matched and considered a geographical location. As it is not infallible this makes it easy for you to delete wrong entries.

Geo this - added microformats by  you.

Try it out yourself:

This is pretty much rough and ready and I’d be happy for feedback how to improve it.

Postcode from latitude and longitude or even IP – fun with Geo APIs and YQL

Tuesday, June 9th, 2009

One of the more complex things about GeoFill was to get postcode information from an IP. However with a collection of APIs and a collated YQL statement even this was possible.

The first thing I needed to get was the IP of the user. This is done with the GeoIP API based on the GeoLite API from MaxMind. This is available as an open table in YQL and can be used thus:

select * from ip.location where ip=”“

Try the lookup in the console or check the lookup result

Response”: {
“Ip”: “216.39.58.17”,
“Status”: “OK”,
“CountryCode”: “US”,
“CountryName”: “United States”,
“RegionCode”: “06”,
“RegionName”: “California”,
“City”: “Sunnyvale”,
“ZipPostalCode”: “94089”,
“Latitude”: “37.4249”,
“Longitude”: “-122.007”,
“Gmtoffset”: “-8.0”,
“Dstoffset”: “-7.0”
}

This gives us a lot of information. What’s really important here is latitude and longitude, as this can be used in the flickr.places API to get a where on earth ID which is a much more defined identifier:

select * from flickr.places where (lat,lon) in (
select Latitude,Longitude from ip.location where ip=””
)

Try the flickr places call in the console or check the flickr result

“places”: {
“accuracy”: “16”,
“latitude”: “37.4249”,
“longitude”: “-122.007”,
“total”: “1”,
“place”: {
“latitude”: “37.371”,
“longitude”: “-122.038”,
“name”: “Sunnyvale, California, United States”,
“place_id”: “P_ls_fybBJwdHP8t”,
“place_type”: “locality”,
“place_type_id”: “7”,
“place_url”: “/United+States/California/Sunnyvale”,
“timezone”: “America/Los_Angeles”,
“woeid”: “2502265”
}

}


Here the interesting part is the woeid which we can use to dig deeper into geo.places:

select * from geo.places where woeid in (
select place.woeid from flickr.places where (lat,lon) in (
select Latitude,Longitude from ip.location where ip=””
)

)

Try the geo places call in the console or check the geo places result

The result is all the information you’d ever want.

“place”: {
“lang”: “en-US”,
“xmlns”: “http://where.yahooapis.com/v1/schema.rng”,
“yahoo”: “http://www.yahooapis.com/v1/base.rng”,
“uri”: “http://where.yahooapis.com/v1/place/28751237”,
“woeid”: “28751237”,
“placeTypeName”: {
“code”: “22”,
“content”: “Suburb”
},
“name”: “Fairgrounds”,
“country”: {
“code”: “US”,
“type”: “Country”,
“content”: “United States”
},
“admin1”: {
“code”: “US-CA”,
“type”: “State”,
“content”: “California”
},
“admin2”: {
“code”: “”,
“type”: “County”,
“content”: “Santa Clara”
},
“admin3”: null,
“locality1”: {
“type”: “Town”,
“content”: “San Jose”
},
“locality2”: {
“type”: “Suburb”,
“content”: “Fairgrounds”
},
“postal”: {
“type”: “Zip Code”,
“content”: “95112”
},
“centroid”: {
“latitude”: “37.326611”,
“longitude”: “-121.878441”
},
“boundingBox”: {
“southWest”: {
“latitude”: “37.275379”,
“longitude”: “-121.89254”
},
“northEast”: {
“latitude”: “37.330879”,
“longitude”: “-121.808723”
}

}
}

Newsmap – using Placemaker to add geo location to a news feed

Friday, May 22nd, 2009

I am right now very excited about the new Placemaker beta – a location extraction web service released at Where2.0. Using Placemaker you can find all the geographical locations in a feed or a text or a web url and you get them back as an array of places.

As a demo I took the Yahoo News feed and ran it through Placemaker. The resulting places are plotted on a map and the map moves from location to location when you hover over the news items.

The result is online at http://isithackday.com/hacks/placemaker/map.php

Yahoo News Map by  you.

Getting the data from the data feed and running it through placemaker is very straight forward. I explained the basic principle in this blog post on the Yahoo Developer Network blog. The only thing to think about is to define the input and output types correctly:


$key = ‘PASTE YOUR API KEY HERE’;
$apiendpoint = ‘http://wherein.yahooapis.com/v1/document’;
$url = ‘http://rss.news.yahoo.com/rss/topstories’;
$inputType = ‘text/rss’;
$outputType = ‘rss’;
$post = ‘appid=’.$key.’&documentURL=’.$url.
‘&documentType=’.$inputType.’&outputType=’.$outputType;
$ch = curl_init($apiendpoint);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$results = curl_exec($ch);
?>

If you look at the source of this example you will find that Placemaker injected contentlocation elements in the feed itself:


xmlns:georss=”http://www.georss.org/georss” xmlns:cl=”http://wherein.yahooapis.com/v1/cle”
xmlns:xml=”http://www.w3.org/XML/1998/namespace” xml:lang=”en”>

2514815

38.8913
-77.0337


23424793

21.511
-77.8068


23424977

48.8907
-116.982


55843872
Guantanamo, CU]]>
19.9445
-75.1541


You’ll also notice that the elements are namespaced and the names of the locations in CDATA blocks, both things I hate with a passion. Not because they don’t make sense, but because simplexml can be drag to make understand them.

What I wanted to do with this data was twofold: create a JSON array of geo locations to plot on a map and a display of the news content. This is the PHP that does that:


$places = simplexml_load_string($results, ‘SimpleXMLElement’,
LIBXML_NOCDATA);
// if there are elements found
if($places->channel->item){
// start a JSON array
$output .= ‘[‘;
// start the HTML output
$html = ‘‘;
?>

The result of this can be seen here http://isithackday.com/hacks/placemaker/map-2.php.

The JavaScript to show the map is pretty straight forward and more or less the demo example of the maps API:


// will be called with the array assembled in PHP
function placeonmap(o){
// if there are locations
if(o.length > 0){
// create a new geopoints array to hold all locations
// this is needed to determine the original zoom
// level of the map
var geopoints = [];
// add map with controls
var map = new YMap(document.getElementById(‘map’));
map.addZoomLong();
map.addPanControl();
// loop over locations
for(var i=0;i // define a new geopoint and store it in the array
var point = new YGeoPoint(o[i].lat,o[i].lon);
geopoints.push(point);
// create a new marker and give it the unique
// id defined in the PHP. Pop up the title of
// the news item and the name of the location when the
// user hovers over the marker
var newMarker = new YMarker(point,o[i].id);
newMarker.addAutoExpand(o[i].title + ‘(‘+o[i].name+’)’);
map.addOverlay(newMarker);
}

// define best zoom level and show map
var zac = map.getBestZoomAndCenter(geopoints);
map.drawZoomAndCenter(zac.YGeoPoint,zac.zoomLevel);
}

// add a mouseover handler to the list of results
YAHOO.util.Event.on(‘news’,’mouseover’,function(e){
// remove the “news” text of the ID of the current target
// as we named the list items news0 to news19
var id = YAHOO.util.Event.getTarget(e).id.replace(‘news’,’‘);
// if there is still something left we have one of the news
// items
if(id!==’‘){
// get the first marker with the ID we defined in the loop.
var marker = map.getMarkerObject(‘m’+id+’x0’);
// if there is one, pan the map there and show the message
// attached to it.
if(marker){
map.panToLatLon(marker.YGeoPoint);
marker.openAutoExpand();
}

}
});
}

// call placeonmap with the JSON array
placeonmap();

That’s pretty much it. I am sure it can be refined, but it is amazing how easy it is to get geo information into any text with Placemaker.

TTMMHTM: Sorry Jinho answers, twittering cat flaps, hot goths and the real AYB

Monday, May 18th, 2009

Things that made me happy this morning: