<?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>Ben Barnett&#039;s Blog</title>
	<atom:link href="http://www.benbarnett.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.benbarnett.net</link>
	<description>Front-end Web Lover.</description>
	<lastBuildDate>Wed, 01 Sep 2010 16:51:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Enhancing jQuery&#8217;s animate function to automatically use CSS3 transitions</title>
		<link>http://www.benbarnett.net/2010/09/01/enhancing-jquerys-animate-function-to-automatically-use-css3-transitions/</link>
		<comments>http://www.benbarnett.net/2010/09/01/enhancing-jquerys-animate-function-to-automatically-use-css3-transitions/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 16:51:34 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[transform]]></category>
		<category><![CDATA[transition]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=76</guid>
		<description><![CDATA[On a client project recently, we&#8217;ve been working with some heavy full page transitions, which can look extra lovely when on hardware accelerated browsers and devices. I was struggling to find a neat way to write the front-end code, which is using jQuery, to degrade and enhance itself automatically without putting switch statements and creating [...]]]></description>
			<content:encoded><![CDATA[<p>On a client project recently, we&#8217;ve been working with some heavy full page transitions, which can look <em>extra</em> lovely when on hardware accelerated browsers and devices. I was struggling to find a neat way to write the front-end code, which is using jQuery, to degrade and enhance itself automatically without putting switch statements and creating multiple stylesheets all over the place.</p>
<p>This is where my <a href="http://playground.benbarnett.net/jquery-animate-enhanced/">jquery-animate-enhanced</a> plugin comes in. The idea was to have a one hundred percent seamless integration, and backwards compatibility with older browsers. For this reason, it just extends $.animate() which we all know and love and detects if you&#8217;re trying to animate something that would be better off done with a CSS3 transition. Absolutely zero effort required.</p>
<h2>The plugin.</h2>
<h1><strong>Extend $.animate() to detect CSS transitions for Webkit, Mozilla and Opera and convert animations automatically. Compatible with IE6+</strong></h1>
<h3>Properties supported: (more to come)</h3>
<ul>
<li>left : using <em>translate(x, y) or translate3d(x, y, z)</em></li>
<li>top : using <em>translate(x, y) or translate3d(x, y, z)</em></li>
<li>opacity</li>
</ul>
<p>Note that any properties not mentioned above will simply be handled by the standard jQuery $.animate() method. This plugin adds new functionality without taking any away.</p>
<h2>Demo</h2>
<div id="target">
<p>Check out a working demo on the <a href="http://playground.benbarnett.net/jquery-animate-enhanced/">plugin&#8217;s homepage</a>.</p>
</div>
<h2>What it does</h2>
<p>The plugin will analyse the properties you&#8217;re animating on, and select the most appropriate method for the browser in use. This means your transitions on <strong>left, top and opacity</strong> will convert to a <strong>CSS3 transition</strong> on Webkit &amp; Mozilla agents that support it, and Opera 10.50+. If the user is on a browser that has no CSS3 transitions, this plugin knows about it and won&#8217;t get involved. Silent degradation <img src='http://www.benbarnett.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Multiple callback mechanisms are created internally to monitor for DOM manipulation and for all &#8216;<strong>transitionend</strong>&#8216; CSS3 events to be picked up. This means you have one neat callback() for the whole animation regardless on whether the plugin is using CSS3, DOM, or both for its animations.</p>
<p>Progressively enhanced CSS3 animations without having to do any browser detection or special CSS, therefore using the same Javascript across your applications and websites.</p>
<p>As this plugin uses CSS3 translate where available, there is an internal callback mechanism to reset the &#8216;left&#8217; and/or &#8216;top&#8217; properties so that your layout is unaffected.</p>
<h2>Usage</h2>
<p>Usage is identical to the <a href="http://api.jquery.com/animate/">jQuery animate() function</a>, but it comes with 3 new paramaters, which are totally optional and safe to leave untouched for general use:</p>
<ul>
<li> <strong>avoidTransforms</strong>: (Boolean)By default the plugin will convert left and top animations to the CSS3 style -webkit-transform (or equivalent) to aid hardware acceleration. This functionality can be disabled by setting this to true.</li>
<li> <strong>useTranslate3d</strong>: (Boolean)By default the plugin will use 2d translations due to wider browser support. Set this to true to use translate3d instead. Recommended for iPhone/iPad development (<a href="http://www.benbarnett.net/2010/08/30/writing-html-and-css-for-mobile-safari-just-the-same-old-code/">here&#8217;s why</a>).</li>
<li> <strong>leaveTransforms</strong>: (Boolean)By default if the plugin is animating a left or a top property, the translate (2d or 3d depending on setting above) CSS3 transformation will be used. To preserve other layout dependencies, once the transition is complete, these transitions are removed and converted back to the real left and top values. Set this to <strong>true</strong> to skip this functionality.</li>
</ul>
<h2>Give it a go</h2>
<p>More information is available either on the <a href="http://github.com/benbarnett/jQuery-Animate-Enhanced">GitHub repository</a>, or on the <a href="http://playground.benbarnett.net/jquery-animate-enhanced/">plugin homepage</a>. Thoughts very much welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/09/01/enhancing-jquerys-animate-function-to-automatically-use-css3-transitions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Writing HTML and CSS for Mobile Safari. Just the same old code?</title>
		<link>http://www.benbarnett.net/2010/08/30/writing-html-and-css-for-mobile-safari-just-the-same-old-code/</link>
		<comments>http://www.benbarnett.net/2010/08/30/writing-html-and-css-for-mobile-safari-just-the-same-old-code/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 12:56:18 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Ramblings]]></category>
		<category><![CDATA[Techniques]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=64</guid>
		<description><![CDATA[The answer is &#8220;kind of&#8221;. I&#8217;m a believer of the &#8220;write once, deploy anywhere&#8221; attitude. I&#8217;m also a big fan of things like WhitherApps; James has done a great job taking the (native) BBC News app and rebuilding it using just HTML and CSS to prove out this very concept. BUT&#8230; people would be lying if [...]]]></description>
			<content:encoded><![CDATA[<p>The answer is &#8220;kind of&#8221;.</p>
<p>I&#8217;m a believer of the &#8220;write once, deploy anywhere&#8221; attitude. I&#8217;m also a big fan of things like <a href="http://whitherapps.com/">WhitherApps</a>; James has done a great job taking the (native) BBC News app and rebuilding it using just HTML and CSS to prove out this very concept.</p>
<p>BUT&#8230; people would be lying if they told you it&#8217;s exactly the same as writing CSS for desktop browsers. It just isn&#8217;t.</p>
<h2>No support for the CSS fixed position</h2>
<p>You could be forgiven for thinking that it just reverts back to <em>absolute </em>positioning like it does in IE6, but in fact it is not same as <em>explicitly</em> setting an element to absolute. The behaviour is subtly different, and I found that running any CSS3 style webkit transitions were much more performant, and less &#8216;flickery&#8217; on an element with fixed position, over one with absolute even though the layout was identical.</p>
<p>Very strange considering there&#8217;s <a href="http://ajaxian.com/archives/a-better-mobile-web-what-else">no support for fixed position</a>. Couldn&#8217;t find that one in the specs anywhere either, so I remain baffled. My solution was to try both position attributes and see which performs better.</p>
<p>Usually though, <a href="http://cubiq.org/iscroll">Cubiq&#8217;s iScroll</a> will do the trick as it&#8217;s more than likely the reason for needing fixed positioning anyway. That plugin genuinely works well by the way. Use it.</p>
<h2>Hardware accelerated CSS transformations&#8230; but are they, really?</h2>
<p>This one took me a good few hours to work out when I could have been quite happily doing far <a href="http://sphotos.ak.fbcdn.net/hphotos-ak-ash2/hs084.ash2/37520_654331589952_286100624_8390763_4183378_n.jpg">more productive</a> things with my day. I knew already that the &#8216;-webkit-transform&#8217; and &#8216;opacity&#8217; attributes were hardware accelerated for webkit transitions. If you&#8217;re experiencing a flicker with css3 transitions, this is how to fix it.</p>
<p>It is true that opacity is hardware accelerated. It is also true that -webkit-transform is hardware accelerated, but, if you&#8217;re using translateX, translateY or translateZ, you don&#8217;t get that luxury. Take a typical CSS transition;</p>
<pre>#element {
    -webkit-transition: -webkit-transform 1s linear;
    -webkit-transform: translateX(0);
}</pre>
<pre>#element.transformed {
    -webkit-transform: translateX(300px);
}</pre>
<p>In any webkit browser, you&#8217;ll get whatever #element is to move 300 pixels to the right, in a linear 1 second animation. On Mobile Safari, it will likely &#8216;flicker&#8217; before/during/after the transition. The key is to use <strong>translate3d(x, y, z). </strong>The simple change shown below makes all the difference.</p>
<pre>#element.transformed {
    <strong>-webkit-transform: translate3d(300px, 0, 0);</strong>
}</pre>
<p>It&#8217;s ridiculously simple, but honestly why would that be hardware accelerated and not the shorter hand, translateX property?</p>
<h2>Avoid Javascript Libraries</h2>
<p>You&#8217;ll notice that the Javascript engine on the iPhone is incredibly slow. The iPad is greatly improved but its still advisable to minimise Javascript, particularly for things like animations. Always use a <em>translate</em> transition over animating the <em>left</em> or <em>top</em> properties. The CSS3 transitions are perfectly smooth and look great. Arguably you don&#8217;t need jQuery for mobile apps as a lot of &#8216;weight&#8217; comes from dealing with cross browser differences; obviously not being an issue if we&#8217;re focussing solely on mobile webkit. With the new CSS selector engine, document.querySelectorAll(); you still get lightening fast &#8216;jQuery style&#8217; DOM selections. Time to brush off the raw Javascript skills (or just be lazy and wait for <a href="http://jquerymobile.com/">jQuery mobile</a>).</p>
<h2>Am I being impatient?</h2>
<p>There&#8217;s only a handful of cases that have proved to be quite time consuming during development, but the point here is a bigger one.</p>
<p>The whole idea of unifying standards across all devices is the way forward. The thing is though that I can&#8217;t help feeling that we&#8217;re harking back to the &#8220;Are you using Netscape or Internet Explorer?&#8221; days. I wish we didn&#8217;t have to know about these tricks. It means that without position fixed, we need to use (and write) Javascript extensions to help us out, but then we add weight and potential bugs to the desktop side of things. Do we really have to start detecting whether we&#8217;re on an iPad and serve up specialised code? What about sites that we wrote before all this came about?</p>
<p>I&#8217;m still behind the idea of using HTML powered apps with simple Objective-C wrappers to encase everything into a native application. With a bit of reading up, and more than one or two stabs in the dark, its definitely not impossible to make an HTML driven app &#8220;feel&#8221; just as native as any other.</p>
<p>I guess one just has to accept that the concept of using <em>exactly</em> the same code on mobile and desktop devices still isn&#8217;t quite there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/08/30/writing-html-and-css-for-mobile-safari-just-the-same-old-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making an Interactive SVG London Tube Map with Raphael JS</title>
		<link>http://www.benbarnett.net/2010/08/24/making-an-interactive-svg-london-tube-map-with-raphael-js/</link>
		<comments>http://www.benbarnett.net/2010/08/24/making-an-interactive-svg-london-tube-map-with-raphael-js/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 13:10:56 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[interactive map]]></category>
		<category><![CDATA[london tube map]]></category>
		<category><![CDATA[raphaeljs]]></category>
		<category><![CDATA[svg]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=34</guid>
		<description><![CDATA[The London Tube Map is a wonderful thing. Making it interactive makes it even more wonderful. The possibilities of what can be done with a fully interactive, SVG (well, RaphaelJS) driven tube map in terms of visualisations are endless. Given that TFL have also made a giant leap towards opening their data, which in itself [...]]]></description>
			<content:encoded><![CDATA[<h1><span style="font-weight: normal; font-size: 13px;">The London Tube Map is a wonderful thing. Making it interactive makes it even more wonderful. The possibilities of what can be done with a fully interactive, SVG (well, RaphaelJS) driven tube map in terms of visualisations are endless. Given that TFL have also made a giant leap towards <a href="http://www.tfl.gov.uk/businessandpartners/syndication/default.aspx">opening their data</a>, which in itself has sewed the seeds from some <a href="http://tubeupdates.com/">pretty exciting projects</a> already; combining the two could be a lot of fun.</span></h1>
<h2>Is there an easy way to convert this increasingly mammoth tube map into a clean, cross browser, interactive map?</h2>
<p><img src="http://farm3.static.flickr.com/2130/2313995479_4ccda2421c.jpg" alt="Historic London Tube Map" width="500" height="324" /></p>
<h2>The short answer is&#8230;. no, but here&#8217;s how anyway.</h2>
<p>Allow me to explain why. I&#8217;m sure someone will find this post and tell me straight away that I could&#8217;ve done this using a much simpler approach, but this is how I tackled it.</p>
<h3>Firstly, get the right Tube Map</h3>
<p>Ok, it sounds obvious but this is quite important as it can drastically affect how much work we have to do. I&#8217;m not implying that I downloaded the map for New York Metro, but the starting format for this key.</p>
<p>The first part is that we need a vector based tube map, i.e. the PDF or even better an SVG version to start with. I tried both formats, in &#8220;normal&#8221; and large print. After popping them all into Adobe Illustrator, I clicked around to find the version which had the most amount of clean separation between layers. Turned out the PDF Large Print tube map was a reasonable starting point. I use that adjective loosely.</p>
<h3>Spring cleaning</h3>
<p>This is probably the most laborious part, but equally the most important to make this thing actually any use. Unfortunately with compressed PDFs, text fields are nearly always seperation in order to preserve the display of the typography as accurately as possible, making lines split into words, and words split into meaningless 1 or 2 letter &#8220;phrases&#8221;. This is great for the human eye, but for actually &#8216;querying&#8217; the document, it&#8217;s useless as we need clean labels for each tube station.</p>
<p>Essentially the job was a manual one. I&#8217;m no Illustrator expert so there may well have been easier way, but it surpassed me if so. Here&#8217;s a demonstration example of what I did:</p>
<p><span style="color: #003300;">Ox</span><span style="color: #800000;">for</span><span style="color: #0000ff;">d C</span><span style="color: #ff6600;">irc</span><span style="color: #800080;">us</span> -&gt; <strong>Oxford Circus</strong></p>
<p>Do you see? To start with, we had 5 different (and meaningless) labels, &#8220;Ox&#8221;, &#8220;for&#8221;, &#8220;d C&#8221;, &#8220;irc&#8221; and &#8220;us.&#8221; Do you also see how I used the Tube line colours for my demo?</p>
<p>By now I&#8217;m sure you&#8217;ve figured out how I spent that evening&#8230;</p>
<h3>Seperate the Tube lines</h3>
<p>Now we have the station names cleaned up and ready for conversion (I&#8217;ll explain how in a minute), it&#8217;d make it even more interactive if we could distinguish between the Tube lines themselves as well. Filtering just on the Central and Picadilly Lines, for example.</p>
<p>This part is a bit simpler and is actually a really simple technique of getting complex paths into Raphael JS.</p>
<p>I simply selected each line in Illustrator, and copied into a new standalone document. I then <em>Saved a Copy, </em>selected <em>SVG 1.1</em> as the document format and clicked <em>Show SVG Code</em>. I was presented with this little beauty for the Central Line:</p>
<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  --&gt;
&lt;!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"&gt;
&lt;svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="400px" height="400px" viewBox="0 0 400 400" enable-background="new 0 0 400 400" xml:space="preserve"&gt;
&lt;path fill="none" stroke="#ED3024" stroke-width="6.65" stroke-linejoin="round" stroke-miterlimit="3.994" d="<strong><span style="color: #3366ff;">M973.98,129.223</span></strong>
<strong><span style="color: #3366ff;">H773.97c-4.87,0-11.67,2.823-15.12,6.269L629.99,264.364c-3.45,3.44-10.25,6.258-15.12,6.258h-79.49</span></strong>
<strong><span style="color: #3366ff;">c-4.87,0-11.66-2.817-15.11-6.258l-33.239-33.236c-3.44-3.448-10.24-6.264-15.11-6.264H-572.959</span></strong>"/&gt;
&lt;/svg&gt;</pre>
<p>I&#8217;ve highlighted the bit we need. This can then be used as simply as:</p>
<pre>var c = paper.path("&lt;&lt;&lt; PATH CONTENTS HERE &gt;&gt;&gt;");</pre>
<p>&#8230;and so on for each line.</p>
<h3>Getting the stations into Raphael JS</h3>
<p>This is the final stage really. Unfortunately there&#8217;s no such easy technique for getting text labels into Raphael type code. After a bit of playing around, I wrote a PHP script to help me with this.</p>
<p>All you need to do as save the stations, and the <em>stations only </em>into a document. This does mean a lot of copying and pasting, or a lot of deleting of tube lines and artifcats, whichever your preference. However, with this done you should just have a document with a bunch of text labels which you save as an SVG 1.1 file somewhere.</p>
<p>Running this PHP script on it will loop through every SVG text node, extract the text and the x and y coordinates for you; making it super easy to plot all the hundreds of stations exactly where they were in SVG, using Raphael.</p>
<pre>header("Content Type: text/plain");
$xml = simplexml_load_file("stations.svg");

foreach($xml-&gt;children() as $child) {
	if ($child-&gt;getName() == "text") {
		$matrix = $child-&gt;attributes();
		$matrix = str_replace(array("matrix(1 0 0 1 ", ")"), "", $matrix);
		$matrix = explode(" ", $matrix);

		// here we go
		$stationName = trim(str_replace(array("%%", '’'), array('\n', "'"), $child), " ");
		$x = $matrix[0];
		$y = $matrix[1];

		// your business logic here
                // echo($stationName);
} }</pre>
<p>One last thing to note is that it seems line breaks (which are essential to mirror the layout of the Tube Map) are converted into seperate text fields when saving down to SVG. For this reason, and its not the cleanest solution I admit, I tokenised the strings with &#8220;%%&#8221; to represent a line break, which were then converted into line breaks using the code above.</p>
<p>Using that script I printed out the exact Javascript variables I needed for the project I was working on for this at the time, looped through them all and created them as text fields:</p>
<pre>var stations = { "Oxford Circus" : { x: 100, y: 100 } };</pre>
<pre>for (p in stations) {
	var station = stations[p];
	var t = paper.text(station.x, station.y, p);
	t.attr({font: 'Arial', 'font-size': 13.5, fill: '#1C3F94'});
}</pre>
<h3>SVG and Illustrator file references</h3>
<p>As a farewell I will leave you with the 2 SVG files which took the most time to produce and will do most of the work for you. I&#8217;m sure they could be cleaned up even further, and I&#8217;m open to any suggestions on how to do so.</p>
<p><a href="http://gist.github.com/547516">SVG Source for Tube Stations</a><br />
<a href="http://gist.github.com/547518">SVG Source for Tube Lines</a></p>
<p>All should be labelled clearly for ease of use. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/08/24/making-an-interactive-svg-london-tube-map-with-raphael-js/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Top of the Geeks: The Top 5 Comedy Geek Music Videos</title>
		<link>http://www.benbarnett.net/2010/08/23/top-of-the-geeks-the-top-5-comedy-geek-music-videos/</link>
		<comments>http://www.benbarnett.net/2010/08/23/top-of-the-geeks-the-top-5-comedy-geek-music-videos/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 12:49:47 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Ramblings]]></category>
		<category><![CDATA[geek music]]></category>
		<category><![CDATA[really-important-work-related-stuff]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=27</guid>
		<description><![CDATA[Its Monday, its raining and if you&#8217;re a geek (or even have geeky inclinations and are in denial about being one), you might be able to extract some joy from the below. Number 5 &#8211; &#8220;The Drupal Song&#8221; This is a special one off LIVE PERFORMANCE! Don&#8217;t miss it. Number 4 &#8211; &#8220;The WordPress Song&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Its Monday, its raining and if you&#8217;re a geek (or even have geeky inclinations and are in denial about being one), you might be able to extract some joy from the below.</p>
<p><strong>Number 5 &#8211; &#8220;The Drupal Song&#8221; </strong></p>
<p>This is a special one off LIVE PERFORMANCE! Don&#8217;t miss it.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/fdbFVWupSsw?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/fdbFVWupSsw?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><strong>Number 4 &#8211; &#8220;The WordPress Song&#8221;</strong></p>
<p>&#8230;by <a href="http://devin.reams.me/" target="_blank">Devin Reams</a>. Why not <a href="http://jaypeeonline.net/wordpress/the-wordpress-song/" target="_blank">get the Lyrics</a> so you can sing along as well. This blog is also powered by WordPress so this is particularly special to me.</p>
<p><object id="viddler" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="437" height="370" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><param name="flashvars" value="fake=1" /><param name="src" value="http://www.viddler.com/player/a257995d/" /><param name="name" value="viddler" /><param name="allowfullscreen" value="true" /><embed id="viddler" type="application/x-shockwave-flash" width="437" height="370" src="http://www.viddler.com/player/a257995d/" name="viddler" flashvars="fake=1" allowfullscreen="true" allowscriptaccess="always"></embed></object></p>
<p><strong>Number 3 &#8211; &#8220;The Twitter Song&#8221;</strong></p>
<p>&#8230;by Chris Thompson, with an incredible 416,000 views at time of writing!</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/wt4XENAi74M?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/wt4XENAi74M?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><strong>Number 2 &#8211; &#8220;The HTML5 Song&#8221;</strong></p>
<p>&#8230;by the brilliant Daniel Davis.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/V2s8AU8PkBU?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/V2s8AU8PkBU?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p><strong>and in at Number 1 &#8211; &#8220;The CSS3 Song&#8221;</strong></p>
<p>Also by Daniel Davis, I hold this and the HTML5 song close to my heart. Enjoy.</p>
<p><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/5b7dNNapMCM?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/5b7dNNapMCM?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/08/23/top-of-the-geeks-the-top-5-comedy-geek-music-videos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Rails and the new Lulu Publication API</title>
		<link>http://www.benbarnett.net/2010/07/20/using-rails-and-the-new-lulu-publication-api/</link>
		<comments>http://www.benbarnett.net/2010/07/20/using-rails-and-the-new-lulu-publication-api/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 21:13:12 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Techniques]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=20</guid>
		<description><![CDATA[Just a quick note to anyone interested in playing around with the Lulu Publication API and Ruby on Rails, the post I wrote a few months ago has been updated to include the recent change of API URLs, and inclusion of the new API Key and Upload Token calls. To see an example app, check [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick note to anyone interested in playing around with the <a href="http://developer.lulu.com/page" target="_blank">Lulu Publication API</a> and Ruby on Rails, the post I wrote a few months ago has been updated to include the recent change of API URLs, and inclusion of the new API Key and Upload Token calls.</p>
<p>To see an <a href="http://www.beforeigrewup.com">example app</a>, check out the <a href="http://www.beforeigrewup.com">free online baby book creator</a>, which has just launched and is written using pretty much the exact code in my post.</p>
<p>Anyway, the updated <a href="/2010/05/19/using-ruby-on-rails-and-the-lulu-publication-api/">Rails/Lulu API howto</a> is just a click away.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/07/20/using-rails-and-the-new-lulu-publication-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Export SVG from Raphael JS to create a PNG bitmap</title>
		<link>http://www.benbarnett.net/2010/06/04/export-svg-from-raphael-js-to-create-a-png-bitmap/</link>
		<comments>http://www.benbarnett.net/2010/06/04/export-svg-from-raphael-js-to-create-a-png-bitmap/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 17:01:38 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Techniques]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=9</guid>
		<description><![CDATA[Update I&#8217;m very pleased to be able to say that Jonathan Spies has taken the roots of this blog post and produced a fully fledged plugin. I&#8217;ve used it on a couple of projects already. Oh how I love the web sometimes. http://github.com/jspies/raphael.serialize Introduction I’ve been playing around with RaphaelJS recently (if you haven’t seen it, check it [...]]]></description>
			<content:encoded><![CDATA[<h2>Update</h2>
<p>I&#8217;m very pleased to be able to say that <a href="http://github.com/jspies" target="_blank">Jonathan Spies</a> has taken the roots of this blog post and produced a <a href="http://github.com/jspies/raphael.serialize" target="_blank">fully fledged plugin</a>. I&#8217;ve used it on a couple of projects already. Oh how I love the web sometimes.</p>
<p><a href="http://github.com/jspies/raphael.serialize" target="_blank">http://github.com/jspies/raphael.serialize</a></p>
<h2>Introduction</h2>
<p>I’ve been playing around with RaphaelJS recently (if you haven’t seen it, <a href="http://raphaeljs.com/" target="_blank">check it out</a>) for an ‘avatar builder’ type project to avoid the use of Flash. It’s a really fun bit of kit to use, but I needed a way to actually save the results of the avatar to a bitmap to avoid having heavy javascript libraries every time the avatar is displayed on a page. After a bit of poking around on forums/blogs I thought I’d tie up all the key pieces in one blog post in case anyone else was in the same boat.</p>
<p>The output is essentially a PNG-24 alpha channel bitmap image, which can then be treated as normal with the likes of ImageMagick (I’ve been adding drop shadows to the avatars for example).</p>
<h2><strong>Extracting <strong>SVG</strong> data from <strong>Raphael</strong></strong></h2>
<p>Unfortunately this isn’t as easy as could be. In browsers that support <strong>SVG</strong>, we can simply extract all the data from the DOM itself to reproduce it, but as <strong>Raphael</strong> uses VML on non-<strong>SVG</strong> browsers (namely, IE) that idea won’t work.</p>
<p>However, the <strong>Raphael</strong> Javascript object does store the data we need in order to <em>re-produce </em>the <strong>SVG</strong>. This requires a little bit of Javascript, and for demonstration purposes I’m using PHP.</p>
<h3>The Javascript</h3>
<p>So the first thing I do build up a JSON object describing the data needed to produce the <strong>SVG</strong> file, with a little help from jQuery. I’ve put the code for this on <a href="http://gist.github.com/423856" target="_blank">this gist</a>. It essentially loops through the ‘paper’ variable that RaphaelJS is using to build up our own array. In mine I was using just paths and images, so that was the only data I needed, however this could easily be expanded to include all the other properties as well.</p>
<h3>The Server Side Code (PHP)</h3>
<p>All this file does is decode the JSON data into an associative array for use in PHP, loop through the properties and outputs an SVN file. I’ve put the PHP I’m using below as there’s not much to it:</p>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family: monospace;">    <span style="color: #000088;">$json</span> <span style="color: #339933;">=</span> <span style="color: #990000;">json_decode</span><span style="color: #009900;">(</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'json'</span><span style="color: #009900;">]</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>

    <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'&lt;<strong>svg</strong> xmlns="http://www.w3.org/2000/<strong>svg</strong>" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'width'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" height="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'height'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" xml:space="preserve"&gt;&lt;desc&gt;Created with <strong>Raphael</strong>&lt;/desc&gt;&lt;defs&gt;&lt;/defs&gt;'</span><span style="color: #339933;">;</span>

    <span style="color: #b1b100;">for</span> <span style="color: #009900;">(</span><span style="color: #000088;">$i</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #990000;">count</span><span style="color: #009900;">(</span><span style="color: #000088;">$json</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">]</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">"image"</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
            <span style="color: #000088;">$base64</span> <span style="color: #339933;">=</span> <span style="color: #990000;">base64_encode</span><span style="color: #009900;">(</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">(</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'src'</span><span style="color: #009900;">]</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>

            <span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;image overflow="visible" x="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">"x"</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" y="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">"y"</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" width="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">"width"</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" height="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">"height"</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" transform="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">"transform"</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" preserveAspectRatio="none" xlink:href="data:image/png;base64,'</span><span style="color: #339933;">.</span><span style="color: #000088;">$base64</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'"&gt;&lt;/image&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">}</span>

        <span style="color: #b1b100;">if</span> <span style="color: #009900;">(</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">]</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">"path"</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
            <span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;path fill="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'fill'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" stroke="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'stroke'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" d="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'path'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" style="opacity: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'opacity'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">';" opacity="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'opacity'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'" transform="'</span><span style="color: #339933;">.</span><span style="color: #000088;">$json</span><span style="color: #009900;">[</span><span style="color: #000088;">$i</span><span style="color: #009900;">]</span><span style="color: #009900;">[</span><span style="color: #0000ff;">'transform'</span><span style="color: #009900;">]</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'"&gt;&lt;/path&gt;'</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">}</span>
    <span style="color: #009900;">}</span>

    <span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/<strong>svg</strong>&gt;'</span><span style="color: #339933;">;</span></pre>
</div>
</div>
<h2>Save the <strong>SVG</strong> and send to Apache Batik for Rasterization</h2>
<p>So this part is fairly simple. I recommend using <a href="http://xmlgraphics.apache.org/batik/tools/rasterizer.html" target="_blank">Apache Batik</a> for the <strong>SVG</strong> rasterization as it seemed to have better results compared to ImageMagick. The first part is simply to write the ‘<strong>SVG</strong> string’ to a file.</p>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family: monospace;"><span style="color: #990000;">file_put_contents</span><span style="color: #009900;">(</span><span style="color: #0000ff;">'generated/avatar.<strong>svg</strong>'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
</div>
</div>
<p>Now, just send it across to Apache Batik with the exec() command, and we have a PNG!</p>
<div class="wp_syntax">
<div class="code">
<pre class="php" style="font-family: monospace;"><span style="color: #990000;">exec</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"java -jar batik-rasterizer.jar /path/to/avatar.<strong>svg</strong>"</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span></pre>
</div>
</div>
<h2>Just the beginning</h2>
<p>So this was just a basic introduction to exporting an <strong>SVG</strong> from <strong>Raphael</strong>, and will need more work for more complex shapes and transformations. I’m planning on writing a RaphaelJS extension to make all this a bit easier, and perhaps offer out the server side code on a public domain so there’s no need to write it out…</p>
<p>So stay tuned. Or, if you’re already doing this, I’d be more than happy to help out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/06/04/export-svg-from-raphael-js-to-create-a-png-bitmap/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Using Ruby on Rails and the Lulu Publication API [UPDATED]</title>
		<link>http://www.benbarnett.net/2010/05/19/using-ruby-on-rails-and-the-lulu-publication-api/</link>
		<comments>http://www.benbarnett.net/2010/05/19/using-ruby-on-rails-and-the-lulu-publication-api/#comments</comments>
		<pubDate>Wed, 19 May 2010 16:57:19 +0000</pubDate>
		<dc:creator>benbarnett</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Techniques]]></category>
		<category><![CDATA[lulu]]></category>
		<category><![CDATA[lulu api]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.benbarnett.net/?p=5</guid>
		<description><![CDATA[A simple overview and tutorial into the Lulu Publication API using Ruby on Rails]]></description>
			<content:encoded><![CDATA[<p>In the past week or so I’ve been working on a little side project that is making fairly heavy use of <strong>Lulu</strong> and their new <a href="http://api.lulu.com/publication/" target="_blank">Publication <strong>API</strong></a>. It’s a brilliant system, and although I can’t blame them as the <strong>Lulu</strong> <strong>API</strong> is a new release, the documentation is a little thin. After a bit of poking around their <a href="http://github.com/luluapi" target="_blank">Python example</a> on Github and more into Ruby’s HTTP class, I’ve managed to find a pretty neat and easy to implement method which I’ve written about here.</p>
<p>To get the communication between your site and the <strong>Lulu</strong> Publication <strong>API</strong> the main libraries we need are;</p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;"><span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'net/https'</span>
<span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'uri'</span>
<span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'curb'</span></pre>
</div>
</div>
<p>…and 4 URLs, along with the API Key (free to <a href="http://developer.lulu.com/apps/register" target="_blank">create one</a>) which should be defined as constants (perhaps in config/environment.rb);</p>
<div class="code">
<pre class="ruby" style="font-family: monospace;">
LULU_AUTHENTICATE = "https://www.lulu.com/account/endpoints/authenticator.php"
LULU_UPLOAD_TOKEN = "http://apps.lulu.com/api/publish/v1/request_upload_token"
LULU_UPLOAD = "https://pubapp.lulu.com/api/publish/v1/upload"
LULU_PUBLISH = "http://apps.lulu.com/api/publish/v1/create"
API_KEY = "ABCDEF123" # replace this with your api key
</pre>
</div>
<p><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;"><a href="http://curb.rubyforge.org/" target="_blank">Curb</a> is simply a hook into the brilliant cURL utility and can be installed as a gem. It’s used here as it makes it dead easy to do a multipart form post, which is required for the ‘upload’ phase of the integration.</span></p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;"><span style="color: #006600; font-weight: bold;">[</span>sudo<span style="color: #006600; font-weight: bold;">]</span> gem install curb</pre>
</div>
</div>
<h2>Step 1 – Obtain your authToken from the <strong>Lulu</strong> <strong>API</strong></h2>
<p>To use the <strong>Lulu</strong> <strong>API</strong>, all you need is a normal <strong>Lulu</strong> account, which is free. You’ll need those details to get the ‘authToken’ from the <strong>Lulu</strong> <strong>API</strong> which simply authenticates all the requests. We also need to be using <em>https</em> for every call to the <strong>API</strong>. Anyway, here’s the code you need for step 1 (I’ve defined my <em>LULU_AUTH_USER</em> and <em>LULU_AUTH_PASS</em> in config/environment.rb for neatness).</p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;"><span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'net/https'</span>
<span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'uri'</span>
<span style="color: #cc0066; font-weight: bold;">require</span> <span style="color: #996600;">'curb'</span>

<span style="color: #008000; font-style: italic;"># LULU_AUTHENTICATE WITH <strong>LULU</strong> TO GET OUR auth_token</span>
url = <span style="color: #cc00ff; font-weight: bold;">URI</span>.<span style="color: #9900cc;">parse</span><span style="color: #006600; font-weight: bold;">(</span>LULU_AUTHENTICATE+'?api_key='+LULU_API_KEY<span style="color: #006600; font-weight: bold;">)</span>
auth_args = <span style="color: #006600; font-weight: bold;">{</span>
<span style="color: #996600;">'username'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> LULU_AUTH_USER,
<span style="color: #996600;">'password'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> LULU_AUTH_PASS,
<span style="color: #996600;">'responseType'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">'json'</span>
<span style="color: #006600; font-weight: bold;">}</span>

http = <span style="color: #6666ff; font-weight: bold;">Net::HTTP</span>.<span style="color: #9900cc;">new</span><span style="color: #006600; font-weight: bold;">(</span>url.<span style="color: #9900cc;">host</span>, url.<span style="color: #9900cc;">port</span><span style="color: #006600; font-weight: bold;">)</span>
http.<span style="color: #9900cc;">use_ssl</span> = <span style="color: #0000ff; font-weight: bold;">true</span>
request = <span style="color: #6666ff; font-weight: bold;">Net::HTTP::Post</span>.<span style="color: #9900cc;">new</span><span style="color: #006600; font-weight: bold;">(</span>url.<span style="color: #9900cc;">path</span><span style="color: #006600; font-weight: bold;">)</span>
request.<span style="color: #9900cc;">set_form_data</span><span style="color: #006600; font-weight: bold;">(</span>auth_args<span style="color: #006600; font-weight: bold;">)</span>

response = http.<span style="color: #9900cc;">start</span> <span style="color: #006600; font-weight: bold;">{</span><span style="color: #006600; font-weight: bold;">|</span>http<span style="color: #006600; font-weight: bold;">|</span> http.<span style="color: #9900cc;">request</span><span style="color: #006600; font-weight: bold;">(</span>request<span style="color: #006600; font-weight: bold;">)</span> <span style="color: #006600; font-weight: bold;">}</span>
json = <span style="color: #6666ff; font-weight: bold;">ActiveSupport::JSON</span>.<span style="color: #9900cc;">decode</span><span style="color: #006600; font-weight: bold;">(</span>response.<span style="color: #9900cc;">body</span><span style="color: #006600; font-weight: bold;">)</span></pre>
</div>
</div>
<p>Now all we need to do is deal with that response. The last line of the code above simply gives us a decoded JSON object, which can be used like this:</p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;"><span style="color: #9966cc; font-weight: bold;">if</span> json<span style="color: #006600; font-weight: bold;">[</span><span style="color: #996600;">'authenticated'</span><span style="color: #006600; font-weight: bold;">]</span> == <span style="color: #0000ff; font-weight: bold;">true</span>
  <span style="color: #008000; font-style: italic;"># we're logged in!</span>
  auth_token = json<span style="color: #006600; font-weight: bold;">[</span><span style="color: #996600;">'authToken'</span><span style="color: #006600; font-weight: bold;">]</span>
<span style="color: #9966cc; font-weight: bold;">else</span>
 <span style="color: #008000; font-style: italic;"># something went wrong, let's review what came back and try again</span>
 <span style="color: #cc0066; font-weight: bold;">puts</span> response.<span style="color: #9900cc;">body</span>
<span style="color: #9966cc; font-weight: bold;">end</span></pre>
</div>
</div>
<h2>Step 2 – Upload the PDFs</h2>
<p>This bit probably took me the longest to work out, but as I mentioned earlier, the <a href="http://curb.rubyforge.org/" target="_blank">Curb gem</a> came to the rescue. Make sure you’ve installed that and then we can form a new request to send our cover PDF and the book PDF. Remember that this will only work if you’ve successfully received an <em>authToken</em> from the authentication stage of the <strong>Lulu</strong> <strong>API</strong>.</p>
<p><strong>UPDATE: Since June 2010, you now need to request an Upload Token before being able to upload files:-</strong></p>
<div class="code">
<pre class="ruby">url = URI.parse(LULU_UPLOAD_TOKEN+'?api_key='+LULU_API_KEY)

publish_args = {
  'auth_user' =&gt; LULU_AUTH_USER,
  'auth_token' =&gt; auth_token,
  'api_key' =&gt; LULU_API_KEY
}
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.path)
request.set_form_data(publish_args)

response = http.start {|http| http.request(request) }
responsebody = response.body.gsub("'", "\"") # Sadly our JSON parser won't work unless we do this (single quotes aren't <a href="http://www.jsonlint.com/" target="_blank">valid JSON</a>)

tokendata = ActiveSupport::JSON.decode(responsebody)</pre>
</div>
<p><strong><br />
</strong></p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;"><span style="color: #008000; font-style: italic;"># LULU_UPLOAD THEM</span>
pdf_cover = <span style="color: #996600;">"/tmp/cover.pdf"</span>
pdf_book = <span style="color: #996600;">"/tmp/book.pdf"</span>

c = <span style="color: #6666ff; font-weight: bold;">Curl::Easy</span>.<span style="color: #9900cc;">new</span><span style="color: #006600; font-weight: bold;">(</span>LULU_UPLOAD<span style="color: #006600; font-weight: bold;">)</span>
c.<span style="color: #9900cc;">multipart_form_post</span> = <span style="color: #0000ff; font-weight: bold;">true</span>
c.<span style="color: #9900cc;">http_post</span><span style="color: #006600; font-weight: bold;">(</span>
       <span style="color: #6666ff; font-weight: bold;">Curl::PostField</span>.<span style="color: #9900cc;">content</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'auth_user'</span>, LULU_AUTH_USER.<span style="color: #9900cc;">to_s</span><span style="color: #006600; font-weight: bold;">)</span>,
       <span style="color: #6666ff; font-weight: bold;">Curl::PostField</span>.<span style="color: #9900cc;">content</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'auth_token'</span>, auth_token.<span style="color: #9900cc;">to_s</span><span style="color: #006600; font-weight: bold;">)</span>,
<span style="color: #6666ff; font-weight: bold;">       Curl::PostField</span>.<span style="color: #9900cc;">content</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'api_key'</span>, LULU_API_KEY<span style="color: #006600; font-weight: bold;">)</span>, <em># note the new API key being sent across</em>
<span style="color: #6666ff; font-weight: bold;">       Curl::PostField</span>.<span style="color: #9900cc;">content</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'upload_token'</span>, tokendata['token'].<span style="color: #9900cc;">to_s</span><span style="color: #006600; font-weight: bold;">)</span>, <em># add our upload_token to the post fields</em>
       <span style="color: #6666ff; font-weight: bold;">Curl::PostField</span>.<span style="color: #9900cc;">file</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'cover'</span>, pdf_cover<span style="color: #006600; font-weight: bold;">)</span>,
       <span style="color: #6666ff; font-weight: bold;">Curl::PostField</span>.<span style="color: #9900cc;">file</span><span style="color: #006600; font-weight: bold;">(</span><span style="color: #996600;">'book'</span>, pdf_book<span style="color: #006600; font-weight: bold;">)</span>     <span style="color: #006600; font-weight: bold;">)</span>

json = <span style="color: #6666ff; font-weight: bold;">ActiveSupport::JSON</span>.<span style="color: #9900cc;">decode</span><span style="color: #006600; font-weight: bold;">(</span>c.<span style="color: #9900cc;">body_str</span><span style="color: #006600; font-weight: bold;">)</span>

<span style="color: #9966cc; font-weight: bold;">if</span> json<span style="color: #006600; font-weight: bold;">[</span><span style="color: #996600;">'written_files'</span><span style="color: #006600; font-weight: bold;">]</span>
  <span style="color: #008000; font-style: italic;"># the files were uploaded!</span>
  ... <span style="color: #9900cc;">business</span> logic here ...
<span style="color: #9966cc; font-weight: bold;">else</span>
  <span style="color: #008000; font-style: italic;"># something went wrong, review the output below</span>
  <span style="color: #cc0066; font-weight: bold;">puts</span> c.<span style="color: #9900cc;">body_str</span>
<span style="color: #9966cc; font-weight: bold;">end</span></pre>
</div>
</div>
<p>It really is as simple as that! Now all we need to do is send the fairly large (but still, easy to interpret) JSON data structure to the final stage of the <strong>Lulu</strong> <strong>API</strong>.</p>
<h2>Step 3 – Send Publish Data to <strong>Lulu</strong> Publication <strong>API</strong></h2>
<p>So this will probably look like the most complicated part, but it’s simply where we configure exactly what sort of book we want; meaning the size, paper/hardback, quality, availability etc etc. Let’s get straight into the data structure.</p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;">create_input =
<span style="color: #006600; font-weight: bold;">{</span>
  <span style="color: #996600;">"allow_ratings"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #0000ff; font-weight: bold;">true</span>,
  <span style="color: #996600;">"project_type"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"hardcover"</span>,
  <span style="color: #996600;">"access"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"direct"</span>,

  <span style="color: #996600;">"bibliography"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span>
  <span style="color: #006600; font-weight: bold;">{</span>
    <span style="color: #996600;">"title"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"My First Book"</span>,
    <span style="color: #996600;">"authors"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #006600; font-weight: bold;">[</span>
      <span style="color: #006600; font-weight: bold;">{</span>
        <span style="color: #996600;">"first_name"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"Ben"</span>,
        <span style="color: #996600;">"last_name"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"Barnett"</span>
      <span style="color: #006600; font-weight: bold;">}</span>
    <span style="color: #006600; font-weight: bold;">]</span>,
    <span style="color: #996600;">"category"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #006666;">4</span>,
    <span style="color: #996600;">"description"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"What a fabulous book!"</span>,
    <span style="color: #996600;">"copyright_year"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"2010"</span>,
    <span style="color: #996600;">"publisher"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"Brushfire Design Ltd"</span>,
    <span style="color: #996600;">"language"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"EN"</span>,
    <span style="color: #996600;">"country_code"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"GB"</span>

  <span style="color: #006600; font-weight: bold;">}</span>,

  <span style="color: #996600;">"physical_attributes"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span>
  <span style="color: #006600; font-weight: bold;">{</span>
    <span style="color: #996600;">"binding_type"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"casewrap-hardcover"</span>,
    <span style="color: #996600;">"trim_size"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"SIZE_825x1075"</span>,
    <span style="color: #996600;">"paper_type"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"regular"</span>,
    <span style="color: #996600;">"color"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"true"</span>
  <span style="color: #006600; font-weight: bold;">}</span>,

  <span style="color: #996600;">"pricing"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span>
  <span style="color: #006600; font-weight: bold;">[</span>
      <span style="color: #006600; font-weight: bold;">{</span>
        <span style="color: #996600;">"product"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"print"</span>,
        <span style="color: #996600;">"currency_code"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"GBP"</span>,
        <span style="color: #996600;">"total_price"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"34.99"</span>
      <span style="color: #006600; font-weight: bold;">}</span>
  <span style="color: #006600; font-weight: bold;">]</span>,

  <span style="color: #996600;">"file_info"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span>
  <span style="color: #006600; font-weight: bold;">{</span>
    <span style="color: #996600;">"cover"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #006600; font-weight: bold;">[</span><span style="color: #006600; font-weight: bold;">{</span><span style="color: #996600;">"mimetype"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"application/pdf"</span>, <span style="color: #996600;">"filename"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"cover.pdf"</span><span style="color: #006600; font-weight: bold;">}</span><span style="color: #006600; font-weight: bold;">]</span>,
    <span style="color: #996600;">"contents"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #006600; font-weight: bold;">[</span><span style="color: #006600; font-weight: bold;">{</span><span style="color: #996600;">"mimetype"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"application/pdf"</span>, <span style="color: #996600;">"filename"</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> <span style="color: #996600;">"book.pdf"</span><span style="color: #006600; font-weight: bold;">}</span><span style="color: #006600; font-weight: bold;">]</span>
  <span style="color: #006600; font-weight: bold;">}</span>
<span style="color: #006600; font-weight: bold;">}</span></pre>
</div>
</div>
<p>The only couple of bits to really worry about are to ensure that you provide just the name of your PDFs, i.e. not the full path (mine were /tmp/cover.pdf) and to set the access type. Supported access levels are ‘private’, ‘public’ (available through search/browse), and ‘direct’.</p>
<p>Hopefully the above layout makes it clear how the JSON will be structured. Obviously at this stage we have a standard Object in Ruby, which we need to convert to a JSON and then send to the Publication <strong>API</strong>:</p>
<div class="wp_syntax">
<div class="code">
<pre class="ruby" style="font-family: monospace;">url = <span style="color: #cc00ff; font-weight: bold;">URI</span>.<span style="color: #9900cc;">parse</span><span style="color: #006600; font-weight: bold;">(</span>LULU_PUBLISH<span style="color: #006600; font-weight: bold;">)</span>
publish_args = <span style="color: #006600; font-weight: bold;">{</span>
  <span style="color: #996600;">'auth_user'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> LULU_AUTH_USER,
  <span style="color: #996600;">'auth_token'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> auth_token,
  <span style="color: #996600;">'project'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> create_input.<span style="color: #9900cc;">to_json,
<span style="color: #000000;"><span style="color: #996600;">  'api_key'</span> <span style="color: #006600; font-weight: bold;">=&gt;</span> LULU_API_KEY <em># note the new API key being sent across</em></span></span>
<span style="color: #006600; font-weight: bold;">}</span>

http = <span style="color: #6666ff; font-weight: bold;">Net::HTTP</span>.<span style="color: #9900cc;">new</span><span style="color: #006600; font-weight: bold;">(</span>url.<span style="color: #9900cc;">host</span>, url.<span style="color: #9900cc;">port</span><span style="color: #006600; font-weight: bold;">)</span>
http.<span style="color: #9900cc;">use_ssl</span> = <span style="color: #0000ff; font-weight: bold;">true</span>
request = <span style="color: #6666ff; font-weight: bold;">Net::HTTP::Post</span>.<span style="color: #9900cc;">new</span><span style="color: #006600; font-weight: bold;">(</span>url.<span style="color: #9900cc;">path</span><span style="color: #006600; font-weight: bold;">)</span>
request.<span style="color: #9900cc;">set_form_data</span><span style="color: #006600; font-weight: bold;">(</span>publish_args<span style="color: #006600; font-weight: bold;">)</span>

response = http.<span style="color: #9900cc;">start</span> <span style="color: #006600; font-weight: bold;">{</span><span style="color: #006600; font-weight: bold;">|</span>http<span style="color: #006600; font-weight: bold;">|</span> http.<span style="color: #9900cc;">request</span><span style="color: #006600; font-weight: bold;">(</span>request<span style="color: #006600; font-weight: bold;">)</span> <span style="color: #006600; font-weight: bold;">}</span>

json = <span style="color: #6666ff; font-weight: bold;">ActiveSupport::JSON</span>.<span style="color: #9900cc;">decode</span><span style="color: #006600; font-weight: bold;">(</span>response.<span style="color: #9900cc;">body</span><span style="color: #006600; font-weight: bold;">)</span>

<span style="color: #9966cc; font-weight: bold;">if</span> json<span style="color: #006600; font-weight: bold;">[</span><span style="color: #996600;">'content_id'</span><span style="color: #006600; font-weight: bold;">]</span>
  <span style="color: #008000; font-style: italic;"># we have a book!</span>
  ... <span style="color: #9900cc;">store</span> the json<span style="color: #006600; font-weight: bold;">[</span><span style="color: #996600;">'content_id'</span><span style="color: #006600; font-weight: bold;">]</span> <span style="color: #9966cc; font-weight: bold;">for</span> reference
<span style="color: #9966cc; font-weight: bold;">else</span>
  <span style="color: #008000; font-style: italic;"># something went wrong</span>
  ... <span style="color: #9900cc;">review</span> output <span style="color: #9966cc; font-weight: bold;">in</span> response.<span style="color: #9900cc;">body</span>
<span style="color: #9966cc; font-weight: bold;">end</span></pre>
</div>
</div>
<h2>That’s it!</h2>
<p>It may look like a lot of code above, but that really is all there is to it. I found the last stage quite fiddly, but it was more to do in terms of getting my PDF to the right DPI and exact sizes etc. You can find some sample PDFs from <a href="http://www.lulu.com/publish/books/?cid=nav_bks" target="_blank">Lulu’s Book Specifications</a> (at the bottom of the page).</p>
<p>Feel free to get in touch if you need any more help getting up and running.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benbarnett.net/2010/05/19/using-ruby-on-rails-and-the-lulu-publication-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
