<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Code Train &#187; w3c</title>
	<atom:link href="http://thecodetrain.co.uk/tag/w3c/feed/" rel="self" type="application/rss+xml" />
	<link>http://thecodetrain.co.uk</link>
	<description>Where Neil Crosby talks about coding on the train...</description>
	<lastBuildDate>Wed, 18 Aug 2010 18:22:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Geolocation &amp; Beer: Part 1 &#8211; Finding the user</title>
		<link>http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-1-finding-the-user/</link>
		<comments>http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-1-finding-the-user/#comments</comments>
		<pubDate>Wed, 05 May 2010 22:10:37 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[barcamb]]></category>
		<category><![CDATA[barcamp]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[w3c]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=389</guid>
		<description><![CDATA[<p>I recently attended <a href="http://barcamb.ltheobald.co.uk/">BarCamb3</a>, a BarCamp held at the lovely <a href="http://www.red-gate.com/">Red Gate Software</a> offices in Cambridge.  My main contribution to the event was talking about a silly little weekend learning project I&#8217;ve been working on &#8211; <a href="http://beernear.me/">Beer Near Me</a>.  </p>

<p>I&#8217;ve split the presentation I gave up into three separate blog posts, which I&#8217;ll be putting up over the next few days.  This one will cover basic use of the <code>navigator.geolocation</code> API, with the next two showing you how to use the data that gives you to <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-2-telling-the-user-where-they-are/">find out where the user actually is</a>, and to <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-3-static-maps/">plot that data using Google&#8217;s static maps API</a>.</p>

<p>To start, I should explain that Beer Near Me was only ever intended to be used as a platform to be used to help me learn about the <a href="http://dev.w3.org/geo/api/spec-source.html"><code>navigator.geolocation</code> API</a> and how it works.  All the data that gets shown by the site was initially kind of secondary to me, as was the map that I use to show it off.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.001.png" alt="GeoLocation &#038; Beer"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.009.png" alt="What will I talk about?"></p>

<p>Of course, <code>navigator.geolocation</code> turned out to be far easier to work with than I expected.</p>

<h2>Support for navigator.geolocation</h2>

<p>The first thing to be aware of is that right now, support for <code>navigator.geolocation</code> is pretty poor.  If you&#8217;re using Firefox 3.5+ or Mobile Safari you can use it out of the box, and you can <a href="http://www.wait-till-i.com/2010/03/04/google-chrome-getting-navigator-geolocation/">turn on geolocation support in Chrome</a>, but apart from that you&#8217;re plain out of luck.  Since the idea behind Beer Near Me was to learn about <code>navigator.geolocation</code> that means that right now I&#8217;m not supporting any other APIs.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.011.png" alt="navigator.geolocation support"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.012.jpg" alt="Other APIs are available"></p>

<p>It&#8217;s not all doom and gloom though.  There are implementations of the API available for use in other browsers as plugins &#8211; for example <a href="http://en.wikipedia.org/wiki/Mozilla_Geode">Geode</a> will get you support in earlier versions of Firefox 3, and Google Gears opens up the ability to play with geolocation in some other browsers.  There&#8217;s also <a href="http://www.loki.com">Loki</a> (a Skyhook based plugin) that will get you support over a whole bunch of browsers but uses a differently specified API. Of course, I&#8217;ve not actually used any of these, so your guess is as good as mine as to whether they are any good or not.  I seem to remember Loki looking interesting a couple of years ago.</p>

<h2>Finding a location</h2>

<p>So, how to actually use <code>navigator.geolocation</code>?  Well, a good place to start would be checking whether the browser supports it.  We&#8217;ll do this in JavaScript, since that&#8217;s the only place we can reliably perform the check.</p>

<pre><code>if (navigator.geolocation) {
    // do geolocation
} else {
    // say sorry to the user
}
</code></pre>

<p>Pretty simple.  It&#8217;s your standard JavaScript functionality check.  If we have the functionality available then we can actually do something with it.</p>

<pre><code>navigator.geolocation.getCurrentPosition(
    foundLocation, // a user generated function
    noLocation,    // yup, user generated too
    {
        enableHighAccuracy: true,
        maximumAge: 1800,
        timeout: 30
    }
);
</code></pre>

<p>Here, we&#8217;re calling <code>getCurrentLocation()</code> with two callback functions and some options.  Once the browser (and the user) has decided whether or not to return a location, either the <code>foundLocation</code> or <code>noLocation</code> functions that you get to write are called, and the user&#8217;s location is passed into them.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.013.jpg" alt="GeoLocation check"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.014.jpg" alt="getCurrentPosition"></p>

<p>Before we get to those callback functions though, lets talk for a minute about the options we&#8217;re passing into <code>getCurrentPosition()</code>.  Essentially, what we&#8217;re saying in the code above is:</p>

<blockquote>
  <p>Try to give me highly accurate positioning if possible. I&#8217;d like to actually know where I am.</p>
  
  <p>Oh, and if you have a position cached that&#8217;s no older than 30 minutes, could you give me that immediately please?  I know that kind of contradicts what I said a moment ago, but I know better than you.</p>
  
  <p>And one more thing &#8211; if it takes you longer than 30 seconds to work out where you are, just give up.  There&#8217;s a good fellow.</p>
</blockquote>

<p>And that&#8217;s it really, with that little bit of code we&#8217;ve set up the browser to do some magic and try and work out where it is.</p>

<h2>Watching for changes to the user&#8217;s location</h2>

<p>The only problem with this is that the iPhone in particular seems a bit rubbish at following these instructions.  The first result it sends back seems to be uniformly Not Good, and generally quite old.  So what can we do about that?  Thankfully, there&#8217;s an easy answer provided to us in the API &#8211; the <code>watchPosition()</code> function.  This uses exactly the same parameters as <code>getCurrentLocation()</code> and can simply be dropped in as a replacement for it.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.015.jpg" alt="Keep finding the user"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.016.jpg" alt="You've got a location!"></p>

<p><code>watchPosition</code> does what you&#8217;d expect it to do.  Instead of finding a location once, it will keep watching the user&#8217;s location and call the success function whenever the location changes.  The thing that <code>watchPosition()</code> is most useful for though, is getting more accurate locations as the user&#8217;s device tries different location finding techniques.</p>

<p>You see, different devices will try and locate themselves in different ways.  Some of the techniques they&#8217;ll use will be be quick, some slow, and some very expensive when it comes to battery life.  For example, here&#8217;s what the iPhone does, as I understand it:</p>

<ol>
<li><p>First, the iPhone will look to see if there&#8217;s a location cached in its memory and give you that if available.</p></li>
<li><p>If you&#8217;re still watching for new locations, it will then try and grab a general location from the cell towers it knows about.</p>

<p>Depending on the number of towers available, this might give you really good, or really bad accuracy.  For example, in Bedford (where I live), using cell tower triangulation I get an accuracy which basically covers the entire town.  Not particularly useful.  It is quick though, and doesn&#8217;t really cost much in terms of power.</p></li>
<li><p>If the cell tower triangulation wasn&#8217;t awesome then the iPhone will gather information about all the WIFI hotspots it can see.  </p>

<p>This data gets sent to Skyhook, which does a whole bunch of triangulation and sends back a result.  This is obviously slower than just hitting the cell towers, but it can give you a really accurate result depending on where you are (better than GPS in some built up areas).</p></li>
<li><p>Finally, if you&#8217;re still looking for a location, the iPhone will fire up the GPS.  </p>

<p>This is expensive, slow, and drains the battery, so is left as a last resort.  It generally gives the best quality results though.</p></li>
</ol>

<p>So, you see, things aren&#8217;t necessarily as simple as asking for a position.  A whole bunch of stuff can be going on in the background, and grabbing the best location the user&#8217;s device knows about as time goes on can be very useful.</p>

<h2>Using the location we&#8217;ve found</h2>

<p>So, now that we&#8217;re requesting a location, what do we do once we actually get one?  Lets have a look.</p>

<pre><code>foundLocation = function(position) {
    // position.coords.latitude
    // position.coords.longitude
    // position.coords.accuracy
    // and more…
}
</code></pre>

<p>As you can see, the function we call on location finding success gets passed a single parameter &#8211; <a href="http://dev.w3.org/geo/api/spec-source.html#position_interface"><code>position</code></a>.  This object contains a <code>coords</code> object, and a <code>timestamp</code> representing the time the location was determined.  It&#8217;s the <code>coords</code> object we&#8217;re interested in right now, since that contains the latitude, longitude and accuracy (measured in metres) of the user&#8217;s current location &#8211; all the information a grown chap could need for finding some beer.  Other applications might make use of the altitude, heading and speed information, but that&#8217;s not vital when looking for beer, so I&#8217;m ignoring it for now.</p>

<h2>Putting it all together</h2>

<p>Quickly putting all this together, here&#8217;s some JavaScript you can copy and paste into a page to see this all in action.</p>

<pre><code>/*global document, navigator */
var beerLocation = {
    foundLocation: function (position) {
        beerLocation.setPara(
            "Lat = " + position.coords.latitude + 
            ", lon = " + position.coords.longitude + 
            ", accuracy = " + position.coords.accuracy + "m");
    },

    noLocation: function () {
        beerLocation.setPara("Boo! You didn't share your location!");
    },

    noGeoLocation: function () {
        beerLocation.setPara(
            "Sorry, but your browser doesn't support geolocation.");
    },

    setPara: function (text) {
        var p = document.getElementById('location-info');
        if (!p) {
            p = document.createElement('p');
            p.id = 'location-info';
            document.body.appendChild(p);
        }

        p.innerHTML = text;
    }
};

if (navigator.geolocation) {
    navigator.geolocation.watchPosition(
        beerLocation.foundLocation, 
        beerLocation.noLocation,
        {
            enableHighAccuracy: true,
            maximumAge: 120000
        }
    );
} else {
    beerLocation.noGeoLocation();
}
</code></pre>

<p>Alternatively, take a look at it in situ and in action on my <a href="http://projects.thecodetrain.co.uk/geolocation/">geolocation test page</a>.  The location shown by this page will keep updating as you move around or your device&#8217;s accuracy improves.  For best results, try it out on an iPhone.</p>

<h2>And finally</h2>

<p>And that&#8217;s how easy it is to find a user&#8217;s location and keep updating it.  You just need to do something with the latitude and longitude once you&#8217;ve found it.</p>

<p>In <a href="http://beernear.me/">Beer Near Me</a> I do two things with the location once it&#8217;s been found &#8211; I <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-2-telling-the-user-where-they-are/">tell the user the street address of the location</a>, and I display it on a map.  And, of course, I&#8217;ll be writing about how I&#8217;m doing that in the next couple of posts.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>I recently attended <a href="http://barcamb.ltheobald.co.uk/">BarCamb3</a>, a BarCamp held at the lovely <a href="http://www.red-gate.com/">Red Gate Software</a> offices in Cambridge.  My main contribution to the event was talking about a silly little weekend learning project I&#8217;ve been working on &#8211; <a href="http://beernear.me/">Beer Near Me</a>.  </p>

<p>I&#8217;ve split the presentation I gave up into three separate blog posts, which I&#8217;ll be putting up over the next few days.  This one will cover basic use of the <code>navigator.geolocation</code> API, with the next two showing you how to use the data that gives you to <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-2-telling-the-user-where-they-are/">find out where the user actually is</a>, and to <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-3-static-maps/">plot that data using Google&#8217;s static maps API</a>.</p>

<p>To start, I should explain that Beer Near Me was only ever intended to be used as a platform to be used to help me learn about the <a href="http://dev.w3.org/geo/api/spec-source.html"><code>navigator.geolocation</code> API</a> and how it works.  All the data that gets shown by the site was initially kind of secondary to me, as was the map that I use to show it off.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.001.png" alt="GeoLocation &#038; Beer"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.009.png" alt="What will I talk about?"></p>

<p>Of course, <code>navigator.geolocation</code> turned out to be far easier to work with than I expected.</p>

<h2>Support for navigator.geolocation</h2>

<p>The first thing to be aware of is that right now, support for <code>navigator.geolocation</code> is pretty poor.  If you&#8217;re using Firefox 3.5+ or Mobile Safari you can use it out of the box, and you can <a href="http://www.wait-till-i.com/2010/03/04/google-chrome-getting-navigator-geolocation/">turn on geolocation support in Chrome</a>, but apart from that you&#8217;re plain out of luck.  Since the idea behind Beer Near Me was to learn about <code>navigator.geolocation</code> that means that right now I&#8217;m not supporting any other APIs.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.011.png" alt="navigator.geolocation support"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.012.jpg" alt="Other APIs are available"></p>

<p>It&#8217;s not all doom and gloom though.  There are implementations of the API available for use in other browsers as plugins &#8211; for example <a href="http://en.wikipedia.org/wiki/Mozilla_Geode">Geode</a> will get you support in earlier versions of Firefox 3, and Google Gears opens up the ability to play with geolocation in some other browsers.  There&#8217;s also <a href="http://www.loki.com">Loki</a> (a Skyhook based plugin) that will get you support over a whole bunch of browsers but uses a differently specified API. Of course, I&#8217;ve not actually used any of these, so your guess is as good as mine as to whether they are any good or not.  I seem to remember Loki looking interesting a couple of years ago.</p>

<h2>Finding a location</h2>

<p>So, how to actually use <code>navigator.geolocation</code>?  Well, a good place to start would be checking whether the browser supports it.  We&#8217;ll do this in JavaScript, since that&#8217;s the only place we can reliably perform the check.</p>

<pre><code>if (navigator.geolocation) {
    // do geolocation
} else {
    // say sorry to the user
}
</code></pre>

<p>Pretty simple.  It&#8217;s your standard JavaScript functionality check.  If we have the functionality available then we can actually do something with it.</p>

<pre><code>navigator.geolocation.getCurrentPosition(
    foundLocation, // a user generated function
    noLocation,    // yup, user generated too
    {
        enableHighAccuracy: true,
        maximumAge: 1800,
        timeout: 30
    }
);
</code></pre>

<p>Here, we&#8217;re calling <code>getCurrentLocation()</code> with two callback functions and some options.  Once the browser (and the user) has decided whether or not to return a location, either the <code>foundLocation</code> or <code>noLocation</code> functions that you get to write are called, and the user&#8217;s location is passed into them.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.013.jpg" alt="GeoLocation check"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.014.jpg" alt="getCurrentPosition"></p>

<p>Before we get to those callback functions though, lets talk for a minute about the options we&#8217;re passing into <code>getCurrentPosition()</code>.  Essentially, what we&#8217;re saying in the code above is:</p>

<blockquote>
  <p>Try to give me highly accurate positioning if possible. I&#8217;d like to actually know where I am.</p>
  
  <p>Oh, and if you have a position cached that&#8217;s no older than 30 minutes, could you give me that immediately please?  I know that kind of contradicts what I said a moment ago, but I know better than you.</p>
  
  <p>And one more thing &#8211; if it takes you longer than 30 seconds to work out where you are, just give up.  There&#8217;s a good fellow.</p>
</blockquote>

<p>And that&#8217;s it really, with that little bit of code we&#8217;ve set up the browser to do some magic and try and work out where it is.</p>

<h2>Watching for changes to the user&#8217;s location</h2>

<p>The only problem with this is that the iPhone in particular seems a bit rubbish at following these instructions.  The first result it sends back seems to be uniformly Not Good, and generally quite old.  So what can we do about that?  Thankfully, there&#8217;s an easy answer provided to us in the API &#8211; the <code>watchPosition()</code> function.  This uses exactly the same parameters as <code>getCurrentLocation()</code> and can simply be dropped in as a replacement for it.</p>

<p><img src="http://thecodetrain.co.uk/images/geolocation/geolocation.015.jpg" alt="Keep finding the user"> <img src="http://thecodetrain.co.uk/images/geolocation/geolocation.016.jpg" alt="You've got a location!"></p>

<p><code>watchPosition</code> does what you&#8217;d expect it to do.  Instead of finding a location once, it will keep watching the user&#8217;s location and call the success function whenever the location changes.  The thing that <code>watchPosition()</code> is most useful for though, is getting more accurate locations as the user&#8217;s device tries different location finding techniques.</p>

<p>You see, different devices will try and locate themselves in different ways.  Some of the techniques they&#8217;ll use will be be quick, some slow, and some very expensive when it comes to battery life.  For example, here&#8217;s what the iPhone does, as I understand it:</p>

<ol>
<li><p>First, the iPhone will look to see if there&#8217;s a location cached in its memory and give you that if available.</p></li>
<li><p>If you&#8217;re still watching for new locations, it will then try and grab a general location from the cell towers it knows about.</p>

<p>Depending on the number of towers available, this might give you really good, or really bad accuracy.  For example, in Bedford (where I live), using cell tower triangulation I get an accuracy which basically covers the entire town.  Not particularly useful.  It is quick though, and doesn&#8217;t really cost much in terms of power.</p></li>
<li><p>If the cell tower triangulation wasn&#8217;t awesome then the iPhone will gather information about all the WIFI hotspots it can see.  </p>

<p>This data gets sent to Skyhook, which does a whole bunch of triangulation and sends back a result.  This is obviously slower than just hitting the cell towers, but it can give you a really accurate result depending on where you are (better than GPS in some built up areas).</p></li>
<li><p>Finally, if you&#8217;re still looking for a location, the iPhone will fire up the GPS.  </p>

<p>This is expensive, slow, and drains the battery, so is left as a last resort.  It generally gives the best quality results though.</p></li>
</ol>

<p>So, you see, things aren&#8217;t necessarily as simple as asking for a position.  A whole bunch of stuff can be going on in the background, and grabbing the best location the user&#8217;s device knows about as time goes on can be very useful.</p>

<h2>Using the location we&#8217;ve found</h2>

<p>So, now that we&#8217;re requesting a location, what do we do once we actually get one?  Lets have a look.</p>

<pre><code>foundLocation = function(position) {
    // position.coords.latitude
    // position.coords.longitude
    // position.coords.accuracy
    // and more…
}
</code></pre>

<p>As you can see, the function we call on location finding success gets passed a single parameter &#8211; <a href="http://dev.w3.org/geo/api/spec-source.html#position_interface"><code>position</code></a>.  This object contains a <code>coords</code> object, and a <code>timestamp</code> representing the time the location was determined.  It&#8217;s the <code>coords</code> object we&#8217;re interested in right now, since that contains the latitude, longitude and accuracy (measured in metres) of the user&#8217;s current location &#8211; all the information a grown chap could need for finding some beer.  Other applications might make use of the altitude, heading and speed information, but that&#8217;s not vital when looking for beer, so I&#8217;m ignoring it for now.</p>

<h2>Putting it all together</h2>

<p>Quickly putting all this together, here&#8217;s some JavaScript you can copy and paste into a page to see this all in action.</p>

<pre><code>/*global document, navigator */
var beerLocation = {
    foundLocation: function (position) {
        beerLocation.setPara(
            "Lat = " + position.coords.latitude + 
            ", lon = " + position.coords.longitude + 
            ", accuracy = " + position.coords.accuracy + "m");
    },

    noLocation: function () {
        beerLocation.setPara("Boo! You didn't share your location!");
    },

    noGeoLocation: function () {
        beerLocation.setPara(
            "Sorry, but your browser doesn't support geolocation.");
    },

    setPara: function (text) {
        var p = document.getElementById('location-info');
        if (!p) {
            p = document.createElement('p');
            p.id = 'location-info';
            document.body.appendChild(p);
        }

        p.innerHTML = text;
    }
};

if (navigator.geolocation) {
    navigator.geolocation.watchPosition(
        beerLocation.foundLocation, 
        beerLocation.noLocation,
        {
            enableHighAccuracy: true,
            maximumAge: 120000
        }
    );
} else {
    beerLocation.noGeoLocation();
}
</code></pre>

<p>Alternatively, take a look at it in situ and in action on my <a href="http://projects.thecodetrain.co.uk/geolocation/">geolocation test page</a>.  The location shown by this page will keep updating as you move around or your device&#8217;s accuracy improves.  For best results, try it out on an iPhone.</p>

<h2>And finally</h2>

<p>And that&#8217;s how easy it is to find a user&#8217;s location and keep updating it.  You just need to do something with the latitude and longitude once you&#8217;ve found it.</p>

<p>In <a href="http://beernear.me/">Beer Near Me</a> I do two things with the location once it&#8217;s been found &#8211; I <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-2-telling-the-user-where-they-are/">tell the user the street address of the location</a>, and I display it on a map.  And, of course, I&#8217;ll be writing about how I&#8217;m doing that in the next couple of posts.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-1-finding-the-user/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting the CSS Validator running as a website</title>
		<link>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/</link>
		<comments>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 10:48:57 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[feci]]></category>
		<category><![CDATA[jigsaw]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[validator]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web-server]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=222</guid>
		<description><![CDATA[<p>A week or so I wrote about <a href="http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/">running the W3C CSS Validator on the command-line</a>.  Yes, I know I said I didn&#8217;t need to run it as a website, but as it turns out the command-line version doesn&#8217;t seem to want to validate local files — only files being served from a  web-server.</p>

<p>So, I went back to scratch and tried installing it on a web-server.  Since my normal stack is Apache, MySQL and PHP I didn&#8217;t have any of the Java-based web-servers suggested by the W3C.  My first attempt at getting the validator working was to use <a href="http://www.w3.org/Jigsaw/">Jigsaw</a> &#8211; the same web-server as the W3C uses to run their version on.  Unfortunately, it didn&#8217;t work for me.  Bugger.</p>

<p>So, I tried <a href="http://tomcat.apache.org/">Tomcat</a>.  After following <a href="http://wiki.apache.org/tomcat/TomcatOnMacOS#head-3bfa4851688758d9bd07a188d4f552806af8b30f">Basil Bourque&#8217;s instructions</a> on <a href="http://wiki.apache.org/tomcat">Apache&#8217;s Tomcat wiki pages</a>, I got Tomcat working.  I then followed the rest of the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">CSS Validator installation instructions</a> for Tomcat, and the validator worked in my browser.  Excellent.</p>

<p>There was a fly in the ointment though.  Whilst the validator worked in my browser, the same could not be said of my attempts to get it working via cURL calls from PHP using POST data.  I was using the same code as I&#8217;d used to validate against the W3C&#8217;s HTML validator, so I knew that I was able to successfully push POST data across to servers.  If I tried using GET requests to send the data to my local validator, then that worked. I verified the same thing was happening on the live CSS validator to make sure the problem wasn&#8217;t with my installation.  I know you&#8217;re thinking &#8220;well, if GET worked, why not just make requests that way?&#8221;  Unfortunately, I know that later I&#8217;ll be asking to validate much larger CSS rulesets — ones that will be far too large to fit on a URL.  So, I needed to use POST.</p>

<p>After a fair bit of poking, I realised that the in-browser version of the CSS Validator was setting an <code>enc</code> attribute value of <code>multipart/form-data</code> on the form when it was uploading files or sending textual data.  Conversely, it turns out that PHP was sending <code>application/x-www-form-urlencoded</code> as the encoding type instead, and the W3C CSS Validator just isn&#8217;t set up to accept that.  After a long time of trying to work out how to send things in <code>multipart/form-data</code> format using PHP&#8217;s cURL functions, I happened upon <a href="http://us2.php.net/manual/en/function.curl-setopt.php#84916">a comment on PHP&#8217;s curl_setopt function</a> which told me that if I gave PHP an array instead of a string it would automagically start using <code>multipart/form-data</code>.  As if by magic, my problem was solved.</p>

<p>My problems setting up my programmatic connection to the CSS Validator could easily have been solved by clearer documentation.  Nowhere that I could find in the Validator&#8217;s documentation was there any mention of needing to make POST requests using <code>multipart/form-data</code>.  If this had been stated somewhere I would at least I have known the path I needed to be looking down.  Likewise, lack of anything other than user-generated documentation for the PHP <code>CURLOPT_POSTFIELDS</code> cURL option made life far more difficult than it should have been.</p>

<p>Still, in the end I have a local version of the W3C&#8217;s CSS validator running on my laptop, and I&#8217;m able to connect to it programmatically to run tests.  Which is nice.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>A week or so I wrote about <a href="http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/">running the W3C CSS Validator on the command-line</a>.  Yes, I know I said I didn&#8217;t need to run it as a website, but as it turns out the command-line version doesn&#8217;t seem to want to validate local files — only files being served from a  web-server.</p>

<p>So, I went back to scratch and tried installing it on a web-server.  Since my normal stack is Apache, MySQL and PHP I didn&#8217;t have any of the Java-based web-servers suggested by the W3C.  My first attempt at getting the validator working was to use <a href="http://www.w3.org/Jigsaw/">Jigsaw</a> &#8211; the same web-server as the W3C uses to run their version on.  Unfortunately, it didn&#8217;t work for me.  Bugger.</p>

<p>So, I tried <a href="http://tomcat.apache.org/">Tomcat</a>.  After following <a href="http://wiki.apache.org/tomcat/TomcatOnMacOS#head-3bfa4851688758d9bd07a188d4f552806af8b30f">Basil Bourque&#8217;s instructions</a> on <a href="http://wiki.apache.org/tomcat">Apache&#8217;s Tomcat wiki pages</a>, I got Tomcat working.  I then followed the rest of the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">CSS Validator installation instructions</a> for Tomcat, and the validator worked in my browser.  Excellent.</p>

<p>There was a fly in the ointment though.  Whilst the validator worked in my browser, the same could not be said of my attempts to get it working via cURL calls from PHP using POST data.  I was using the same code as I&#8217;d used to validate against the W3C&#8217;s HTML validator, so I knew that I was able to successfully push POST data across to servers.  If I tried using GET requests to send the data to my local validator, then that worked. I verified the same thing was happening on the live CSS validator to make sure the problem wasn&#8217;t with my installation.  I know you&#8217;re thinking &#8220;well, if GET worked, why not just make requests that way?&#8221;  Unfortunately, I know that later I&#8217;ll be asking to validate much larger CSS rulesets — ones that will be far too large to fit on a URL.  So, I needed to use POST.</p>

<p>After a fair bit of poking, I realised that the in-browser version of the CSS Validator was setting an <code>enc</code> attribute value of <code>multipart/form-data</code> on the form when it was uploading files or sending textual data.  Conversely, it turns out that PHP was sending <code>application/x-www-form-urlencoded</code> as the encoding type instead, and the W3C CSS Validator just isn&#8217;t set up to accept that.  After a long time of trying to work out how to send things in <code>multipart/form-data</code> format using PHP&#8217;s cURL functions, I happened upon <a href="http://us2.php.net/manual/en/function.curl-setopt.php#84916">a comment on PHP&#8217;s curl_setopt function</a> which told me that if I gave PHP an array instead of a string it would automagically start using <code>multipart/form-data</code>.  As if by magic, my problem was solved.</p>

<p>My problems setting up my programmatic connection to the CSS Validator could easily have been solved by clearer documentation.  Nowhere that I could find in the Validator&#8217;s documentation was there any mention of needing to make POST requests using <code>multipart/form-data</code>.  If this had been stated somewhere I would at least I have known the path I needed to be looking down.  Likewise, lack of anything other than user-generated documentation for the PHP <code>CURLOPT_POSTFIELDS</code> cURL option made life far more difficult than it should have been.</p>

<p>Still, in the end I have a local version of the W3C&#8217;s CSS validator running on my laptop, and I&#8217;m able to connect to it programmatically to run tests.  Which is nice.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Running the W3C CSS Validator locally from the command line</title>
		<link>http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/</link>
		<comments>http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 21:36:18 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[command line]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[feci]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[offline]]></category>
		<category><![CDATA[validator]]></category>
		<category><![CDATA[w3c]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=203</guid>
		<description><![CDATA[<p>One of the things I&#8217;m currently working on is being able to run automated tests of FrontEnd Web Systems.  In order to carry out the first phase of this testing I need local installations of the <a href="http://validator.w3.org/">HTML Validator</a>, <a href="http://jigsaw.w3.org/css-validator/">CSS Validator</a> and <a href="http://jslint.com">JsLint</a> (when automatically running these tests many times a day it&#8217;s not fair to put that load on these free services).</p>

<p>I&#8217;m currently working on the CSS portion of the First Phase, so I&#8217;ve been looking at getting the W3C CSS Validator running locally on my machine.  Since there was a tiny bit more to it than there seemed from the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">W3C&#8217;s setup instructions</a>, I thought I&#8217;d better write down how I did it.</p>

<ol>
<li><p><a href="http://www.w3.org/Jigsaw/#Getting-2-2-6">Download the Jigsaw web server</a> and unzip it to a location of your choice.  We&#8217;ll be needing the servlet.jar file from it later (it&#8217;s in <code>Jigsaw 2/classes/servlet.jar</code>)</p></li>
<li><p>Open a terminal window, and change directory to somewhere you&#8217;re happy to put the CSS Validator.  The CVS password, when prompted, is &#8220;anonymous&#8221;.</p>

<pre><code>CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs login
CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs checkout \
2002/css-validator
cd 2002/css-validator
mkdir lib
cp {your servelet.jar location} lib
ant jar
</code></pre></li>
<li><p>Assuming nothing goes wrong, you&#8217;ve got yourself a self-contained, offline CSS Validator.  Awesome.</p></li>
<li><p>Test the validator by running the following:</p>

<pre><code>java -jar css-validator.jar --output=soap12 http://www.w3.org/
</code></pre></li>
<li><p>By running the following, you can see the options available to you from the validator:</p>

<pre><code>java -jar css-validator.jar
</code></pre>

<p>These options are explained in the <a href="http://jigsaw.w3.org/css-validator/manual.html">CSS Validator User Manual</a>.</p></li>
</ol>

<p>And that, as they say, is all there is to it.  From this, it shouldn&#8217;t be too difficult to set the validator up to run as a website if you want to, but that wasn&#8217;t necessary for me right now, so I didn&#8217;t do it myself.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>One of the things I&#8217;m currently working on is being able to run automated tests of FrontEnd Web Systems.  In order to carry out the first phase of this testing I need local installations of the <a href="http://validator.w3.org/">HTML Validator</a>, <a href="http://jigsaw.w3.org/css-validator/">CSS Validator</a> and <a href="http://jslint.com">JsLint</a> (when automatically running these tests many times a day it&#8217;s not fair to put that load on these free services).</p>

<p>I&#8217;m currently working on the CSS portion of the First Phase, so I&#8217;ve been looking at getting the W3C CSS Validator running locally on my machine.  Since there was a tiny bit more to it than there seemed from the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">W3C&#8217;s setup instructions</a>, I thought I&#8217;d better write down how I did it.</p>

<ol>
<li><p><a href="http://www.w3.org/Jigsaw/#Getting-2-2-6">Download the Jigsaw web server</a> and unzip it to a location of your choice.  We&#8217;ll be needing the servlet.jar file from it later (it&#8217;s in <code>Jigsaw 2/classes/servlet.jar</code>)</p></li>
<li><p>Open a terminal window, and change directory to somewhere you&#8217;re happy to put the CSS Validator.  The CVS password, when prompted, is &#8220;anonymous&#8221;.</p>

<pre><code>CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs login
CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs checkout \
2002/css-validator
cd 2002/css-validator
mkdir lib
cp {your servelet.jar location} lib
ant jar
</code></pre></li>
<li><p>Assuming nothing goes wrong, you&#8217;ve got yourself a self-contained, offline CSS Validator.  Awesome.</p></li>
<li><p>Test the validator by running the following:</p>

<pre><code>java -jar css-validator.jar --output=soap12 http://www.w3.org/
</code></pre></li>
<li><p>By running the following, you can see the options available to you from the validator:</p>

<pre><code>java -jar css-validator.jar
</code></pre>

<p>These options are explained in the <a href="http://jigsaw.w3.org/css-validator/manual.html">CSS Validator User Manual</a>.</p></li>
</ol>

<p>And that, as they say, is all there is to it.  From this, it shouldn&#8217;t be too difficult to set the validator up to run as a website if you want to, but that wasn&#8217;t necessary for me right now, so I didn&#8217;t do it myself.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
