Christian Heilmann

Posts Tagged ‘javascript’

Introducing Placemaker – a talk at the YDN Tuesday in London

Tuesday, July 7th, 2009

This is a talk I’ve given at the YDN Tuesday on 7th of July 2009 in London. It is an introduction to Placemaker, a new geolocation service by Yahoo. Check the slides, audio and the notes below.

Notes

Introducing Placemaker

Hello, I am Chris. Hacker by passion. When I went to the first WhereCamp about two years ago I thought nobody can out-geek me. I was wrong. Geolocation and Geocoding is quite some hard-core branch of geekery. So let me tell you about a nice little product that makes things easy for you.

Placemaker

This is Yahoo Placemaker and it is an API. You give it a URL to get data from or a text to extract geographical information from. Here are the docs. Now go forth and build cool stuff. OK then… Let’s take a look at the need for something like Placemaker.

A web of information

The web is full of information. Which is cool. The problem is that we accumulated and still accumulate more and more information without giving it proper structure.

Searching and finding

Search engines help us find stuff. However, as being found means making money the first search results are not necessarily the best – only the ones that have been promoted the best way.

Analysing and deciding

Analysing all the data of the web is a massive job. And computers are stupid. Computers are decision engines that would be thoroughly stumped when asked “do I look fat in this dress” as they forget the underlying dangers in answering this question in one way or another.

Human additives

This is why we need humans. By enriching our content with structured, easier to parse data we make it easier for machines to harvest only the necessary parts of our documents. In the past that was keywords, now we use microformats and tagging. The latter is very useful as it can be crowdsourced. People tagging my photos on flickr or my site on del.icio.us make it easier for them to find them later on and give me an idea what keywords I hadn’t thought of.

Mobility

This is all fine and good, but the real change we see in behaviour of web users is that we become more and more mobile. Laptops, Mobile devices and Netbooks are a very common sight and wireless networks and fast 3G connectivity allows people to enjoy the web on the go.

This also means that people can locate themselves on the planet and expect information from their physical surroundings rather than just looking for words, matching and hoping the “night in paris” information they are looking for doesn’t end up in imagery of a disappointing night vision movie experience. In other words, for our content to be found we need to have geographical information in there that defines the locality of the text, not only what it talks about.

Finding the hidden goodies

And this is what Placemaker does for us – give it a text or a url and it returns you the geographical information in it, defined as names, a where on earth ID and as latitude and longitude.

Say I throw the following text at it:

First we take Manhattan and then we take Berlin.

If you get an API key you can POST this information to the Placemaker API endpoint like this:

http://wherein.yahooapis.com/v1/document

documentContent=First+we+take+Manhattan+and+then+we+take+Berlin.
documentType=text/plain
appid=my_appid

Using different parameters

Placemaker takes different parameters that help you filter down the results to what you want.

appid
nothing happens without it!
inputLanguage
fr-CA,de-DE…
outputType
xml or RSS
documentContent
text to analyse
documentTitle
additional title
documentURL
url to analyse
documentType
MIME type of doc
autoDisambiguate
remove duplicates, set to false to get more results
focusWoeid
filter around a woeid – 400km radius

Placemaker result sets

With the above data and parameters you will get the following XML document back:




0.001987
build 090508
48


0
Undefined


0
0



1
Supername


0
0




52.5161
13.377


40.6838
-74.0477


52.6675
13.7262




638242
Town


52.5161
13.377


0
1
8



12589342
County


40.791
-73.9659


0
1
8



12589342
14
23
1

plaintext



638242
41
47
1

plaintext





Working with Placemaker results

Placemaker results have a lot of cool things in them, all explained in detail in the docs. Let’s concentrate on the things we really want to play with here.

First up is a list of places the API found in the text. These are PlaceDetails elements with a nested place element:



12589342
County


40.791
-73.9659


0
1
8

This is cool, but it doesn’t tell us where this information came from. For this there is a referenceList element with an array of references


638242
41
47
1

plaintext

Notice the element with the name woeIds, as – oh joy of joys – a reference can have several woeids it is connected with. In order to find out where the text Placemaker found as a match is located in the document, you either get start and end for text content of the XPATH for structured content (XML/RSS). This is pretty sweet, of course.

Annoyances

There are a few annoyances when it comes to working with Placemaker.

The first is a limit of 50,000 bytes for the text to be analyzed which is less than you think when you remember just how much we pack into our web documents.

The second is that the web is simply not a clean and nice dataset. When you read an HTML document from a live site you’ll find that in many cases Placemaker chokes – for starters only valid UTF-8 documents go through.

The third is that Placemaker has no JSON output at the moment, which means you cannot use results in JavaScript without writing an own converter.

Placemaker only allows for POST requests which makes it a bit less easy to play with than with GET enabled APIs (as you can simply open them in a browser window).

My biggest annoyance is the disconnect of places and references. This is not a problem of Placemaker as it wasn’t meant exclusively to match content to places – just find places. But it makes my favourite use cases – embedding geo location at the right spot in a document – harder.

Workarounds

Of course there are workarounds for all these issues (except for the 50000 byte limit).

Fixes

As with anything on the web, there are ways to work around these annoyances.

Fixing the broken web with YQL

The first trick is to use YQL to load the HTML and filter it before you send it to Placemaker.


$key = ‘YOUR_API_KEY’;
if(isset($_GET[‘url’])){
$realurl =’http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%20%3D%20%22’.urlencode($_GET[‘url’]).’%22&format=xml’;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $realurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$c = curl_exec($ch);
curl_close($ch);
if(strstr($c,’<’)){
$c = preg_replace(“/.*|.*/”,’‘,$c);
$c = preg_replace(“/ ” encoding=”UTF-8”?>/”,’‘,$c);
$c = strip_tags($c);
$c = preg_replace(“/[r?n]+/”,”“,$c);
$ch = curl_init();
define(‘POSTURL’, ‘http://wherein.yahooapis.com/v1/document’);
define(‘POSTVARS’, ‘appid=’.$key.’&documentContent=’.urlencode($c).
‘&documentType=text/html&outputType=xml’);
$ch = curl_init(POSTURL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, POSTVARS);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$x = curl_exec($ch);
header(‘content-type:text/xml’);
echo $x;
}

}
?>

The YQL implementation of select * from html runs the HTML through Tidy to fix issues and is encoding agnostic. That way Placemaker now can get data from sources it normally chokes on. Notice that it is a good idea to filter out tags and whitespace to save on byte-size.

Matching references and places

The best way to explain this is to build a small implementation. For example a simple form that allows a user to enrich a text with Geo Microformats:

The code is not hard, the main trick is to create an array from the known places and then match them with the IDs of a reference in a nested loop.



	

// if some text was sent through
if(isset($_POST[‘analyze’])){
$content = $_POST[‘analyze’];
$template = $_POST[‘template’];
// define the API key and do the call to Placemaker
$key = ‘C8meDB7V34EYPVngbIRigCC5caaIMO2scfS2t’.
‘.HVsLK56BQfuQOopavckAaIjJ8-’;
$ch = curl_init();
define(‘POSTURL’, ‘http://wherein.yahooapis.com/v1/document’);
define(‘POSTVARS’, ‘appid=’.$key.’&documentContent=’.
urlencode($content).
‘&documentType=text/plain&outputType=xml’);
$ch = curl_init(POSTURL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, POSTVARS);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$x = curl_exec($ch);

// create an object from the XML
$places = simplexml_load_string($x, ‘SimpleXMLElement’,
LIBXML_NOCDATA);
// WTF?
// loop over places and create an array with
// the woeid as the key
$foundplaces = array();
foreach($places->document->placeDetails as $p){
$woeid = ‘woeid’.$p->place->woeId;
$foundplaces[$woeid] = array(
‘name’ => str_replace(‘, ZZ’,’‘,$p->place->name.’‘),
‘type’ => $p->place->type.’‘,
‘woeId’ => $p->place->woeId.’‘,
‘lat’ => $p->place->centroid->latitude.’‘,
‘lon’ => $p->place->centroid->longitude.’’
);
}

// loop over the references and over the woeids
$refs = $places->document->referenceList->reference;
$microformats = array();
foreach($refs as $r){
foreach($r->woeIds as $wi){
// get dataset connected with the current woeid
$currentloc = $foundplaces[“woeid”.$wi];

// check if all interesting data exists
// get the template and replace the
// placeholders
if($r->text != ‘’ && $currentloc[‘name’] != ‘’ &&
$currentloc[‘lat’] != ‘’ && $currentloc[‘lon’] != ‘’){
$lat = $currentloc[‘lat’];
$lon = $currentloc[‘lon’];
$mf = preg_replace(‘/%place%/’,$r->text,$template);
$mf = preg_replace(‘/%lat%/’,$lat,$mf);
$mf = preg_replace(‘/%lon%/’,$lon,$mf);
$content = preg_replace(‘/’.$r->text.’/’,$mf,$content);
}

}
}

}
?>

Making Placemaker GET it with YQL

Another thing YQL allows developers to do is to extend it with own open tables that run JavaScript conversions on the server side. One of those is the YQL open table which does all the things Placemaker does but on the server and offers JSON output.

The great thing about the JSON output is that it already matches up places and references for us:

{
“query”:{
count“,
created“,
lang“,
updated“,
uri“,
“diagnostics”:{
publiclyCallable“,
“url”:[{
execution-time“,
content
},
{

execution-time“,
content
},
{

execution-time“,
content
}

],
“javascript”:{
instructions-used
},
user-time“,
service-time“,
build-version
},
“results”:{
“matches”:{
“match”:[{
“place”:{
woeId“,
type“,
name, Berlin, DE”,
“centroid”:{
latitude“,
longitude
}

},
“reference”:{
woeIds“,
start“,
end“,
isPlaintextMarker“,
text“,
type“,
“xpath”:””
}

},
{

“place”:{
woeId“,
type“,
name, New York, NY, US”,
“centroid”:{
latitude“,
longitude
}

},
“reference”:{
woeIds“,
start“,
end“,
isPlaintextMarker“,
text“,
type“,
“xpath”:””
}

}
]

}
}

}
}

Using the open table we can easily use Placemaker in JavaScript:

function gotit(o){
var matches = o.query.results.matches.match;
for(var i=0,j=matches.length;i console.log(‘Name: ’ + matches[i].place.name);
console.log(‘lat: ’ + matches[i].place.centroid.latitude);
console.log(‘lon: ’ + matches[i].place.centroid.longitude);
console.log(‘Match: ’ + matches[i].reference.text);
}

}

var content = ‘First we take Manhattan and then we take Berlin’;
var yql = ‘select * from geo.placemaker where documentContent = “’ +
content + ‘” and documentType=”text/plain” and appid = “”’;
var url = ‘http://query.yahooapis.com/v1/public/yql?’ +
‘format=json&callback=gotit&env=’ +
‘http%3A%2F%2Fdatatables.org%2Falltables.env&q=’ +
encodeURIComponent(yql);
var s = document.createElement(‘script’);
s.setAttribute(‘src’,url);
document.getElementsByTagName(‘head’)[0].appendChild(s);

Implementations

  • Yahoo News Map – Yahoo News Map uses the Yahoo RSS feed run through Placemaker to show news on a map and allow to navigate with the map.
  • TweetLocations – Tweetlocations shows a map of your latest tweets.
  • Geo this! (Greasemonkey) – Geo This! is a Greasemonkey script for WordPress that adds a button to analyze and tag the content before submitting the blog post.
  • GeoMaker – GeoMaker is a frontend to Placemaker that turns a URL or a text into a map.
  • GeoMaker API – GeoMaker also has an own API that makes it easy to convert URLs to all kind of handy formats.
  • JS-PlacemakerJS Placemaker is a JavaScript wrapper for Placemaker using the open YQL table.

You have the data, you have the tools, now go and make some ideas a reality

That’s all I have for you today. Check the resources coming up and have a play with Placemaker. Contact me once you’ve done something cool and I’ll be happy to tell the team about it. Here are some ideas:

Flickr knows woeid

Using YQL and open tables you can get geolocated photos from a text analysed with Placemaker:

select * from flickr.photos.info where photo_id in
(

select id from flickr.photos.search where woe_id in
(

select match.place.woeId from geo.placemaker where
documentContent = “First we take Manhattan and then we take Berlin”
and documentType=”text/plain” and appid = “”
)

and license=4
)

Other Yahoo Geo resources

The Yahoo Geo section of the Yahoo Developer Network has all the other Geo goodies for us. Maps, FireEagle and even the Placemaker dataset for download is all there for you to use.

The Guardian Data Store

The Guardian has a really nice blog/resource that always has new data for you to play with: the Guardian Data Store. Have a look and a play.

Creating accessible JavaScript menu systems – some basic steps that get forgotten

Tuesday, June 23rd, 2009

OK, so you want to write yet another collapsing menu/section/widget thingamabob. This is really easy and in the following few examples I want to point out some ideas that make it much easier for you.

The following is what we’re going to build – it doesn’t have any bells and whistles like smooth animation, random unicorns, swoosh noises or whatever else you might want to come up with, but it is a good solid base to work from.

Collapsing menu example by  you.

Click the image to go to the live example.

The Markup

The first trick is to use easy to understand and highly styleable markup for your widget. You see a lot of widgets that use endless DIVs, SPANs, IDs on every element and classes on every sub-element. If you build a simple solution (and not a catch-all reusable widget that is part of a framework) none of that is needed. In this case the markup is the following:


In other words: a nested list with headings for the different sections. This makes sense without styling or scripting which is still and important point considering mobile devices or environments that have JavaScript turned off (and yes, they are not mythical but do exist).

Assistive access does not mean lack of JavaScript

The first mistake that people do is to think that this is all you need to be accessible – as users with assistive technology have no JavaScript, right? Wrong. Assistive technology is not a browser replacement but in most cases hooks into browser functionality and offers easier access. In other words, what the browser gets the assistive technology gets and you have to make sure it still makes sense without a mouse (to name just one example).

Thinking too complex

The next extra step people take is starting to loop through the menu construct to hide the elements with JavaScript. This is made much easier with clever libraries that don’t use the DOM to do that but piggy-back on the CSS selector engine, but for good old IE6 this is still not an option. And you don’t need to. In order to hide the nested lists in the above example all you need to do is to apply a class to the main list and leave the rest to CSS:




This means that in order to show any of the nested lists, all you need to to is to add a class called “open” to the parent list item. The CSS to undo the hiding is the following:



You can add the classes on the backend when you render the page – which makes a lot more sense to indicate a current open section of the page than any JavaScript analyzing of window.location or other shenanigans. See the first stage demo. You can also define a “current” class which means you can style it differently and the script will simply quietly skip that section and not collapse it at all.

That is the beauty in leaving all the showing and hiding to the CSS. Of course you can’t animate in CSS (unless you use webkit), but you can make your animation precede the change in classes.

Hiding and showing

So the way to show and hide things is simply to add and remove classes. We need to use event handling to listen for click events to do that. Click events are the only safe ones as they fire with keyboard and mouse. The problem is that a header can be made clickable, but is not keyboard accessible. To work around this, let’s use DOM scripting to inject a button element into the headers. You can use CSS to make it look not like a button:



The second stage demo shows how this works and here’s the code.


(function(){

// get the menu and make sure it exists
var m = document.getElementById(‘menu’);
if(m){

// add a class to allow the CSS magic to happen
m.className = ‘js’;

// loop over all headers
var headers = m.getElementsByTagName(‘h3’);
for(var i=0;headers[i];i++){
// get the content of the current header
var content = headers[i].innerHTML;
// create a button, delete the content of the header
// replace it with the button and set the content to
// the cached header content
var a = document.createElement(‘button’);
headers[i].innerHTML = ‘’;
headers[i].appendChild(a);
a.innerHTML = content;
}

// apply a single click event to the menu
m.addEventListener(‘click’,function(e){

// find the event target and chec that it was a button
var t = e.target;
if(t.nodeName.toLowerCase()===’button’){

// get the LI the button is in
var mom = t.parentNode.parentNode;

// check if its class name is not content and
// remove the open class if it exists, else
// add an open class

if(mom.className!==’current’){
if(mom.className = 'open'){
mom.className = '';
} else {
mom.className = 'open';
}

}

// don't do the normal things buttons do
e.preventDefault();
}

},true);
}

})()

This code also takes advantage of event delegation – there is so no need to apply and event handler to each heading – even if that is really easy to do with a library and an each() or batch() command. Event handling is a great concept and the tricks you find when you bother to read the docs are staggering.

Hiding is not removing

This is where most menu scripts stop. Great stuff, it expands and collapses and everybody is happy. Unless you are an unhappy chap and you need to use a keyboard to access it – or an older mobile device. Try it out yourself – use the second example by tabbing from link to link. You’ll find that you have to tab through the invisible links to reach the next section to open or hide. That surely can’t be the idea, right?

The trick to work around is to change the tabindex property of an element. A value of 1 will remove it from the tabbing order and setting it back to 0 will make them available again. So, to make keyboard access easier, let’s remove the tab order upfront and reset or remove it when we show and hide the menus. This is terribly annoying as we have to loop through the links. I hate loops, but browsers are not our friends.


(function(){

// get the menu and make sure it exists
var m = document.getElementById(‘menu’);
if(m){

// add a class to allow the CSS magic to happen
m.className = ‘js’;

// loop over all headers
var headers = m.getElementsByTagName(‘h3’);
for(var i=0;headers[i];i++){
// get the content of the current header
var content = headers[i].innerHTML;
// create a button, delete the content of the header
// replace it with the button and set the content to
// the cached header content
var a = document.createElement(‘button’);
headers[i].innerHTML = ‘’;
headers[i].appendChild(a);
a.innerHTML = content;
}

// loop over all nested lists
// and set the taborder of the nested links to -1 to
// remove them from the tab order

var uls = m.getElementsByTagName(‘ul’);
for(var i=0;uls[i];i++){
if(uls[i].parentNode.className!‘open’ &&
uls[i].parentNode.className!==’current’){
var as = uls[i].getElementsByTagName(‘a’);
tabOrder(as,-1);
}

}

// apply a single click event to the menu
m.addEventListener(‘click’,function(e){

// find the event target and chec that it was a button
var t = e.target;
if(t.nodeName.toLowerCase()===’button’){

// get the LI the button is in
var mom = t.parentNode.parentNode;

// check if its class name is not content and
// remove the open class if it exists, else
// add an open class. Also, remove or add the
// links to the tab order

if(mom.className!==’current’){
if(mom.className = 'open'){
mom.className = '';
tabOrder(as,-1);
} else {
mom.className = 'open';
tabOrder(as,-1);
}

}

// don't do the normal things buttons do
e.preventDefault();
}

},true);
}

// remove from or add elements to the tab order

function tabOrder(elms,index){
for(var i=0;elms[i];i++){
elms[i].tabIndex = index;
}

}
})()

The third demo does exactly that – use your keyboard and marvel at being able to tab from parent element to parent element when sub-sections are collapsed.

Fixing it for Internet Explorer 6 and 7bad old browsers

Now, this is all good and fine but of course we need to fix the code to work around the quirks of browsers that don’t understand the W3C event model or consider an element with a name attribute the same as one with and id. We could fork and fix in the code we have here, but frankly I am tired of this. People give us libraries to work around browser differences and to make our lives easier. This is why we can use YUI for example to make this work reliably cross-browser:



Good start

This is just a start to make this work. A real menu should also have support for all kind of keys that a menu like this in a real app gives us and notify screen readers of all the happenings. For this, we need ARIA. Right now, I’d be happy to get some comments here :)

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: Events, Latte Art, Full Frontal and Game developers vs. porn stars

Sunday, April 26th, 2009

Things that made me happy this morning:

  • Getting upgraded to business class on my flight back from Hong Kong as BA didn’t have a vegetarian meal for me! Flatbed win with 8 hours straight sleep.
  • Celebrating my birthday with my friends and getting a giant duck: Giant Duck
  • PPK’s slides on JavaScript Events from his presentation at Yahoo
  • Splendid Cappucino Latte Art
  • Meeting colleagues from long long ago randomly in Australia and them blogging about your talk
  • A great presentation by filament group on Access oriented web design
  • Vimeo doing a very nice custom Flash effect for the Let it Shine ad.
  • Sand/Stone is an interesting idea, “a 6,000km-long wall of artificially solidified sandstone architecture that would span the Sahara Desert, east to west, offering a combination of refugee housing and a “green wall” against the future spread of the desert”
  • The Full Frontal conference is now live, come to Brighton in November to get your JavaScript fix.
  • A good comparison of Game Developers and Porn Stars

Is it getting harder and harder to show very easy examples?

Tuesday, April 7th, 2009

I am right now teaching a four day class of DOM and Ajax in Sunnyvale, California and also do some tech editing for Scriptin with JavaScript and Ajax by Charles Wyke-Smith and I find one thing that is pretty worrying: easy examples of web development practices are dangerous to show these days.

I’m talking about practices that make it easy to get quick results and give readers and attendees “I am getting this – this is easy” fuzzy warm feelings.

One very obvious example is form validation and re-rendering of a form using PHP_SELF and displaying user data using $_GET or $_POST. Unfiltered they are a free invitation for any XSS attack and will turn your server into a spam-hub or bot-net drone. Explaining countermeasures of XSS normally is out of scope for an example that only shows how a form would work that you enhance progressively.

The same applies to simply outdated ideas like onevent handlers. It is easy to show an example that uses a few onclick handlers, but explaining event handling really well takes a bit of time. Again, this is something that really does not fit in the scope of a DOM course.

I do however think that it is important to get it in there, as there is no such thing as knowing one technology in the web development stack and being able to use it. There’s a lot of overlap with other areas and in order to be a good developer and play well with others you need to be aware of your effects and areas of overlap with your colleagues’ skill-sets.

The other extreme I find myself doing is being too over-cautious. I went through the tough times of the first browser wars and got a deep-rooted mistrust towards anything some browser tells me is OK to do and use. However, I get the feeling that it doesn’t really matter any more if Internet Explorer has a problem with name vs. ID or whatever other shenanigans we have to be aware of when we build things from scratch.

I do get the distinct feeling that not building on top of a good client-side library is simply a waste of time these days. Libraries allow us to write code, not to work around bugs and wonder what other safety measure we have to put in.

That’s why I started asking people in my courses to use Firefox with Firebug and use a good text editor to code along. Today I managed to breeze through how to write HTML that is ready for internationalisation and works with assistive technology, over simple DOM access to the document and at the end writing a validation script for a form using generated DOM content. By concentrating on how things are meant to work instead of debugging random issues I managed to get the students to reach far into the matter in a day – even those who never touched JavaScript before.

Maybe it is time to get beginners accustomed to a market that builds on working solutions and benefits from browser abstraction via libraries than teaching developing from total scratch – bad browsers and bad people taking advantage of any technology to gain access or spam us seem to have made this way of working redundant.