<?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>isambard &#187; Techniques</title>
	<atom:link href="http://isambard.com.au/blog/category/techniques/feed/" rel="self" type="application/rss+xml" />
	<link>http://isambard.com.au/blog</link>
	<description>musings on information design and architecture</description>
	<lastBuildDate>Sun, 13 May 2012 23:38:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Using Javascript with Sharepoint 2007</title>
		<link>http://isambard.com.au/blog/2012/05/07/using-javascript-with-sharepoint-2007/</link>
		<comments>http://isambard.com.au/blog/2012/05/07/using-javascript-with-sharepoint-2007/#comments</comments>
		<pubDate>Mon, 07 May 2012 05:11:59 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Sharepoint]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=911</guid>
		<description><![CDATA[It&#8217;s relatively simple to include Javascript in your Sharepoint pages. With some judicious editing you can add your code inline or via separate code files. Embedding Javascript To include Javascript in your page: use a Content Editor Webpart (CEWP) edit via the Source Editor button (not Rich Text Editor), and add your code within standard [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s relatively simple to include Javascript in your Sharepoint pages.  With some judicious editing you can add your code inline or via separate code files.</p>
<h2>Embedding Javascript</h2>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/05/code2.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/05/code2-300x212.png" alt="" title="code" width="300" height="212" class="alignright size-medium wp-image-926" /></a>To include Javascript in your page:</p>
<ol>
<li>use a Content Editor Webpart (CEWP)</li>
<li>edit via the <strong>Source Editor</strong> button (not Rich Text Editor), and</li>
<li>add your code within standard <code>&lt;script>&lt;/script></code> tags</li>
</ol>
<p>Within the script block just add your normal code, comments, etc.  The only issue you&#8217;ll have is being able to indent the text and make it look pretty.  Tab doesn&#8217;t help; you&#8217;ll need to use spaces (the horror!).</p>
<blockquote><p>
<a href="http://isambard.com.au/blog/wp-content/uploads/2012/05/editSource.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/05/editSource-300x106.png" alt="" title="editSource" width="300" height="106" class="alignright size-medium wp-image-912" /></a><strong>Don&#8217;t use the Rich Text Editor</strong><br />
Important!  Always use the <strong>Source Editor</strong> function to manipulate your code, or any other content within the same CEWP.  If you use the <strong>Rich Text Editor</strong> at any point it will delete all your script.
</p></blockquote>
<h2>Linking to Javascript source files</h2>
<p>Sometimes your javascript code may be a little too long to embed.  Or, like me, you&#8217;ve been burnt once too often by clicking the Rich Text Editor button by mistake.    At such times you might prefer to link to separate javascript files rather than embedding all directly.</p>
<p>To link to a separate file:</p>
<ol>
<li>save the Javascript content as a separate .JS file and upload to somewhere on your site.  I tend use a /scripts subfolder within the default documents library.
<li>add/edit your CEWP to reference the script file:
</ol>
<pre>
&lt;script type="text/javascript" src="<b>full path to script file</b>">&lt;/script>
</pre>
<p>For example, here&#8217;s a CEWP that includes a separate Javascript file and then references a function (presumably) defined within it.</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/05/codeFile.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/05/codeFile-300x152.png" alt="" title="codeFile" width="300" height="152" class="alignnone size-medium wp-image-922" /></a></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2012%2F05%2F07%2Fusing-javascript-with-sharepoint-2007%2F&amp;title=Using%20Javascript%20with%20Sharepoint%202007" id="wpa2a_2"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2012/05/07/using-javascript-with-sharepoint-2007/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hacked</title>
		<link>http://isambard.com.au/blog/2012/04/12/hacked/</link>
		<comments>http://isambard.com.au/blog/2012/04/12/hacked/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 04:30:08 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=829</guid>
		<description><![CDATA[Just discovered this website had been hacked. First clue was when the site got banned by a corporate web filter as &#8220;adult material&#8221;. Unless someone had posted a particularly vitriolic comment that was unlikely. I won&#8217;t provide any more oxygen to the hackers over what exactly happened, but here&#8217;s the steps taken to get back [...]]]></description>
			<content:encoded><![CDATA[<p>Just discovered this website had been hacked.  First clue was when the site got banned by a corporate web filter as &#8220;adult material&#8221;.  Unless someone had posted a particularly vitriolic comment that was unlikely.</p>
<p>I won&#8217;t provide any more oxygen to the hackers over what exactly happened, but here&#8217;s the steps taken to get back online.  </p>
<h2>(1) Run to Google</h2>
<p>As always, find a friend who&#8217;s been through it before.  In particular these two pages proved useful.</p>
<ul>
<li><a href="http://codex.wordpress.org/FAQ_My_site_was_hacked" target="_blank">http://codex.wordpress.org/FAQ_My_site_was_hacked</a></li>
<li><a href="http://ocaoimh.ie/2008/06/08/did-your-wordpress-site-get-hacked/" target="_blank">http://ocaoimh.ie/2008/06/08/did-your-wordpress-site-get-hacked/</a></li>
</ul>
<p>First steps taken after reading them (and they explain more about each step):</p>
<ul>
<li>change passwords (for both wordpress and mySQL)</li>
<li>setup secret keys and salts</li>
<li>check .htaccess</li>
<li>delete all unused themes</li>
</ul>
<h2>(2) Install the exploit scanner</h2>
<p>There is a plugin available that can help check for suspicious code:</p>
<p><a href="http://ocaoimh.ie/exploit-scanner/" target="_blank">http://ocaoimh.ie/exploit-scanner/</a></p>
<p>Follow the provided instructions to install.  </p>
<p>When I ran the scanner it located dodgy code in a plethora of files.  Comparing those files to a (sadly) old backup I discovered they were not part of the original wordpress installation.  They also, suspiciously, all had an identical and recent install date/time.</p>
<p>Therefore next step was to delete them all.  And that did most of the work.  I got my site back.  Almost&#8230;.</p>
<h2>(3) Fix the theme</h2>
<p>After deleting all the extra files, the site was almost back.  It now did not show the &#8220;you&#8217;ve been hacked page&#8221;.  But instead it showed the contents of my theme&#8217;s CSS file.  Obviously some corruption in there somewhere.  </p>
<p>First step was to temporarily install a basic theme and switched to that.  All worked well and my site was back up and running.  Just ugly(er).  To improve I then deleted the corrupted theme and re-installed from a backup.  And everything was back to normal.</p>
<h2>Conclusion</h2>
<p>Thankfully my intrusion proved quite simple to remove. Whether I removed every element we&#8217;ll find out in the next days as we see how long the site stays up.  However lessons learnt are quite simple:</p>
<ol>
<li>get a recent/regular backup (of content and data).  Having another folder listing what files should be there proved invaluable in quickly deleting what was added.</li>
<li>keep up to date with releases.  </li>
<li>if you&#8217;re site suddenly gets blocked by a web filter, don&#8217;t blame a rude commenter!</li>
</ol>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2012%2F04%2F12%2Fhacked%2F&amp;title=Hacked" id="wpa2a_4"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2012/04/12/hacked/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing a rollout status map using Google Maps</title>
		<link>http://isambard.com.au/blog/2012/02/17/implementing-a-rollout-status-map-using-google-maps/</link>
		<comments>http://isambard.com.au/blog/2012/02/17/implementing-a-rollout-status-map-using-google-maps/#comments</comments>
		<pubDate>Fri, 17 Feb 2012 01:20:07 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[map]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=783</guid>
		<description><![CDATA[If needing to present data that pertains to specific geographic locations, the logical approach is a map. Having just worked with Google Maps, and discovered how easy it is to implement, this article summarises all the key information needed to quickly make a map of your own. After the fun of working out how to [...]]]></description>
			<content:encoded><![CDATA[<p>If needing to present data that pertains to specific geographic locations, the logical approach is a map.  Having just worked with Google Maps, and discovered how easy it is to implement, this article summarises all the key information needed to quickly make a map of your own. </p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/02/end.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/02/end.png" alt="" title="end" width="452" height="383" class="alignnone size-full wp-image-817" /></a><br />
<span id="more-783"></span></p>
<blockquote><p>After the fun of working out how to build these maps by hand, a colleague pointed out that there are online services available that can do all the hard work for you.  One we tried, and recommend, was <a href="http://batchgeo.com/">http://batchgeo.com/</a>.  Worth a look, even if you&#8217;re a masochist and want to go manually.</p></blockquote>
<h2>Getting started</h2>
<p>All the information you need to work with Google Maps is published here:<br />
<a href="http://code.google.com/apis/maps/documentation/javascript/basics.html">http://code.google.com/apis/maps/documentation/javascript/basics.html</a></p>
<p>But all you really need to know for working it into your website is:</p>
<ul>
<li> the API is in Javascript</li>
<li>it works very well with JQuery, and</li>
<li>it&#8217;s free (commercial or otherwise) unless you&#8217;re hitting their server big time.</li>
</ul>
<p>Tempting?  Read on.</p>
<h2>Step 1 &#8211; Drawing a map on your site</h2>
<p>The basic code to include a Google Map on your site is very straightforward.  Start with this template:</p>
<pre>
&lt;html>
&lt;head>>
  &lt;script type="text/javascript"
          src="http://maps.googleapis.com/maps/api/js?sensor=false">
  </&lt;script type="text/javascript">

	function initialize() {
    		var myOptions = {
      		zoom: 5,
      		center: new google.maps.LatLng(-25.363882,131.044922),
      		mapTypeId: google.maps.MapTypeId.ROADMAP
    	}

	var map = new google.maps.Map(document.getElementById("map_canvas"),
                                      myOptions);

	}
  &lt;/script>
&lt;/head>

&lt;body onload="initialize()">
  &lt;div id="map_canvas">&lt;/div>
&lt;/body>
&lt;/html>
</pre>
<p>This will publish a Google Map, centred on Uluru, Australia, and zoomed to show the whole country.  Play with the values in the options set to establish the default map you prefer.</p>
<h2>Working with latitude and longitude</h2>
<p>The centre of your map needs to be a position given in latitude and longitude.  If you don&#8217;t happen to know the figures then there is a way to get them out of Google Maps.</p>
<ol>
<li>Go to the location you want the coordinates for</li>
<li>Right-click on the location and select <strong>What&#8217;s Here</strong> from the menu</li>
</ol>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/02/findCoordinates.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/02/findCoordinates-300x158.png" alt="" title="How to copy latitude and longitude from Google Maps" width="300" height="158" class="alignright size-medium wp-image-788" /></a><br />
The coordinates you require will then appear when you hover over the location on the map.  More usefully, they also are pasted into the search box, from where you can copy&#038;paste them into your code.</p>
<h2>Improvement 1: Adding points of interest</h2>
<p>Each point you want to position on your new map is known as a marker.  </p>
<p><a href="http://code.google.com/apis/maps/documentation/javascript/overlays.html#Markers">http://code.google.com/apis/maps/documentation/javascript/overlays.html#Markers</a></p>
<p>It&#8217;s just one line of code to add one.  Let&#8217;s put one at Mount Isa, near the centre of our new map.</p>
<pre>
var marker = new google.maps.Marker({
	position: new google.maps.LatLng(-20.722481,139.494781),
	map: map,
	title: "Mt Isa"
	});
</pre>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/02/marker1.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/02/marker1-150x150.png" alt="" title="marker1" width="150" height="150" class="alignright size-thumbnail wp-image-791" /></a><br />
The value for <code>map</code> must match the map object you previously created. The marker will then appear at the position you give, with the title appearing on hover.</p>
<p>A fourth option, <code>icon</code> allows you to specify a different icon for your marker to the Google default hot air balloon.  Any image file is satisfactory, but for a decent range of alternatives check out <a href="http://mapicons.nicolasmollet.com/">http://mapicons.nicolasmollet.com/</a>. </p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/02/markerIcon.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/02/markerIcon-150x150.png" alt="" title="markerIcon" width="150" height="150" class="alignright size-thumbnail wp-image-792" /></a><br />
To use, just upload the icon somewhere you can link to it, and add the URL to your marker:</p>
<pre>
var marker = new google.maps.Marker({
	position: new google.maps.LatLng(-20.722481,139.494781),
	map: map,
	title: "Mt Isa",
        <strong>icon: "needsAttention.png"</strong>
	});
</pre>
<h2>Adding a popup window</h2>
<p>The title gives you room for brief information on the location, visible only on mouseover.  For something a little more descriptive you can add a popup window to display when the user clicks on the point.  The window remains in view until the user chooses to close it:</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/02/infoWindow.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/02/infoWindow.png" alt="" title="infoWindow" width="359" height="233" class="alignnone size-full wp-image-800" /></a></p>
<p></a>In Google Maps speak, these are known as <a href="http://code.google.com/apis/maps/documentation/javascript/overlays.html#InfoWindows">InfoWindows</a>.  The key point when working with them is that you first need to create your window&#8217;s content (any valid HTML will do), and then you create the link so that the window appears when the user clicks on your marker.</p>
<pre>
	var info = "&lt;p>Here's some extra information&#038;lt/br />over two lines.&lt;/p>";
	google.maps.event.addListener(marker,'click', function() {
		infowindow = new google.maps.InfoWindow({content: info});
		infowindow.open(map, marker);
		});
</pre>
<p>Tips:</p>
<ul>
<li>The <code>marker</code> in the final line must match the variable name for the marker you&#8217;re connecting to.</li>
<li>You can use any styling/layout tricks you want to make the popup look prettier.</li>
<li>Google will try and size it for you automagically, unless you force specific sizing.</li>
</ul>
<h2>Scaling for multiple points</h2>
<p>The code so far is great for just a few points, but soon becomes painful with any reasonable number. Moreso if the information you want to present needs to change (e.g. a status message for each location is updated regularly).</p>
<p>So for the final version we&#8217;ll start leveraging JQuery and JSON to generate our markers from a separate list.  For now we&#8217;ll keep that list in the same file, but it&#8217;s relatively simple to integrate via a different file or format.</p>
<p>First the data.  Obviously this can be any values that you want to present, just ensure each record has the same structure.</p>
<pre>
var branches =
[
	{
	"title":	"Uluru",
	"position":	[-25.363882,131.044922],
	"deploymentDate": "23 April 2012",
	"trainingDate": "13 March 2012",
	"status": "Not Started"
	},
	{
	"title":	"Alice Springs",
	"position":	[-23.700651,133.880038],
	"deploymentDate": "23 April 2012",
	"trainingDate": "13 March 2012",
	"status": "On Schedule"
	},
	{
	"title":	"Avalon Beach",
	"position":	[-33.636248,151.329197],
	"deploymentDate": "23 April 2012",
	"trainingDate": "13 March 2012",
	"status": "Needs Attention"
	},
	{
	"title":	"Kent St",
	"position":	[-33.866229,151.204190],
	"deploymentDate": "23 April 2012",
	"trainingDate": "13 March 2012",
	"status": "Not Started"
	}
]
</pre>
<p>Now the JQuery to loop through our data and add the markers:</p>
<pre>
$(branches).each(function() {
	var branch = this;
	var title = branch.title + ": " + branch.status;

//create the marker
	var marker = new google.maps.Marker({
		position: new google.maps.LatLng(branch.position[0], branch.position[1]),
		map: map,
		title: title,
		});

//create the infoWindow
	var info = "&lt;h2>" + branch.title + "&lt;/h2>";
	info += "&lt;p>training date: " + branch.trainingDate;
	info += "&lt;br />deployment date: " + branch.deploymentDate + "&lt;/p>";
	info += "&lt;p>status: &lt;b>" + branch.status + "&lt;/b>&lt;/p>";

//link marker to infoWindow
	google.maps.event.addListener(marker,'click', function() {
		infowindow = new google.maps.InfoWindow({content: info});
		infowindow.open(map, marker);
		});
});
</pre>
<p>Add this and the data into your initialise method.  And remember to include the JQuery script reference in your <code>head</code>.</p>
<h2>side note &#8211; How to publish this map in Sharepoint?</h2>
<p>Adding this content to Sharepoint is complex because of the need to include the separate Javascript libraries.  As a result the simplest approach is to use an iframe. Build your map as a standalone webpage, then embed it via an iframe defined within a Content Editor Webpart.</p>
<h2>Conclusion</h2>
<p>As you can see it&#8217;s reasonably simple to embed a smart map on your site that identifies and describes points of interest to your users.</p>
<p>If you want to try for yourself, here are some sample files to get you going:</p>
<ul>
<li><a href='http://isambard.com.au/blog/wp-content/uploads/2012/02/simple.zip'>simple/manual</a> (1 marker, 1 window) &#8211; good template if only a small number of locations</li>
<li><a href='http://isambard.com.au/blog/wp-content/uploads/2012/02/multipoint.zip'>multipoint</a> (uses jQuery/JSON approach as described) &#8211; best if wanting to map too many points to manage manually.</li>
</ul>
<blockquote><p>
If using the multipoint template, one &#8220;exercise for the reader&#8221; is to make it so that if a user has one infoWindow open, selecting a different point automatically closes the currently open window before opening the new one.  Currently this code allows the user to open multiple windows simultaneously.
</p></blockquote>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2012%2F02%2F17%2Fimplementing-a-rollout-status-map-using-google-maps%2F&amp;title=Implementing%20a%20rollout%20status%20map%20using%20Google%20Maps" id="wpa2a_6"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2012/02/17/implementing-a-rollout-status-map-using-google-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UI Rule #92 &#8211; Don&#8217;t sacrifice the useful to fit your design</title>
		<link>http://isambard.com.au/blog/2012/01/30/ui-rule-92-dont-sacrifice-the-useful-information-to-fit-your-design/</link>
		<comments>http://isambard.com.au/blog/2012/01/30/ui-rule-92-dont-sacrifice-the-useful-information-to-fit-your-design/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 04:15:58 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=774</guid>
		<description><![CDATA[Everybody needs a lego moleskine. Comparison shopping at the UK Book Depository proved troublesome because they decided to cut the product title short, removing the information that actually differentiated the products being chosen: Hard to tell which one to choose when everything you want to know about the choices is unavailable. Should I get the [...]]]></description>
			<content:encoded><![CDATA[<p>Everybody needs a lego moleskine.  Comparison shopping at the <a href="http://www.bookdepository.co.uk/search?searchTerm=lego+moleskine&#038;search=search">UK Book Depository</a> proved troublesome because they decided to cut the product title short, removing the information that actually differentiated the products being chosen:</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/01/bookDepository.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/01/bookDepository.png" alt="" title="bookDepository" width="766" height="659" class="alignleft size-full wp-image-775" /></a></p>
<p>Hard to tell which one to choose when everything you want to know about the choices is unavailable. Should I get the &#8220;Lego Y..&#8221; or, mmmmm, the other &#8220;Lego Y..&#8221;?</p>
<p>Compare to Amazon, who manage to fit the full name in without issue:</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2012/01/amazon.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2012/01/amazon.png" alt="" title="amazon" width="785" height="401" class="alignleft size-full wp-image-776" /></a></p>
<p>If you&#8217;re going to allow a certain number of characters for a value, assume all of those characters may be important at some point.  And make sure somewhere on your interface you let them all get their moment in the sun.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2012%2F01%2F30%2Fui-rule-92-dont-sacrifice-the-useful-information-to-fit-your-design%2F&amp;title=UI%20Rule%20%2392%20%E2%80%93%20Don%E2%80%99t%20sacrifice%20the%20useful%20to%20fit%20your%20design" id="wpa2a_8"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2012/01/30/ui-rule-92-dont-sacrifice-the-useful-information-to-fit-your-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Want your iPad calendar to start the week on Monday?  Move to Namibia</title>
		<link>http://isambard.com.au/blog/2012/01/25/want-your-ipad-calendar-to-start-the-week-on-monday-move-to-namibia/</link>
		<comments>http://isambard.com.au/blog/2012/01/25/want-your-ipad-calendar-to-start-the-week-on-monday-move-to-namibia/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 01:49:58 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[iPad]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=769</guid>
		<description><![CDATA[Frustratingly, my iPad calendar appeared to unilaterally decide that the first day of the week was Sunday. And there was no obvious setting to change it, like there is for Calendar on the Mac. Turns out this &#8220;feature&#8221; is decided by Apple based on your region. They believe Australian weeks start on Sunday so that&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Frustratingly, my iPad calendar appeared to unilaterally decide that the first day of the week was Sunday.  And there was no obvious setting to change it, like there is for Calendar on the Mac.</p>
<p>Turns out this &#8220;feature&#8221; is decided by Apple based on your region.  They believe Australian weeks start on Sunday so that&#8217;s the way it is.  To change the day, change your region.</p>
<p>For Australians wanting their calendar to start on a Monday:</p>
<ol>
<li>Launch settings</li>
<li>Select General > International</li>
<li>change region format to Namibia</li>
</ol>
<p>This bizarre choice seems to have the best option for calendar setting, as well as changes it makes to keyboards (what currency symbol you see), date and time formats, even which google you default to when you search.  Namibia appears to leave all the other settings &#8220;just like Australia&#8221;, and still default to google.com.au for searching in Safari.</p>
<p>Thanks to the clever chaps on the <a href="http://forums.whirlpool.net.au/archive/1793827">Whirlpool forums</a>, particularly dokh22, for uncovering this.  Now how long before Apple gives us a calendar setting to do it properly?</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2012%2F01%2F25%2Fwant-your-ipad-calendar-to-start-the-week-on-monday-move-to-namibia%2F&amp;title=Want%20your%20iPad%20calendar%20to%20start%20the%20week%20on%20Monday%3F%20%20Move%20to%20Namibia" id="wpa2a_10"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2012/01/25/want-your-ipad-calendar-to-start-the-week-on-monday-move-to-namibia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple image (frame-by-frame) animation in IOS and Xcode</title>
		<link>http://isambard.com.au/blog/2011/11/05/simple-image-animation-in-ios-and-xcode/</link>
		<comments>http://isambard.com.au/blog/2011/11/05/simple-image-animation-in-ios-and-xcode/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 02:19:32 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=720</guid>
		<description><![CDATA[Adding frame-by-frame animations to your iOS application is simple once you find out that a UIImageView can be initialised with an array of images, not just one image. This post was inspired by a colleague who had not uncovered that fact, and so had spent time arduously linking separate views with timers. This post shows [...]]]></description>
			<content:encoded><![CDATA[<p>Adding frame-by-frame animations to your iOS application is simple once you find out that a UIImageView can be initialised with an array of images, not just one image. </p>
<p>This post was inspired by a colleague who had not uncovered that fact, and so had spent time arduously linking separate views with timers.  This post shows how to use a single view and 3 lines of animation code to do all the work.</p>
<h2>What to do?</h2>
<p>What we&#8217;ll do as a test is animate the blinking eyes on a tennis-playing ninja splash screen.  To trigger the animation will add a &#8220;blink&#8221; button on the same screen.</p>
<p>Don&#8217;t ask how we ended up with that as the example (thanks to the friend).  But you can download the entire project, or just the images if wanting to join in.<br />
<span id="more-720"></span></p>
<ul>
<li><a href='http://isambard.com.au/blog/wp-content/uploads/2011/11/ninjaProject.zip'>download the project</a></li>
<li><a href='http://isambard.com.au/blog/wp-content/uploads/2011/11/ninjaImages.zip'>download the images</a></li>
</ul>
<p>The steps:</p>
<ol>
<li>prepare the images</li>
<li>create the project</li>
<li>create/update a XIB with the image and button</li>
<li>add the animation code and link to the same image and button</li>
</ol>
<blockquote><p>
All the neat animation stuff is described in the 4th step, so feel free to scroll straight to it.  The previous three steps cover all that&#8217;s needed to get your project ready to animate.  I&#8217;ve included it because I hate reading articles  that assume you&#8217;ve covered all the basics already.  Or worse just dismiss it with one line (first step, invent time travel).
</p></blockquote>
<p>Note this process was captured in xCode4/IOS5.  None of the code in here has changed much in recent releases but you may have to adjust some of the steps if running an earlier setup (one thing that has changed in this version is the options when creating a project).</p>
<h2>(1) prepare the images</h2>
<p>Your imagery is limited only by your artistic talents, or abilities to search Google Images or Flickr (remember to honour their copyright, boys and girls).  </p>
<p>Only suggestion is to limit the animation element to the smallest possible; keeps sizes small.  For example, for the blinking ninja, instead of 3 different ninjas with different eye positions (open, half closed, closed), I created one ninja with no eyes, and then three images of just the different eyes.  What we&#8217;ll do in the project is then add the main ninja as one image view, and put the eyes over the top in a separate image.</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/ninja-AllImages.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/ninja-AllImages.png" alt="" title="ninja-AllImages" width="362" height="339" class="aligncenter size-full wp-image-747" /></a></p>
<p>Whatever approach you take, ensure all the images that will be animated are the same size.  This will ensure when animated they appear over each other.</p>
<h2>create the project</h2>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/10/project-01-create.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/10/project-01-create-300x200.png" alt="" title="project-01-create" width="300" height="200" class="alignright size-medium wp-image-729" /></a><br />
Crack open Xcode and choose <strong>File > New Project</strong>.  I&#8217;m in the latest and greatest (4.2) so your options may vary, but for this version:</p>
<ul>
<li>choose <strong>Single View Application</strong></li>
<li>choose not to use storyboard (so we get a XIB to mess with)</li>
</ul>
<p>Once created we have a simple project containing the key source files:</p>
<ul>
<li>appDelegate.h</li>
<li>appDelegate.m</li>
<li>ViewController.h</li>
<li>ViewController.m</li>
<li>ViewController.xib</li>
</ul>
<blockquote><p>The good news is we&#8217;re only going to be editing the three ViewController files.  Which means you can pretty much follow all of these steps to add an animation to an existing view within your current application;  just join in from the next step.</p></blockquote>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/10/project-02-addFiles.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/10/project-02-addFiles-269x300.png" alt="" title="project-02-addFiles" width="269" height="300" class="alignright size-medium wp-image-736" /></a>Now add your animation images to the project.  Either right-click in the folder view and select <strong>Add Files To..</strong>, or choose <strong>File > Add Files To..</strong> from the menu.</p>
<h2>(2) create/update XIB with the image and button</h2>
<p>Our XIB has already been created in the project.  What to do now is setup the images and buttons we meed, including the outlets needed so we can communicate with them from our code.</p>
<p>Firstly the images.  Remember we need to add two:  1 as the background (which we don&#8217;t need to interact with) and one for the animated eyes (which we will need to talk to).</p>
<p>To hook things up let&#8217;s create the outlets first, and then link in the XIB. Open ViewController.h and add our definition (new text in bold):</p>
<pre>
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    <strong>IBOutlet UIImageView *eyesImage;</strong>
    <strong>IBOutlet UIButton *blinkButton;</strong>
}

<strong>@property (nonatomic, retain) IBOutlet UIImageView *eyesImage;</strong>
<strong>@property (nonatomic, retain) IBOutlet UIButton *blinkButton;</strong>

@end;
</pre>
<p>Then switch over to ViewController.m (tip: 3 fingers down gesture if using a trackpad) and synthesize them:</p>
<pre>
@import "ViewController.h"

@implementation ViewController

<strong>@synthesize eyesImage;</strong>
<strong>@synthesize blinkButton;</strong>
</pre>
<p>Remember if we create them, we should also destroy them:</p>
<pre>
- (void)viewDidUnload
{
    [superviewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    <strong>self.eyesImage = nil;</strong>
    <strong>self.blinkButton = nil;</strong>
}
</pre>
<p>That gives us our outlets so we can link to, and manipulate these items on our XIB.  Note we don&#8217;t currently need to manipulate the button but the outlet is there just in case (for example if needing to disable the button at some point).</p>
<p>The only other item to add in the code before we edit the XIB is the method to be called when we click the button.</p>
<p>Back into viewController.h and add the definition:</p>
<pre>
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    IBOutlet UIImageView *eyesImage;
    IBOutlet UIButton *blinkButton;
}

@property (nonatomic, retain) IBOutlet UIImageView *eyesImage;
@property (nonatomic, retain) IBOutlet UIButton *blinkButton;

<strong>- (IBAction) blink;</strong>

@end;
</pre>
<p>And then back to ViewController.m, and insert the method somewhere in the list:</p>
<pre><strong>
- (IBAction) blink {
  //blink
}
</strong></pre>
<p>Save the files and we&#8217;re ready to connect them to elements in the XIB.</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/imageView.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/imageView-300x113.png" alt="" title="imageView" width="300" height="113" class="alignright size-medium wp-image-746" /></a><br />
Firstly open the XIB and drag an imageView onto the work area.<br />
Set the size and content to be our background/static image for the animation.    Don&#8217;t worry with any outlets as we never need to talk to this image.</p>
<p>Now add a 2nd image view to the work area.  Set its position and size to match where the animation is to be presented.  If it helps you with positioning, set the default image to the first of your animation frames.</p>
<p>Once the animated image view is in place, hook up the outlet.  We need to link this to our eyesImage outlet so we can manipulate it.  Just select the Outlets panel for the view, click in the circle for Referencing Outlet and then drag to File&#8217;s Owner on the left side of the work area.  if all has worked you&#8217;ll then get a dropdown list in which you can select eyesImage.  Once selected your outlet will be added.</p>
<p>That&#8217;s all you need to do for the animation.  Now for the button.</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/button.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/button-300x109.png" alt="" title="button" width="300" height="109" class="alignright size-medium wp-image-763" /></a>Drag a Round Rect Button onto the work area and position somewhere appropriate.  Then add a suitable label (&#8220;blink&#8221; comes to mind).  View the Outlets panel for the button and drag from the Referencing Outlet to File&#8217;s Owner (as we did for the image) and select the blinkButton outlet.  And then, to link to our blink method, drag from the TouchUpInside outlet to the same File&#8217;s Owner.  If all has worked you&#8217;ll then be able to select <code>blink</code> and connect it up.</p>
<p>So that&#8217;s all the XIB sorted.  We&#8217;ve got a background/static image.  We&#8217;ve got a smaller image with an eyesImage outlet for the animation.  And we&#8217;ve got a button that when clicked will trigger our <code>blink()</code> method.  Only one step to go.</p>
<table width="100%">
<tr>
<td valign=top><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/imageOutlets2.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/imageOutlets2-198x300.png" alt="" title="imageOutlets" width="198" height="300" class="alignnone size-medium wp-image-760" /></a></td>
<td valign=top><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/buttonOutlets.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/buttonOutlets-187x300.png" alt="" title="buttonOutlets" width="187" height="300" class="alignnone size-medium wp-image-760" /></a></td>
</tr>
</table>
<p>Save your XIB and then run your project.  You won&#8217;t see anything moving but at least your background image should be in view.</p>
<h2>add the animation code and link to the image and button</h2>
<p>Now for the fun part.</p>
<p>To animate an image we load up the image view with an array of images, set some parameters for how fast and how long the animation runs, and then start it off.  For efficiency we&#8217;ll put all the animation setup into <code>viewDidLoad</code> (so done once when the view first appears), and then just trigger the animation each time we click the button.</p>
<p>So back into viewController.m, let&#8217;s first setup the animation:</p>
<pre>
- (void)viewDidLoad
{
    [superviewDidLoad];
    
        <strong>
       //setup animation
    NSArray *eyeFrames = [NSArrayarray];
    eyeFrames = [[NSArrayalloc] initWithObjects:
                 [UIImageimageNamed:@"eyes1-open.png"],
                 [UIImageimageNamed:@"eyes2-half.png"],
                 [UIImageimageNamed:@"eyes3-closed.png"],
                 nil];
    eyesImage.animationImages = eyeFrames;
    eyesImage.animationDuration = 0.25;
    eyesImage.animationRepeatCount = 1;
    [eyeFrames release];   
    </strong>

}
</pre>
<p>We&#8217;ve added an array of three images to our eyesImage outlet. The animation will take a quarter of a second and will only run once.  Once implemented you&#8217;ll return to these settings (often!) to get the appearance just right.</p>
<p>Once setup, triggering it is just one line of code:</p>
<pre>
- (void) blink {
    <strong>[eyesImage startAnimating];</strong>
}
</pre>
<p>Save and run your project. Then everytime you click the button, magic happens.</p>
<h2>Conclusion</h2>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/11/finished.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/11/finished-159x300.png" alt="" title="finished" width="159" height="300" class="alignright size-medium wp-image-761" /></a> While it took a while to get there, animating our image took only 7 lines of code.  Armed with that code you are limited by only your graphical capabilities.  Just build your images, repeat the 7 lines, and then spend an age tweaking the duration to get it looking right.  </p>
<p>After a while you may find this approach a bit too limited as it scrolls through the image frames at a regular pace.  If wanting a bit more control over the animation  pace, then you&#8217;ll need to step up and start using proper animation blocks.  Next time.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2011%2F11%2F05%2Fsimple-image-animation-in-ios-and-xcode%2F&amp;title=Simple%20image%20%28frame-by-frame%29%20animation%20in%20IOS%20and%20Xcode" id="wpa2a_12"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2011/11/05/simple-image-animation-in-ios-and-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IOS5 &#8211; Wireless sync is the gravy</title>
		<link>http://isambard.com.au/blog/2011/10/28/ios5-wireless-sync-is-the-gravy/</link>
		<comments>http://isambard.com.au/blog/2011/10/28/ios5-wireless-sync-is-the-gravy/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 03:10:57 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[iPad]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=733</guid>
		<description><![CDATA[Finally managed to download and install the IOS5 update for the iPad. Most of the new features are unobtrusive, although still trying to find some of them. However what wins is the wireless synchronisation feature. Now I can update my library (songs, books, tv) on my computer and click Sync. And the iPad gets updated [...]]]></description>
			<content:encoded><![CDATA[<p>Finally managed to download and install the IOS5 update for the iPad.  Most of the new features are unobtrusive, although still trying to find some of them.</p>
<p>However what wins is the wireless synchronisation feature.  Now I can update my library (songs, books, tv) on my computer and click Sync.  And the iPad gets updated while not connected.  While not even switched on.  While in my briefcase in another room.  </p>
<p>Sweet.</p>
<p>[Although I'll admit it's probably sweet because Apple kept us tethered for far too long!]</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2011%2F10%2F28%2Fios5-wireless-sync-is-the-gravy%2F&amp;title=IOS5%20%E2%80%93%20Wireless%20sync%20is%20the%20gravy" id="wpa2a_14"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2011/10/28/ios5-wireless-sync-is-the-gravy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to improve UPK: bonus item</title>
		<link>http://isambard.com.au/blog/2011/06/27/how-to-improve-upk-bonus-item/</link>
		<comments>http://isambard.com.au/blog/2011/06/27/how-to-improve-upk-bonus-item/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 06:14:27 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[UPK]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=698</guid>
		<description><![CDATA[I&#8217;m in the midst of collating a series of issues/quirks with UPK 3.6.1, hoping that Oracle are listening. While organising here&#8217;s a bonus item. When I&#8217;m editing frame properties, don&#8217;t present a tooltip that has the unerring habit of appearing directly over the top of where I&#8217;m trying to type!! B!@#y annoying.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m in the midst of collating a series of issues/quirks with UPK 3.6.1, hoping that Oracle are listening.  While organising here&#8217;s a bonus item.</p>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/06/UPK-Fix-26-kill-tooltip.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/06/UPK-Fix-26-kill-tooltip.png" alt="" title="UPK-Fix-26-kill-tooltip" width="248" height="155" class="aligncenter size-full wp-image-700" /></a></p>
<p>When I&#8217;m editing frame properties, don&#8217;t present a tooltip that has the unerring habit of appearing directly over the top of where I&#8217;m trying to type!!  B!@#y annoying.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2011%2F06%2F27%2Fhow-to-improve-upk-bonus-item%2F&amp;title=How%20to%20improve%20UPK%3A%20bonus%20item" id="wpa2a_16"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2011/06/27/how-to-improve-upk-bonus-item/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sharing a Calendar in Sharepoint 2007 &#8211; Part II</title>
		<link>http://isambard.com.au/blog/2011/05/19/sharing-a-calendar-in-sharepoint-2007-part-ii/</link>
		<comments>http://isambard.com.au/blog/2011/05/19/sharing-a-calendar-in-sharepoint-2007-part-ii/#comments</comments>
		<pubDate>Thu, 19 May 2011 04:45:25 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[interface design]]></category>
		<category><![CDATA[Sharepoint]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=653</guid>
		<description><![CDATA[Earlier I wrote about how you can use XML+XSL to get around the limitation in Sharepoint 2007 of sharing calendars across multiple sites. This technique stores your events as XML and allows you to publish entries wherever and however you wish. This article expands that earlier introduction with some tips and tricks we collating when [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://isambard.com.au/blog/2011/01/10/sharing-a-calendar-in-sharepoint-2007/">Earlier</a> I wrote about how you can use XML+XSL to get around the limitation in Sharepoint 2007 of sharing calendars across multiple sites.  This technique stores your events as XML and allows you to publish entries wherever and however you wish.</p>
<p>This article expands that earlier introduction with some tips and tricks we collating when implementing this for one client:</p>
<ul>
<li>working outside Sharepoint</li>
<li>presenting a URL</li>
<li>sorting items</li>
<li>grouping items</li>
<li>showing a message if a filter set is empty</li>
</ul>
<p>Note:  You can <a href="http://isambard.com.au/blog/wp-content/uploads/2011/05/calendar-v2.zip">download sample XML and XSL</a> here.  These files show all the techniques described in this article.</p>
<table>
<tbody>
<tr>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-xml.png"><img class="alignnone size-thumbnail wp-image-660" title="image-xml" src="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-xml-150x150.png" alt="" width="150" height="150" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-filter.png"><img class="alignnone size-thumbnail wp-image-661" title="image-filter" src="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-filter-150x150.png" alt="" width="150" height="150" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-group.png"><img class="alignnone size-thumbnail wp-image-662" title="image-group" src="http://isambard.com.au/blog/wp-content/uploads/2011/05/image-group-150x150.png" alt="" width="150" height="150" /></a></td>
</tr>
<tr>
<td>the original XML</td>
<td>filtered view</td>
<td>grouped view</td>
</tr>
</tbody>
</table>
<p><span id="more-653"></span></p>
<h2>Working outside SharePoint</h2>
<p>It can be painful to develop your XML/XSL solution in Sharepoint because of the need to upload new versions (or edit webparts), then refresh to see the results, or lack thereof.  Easier to work outside and just upload when done.</p>
<p>To link your XML and XSL outside SharePoint edit your XML file to include a link to your XSL file:</p>
<pre>&lt;!--?xml version="1.0" encoding="utf-8"?--&gt;
<strong>&lt;!--?xml-stylesheet type="text/xsl" href="calendar.xsl"?--&gt;</strong>
....</pre>
<p>Now when you open your XML file in a browser it will use your XSL to present.</p>
<p>Save your XLS as a file with a name to match the XML link and you&#8217;re nearly there.  The only other change you may need to make is to extend your XSL so it generates a full webpage, not just a fragment.</p>
<p>For example our standard calendar presentation XSL generates a paragraph:</p>
<pre>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
&lt;xsl:template match="calendar"&gt;
&lt;p&gt;
&lt;xsl:for-each select="event[program='Leadership Foundations']"&gt;
...
&lt;/xsl:for-each&gt;
&lt;/p&gt;
&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</pre>
<p>To work outside SharePoint it needs to generate a proper page; make it do so by simply adding HTML and BODY tags:</p>
<pre>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
&lt;xsl:template match="calendar"&gt;
<strong>&lt;html&gt;</strong>
<strong>&lt;body&gt;</strong>
&lt;p&gt;
&lt;xsl:for-each select="event[program='Leadership Foundations']"&gt;
...
&lt;/xsl:for-each&gt;
&lt;/p&gt;
<strong>&lt;body&gt;</strong>
<strong>&lt;html&gt;</strong>
&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</pre>
<p>Just remember to remove these bonus lines when re-inserting into your SharePoint site.</p>
<h2>Presenting a URL</h2>
<p>If one element you&#8217;re recorded in your XML is a URL then chances are you&#8217;ll want to use XSL to convert that into a link.  And the obvious approach you&#8217;d think would be the simplest:</p>
<pre>&lt;a href='&lt;xsl:value-of select="link"&gt;'&gt;link text&lt;/a&gt;</pre>
<p>Other than the issue over nested quotes, all looks pretty straightforward.  Except it doesn&#8217;t work.</p>
<p>The solution is to use a different format for the URL selection:</p>
<pre>&lt;a href="{link}"&gt;link text&lt;/a&gt;</pre>
<p>Now it works fine.</p>
<h2>Sorting items</h2>
<p>One feature we wanted to implement was the automatic sorting of results.  This meant anyone maintaining the master XML list did not need to worry about where to add individual items to preserve their order.  They could just add anywhere in the file and be confident they&#8217;d appear in the correct sequence when displayed.</p>
<p>To sort results, add the <code>&lt;xsl:sort&gt;</code> command as the first element within your  loop. For example to sort by a date element:</p>
<pre>&lt;xsl:for-each select="event"&gt;
    &lt;xsl:sort select="date" /&gt;
    ...
&lt;/xsl:for-each&gt;</pre>
<p>Check <a href="www.w3schools.com/xsl/el_sort.asp">W3Schools</a> if wanting to do something more complicated than an ascending text order.</p>
<p>As you can see from this example, what we were wanting to search on were dates.  And early on we&#8217;d decided that users would enter dates in &#8220;human&#8221; format (ie &#8217;23 May 2011&#8243;, not 20110523).   One issue we had on sorting dates was the chestnut of how to sort &#8220;2 May 2011&#8243; to appear before &#8220;15 May 2011&#8243;.  Our solution was to require all dates in the XML to be two characters (&#8220;02 May 2011&#8243; not &#8220;2 May 2011&#8243;) and then use XSL to remove the ugly leading zero when displayed.  The code to remove that zero is straightforward:</p>
<pre>&lt;xsl:choose&gt;
    &lt;xsl:when test="substring(date,1,1)=0"&gt;
         &lt;xsl:value-of select="substring(date,2)" /&gt;
    &lt;xsl:otherwise&gt;
&lt;/xsl:choose&gt;</pre>
<p>You have to use the <code>&lt;xsl:choose&gt;</code> construct because while XSL does have an IF statement (not surprisingly <code>&lt;xsl:if&gt;</code>), it does not have an equivalent ELSE.</p>
<p>Note:  The alternative would be to define the date in a nice sortable format (I vote for YYYYMMDD).  And then use similar XSL transformations to present in a more readable format.  Either way you&#8217;re putting some overhead on the user.  We stuck with this simple approach because it was (a) less user effort and (b) allowed a wider range of dates to be acceptable.  For example we had some programs that only specified a month.  Sorting this way meant we could accept &#8220;May 2011&#8243; as a valid date.</p>
<h2>Grouping items</h2>
<p>Now this I thought would be easy. Since we&#8217;re working on a calendar, let&#8217;s group entries according to the month.  ie:</p>
<p>April 2011<br />
- This course (12 April, London)<br />
- That course (19 April, Helsinki)<br />
May 2011<br />
- That course (2 May, Romford)<br />
- The other course (30 May, Malaka)</p>
<p>After several false starts, all roads do eventually lead to a fabled Meunchian method.  Trouble is, even after building it, I&#8217;ve no idea how it works.  Of all the articles uncovered to try and explain it, <a href="docstore.mik.ua/orelly/xml/xslt/ch06_02.htm">this one came closest</a>.  Cut&amp;paste their approach (or <a href="http://isambard.com.au/blog/wp-content/uploads/2011/05/calendar-v2.zip">our example</a> using it) and you should be able to get it to work.</p>
<h2>Showing a message if the filter set is empty</h2>
<p>In the <a href="http://isambard.com.au/blog/2011/01/10/sharing-a-calendar-in-sharepoint-2007/">first article</a> we covered how simple it is to present a subset of your entries. However once implemented we discovered we needed to address the situation where a subset was empty.  Rather than just showing a blank list we wanted to show a messsage directing the visitor to other sources.</p>
<p>Simplest way to implement this is to repeat the same filter query used to generate the subset. Just place within a COUNT() and use as a test:</p>
<pre>&lt;xsl:choose&gt;
     &lt;xsl:when test="count(event[program='First Program']) &gt; 0"&gt;

          &lt;xsl:for-each select="event[program='First Program']"&gt;
          ...
          &lt;/xsl:for-each&gt;

     &lt;/xsl:when&gt;
     &lt;xsl:otherwise&gt;
          &lt;xsl:text&gt;No events recorded for this program.&lt;/xsl:text&gt;
     &lt;/xsl:otherwise&gt;
&lt;/xsl:choose&gt;</pre>
<p>Only potential issue may be around your formatting.  Be mindful of where your layout tags appear depending on which data is presented.</p>
<h2>Conclusion</h2>
<p>With just these techniques you can present and manipulate your content in quite ingenious ways.  Just good luck trying to understand the Muench.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2011%2F05%2F19%2Fsharing-a-calendar-in-sharepoint-2007-part-ii%2F&amp;title=Sharing%20a%20Calendar%20in%20Sharepoint%202007%20%E2%80%93%20Part%20II" id="wpa2a_18"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2011/05/19/sharing-a-calendar-in-sharepoint-2007-part-ii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding a table of contents to your ePUB</title>
		<link>http://isambard.com.au/blog/2011/04/12/adding-a-table-of-contents-to-your-epub/</link>
		<comments>http://isambard.com.au/blog/2011/04/12/adding-a-table-of-contents-to-your-epub/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 04:18:30 +0000</pubDate>
		<dc:creator>steven</dc:creator>
				<category><![CDATA[Techniques]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[ePub]]></category>
		<category><![CDATA[iBooks]]></category>
		<category><![CDATA[technical writing]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://isambard.com.au/blog/?p=834</guid>
		<description><![CDATA[With ePUBs it is straightforward to add a table of contents to your book, allowing your readers to quickly navigate within your content. Interestingly how you do it is not a part of the ePUB specification itself, but highlights ePUB&#8217;s development from earlier digital book initiatives. This article assumes you are creating/editing your ePUB source [...]]]></description>
			<content:encoded><![CDATA[<p>With ePUBs it is straightforward to add a table of contents to your book, allowing your readers to quickly navigate within your content. Interestingly how you do it is not a part of the ePUB specification itself, but highlights ePUB&#8217;s development from earlier digital book initiatives.</p>
<p>This article assumes you are creating/editing your ePUB source content directly.  If generating an ePUB via a development tool (eg Pages, InDesign) then it can automatically generate the TOC for you.  However even if doing so this article will help describe what is being built for you.</p>
<blockquote><p>
To help, I&#8217;ve included a smorgasbord of sample ePUBs to demonstrate how tables of contents are included.  There&#8217;s a <a href='http://isambard.com.au/blog/wp-content/uploads/2012/04/BasicBook.epub_.zip'>basic book</a> (single level/standard TOC) as well as books with <a href="http://isambard.com.au/blog/wp-content/uploads/2012/04/2LevelTOC.epub_.zip">2</a>, <a href="http://isambard.com.au/blog/wp-content/uploads/2012/04/3LevelTOC.epub_.zip">3</a>, <a href="http://isambard.com.au/blog/wp-content/uploads/2012/04/4LevelTOC.epub_.zip">4</a>, or <a href="http://isambard.com.au/blog/wp-content/uploads/2012/0452LevelTOC.epub_.zip">5 level TOCs</a>.<br />
Download the one you want or take the <a href="http://isambard.com.au/blog/wp-content/uploads/2012/04/FiveTestBooks.zip" target="_blank">whole pack</a>. Note that because WordPress considers EPUBs a security risk, they&#8217;ve all be zipped.
</p></blockquote>
<h2>Do I need to do this?</h2>
<p><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/contents-ade.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/contents-ade.png" alt="" title="contents-ade" width="274" height="271" class="alignright size-full wp-image-857" /></a>A table of contents is optional (your ePUB is valid and usable without one).  What&#8217;s more how it actually presents for your readers is dependent on the reader.  As such you should decide for each book, and your target market, whether worth the development effort.</p>
<h2>How do I do this?</h2>
<p>Adding a table of contents to your ePUB has two key steps:</p>
<ol>
<li>Creating a valid .NCX file</li>
<li>Including the .NCX file in your book</li>
</ol>
<p>Let&#8217;s work through these steps in turn.</p>
<h2>Creating a valid .NCX file</h2>
<p>The .NCX file defines your table of contents.  There&#8217;s no rule about what filename to give it, but the default option for most eBooks appears to be TOC.NCX.  So we&#8217;ll assume we&#8217;ve called it that too.</p>
<p>The definition for your TOC.NCX file is not part of the ePUB specification but is instead maintained by the DAISY Consortium and co-opted by <a href="http://idpf.org/">IPDF</a> who manage ePUBs for us.  Browse the <a href="http://www.niso.org/workrooms/daisy/Z39-86-2005.html#NCX">detailed specification</a> and see if you can find out what NCX stands for.</p>
<p>In essence an .NCX file is an XML file. It lists the elements for your table of contents within a simple and standard framework:</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE ncx
  PUBLIC "-//NISO//DTD ncx 2005-1//EN"
  "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
&lt;head>
	-- insert required metadata
&lt;/head>
&lt;docTitle>&lt;text>DOCTITLE&lt;/text>&lt;/docTitle>
&lt;docAuthor>&lt;text>DOCAUTHOR&lt;/text>&lt;/docAuthor>
&lt;navMap>
	-- insert required navigation structure
&lt;/navMap>
&lt;/ncx>
</pre>
<p>Copy that and use as the basis for your TOC.NCX, while we fill in the missing bits: metadata, title, author, navigation structure.</p>
<h3>(1) insert required metadata</h3>
<p>Every .NCX file needs to define four metadata elements:</p>
<ul>
<li><code>dtb:uid</code> &#8211; this is the unique ID for your publication.  It needs to match the ID given in content.opf.
<li><code>dtb:depth</code> &#8211; this is the number of levels in your TOC. Normally this would be 1 but you can add more levels &#8211; see hierarchical contents below
<li><code>dtb:totalPageCount</code> &#8211; this is not used: set to zero
<li><code>dtb:maxPageNumber</code> &#8211; this is not used: set to zero
</ul>
<p>For example, here&#8217;s the .NCX header for a standard table of contents with only 1 layer of entries.</p>
<pre>
&lt;head>
	&lt;meta name="dtb:uid" content="a897sad23fd23ds" />
	&lt;meta name="dtb:depth" content="1" />
	&lt;meta name="dtb:totalPageCount" content="0" />
	&lt;meta name="dtb:maxPageNumber" content="0" />
&lt;/head>
</pre>
<p>&nbsp;</p>
<h3>(2) record title and author</h3>
<p>The document title and author should match those recorded in the main metadata within content.opf (DC:Title, DC:Creator respectively).  Some readers may reference these values when displaying the contents, although those in my limited test suite all seem to ignore these values and focus on those in content.opf.</p>
<blockquote><p>In the sample ePUBs included with this article I deliberate added &#8220;(NCX)&#8221; to the end of the title and author in each .NCX file.  Just to see if/where it appeared.  Never did.  But your mileage may vary.</p></blockquote>
<h3>(3) insert required navigation structure</h3>
<p>The <code>navMap</code> is where the entries in your table of contents are defined using special XML elements called <code>navPoints</code>.  </p>
<pre>
&lt;navPoint playOrder="x">
     &lt;navLabel><text>Text to show in the table</text>&lt;/navLabel>
     &lt;content src="url" />
&lt;/navPoint>
</pre>
<p>The playOrder is numeric, indicating the sequence that the content elements should be traversed in when navigating.  Note that this does not need to match the order you list them (and they appear) in the TOC.  Nor does it need to match the sequence in the <code>&lt;spine></code> section of content.opf.</p>
<blockquote><p>
My testing (and the <a href="http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html#Section2.4.2">OPF specification</a>) indicate that the playOrder is not used to determine the sequence content is browsed.  When users move through the content sequentially, this sequence is defined by the &lt;spine> element in content.opf.  However, even though playOrder is not used, it is recommended that meaningful values are recorded &#8220;just-in-case&#8221;.  It also ensures your ePUB validation, if using <a href="http://code.google.com/p/epubcheck/" target="_blank">epubcheck</a>, will be successful.
</p></blockquote>
<p>The text will present as entered in your TOC; be mindful that not all readers will have a lot of room so don&#8217;t make the entries too long.</p>
<p>The URL needs to be the reference to the file/location that is the target of this TOC entry.  This will be the filename if you have created separate chapter files.  Else you could reference separate sections within a single document via anchor tags.</p>
<p>For example, here are sample entries from the start of one EBook.</p>
<pre>

&lt;navPoint playOrder="1">
  &lt;navLabel>&lt;text>cover&lt;/text>&lt;/navLabel>
  &lt;content src="00-cover.xhtml" />
&lt;/navPoint>
&lt;navPoint playOrder="2">
  &lt;navLabel>&lt;text>preface&lt;/text>&lt;/navLabel>
  &lt;content src="10-frontis.xhtml#preface" />
&lt;/navPoint>
&lt;navPoint playOrder="3">
  &lt;navLabel>&lt;text>credits&lt;/text>&lt;/navLabel>
  &lt;content src="10-frontis.xhtml#credits" />
&lt;/navPoint>
&lt;navPoint playOrder="4">
  &lt;navLabel>&lt;text>Chapter 1 - Background&lt;/text>&lt;/navLabel>
  &lt;content src="chapter1.xhtml" />
&lt;/navPoint>
</pre>
<p>Note: If using anchor tabs, the other end of the link needs to be to an ID, not name tag. <a href="http://isambard.com.au/blog/2011/01/11/epub-doesnt-like-named-anchors-only-ids/" target="_blank">Read this</a> for the explanation.</p>
<h3>Including the .NCX file in your book</h3>
<p>Only two small changes are made to your existing eBook to include your .NCX content, both made to content.opf:</p>
<ul>
<li>add your TOC.NCX file to the ebook manifest.  Application type needs to be<br />
<code>application/x-dtbncx+xml</code></li>
<li>add a reference to the new TOC.NCX to your ebook spine. This is added as an attribute in your <code>&lt;spine></code> tag:</li>
</ul>
<pre>
&lt;manifest>
  &lt;item href="toc.ncx" id="ncx" media-type="application/x-dtbncx+xml"/>
  ...
&lt;/manifest>

&lt;spine toc="ncx">
  &lt;itemref idref="chapter1" />
  ...
&lt;/spine>
</pre>
<p>That&#8217;s it.  Save CONTENT.OPF, build and test.</p>
<h2>Next steps</h2>
<p>Once you&#8217;ve mastered the basic table of contents, you&#8217;re ready to investigate some more advanced options:</p>
<h3>hierarchical contents</h3>
<p>You can create multiple levels in your table of contents simply by nesting your navPoint elements. </p>
<pre>
...
&lt;navPoint id="navpoint" playOrder="1">
          &lt;navLabel><text>Chapter 1</text></navLabel><content src="chapter1.xhtml"/>
          &lt;navPoint playOrder="2">
<navLabel><text>Section 1</text></navLabel><content src="chapter1.xhtml#section1" />&lt;/navPoint>
          &lt;navPoint playOrder="3">
<navLabel><text>Section 2</text></navLabel><content src="chapter1.xhtml#section2" />&lt;/navPoint>
...
</pre>
<p>Don&#8217;t forget to work through the playOrder values to retain a logical sequence to your content.  Even though not sure who/where these values are used <img src='http://isambard.com.au/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>How hierachical contents are displayed or navigated depends very much on the reader.  It also appears to vary how many levels of content are supported. The standard itself sets no limits (or tells you what to call them: chapter, part, section, ..).  However mileage may vary with different readers so don&#8217;t go overboard. The following table shows results with the two readers I spend most of my time with:  Adobe Digital Editions (ADE) and iBooks (on the iPad). The two columns for ADE show the default view (when first opening your book) and the expanded view.</p>
<table border=0>
<r></p>
<td>single level (basic book)</td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/BasicBook-ADE.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/BasicBook-ADE-150x150.png" alt="" title="BasicBook-ADE" width="150" height="150" class="alignnone size-thumbnail wp-image-870" /></a></td>
<td></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/BasicBook-iPad.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/BasicBook-iPad-150x150.png" alt="" title="BasicBook-iPad" width="150" height="150" class="alignnone size-thumbnail wp-image-871" /></a></td>
</tr>
<td>two levels</td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-ADE-Default.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-ADE-Default-150x150.png" alt="" title="2LevelTOC-ADE-Default" width="150" height="150" class="alignnone size-thumbnail wp-image-862" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-ADE-expand.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-ADE-expand-150x150.png" alt="" title="2LevelTOC-ADE-expand" width="150" height="150" class="alignnone size-thumbnail wp-image-860" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-iPad.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/2LevelTOC-iPad-150x150.png" alt="" title="2LevelTOC-iPad" width="150" height="150" class="alignnone size-thumbnail wp-image-861" /></a></td>
</tr>
<td>three levels</td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-ADE-default.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-ADE-default-150x150.png" alt="" title="3LevelTOC-ADE-default" width="150" height="150" class="alignnone size-thumbnail wp-image-863" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-ADE-expand.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-ADE-expand-150x150.png" alt="" title="3LevelTOC-ADE-expand" width="150" height="150" class="alignnone size-thumbnail wp-image-864" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-iPad.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/3LevelTOC-iPad-150x150.png" alt="" title="3LevelTOC-iPad" width="150" height="150" class="alignnone size-thumbnail wp-image-865" /></a></td>
</tr>
<td>four levels</td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/4LevelTOC-ADE-default.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/4LevelTOC-ADE-default-150x150.png" alt="" title="4LevelTOC-ADE-default" width="150" height="150" class="alignnone size-thumbnail wp-image-866" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/4LevelTOC-ADE-expand.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/4LevelTOC-ADE-expand-150x150.png" alt="" title="4LevelTOC-ADE-expand" width="150" height="150" class="alignnone size-thumbnail wp-image-867" /></a></td>
<td></td>
</tr>
<td>five levels</td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/5LevelTOC-ADE-Default.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/5LevelTOC-ADE-Default-150x150.png" alt="" title="5LevelTOC-ADE-Default" width="150" height="150" class="alignnone size-thumbnail wp-image-868" /></a></td>
<td><a href="http://isambard.com.au/blog/wp-content/uploads/2011/04/5LevelTOC-ADE-expand.png"><img src="http://isambard.com.au/blog/wp-content/uploads/2011/04/5LevelTOC-ADE-expand-150x150.png" alt="" title="5LevelTOC-ADE-expand" width="150" height="150" class="alignnone size-thumbnail wp-image-869" /></a></td>
<td></td>
</tr>
</table>
<p>Notice: </p>
<ul>
<li>for iBooks, it gives up after 2 levels of contents.  Unable to find anything official that states that&#8217;s a limit, but if aiming for that platform I&#8217;d stop at 2.</li>
<li>for Adobe Digital Editions, the menu gets a little confused at the deeper levels &#8211; notice at 5 levels of contents the first level does not appear.  Not sure if anything can be done to fix that, but also reason to avoid going that deep.</li>
</ul>
<blockquote><p>The above images are taken from the sample ebooks included with this article.  Feel free to use to test how well supported in your chosen reader.
</p></blockquote>
<h3>multiple tables (pageLists and navLists)</h3>
<p>The standard table of contents is defined within a <code>navMap</code>.  This is the complete, logical structure of your book.  However the .NCX specification also allows you add two additional types of references to your TOC:</p>
<ul>
<li>pageList &#8211; use if needing to offer navigation by page (rather than topic/section). Your ePUB can only include one pageList, and it cannot be hierarchical &#8211; one layer only.</li>
<li>navList &#8211; use if wanting to offer other any other arbitrary collection of topics, for example a list of illustrations or a collection of chocolate recipes taken from your complete recipe book.  You can have as many navLists as you want, although they too can only be single level.  An additional element, navLabel, can be added to give a title to your collection.</li>
</ul>
<p>The steps involved in defining and including these tables is complex enough to warrant their own article, coming soon.</p>
<h2>Conclusion</h2>
<p>A table of contents is a valuable addition to most books, particularly non-fiction or reference titles. Adding one is reasonably simple, and thus worth the effort. However keep to the basics if wanting to be functional in the widest range of readers.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fisambard.com.au%2Fblog%2F2011%2F04%2F12%2Fadding-a-table-of-contents-to-your-epub%2F&amp;title=Adding%20a%20table%20of%20contents%20to%20your%20ePUB" id="wpa2a_20"><img src="http://isambard.com.au/blog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://isambard.com.au/blog/2011/04/12/adding-a-table-of-contents-to-your-epub/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

