** We finally have an open video format with WebM which is a container based on Matroska with VP8 as the video and Vorbis for audio. It is backed by Opera, Mozilla and Google amongst other huge players. IE9 says it will support it with a plugin and Safari seems to be supporting it via a Quicktime plugin.
** Google also released BigQuery which is a REST API to analyse data in Google Storage. One of the uses they showed is the Prediction API which does natural language analysis and could become a contender for Open Calais.
** Android got a major update – it now runs the superfast V8 engine, you will have access to accelerometer and camera with a JavaScript API and you can send applications to the phone from computers via the cloud. Makes me want to kill the guy who dropped my Nexus One and hope HTC will be quick in repairing it.
When I went to California last I was lucky enough to meet some friends from Google for lunch at their office and as a surprise on the way out I got a Nexus One as a present:
I loved it immediately. It is a very slick phone with a real “developer touch”. This means:
To get data on or off it I connect it to a USB port and copy the stuff – no need to fire up some “Media Explorer” or iTunes.
The handling was wonderful – even though I never had a touch phone before I had no issues with it at all (except when I tried to type German SMS with the English dictionary on)
The geolocation stuff, Google Goggles, Google Maps, Point by Point navigation and all the other stuff that only runs on this platform beat the pants off the iPhone (at least for me)
The camera is amazing and the display is crisp as can be
That is until yesterday night. When I gave the phone to someone at the Future of Web Design after party to have a look at it he dropped it. I didn’t check and just pocketed it and this morning I found the display to look like this:
It has a bit of a Eastman Colour vibe to it but makes it impossible to use. Funnily enough the touch stuff still works perfectly but outside of artificial light you cannot see anything on it any longer.
Now I am busted:
Where can I get a free Nexus One repaired in the UK? This is a no contract phone.
What can I do about my Jewels and Layar addiction?
It is a great example how being a very, very early adopter can bite you in the bum if something as simple as gravity messes with you :(.
The Open Data Group of the lovely area of Warwickshire in England is running a hack competition right now and they ask hackers to build something cool with their data sets.
I looked at the catalogue of offers and took the simple way out – I created a mashup showing you the parks, museums, schools and libraries in the area both as lists with all the information and a an interactive map.
Notice that the last dataset is vastly different to the others (uppercase elements for a start) and also that it contains the gem of 52.4786839 – would be good to spell-check your elements :) (that cost me 20 minutes of my life later on).
Now, I could load all of these one by one and then start converting the data to a useful format but as I am lazy I use YQL for that:
select * from xml where url in (
"http://ws.warwickshire.gov.uk/parks.xml",
"http://ws.warwickshire.gov.uk/libraries.xml",
"http://ws.warwickshire.gov.uk/museums.xml",
"http://opendata.s3.amazonaws.com/schools/schools-warwickshire.xml"
)
This, sent to the right YQL webservice endpoint results in an aggregated XML document and means I only have to have one HTTP request to load the data. Check this link to see the aggregated file.
Planning the mashup
Now, I’ve built mashups like these tons of times and mostly they end up to be a quick but terrible mess. Therefore I thought I change my approach. As the main solution I simply wanted to show a list of all the parks, museums, libraries and schools. This would work regardless of environment and ability of the user agent. Instead of assembling a JSON object to plot the information on the map I wanted to use the HTML as my data source by adding some classes (much like Microformats were meant to be used before the world forgot about them to chase CSS3 transition effects).
The HTML and CSS
So the first thing to do was to make sure my CSS works out fine. I did this by using the YUI CSS grids for my layout (building the interface with the grids builder)
This gave me an HTML skeleton to work from and also got rid of all the font issues across browsers which meant that in the end all my CSS file had to do was to show and hide things and put on a lick of paint (don’t judge me – I built this in FireBug).
The last thing I needed was a container DIV with a placeholder for the map and one for the information to be displayed about the marker the user clicked on the map:
Retrieving and converting the data
With that out of the way, all I needed was to get the data from YQL into my own HTML - for this I used PHP and cURL:
$yql = 'select * from xml where url in ('.
'"http://ws.warwickshire.gov.uk/parks.xml",'.
'"http://ws.warwickshire.gov.uk/libraries.xml",'.
'"http://ws.warwickshire.gov.uk/museums.xml",'.
'"http://opendata.s3.amazonaws.com/schools/schools-warwickshire.xml"'.
')';
$url = 'http://query.yahooapis.com/v1/public/yql?q='.urlencode($yql).
'&diagnostics=false&format=json';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
$data = json_decode($output);
This gives me all the data in the $data variable as a native PHP object. All that I needed to do was to analyse the data coming back and wrap it in the right HTML.
Displaying the HTML for each section
echo '
Parks ('.
sizeof($data->query->results->parks->park).
')
';
foreach($data->query->results->parks->park as $k=>$p){
echo '
I add a DIV with the class section around each of the parts I want to show and wrap the results in an unordered list with an ID. I add a class called hasimg to the list items that contain an image to allow for the right CSS layout and I wrap the name of the section in a SPAN with the class name. This allows me later on to read this information to plot it on a map. Each list item also gets a running ID of p1, p2, p3 and so on which allows me to read the information when the user clicks the marker on the map.
I’ve written a small helper function called addpara() to only write out the paragraphs of elements that have content as I wanted to avoid empty P elements. The section ends with a P with the class geo which contains a SPAN with the coordinates – once again to allow me to plot it on a map.
This gets repeated for parks, museums and libraries but the schools data set needed special treatment. First of all the format was different, but it also returned data in uppercase, which is just not fun.
That’s why I used ucwords() and strtolower() to clean up the data before displaying it:
That’s the lot. If you turn off JavaScript in the mashup you can see the outcome of these efforts – a long list of different sights preceeded by a heading.
Adding the map and collapsing the sections
The next step in the process was to ad the JavaScript functionality. I added a class called js to the body of the document when JavaScript is available and included the Yahoo Maps API and the YUI library. The latter allows me simple and browser independent access to both the DOM and events in the browser, the former is of course needed to show the map.
Adding the class to the body saves me a lot of trouble. Instead of looping through all the lists and hiding them (as I want to show and hide them when you click on the headers), I can now do that in the CSS:
I define wws as a namespace, but I don’t need to worry about embedding the code in the closure as YUI’s use() method does that for me. I add the class to the body (as the HTML maintainer might remove the other JavaScript that does that – it is only there to fire as soon as possible). Then I add a tabIndex of -1 to all the elements I want to make interactive – this makes them available to keyboard users.
Using the wonders of Event Delegation it is very easy to make all the H2 headings in the #bd clickable and show and hide the following ULs:
Y.delegate('click', function(e) {
e.preventDefault();
var dad = Y.one(e.target).ancestor('div');
if(dad.hasClass('show')){
dad.removeClass('show');
} else {
dad.addClass('show');
var next = Y.one(e.target).next('ul');
next.focus();
}
}, '#bd', 'h2');
I add and remove the show class to show and hide the ULs and move the focus to the list when the header is clicked.
Next I wanted to explain to the end users what can be done here. You will find a lot of mashups that will have this info in the HTML but what if JavaScript is not available? You explain functionality that is not available and confuse users. This is why I add the information to the info section and add a class to allow for different styling as this section will be re-used to show the information of the marker I clicked on.
Y.one('#info').set('innerHTML',
'
Get all the information here
'+
'
Click any of the icons on the map to the right to get '+
'detail information about the location.
'+
'
You can make the map less busy by turning features on and off'+
'with the buttons above.
'
).addClass('intro');
Next up I start the map:
var points = [];
wws.map = new YMap(Y.one('#map')._node);
wws.map.addTypeControl();
wws.map.addZoomLong();
wws.map.addPanControl();
wws.map.disableKeyControls();
wws.map.setMapType(YAHOO_MAP_HYB);
The points array will hold all the points I want to show on the map. Yahoo maps can get the right zoom level and map centre automatically for you when you give it an array of points. I disable the key controls to make sure the map doesn’t interfere with page scrolling and define hybrid as the map type. As the map needs to be globally accessible I attach it to the wws namespace.
var parks = Y.all('#parks .name').get('innerHTML');
var parklocs = Y.all('#parks .geo span').get('innerHTML');
for(var i=0,j=parks.length;i
And off we go.
So what’s going on here? I read the names of all the parks and the location of all the parks using the Y.all() method of YUI3. I then loop over the parks, split the coordinate information on the comma and create a new GeoPoint from it. I add the point to the points array, define an image for the point and create a new YMarker. In the marker I add the point, the image and a running ID. This will label the markers internally as mp0, mp1, mp2 and so forth. This I need to connect the marker with the content section in the list (remember I added a running ID on the list items when I wrote them out in PHP).
I then add a capturing function to the marker that fires when it is clicked. In this one I read out the ID of the marker (using the rather obtruse i.thisObj.id property), remove the “m” from the ID and get the content of the element with this ID - which is the connected list item. I send the content to the showinfo() function.
Furthermore I add an AutoExpand with the name of the park and a “click for more” message to the marker and add it to the map.
This functionality is repeated for all the different sections which seems a waste but years of building this kind of stuff taught me that a few weeks down the line you will have to make amendments for different sections anyway so a bit of copy and paste doesn’t hurt.
var zac = wws.map.getBestZoomAndCenter(points);
var level = zac.zoomLevel;
wws.map.drawZoomAndCenter(zac.YGeoPoint,level-2);
I get the best zoom level and the centre of the map and draw it. I remove two levels from the best level as the markers are very dense on this map and I didn’t want to overwhelm the end user.
I then needed some interactive elements to allow resizing of the map and to show and hide the different markers. For this I create buttons as that is what they are there for – firing JavaScript functionality. I add the buttons to the container element and give each an ID to differentiate between them.
Y.delegate('click',function(event){
var t = Y.one(event.target);
switch(t.get('id')){
case 'size':
if(t.get('innerHTML').indexOf('smaller map')!=-1){
t.set('innerHTML','↓ larger map ↓');
Y.one('#map').setStyle('height','280px');
} else {
t.set('innerHTML','↑ smaller map ↑');
Y.one('#map').setStyle('height','600px');
}
break;
case 'librariesbutton':
if(t.get('innerHTML').indexOf('hide')!=-1){
wws.toggleMarkers('ml',0);
t.set('innerHTML','show libraries');
t.addClass('inactive');
} else {
wws.toggleMarkers('ml',1);
t.set('innerHTML','hide libraries');
t.removeClass('inactive');
}
break;
[... repeated for the others ...]
}
},'#container','button');
Again I use event delegation to attach functionality to all buttons in the container element and differentiate by reading out the event target and its ID. For the resizing button I resize the map and change the content of the button. For the other buttons I call the toggleMarkers() method using the string to identify the markers and a boolean to turn them on or off and change the content of the button. To allow for extra styling I also add and remove a class called inactive.
The showinfo() function simply changes the content of the info element and removes the intro class to trigger the less “in your face” style the intro blurb had. It then checks if the content contains a link and sends the focus of the document to that one – or to the info element itself. This helps keyboard users.
wws.toggleMarkers = function(str,what){
var markers = wws.map.getMarkerIDs();
for(var i=0;i
The toggleMarkers() method retrieves all the marker IDs from the map and loops through them. If they match the ID string sent through by the button event handler it shows and hides all the markers of a certain type. Notice that the opposite of hide() is unhide() in the Yahoo Maps API :/.
That’s all folks
And that is the mashup – some styling in Firebug, a few PHP tricks to pack the content before sending it on the wire and doing local caching and I was done. And so can you. Go forth and hack.
Last Friday I was up in Dublin at the Future of Web apps and gave my talk “Powerful Tools that You Need (and Probably Don’t Know About)”. I took FOWA as an opportunity to (re-)introduce the audience to some of the tools Yahoo offers and to brand the drive of developers to do everything by themselves instead of using already built solutions as ineffective.
The slides of my talk are available on SlideShare:
Yesterday I had a back and forth on Twitter with Paul Irish and Divya Manian on Twitter about a thing that is full of win but also drives me crazy.
Those two lads built http://html5readiness.com/ – a beautiful demo of what you can do with CSS transformations, JavaScript and markup these days. Here’s what it looks like:
In essence this is the designer’s eye for http://caniuse.com/ which listed the same information in a lesser visual but very useful manner.
When I looked at the visualisation I went “WOW” and so did a lot of other people. But actually when using the site my fascination and interest quickly disolved.
I consider myself quite an observant person and I can read really, really fast. Looking at this visualization though I found myself constantly having to check from the coloured ray to the legend to understand just which browser we are currently talking about. Clicking the fixed browser position checkbox made this a bit more obvious but I am still very confused – especially as the colours are close to each other (on my laptop) and the rollover colour change doesn’t match the legend any more. This gets even more confusing when the colour of the main ray and the rollover changes:
I have no clue why the ray is coloured differently. I might think it is the connector between HTML5 and CSS3, but Geo Location is not part of HTML5.
The next thing I normally do to any interface is to turn off CSS to see how it degrades for non-visual users or on old mobile devices (yes, I do have to use an old Blackberry from time to time).
If you do this on HTML5 readiness you get a terrible experience:
There is no connection between the year names and the browser support (other than links – a nested list would make the connection much more obvious).
None of the links (like “Multiple backgrounds”) does anything.
What really made me very confused was looking at the source code though. The authors use B and I tags all over the shop and one of the rays for example is:
Back in the real world, however, WYSIWYG editors have B and I buttons which include these elements as BOLD and ITALIC. Now, as accessibility and semantics fans we’ve been bickering for years that this is a bad idea as this is painting with HTML rather than telling a user agent that the text needs to be emphasized or strong. We made quite some headway with this – and people started listening to us. Now we go back and say “oh well then, actually this is all fine – use whatever you want”.
All in all this example reminds me of something I built 8 years ago:
This was friggin cool back then. It was done for the Commodore 64 scene and it had to work in every browser that knows HTML - including Amiga ones. I managed to make it a “how is that done” moment by not using an image but instead a layout table with spacer gifs:
.: the very best of :.
Wow, terrible, right? Who would use tables for layout? This is madness – these are technologies we shouldn’t need to use any longer.
Or is it? By using the plethora of HTML elements in the visualisation above we do exactly the same thing! HTML is there to logically structure content and give it semantic meaning – not to paint lovely pictures.
The page uses Can I use as its source of data – but instead of using a scraper and converting it to the necessary HTML (and by that making it possible to update automatically) the data is duplicated – and once displayed with no semantic value or logical structure whatsoever. We have the technology to convert sensible, good and clean HTML and turn it into something different. I’ve proven that in the past with the data table to charts conversion script:
I really don’t understand why we forget the simple promise we share with our users over and over again:
Build on stuff that works and then make it more interactive and pretty
In the case of this visualisation – use data tables and generate all the fluff and classes you need to make the CSS work out with JavaScript. Or – how about using SVG for the whole thing?
I am not saying that Paul and Divya did something bad – I am big fans of their work – I am just saying that we keep doing the same mistakes. If you would not write some HTML by hand and only need it for an effect – you are doing things wrong.