<?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>November Echo Romeo Delta</title>
	<atom:link href="http://novemberechoromeodelta.com/feed" rel="self" type="application/rss+xml" />
	<link>http://novemberechoromeodelta.com</link>
	<description>Tech Stuff</description>
	<lastBuildDate>Wed, 14 Jul 2010 00:17:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Web Directions South 2009</title>
		<link>http://novemberechoromeodelta.com/20091009-web-directions-south-2009</link>
		<comments>http://novemberechoromeodelta.com/20091009-web-directions-south-2009#comments</comments>
		<pubDate>Fri, 09 Oct 2009 05:51:15 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[conference]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/?p=221</guid>
		<description><![CDATA[The day before yesterday i flew from Darwin to Sydney for the Web Directions South conference. It was about 30° when i left Darwin, at 7 o&#8217;clock that morning, but when i arrived in Sydney it was a chilly 17°, which was a bit of a shock to my system. The conference was in the [...]]]></description>
				<content:encoded><![CDATA[<p>The day before yesterday i flew from Darwin to Sydney for the <a href="http://south09.webdirections.org" target="_blank">Web Directions South conference</a>. It was about 30° when i left Darwin, at 7 o&#8217;clock that morning, but when i arrived in Sydney it was a chilly 17°, which was a bit of a shock to my system.</p>
<p>The conference was in the convention centre at Darling Harbour, near Sydney&#8217;s central business district. I&#8217;d been to a few conferences before, but never to an IT related one. I was going on my own and i didn&#8217;t expect there to be anyone i knew there.<span id="more-221"></span></p>
<p>When i registered, i was given a large name tag to hang round my neck, with a conference timetable on the back and a flyer for a couple of after conference parties. I was also given a conference shoulder bag containing a bundle of sponsors&#8217; leaflets and a book with various articles in it and information about each of the conference sessions.</p>
<p>The opening session was a talk by Matt Webb, called &#8220;Escalante&#8221;. To be honest, i can barely remember anything about it and i&#8217;m not really sure what it was about. It was a bit rambling and seemed barely relevant.</p>
<p>After that there were four streams of split sessions. I went to Mark Stanton&#8217;s talk, &#8220;Speed Matters&#8221;, on optimising web sites for speed. Mark&#8217;s a good speaker and what he had to say was interesting. I picked up a couple of tips from his talk, but mostly it served to reassure me that i was pretty well up to speed on this subject already.</p>
<p>After that, i stayed in the same room for &#8220;Using Ajax to enhance UX&#8221;, by Tania Lang. It was in the &#8220;Design&#8221; stream, but it sounded like it would be interesting. Unfortunately, it wasn&#8217;t &#8211; not to me, anyway. I bailed after about ten minutes and went to the &#8220;Development&#8221; stream talk by Ben Galbraith, entitled &#8220;The state of development tools&#8221;. I found that much more interesting, although i can&#8217;t remember anything about it now!</p>
<p>After lunch, i listened to Dmitry Baranovsky explaining why he hates the HTML 5 &#8220;Canvas&#8221; element. He was a highly entertaining speaker and got a lot of laughs while he was talking. I knew very little about Canvas before his talk and i came away with quite a good understanding of what it&#8217;s all about.</p>
<p>The next session in the Development stream was Earle Castledine talking about &#8220;jQuery&#8221;. Although i don&#8217;t like jQuery much (i prefer plain javascript), i do want to learn it, so i was hoping this talk might give me a bit of a basis to start learning it from. Unfortunately, as well as not being a particularly good speaker, Earle only mentioned jQuery in passing once during the first fifteen minutes and was talking about stuff that i found pretty much incomprehensible and which seemed completely unrelated to  jQuery.</p>
<p>I left there and went to a panel discussion on the state of the web as a platform. There were five men, one from Microsoft, one from Adobe, one from W3C &#8211; i don&#8217;t know who the other two were. Their discussion was mildly interesting, although didn&#8217;t really seem to have much substance. They were an improvement on the non-jQuery talk though.</p>
<p>The closing session of the first day was Cameron Adams talking about Google Wave. He was a good speaker and the talk was entertaining and reasonably informative.</p>
<p>Kelly Goto started the second day, talking about &#8220;WorkFLOW&#8221;. I&#8217;m not sure i really got very much out of her talk, but she was a good speaker and it was an entertaining start to the day.</p>
<p>Next i listened to Gian Wild talking about WCAG2 &#8211; which is the second version of the W3C web accessibility guidelines. I have to admit i&#8217;m not fully up to speed on WCAG1 (although i am familiar with the principles and practices of web site accessibility), but it was interesting and it will definitely be useful to me to have a bit of background in this in the future.</p>
<p>Elliot Jay Stocks&#8217;s talk on &#8220;Progressive Enhancement&#8221; was the next one i went to. Elliot&#8217;s a good speaker and his talk was interesting. I wouldn&#8217;t say i actually learnt anything from it, as such, but it was good to get an insight into his perspective on things.</p>
<p>After lunch, i listened to Kevin Yank talking about &#8220;CSS Frameworks&#8221;. I&#8217;ve considered and rejected CSS frameworks a couple of times, but the talk was interesting and informative. I don&#8217;t think i&#8217;ll end up using CSS frameworks as a result of listening to it, but it&#8217;s good to hear some of the pros and cons in case i work on a site that could benefit from it in future.</p>
<p>Rob Mitchell and Mike Williams did the last talk in the development stream for the conference. It was called &#8220;Test your JavaScript&#8221;. Neither of them were the best speakers at the conference, but they kept it flowing reasonably well and it was interesting. I didn&#8217;t come out of it feeling like i knew much more about the subject, but it did inspire me to investigate it in more depth soon.</p>
<p>The closing talk was &#8220;15 years in&#8221; by Dan Hill. He was quite a good speaker and it was interesting enough, with some of the best slides of the conference. But he was off in designer fantasy land for a lot of it, and most of what he was talking about barely seemed to relate to reality, let alone to the web. According to the conference book, the subject was about something like taking ideas from web design and incorporating them into the real world. <em>Yeah, right!</em></p>
<p>There were about 700 people at the conference. Attending it was certainly an interesting experience, although i&#8217;m not really sure what or how much i gained from it. But it was definitely worth going to &#8211; apart from anything else, to get a bit of a finger on the pulse of the Australian web industry.</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20091009-web-directions-south-2009/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fedora 11 on a Samsung N140</title>
		<link>http://novemberechoromeodelta.com/20090910-fedora-11-on-a-samsung-n140</link>
		<comments>http://novemberechoromeodelta.com/20090910-fedora-11-on-a-samsung-n140#comments</comments>
		<pubDate>Thu, 10 Sep 2009 20:17:46 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/?p=213</guid>
		<description><![CDATA[I got myself a Samsung N140 netbook a couple of days ago, as i&#8217;m going back to Australia for a couple of months soon and i don&#8217;t want to have to drag my heavy old Thinkpad around with me. I&#8217;m likely to have to do some web development work while i&#8217;m there, so i wanted [...]]]></description>
				<content:encoded><![CDATA[<p>I got myself a Samsung N140 netbook a couple of days ago, as i&#8217;m going back to Australia for a couple of months soon and i don&#8217;t want to have to drag my heavy old Thinkpad around with me. I&#8217;m likely to have to do some web development work while i&#8217;m there, so i wanted something i could work with comfortably. The N140 seemed to fit the bill &#8211; it&#8217;s got a non-gloss screen, for a start, and a full sized keyboard. It also comes with a 6-cell battery, which promises about 9 hours of off-mains use &#8211; and, from my experience so far, it gets pretty close to that, too.<span id="more-213"></span></p>
<p>You can get it with Windows XP or Linux (for £20 less). I chose the Windows version because i wanted to be able to dual boot &#8211; so i could upgrade the firmware on my Nokia 5800. I tried doing it using XP in a VirtualBox virtual machine on my Thinkpad, but it didn&#8217;t work. I could take it to a Nokia service centre and get it done for free, but i&#8217;d have to leave my phone there for a day or two and £20 for a Windows system seemed worth it to avoid that hassle. Anyway, i&#8217;m going to be running XP in a virtual machine on this system too (for testing web sites), so i don&#8217;t mind having a licence for it.</p>
<p>The first thing i did was install Linux. I&#8217;m running Fedora 11 on my Thinkpad, so it made sense to install that on my netbook too. Installation was fairly easy &#8211; using the live version and writing it onto a flash stick using the supplied utility. There was one annoying glitch in Fedora installation though &#8211; when i tried to manually set up the partitioning system it refused to allow the root partition to be ext3 because the image on the installation system was ext4 and it refused to allow it to be ext4, saying it had to be ext3. (I must remember to file a bug report!)</p>
<p>In the end, i allowed it to set up its own choice of partitioning scheme &#8211; which i&#8217;m not really happy with, but which worked. When you first set up XP on this system, it allows you to create two partitions &#8211; so i created the minimum possible one for Windows (which is still way too big) and i used the rest for Linux. Samsung&#8217;s system restore system also grabbed a 7GB partition at the beginning of the disk. At some point i&#8217;ll get round to deleting that and shifting the windows system down there, freeing up 25GB of hard drive space in the process.</p>
<p>Most things worked out of the box with Fedora 11 &#8211; sound, bluetooth, ethernet, SD card reader, touchpad, webcam. But the wireless interface didn&#8217;t work and nor did the built-in mic.</p>
<p>I think support for this wireless card (Realtek RTL8192) is included in version 2.6.31 of the Linux kernel &#8211; which is currently in development &#8211; but it&#8217;s not in the current Fedora version (2.6.30.5) and  i didn&#8217;t really want to build a custom kernel if i could avoid it, so i used ndiswrapper &#8211; which works fine.</p>
<p>I got the RTL8192 driver from the CD that came with the computer &#8211; it wasn&#8217;t easy to find, but it&#8217;s there on the disk. But i had a bit of trouble getting ndiswrapper to work. For some reason when you install ndiswrapper using yum, it doesn&#8217;t require the kernel module &#8211; so, of course, it won&#8217;t work. You have to explicitly install kmod-ndiswrapper as well. Once i&#8217;d worked that out wireless networking just worked (with NetworkManager).</p>
<p>Once you&#8217;ve installed ndiswrapper, install the driver with</p>
<p><code>ndiswrapper -i net819xp.inf</code></p>
<p>(you&#8217;ll need all three of the driver files in the directory you execute that command from).</p>
<p>then</p>
<p><code>ndiswrapper -m</code></p>
<p>should write the configuration file for modprobe. Once that&#8217;s done,</p>
<p><code>modprobe ndiswrapper</code></p>
<p>should get wireless working and the interface showing up in NetworkManager. If not, a reboot will do it.</p>
<p>Getting the built-in mic to work was a bit trickier. First, i installed the gnome-volume-control (also known as gnome-alsa-mixer) application, hoping that there would be a switch somewhere that would turn it on. But there wasn&#8217;t. So i resorted to the best mixer of the lot &#8211; the one that always seems to show all controls, even when nothing else does &#8211; <em>gamix</em>. Unfortunately gamix isn&#8217;t packaged for Fedora any more (i should try lobbying for its inclusion again i guess), so i always keep the source code handy.</p>
<p>Getting gamix to build required installing a few development libraries &#8211; <em>glib-devel</em>, <em>alsa-lib-devel</em>, and <em>gtk+-devel</em>. Once i built and installed it, gamix showed a switch that the gnome mixer didn&#8217;t: &#8220;mic&#8221;/&#8221;front mic&#8221; in the capture section. Switching this to &#8220;front mic&#8221; made the built-in mic work. The sound isn&#8217;t very good though, so unless you really need it, it&#8217;s not worth the bother!</p>
<p>The other problem i had was with some of the software. In particular, Thunderbird&#8217;s account settings window and Nautilus&#8217;s configuration window are too tall for the 600 pixel screen. This is really annoying, as it means you can&#8217;t get at important parts of the configuration. Both of these bugs have been reported on their respective bugzillas.</p>
<p>The workaround i used was to use the System&#8211;&gt;Preferences&#8211;&gt;Display dialog to rotate the screen left &#8211; and then turn the netbook on its side. That way, you can get at everything on the config window. It&#8217;s a bit awkward, but it works!</p>
<p>Some of the function keys work with Fedora and some don&#8217;t. Using the &#8216;Keyboard Shortcuts&#8217; dialog i set Fn-ESC (which has a moon on it) to suspend, and Fn-F12 (which is &#8220;scroll lock&#8221;) to &#8220;lock keyboard&#8221;. I wanted to use Fn-F10 for this, as it&#8217;s got a picture of a screen with an &#8220;X&#8221; in the middle of it, but that doesn&#8217;t seem to generate a key code.</p>
<p>The volume keys work, but the brightness keys don&#8217;t &#8211; which is a bit of a problem, as when the N140 is being used on battery power the brightness drops to a very low level and there&#8217;s nothing you can do about it. This obviously helps with battery life, but it would be nice to have the choice.</p>
<p>A workaround for this seems to be to suspend it with the power connected, then disconnect the power and then wake it up. When you do that, it comes back on with full screen brightness, even though it&#8217;s running on batteries.</p>
<p>Overall, i&#8217;m very happy with the N140 so far. It&#8217;s mostly very well designed and a pleasure to use. Its one really weak point, however, is the keyboard layout &#8211; it&#8217;s not centered. That might not matter much if you type with two fingers, but if you touch type it&#8217;s a big problem.</p>
<p>Surely it would have been simple to move one key from the right of each row over to the left hand side. That would leave the centre point of the letter and number keys &#8211; the gap between the &#8216;g&#8217; and the &#8216;h&#8217; &#8211; in the middle. As it is, it&#8217;s too far to the left and if you touch type your left palm is sitting on the corner of the palm rest, which isn&#8217;t very good ergonomically. A single key width to the right and it would be perfect.</p>
<p>I considered pulling the keys off and moving them over, and then modifying the key mapping. But keymapping is an awkward business in Linux and it may well be more trouble than it&#8217;s worth. It&#8217;s also complicated by the fact that i may want to dual boot Windows &#8211; i don&#8217;t even know if it&#8217;s possible to remap the keys in XP.</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090910-fedora-11-on-a-samsung-n140/feed</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>WordPress Plugin Dependency Checking</title>
		<link>http://novemberechoromeodelta.com/20090727-wordpress-plugin-dependency-checking</link>
		<comments>http://novemberechoromeodelta.com/20090727-wordpress-plugin-dependency-checking#comments</comments>
		<pubDate>Mon, 27 Jul 2009 12:07:00 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/?p=203</guid>
		<description><![CDATA[I use the excellent NextGen Gallery to manage the images in several web sites. But it uses javascript to display the individual full-size images, and that&#8217;s no use for search engine optimization, so i&#8217;m writing a plugin to produce a templateable HTML front end for it. That plugin obviously requires NextGen Gallery to be installed [...]]]></description>
				<content:encoded><![CDATA[<p>I use the excellent NextGen Gallery to manage the images in several web sites. But it uses javascript to display the individual full-size images, and that&#8217;s no use for search engine optimization, so i&#8217;m writing a plugin to produce a templateable HTML front end for it.</p>
<p>That plugin obviously requires NextGen Gallery to be installed &#8211; or, at least, for its database tables to be available &#8211; but WordPress&#8217;s plugin activation system doesn&#8217;t have any built-in way of checking dependencies.<span id="more-203"></span></p>
<p>I tried testing for one of NGG&#8217;s tables in the activation function of my plugin, but i couldn&#8217;t get that to work, as there doesn&#8217;t seem to be a mechanism for plugin activation to fail gracefully. So i did a bit of google searching and turned up a possible solution at <a href="http://fullthrottledevelopment.com/creating-dependent-wordpress-plugins" target="_blank">http://fullthrottledevelopment.com/creating-dependent-wordpress-plugins</a>.</p>
<p>Their solution uses a function which runs every time plugins.php is loaded, which checks to see if the plugin is being activated and, effectively, deactivates it with an error message. That half worked for me, but it didn&#8217;t prevent the code in my plugin&#8217;s activation function from being run (it creates a page and registers some permalink rules). That leaves plugin activation stuff done but the plugin not activated &#8211; which isn&#8217;t good.</p>
<p>So i tried moving the plugin activation code into the dependency check function &#8211; but it wouldn&#8217;t work there and i couldn&#8217;t quite manage to work out why. Then i tried moving the dependency check code into the plugin activation function &#8211; but that didn&#8217;t work properly either.</p>
<p>I was just about to give up and not bother with dependency checking when i came across a blog post called “<a href="http://www.simonwheatley.co.uk/2007/11/22/wordpress-message-on-failed-activation/" target="_blank">I’ve made a useless WordPress plugin…</a>” by Simon Wheatley. He&#8217;s checking for PHP version, but the principle&#8217;s the same.</p>
<p>Simon&#8217;s solution is so simple that i can&#8217;t see why you&#8217;d need anything more complicated. Just check dependencies in the top of the plugin file and die with an error message if they&#8217;re not met. None of the other code in the file will ever be executed if this dependency check fails &#8211; so there&#8217;s no half done activation to worry about.</p>
<p>This was the code i ended up using:</p>
<p><code><br />
global $wpdb;</code></p>
<p><code>$sql = "SHOW TABLES LIKE '{$wpdb-&gt;prefix}ngg_gallery'";<br />
$results = $wpdb-&gt;get_results( $sql );<br />
if ( ! $wpdb-&gt;num_rows )<br />
{<br />
die( '&lt;p&gt;This plugin will not work unless NextGen Gallery is installed and activated.&lt;/p&gt;' );<br />
}</code></p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090727-wordpress-plugin-dependency-checking/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Nokia 5800 Touch Screen Smartphone</title>
		<link>http://novemberechoromeodelta.com/20090509-nokia-5800-touch-screen-smartphone</link>
		<comments>http://novemberechoromeodelta.com/20090509-nokia-5800-touch-screen-smartphone#comments</comments>
		<pubDate>Sat, 09 May 2009 20:30:15 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/?p=192</guid>
		<description><![CDATA[I just bought my first Symbian mobile &#8211; a Nokia 5800. I considered the geekier option of getting the android-powered G2, which was due to be released about the same time by Vodafone, but after a bit of consideration i eventually decided on the Nokia. There were a couple of reasons for that: firstly the [...]]]></description>
				<content:encoded><![CDATA[<p>I just bought my first Symbian mobile &#8211; a Nokia 5800. I considered the geekier option of getting the android-powered G2, which was due to be released about the same time by Vodafone, but after a bit of consideration i eventually decided on the Nokia. There were a couple of reasons for that: firstly  the G2 doesn&#8217;t function as a modem &#8211; which was something i wanted a phone to be able to do. Secondly, the G2 hasn&#8217;t got a headphone socket &#8211; and i want to be able to use wired headphones with it.<span id="more-192"></span> Apart from those, the G2 is bigger and uglier than the 5800. And, anyway, i spend far too much time playing around with the operating system of my Linux laptop, without having a Linux phone to waste my time (and ruin my eyesight) with as well.</p>
<p>So far, i&#8217;m impressed with the 5800 &#8211; it&#8217;s pleasant to use and the interface is well designed. It&#8217;s got a very usable full-screen keyboard for fast text input. I used it to write this and i didn&#8217;t find it at all frustrating &#8211; and i haven&#8217;t got dainty little fingers, that&#8217;s for sure! I can type reasonably fast and accurately by holding the phone in both hands and hitting the keys with the corners of my index finger tips. I touch type but i reckon with practice i could get fast enough with this phone to be happy with it.</p>
<p>I&#8217;ve installed putty on it and i can ssh to my laptop. The font is really small in putty, but i can just about read it without glasses. The user interface is a bit clunky &#8211; you have to click &#8220;send&#8221; and then a button for the type of thing you&#8217;re sending, e.g., a line of text or &#8220;ctrl+&#8221; &#8211; but it works well enough. I wouldn&#8217;t want to have to do a lot of work via putty on this phone, but it&#8217;s nice to have an ssh terminal i my pocket. The only thing i haven&#8217;t found a way to do is send a right hand angle bracket &#8211; which means i&#8217;ve got no way of redirecting output to a file &#8211; which isn&#8217;t a particularly big deal most of the time, but it would be useful. Putty doesn&#8217;t seem to have any way of scrolling back up the screen buffer either, which is a bit irritating.</p>
<p>The thing that really bemused me though was the ability to go to a full-screen display. Once you&#8217;re there, that&#8217;s it &#8211; you&#8217;re stuck. There&#8217;s no way back and no way to input anything, so you can&#8217;t even log off. Symbian doesn&#8217;t appear to have any way to kill rogue programs, either, so (although you can switch to other programs) the only way to close putty is to turn the phone off and back on again.</p>
<p>I was hoping to find a usable pdf reader for the 5800, as i&#8217;ve got quite a backlog of pdf literature that i want to be able to read away from the computer, but there doesn&#8217;t seem to be one. Adobe reader is available, but it&#8217;s not very good &#8211; and it&#8217;s expensive. Being used to downloading the linux and windows versions of it for free, i can&#8217;t say i&#8217;m excited about having to pay for an inferior version of it for my phone. But it&#8217;s useless anyway, so i won&#8217;t be buying it. However, the combination of the display size and the inherent inflexibilty of the pdf format means it&#8217;s probably not much of a goer on this size of device anyway.</p>
<p>The onboard gps is handy &#8211; particularly when combined with the google maps app. It&#8217;s nice to be able to get a map of the area with your location already marked on it.  No need to carry a map ever again &#8211; so long as there&#8217;s mobile coverage, anyway!</p>
<p>And i&#8217;ve finally discovered a device that i can bear to watch television on. I&#8217;m not at all a fan of tv &#8211; and won&#8217;t even have one in the house if i&#8217;ve got a choice. But i&#8217;ve been enjoying watching downloaded programs from Australia&#8217;s SBS and ABC television stations. Despite its small size, the 3.2in, 640 x 360, 16m colour screen is surprisingly pleasant to watch &#8211; and i never thought i&#8217;d be saying that!</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090509-nokia-5800-touch-screen-smartphone/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Moving From Drupal Back To WordPress</title>
		<link>http://novemberechoromeodelta.com/20090326-moving-from-drupal-back-to-wordpress</link>
		<comments>http://novemberechoromeodelta.com/20090326-moving-from-drupal-back-to-wordpress#comments</comments>
		<pubDate>Thu, 26 Mar 2009 14:01:51 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[drupal]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/?p=151</guid>
		<description><![CDATA[As i wrote in a previous post, i converted this blog from WordPress to Drupal a couple of months back &#8211; to get some experience of working with Drupal. But i never liked Drupal and i rapidly came to the conclusion that it&#8217;s really not a good platform for a standalone blog. WordPress beats it [...]]]></description>
				<content:encoded><![CDATA[<p>As i wrote in <a title="Converting From WordPress To Drupal" href="20090109-converting-from-wordpress-to-drupal">a previous post</a>, i converted this blog from WordPress to Drupal a couple of months back &#8211; to get some experience of working with Drupal. But i never liked Drupal and i rapidly came to the conclusion that it&#8217;s really not a good platform for a standalone blog. WordPress beats it hands down on all criteria and i didn&#8217;t particularly enjoy having to maintain this blog on the Drupal platform.<span id="more-151"></span></p>
<p>I started thinking about converting it back again almost straight away, but i didn&#8217;t do it. However, the more i worked with Drupal, the less i wanted to &#8211; and thoughts of moving back to WordPress came into my head every time i had to do anything with it. At first it seemed like a pain in the arse, but the more i thought about it the better it seemed &#8211; and it would be less of a pain in the arse in the long run than having to keep working with Drupal. The longer i left it the harder it would be &#8211; as there would be more blog posts to shift from platform to platform &#8211; so, this morning, i decided to bite the bullet and do it.</p>
<p>I did it the same way as i&#8217;d done it going in the other direction &#8211; manually. I copied and pasted the posts from Drupal into the WordPress editor (as <em>source</em>, so the formatting got copied too) and i set the &#8220;published&#8221; time and date to what they&#8217;d been originally. Then i copied the comments &#8211; inputing them as normal comments, but then editing them to change the poster&#8217;s name and web site and set the date and time to match the originals.</p>
<p>While i was using Drupal, i got a bit slack with keeping up the URL scheme that i&#8217;d been using under WordPress (i&#8217;d had WP configured to automatically add a date prefix, but Drupal didn&#8217;t do that), so i had to write a few &#8220;Redirect permanent&#8221; entries to .htaccess to make sure anyone following a Google link would arrive at the right page.</p>
<p>I&#8217;d also improved the layout a bit when i converted the template from WP to Drupal &#8211; so i had to do the same thing to the old WordPress theme now.</p>
<p>But finally, i&#8217;m pleased to say, this blog is back running on WordPress again!</p>
<p>Like i said, i don&#8217;t like Drupal much, for several reasons, but this was more about which is the best blogging platform rather than which is the best content management system. I&#8217;ve no doubt that Drupal is better for some things than WordPress is, but blogging isn&#8217;t one of them.</p>
<p>What i&#8217;d missed about WordPress was the excellent editor setup, the really useful statistics that you get with the Statpress plugin, notification of comments (it never worked in Drupal), very easy plugin update &#8211; and you can even update the whole system with just a couple of clicks now, too! I missed the nice, user-friendly dashboard and the useful administration bits and pieces that come as standard with WordPress.</p>
<p>Overall, WordPress is just much more pleasant to administer.</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090326-moving-from-drupal-back-to-wordpress/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Making A WordPress Theme</title>
		<link>http://novemberechoromeodelta.com/20090320-making-a-wordpress-theme</link>
		<comments>http://novemberechoromeodelta.com/20090320-making-a-wordpress-theme#comments</comments>
		<pubDate>Fri, 20 Mar 2009 16:56:21 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[web design]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/wordpress/?p=146</guid>
		<description><![CDATA[In a blog post about his &#8220;Starkers&#8221; WordPress theme, designer Elliot Jay Stocks talks about how he used to approach designing for WordPress. He would start with the default theme and remove the bits he didn&#8217;t need. That was pretty much how i started off doing it myself &#8211; until it struck me i was [...]]]></description>
				<content:encoded><![CDATA[<p>In a <a title="Starkers theme blog post" href="http://elliotjaystocks.com/blog/2008/free-starkers-wordpress-theme/" target="_blank">blog post about his &#8220;Starkers&#8221; WordPress theme</a>, designer Elliot Jay Stocks talks about how he used to approach designing for WordPress. He would start with the default theme and remove the bits he didn&#8217;t need. That was pretty much how i started off doing it myself &#8211; until it struck me i was going about things back to front.<span id="more-146"></span></p>
<p>Nowadays, rather than basing a theme around WordPress, i build a static page and then slot WordPress into it. I create the page exactly as i would if i was going to build a static site &#8211; starting off with just one single HTML file and the CSS. That way i can get the layout right without having to mess around with any WordPress stuff. Then, once i&#8217;ve got it looking right, i slot in the content management system.</p>
<p>The basics of building a WordPress theme are quite simple &#8211; once you get the hang of it. If you want to build a theme yourself, or if you want to convert a static web site into a content managed WordPress site, here&#8217;s how to go about it. This explains how to create a theme with just two files &#8211; index.php and style.css <em>(those names are important)</em> &#8211; which is a very rough and ready way to do it. This is aimed at people who <em>do</em> know HTML and CSS, but who don&#8217;t know WordPress.</p>
<p>The first thing to understand is that WordPress doesn&#8217;t do the layout &#8211; you do. WordPress just injects the content into the page you design. The way it does it is with PHP statements that output the relevant part of the content wherever you put them in the page. You don&#8217;t need to know anything about PHP to make this work &#8211; and if you don&#8217;t know PHP, you can think of the PHP statements as sort of <em>magic</em> HTML tags, and not worry too much about the code that&#8217;s inside them. WordPress documentation usually refers to them as &#8220;template tags&#8221;.</p>
<p>Note that these PHP tags start with &#8220;<code>&lt;?php</code>&#8221; and end with &#8220;<code>?&gt;</code>&#8221; and you must keep the whole thing together as a unit. They mostly produce plain text &#8211; and therefore will be formatted only by the HTML tags you wrap round them. However, a few of them do produce HTML &#8211; for example the output from both the <em>wp_list_pages</em> and the <em>dynamic_sidebar</em> tags is formatted as an unordered list (&lt;ul&gt;) (they&#8217;re mentioned below).</p>
<p>An example of one of WordPress&#8217;s &#8220;magic&#8221; PHP tags is <code>&lt;?php bloginfo('name') ?&gt;</code> . This displays the name of your blog at whatever position you place the tag in your HTML. You set the name that&#8217;s displayed with this tag in the WordPress control panel&#8217;s &#8220;Settings&#8221; menu, on the &#8220;General&#8221; page &#8211; in the field labelled &#8220;Blog Title&#8221;.There are probably two places where you&#8217;ll want to use the <code>&lt;?php bloginfo('name'); ?&gt;</code> tag &#8211; between the &lt;title&gt; and &lt;/title&gt; tags in the &lt;header&gt; section, and between the &lt;h1&gt; and &lt;/h1&gt; tags in the header part of your &lt;body&gt; section. So you can start off by replacing the text in those places with that tag.</p>
<p>If you care about search engine optimization (and about making things more pleasant for your users), you won&#8217;t want to have just the blog name in the &lt;title&gt; tag on every page, so you&#8217;ll probably want to put the page title in it as well. To do that, you use the <code>&lt;?php wp_title(); ?&gt;</code> tag. Now your header title should look something like this:</p>
<p><code>&lt;title&gt;&lt;?php bloginfo('name'); ?&gt; &lt;?php wp_title(); ?&gt;&lt;/title&gt;</code></p>
<p>These are some other tags you&#8217;ll probably want to use in your &lt;header&gt; section:</p>
<p><code>&lt;meta http-equiv="Content-Type" content="&lt;?php bloginfo('html_type'); ?&gt;; charset=&lt;?php bloginfo('charset'); ?&gt;" /&gt;</code></p>
<p><code>&lt;link rel="alternate" type="application/rss+xml" title="&lt;?php bloginfo('name'); ?&gt; RSS Feed" href="&lt;?php bloginfo('rss2_url'); ?&gt;" /&gt;</code></p>
<p><code>&lt;link rel="alternate" type="application/atom+xml" title="&lt;?php bloginfo('name'); ?&gt; Atom Feed" href="&lt;?php bloginfo('atom_url'); ?&gt;" /&gt;</code></p>
<p><code>&lt;link rel="pingback" href="&lt;?php bloginfo('pingback_url'); ?&gt;" /&gt;</code></p>
<p>And you&#8217;ll definitely want this one</p>
<p><code>&lt;link rel="stylesheet" href="&lt;?php bloginfo('stylesheet_url'); ?&gt;" type="text/css" media="screen" /&gt;</code></p>
<p>Then, immediately before the &lt;/header&gt; tag, you should put this one:</p>
<p><code>&lt;?php wp_head(); ?&gt;</code></p>
<p>which allows WordPress to put anything into the header that it needs to put there to make it work properly.</p>
<p>In the &lt;body&gt; section you&#8217;ll probably want to use the &lt;h1&gt; page header tags, which i&#8217;ve covered above. You may also want a sub-header, or tagline, which you can set in the &#8220;Tagline&#8221; field of WordPress&#8217;s &#8220;General Settings&#8221; page. To include this in your HTML, you use this tag: <code>&lt;?php bloginfo('description') ?&gt;</code></p>
<p>Then we come to the site&#8217;s main content. You&#8217;d probably want to have a div that&#8217;ll hold the main content on each page. I&#8217;ll call that div &#8220;content&#8221;. This is what it will probably look like:</p>
<p><code>&lt;div id="content"&gt;</code></p>
<p><code>&lt;?php if (have_posts()) : ?&gt;&lt;!-- <strong>see note 1</strong> --&gt;</code></p>
<p><code>&lt;?php while (have_posts()) : the_post(); ?&gt;&lt;!-- <strong>see note 2</strong> --&gt;</code></p>
<p><code>&lt;div &lt;?php post_class() ?&gt; id="post-&lt;?php the_ID(); ?&gt;"&gt;</code></p>
<p><code>&lt;h2&gt;&lt;a href="&lt;?php the_permalink() ?&gt;" rel="bookmark" title="Permanent Link to &lt;?php the_title_attribute(); ?&gt;"&gt;&lt;?php the_title(); ?&gt;&lt;/a&gt;&lt;/h2&gt;</code></p>
<p><code>&lt;span style="font-size:80%";&gt;&lt;?php the_time('F jS, Y') ?&gt; by &lt;?php the_author() ?&gt;&lt;/span&gt;</code></p>
<p><code>&lt;div class="entry"&gt;</code></p>
<p><code>&lt;?php the_content('Read the rest of this entry &amp;raquo;'); ?&gt;</code></p>
<p><code>&lt;/div&gt;</code></p>
<p><code>&lt;p class="postmetadata"&gt;&lt;?php the_tags('Tags: ', ', ', '&lt;br /&gt;'); ?&gt; Posted in &lt;?php the_category(', ') ?&gt; | &lt;?php edit_post_link('Edit', '', ' | '); ?&gt; &lt;?php comments_popup_link('No Comments &amp;#187;', '1 Comment &amp;#187;', '% Comments &amp;#187;'); ?&gt;&lt;/p&gt;</code></p>
<p><code>&lt;/div&gt;</code></p>
<p><code>&lt;?php endwhile; ?&gt;<code>&lt;!-- <strong>see note 2</strong> --&gt;</code></code></p>
<p><code>&lt;div class="navigation"&gt;</code></p>
<p><code><code>&lt;div class="alignleft"&gt;&lt;?php next_posts_link('&amp;laquo; Older Entries') ?&gt;&lt;/div&gt;</code></p>
<p><code>&lt;div class="alignright"&gt;&lt;?php previous_posts_link('Newer Entries &amp;raquo;') ?&gt;&lt;/div&gt;</code></p>
<p><code>&lt;/div&gt;</code></p>
<p><code>&lt;?php else : ?&gt;<code>&lt;!-- <strong>see note 1</strong> --&gt;</code></p>
<p><code>&lt;h2 class="center"&gt;Not Found&lt;/h2&gt;</code></p>
<p><code>&lt;p class="center"&gt;Sorry, but you are looking for something that isn't here.&lt;/p&gt;</code></p>
<p><code>&lt;?php get_search_form(); ?&gt;</code></p>
<p><code>&lt;?php endif; ?&gt;&lt;!-- <strong>see note 1</strong> --&gt;</code></p>
<p><code>&lt;/div&gt;&lt;!-- end of content div --&gt;</code><br />
</code></code><br />
The above is mostly taken from the WordPress default theme &#8211; but i&#8217;ve modified it a bit and reformatted it to try and make it work a bit better in this blog post. At first glance it may look like total gobbledgook, but you can just lift the whole thing and paste it into your main page section. The above code will take care of displaying blog posts or static pages &#8211; which you can create and organise using WordPress&#8217;s content management system.</p>
<p>I&#8217;ve inserted html comments referring to note 1 and 2. The tags that these are next two are structurally important and you should be careful not to delete them or move them around.</p>
<p>(<strong>1</strong>) The &#8220;if (have_posts())&#8221;, &#8220;else&#8221;, and &#8220;endif&#8221; tags wrap around two separate code sections &#8211; the part before the &#8220;else&#8221; displays posts (or pages) and the part after it displays a &#8220;Not Found&#8221; page if there are no posts or pages. Exactly what posts or pages are displayed by these is controlled by other parts of the WordPress system &#8211; but whatever it is that should be displayed on the page will be displayed by the code between the &#8220;if&#8221; and &#8220;else&#8221; tags.</p>
<p>(<strong>2</strong>) The &#8220;while (have_posts())&#8221; and &#8220;endwhile&#8221; tags wrap round code that may be used multiple times in one page. This happens on pages that show several blog posts, or <em>teasers</em> from several blog posts. For example, the home page of a blog might show the most recent 5 posts in reverse date order. How many are shown per page is set in the &#8220;Blog pages show at most&#8221; field on the &#8220;Reading Settings&#8221; page.</p>
<p>I&#8217;m not going to go into too much detail about most of what&#8217;s in that block of code &#8211; but if you&#8217;re reasonably familiar with HTML you should be able to work out more or less what&#8217;s going on. However there are one or two things worth pointing out. If you read through it, you&#8217;ll notice something that makes the &#8220;template tags&#8221; different from normal html tags &#8211; and that&#8217;s that they can be <em>embedded within</em> html tags. For instance,  in</p>
<p><code>&lt;a href="&lt;?php the_permalink() ?&gt;" rel="bookmark" title="Permanent Link to &lt;?php the_title_attribute(); ?&gt;"&gt; &lt;?php the_title(); ?&gt;&lt;/a&gt;</code></p>
<p>the <code>&lt;?php the_permalink() ?&gt;</code> tag is inside the &lt;a&gt; tag. When the page is sent to the browser, it gets replaced by the URL that&#8217;s needed by the &#8216;href&#8217; attribute.</p>
<p>This section of code:</p>
<p><code>&lt;span style="font-size:75%";&gt;&lt;?php the_time('F jS, Y') ?&gt; by &lt;?php the_author() ?&gt;&lt;/span&gt;</code></p>
<p>puts the date and time that the post was published, along with the author&#8217;s name, at the top of the post, underneath the header. Depending on how you want your site, you might want to leave this out altogether &#8211; or you may want to style it differently.</p>
<p>This section:</p>
<p><code>&lt;p class="postmetadata"&gt;&lt;?php the_tags('Tags: ', ', ', '&lt;br /&gt;'); ?&gt; Posted in &lt;?php the_category(', ') ?&gt; | &lt;?php edit_post_link('Edit', '', ' | '); ?&gt; &lt;?php comments_popup_link('No Comments &amp;#187;', '1 Comment &amp;#187;', '% Comments &amp;#187;'); ?&gt;&lt;/p&gt;</code></p>
<p>Displays &#8220;meta&#8221; data that may be associated with the post or page. It shows tags and the category it&#8217;s in. If you don&#8217;t want to display tags or categories, you can delete those parts of it. The &#8220;edit_post_link&#8221; bit produces an &#8220;edit post&#8221; link that&#8217;s only shown to users who are logged on and are authorized to edit that post.</p>
<p>If you follow the logic of the html, you can probably move things around within this main code block fairly easily, or remove them altogether. Get it working properly first, before you start playing around with it though.</p>
<p><a name="sidebar"></a>Next, you&#8217;ll probably want a sidebar with some menu items in it. Of course, you set your sidebar up with HTML and CSS as usual. All you need to put in it for it to work with WordPress is</p>
<p><code>&lt;?php dynamic_sidebar() ?&gt;</code></p>
<p>Then you can add &#8220;widgets&#8221; to it from your WordPress control panel&#8217;s &#8220;Widgets&#8221; page (in the &#8220;Appearance&#8221; section of the main menu).</p>
<p>To make the sidebar work, though, you must have a file called &#8216;functions.php&#8217; in your theme directory, containing something like:</p>
<p><code>&lt;?php<br />
if ( function_exists('register_sidebar') )<br />
register_sidebar(array(<br />
'before_widget' =&gt; '&lt;li id="%1$s" class="widget %2$s"&gt;',<br />
'after_widget' =&gt; '&lt;/li&gt;',<br />
'before_title' =&gt; '',<br />
'after_title' =&gt; '',<br />
));<br />
</code></p>
<p>If you don&#8217;t have this file, your sidebar won&#8217;t show up in the Widgets menu.</p>
<p>At the bottom of your HTML, immediately before the &lt;/body&gt; tag, you should add the <code>&lt;?php wp_footer(); ?&gt;</code> tag &#8211; it allows WordPress to insert anything it needs to insert into the foot of the page, just like the <code>&lt;?php wp_header(); ?&gt;</code> tag did in the header.</p>
<p>That&#8217;s pretty much it for the absolute basics of WordPress theme development. There&#8217;s one other thing you may need to know, though, and that&#8217;s how to make a horizontal menu (at the top of the page, say). For that you use</p>
<p><code>&lt;?php wp_list_pages('title_li='); ?&gt;</code></p>
<p>which will produce an unordered list (&lt;ul&gt;), which you can set to display inline and style appropriately using CSS.</p>
<p>Talking of CSS, i&#8217;d recommend using Firefox web browser for developing your WordPress site &#8211; and installing the &#8220;Web Developer&#8221; plugin and the &#8220;Aardvark&#8221; plugin. They both work differently, but they both allow you to hover the pointer over any part of a web page and see what class or id that HTML element is set to. It&#8217;s very handy to be able to do this when you&#8217;re working with WordPress layout, because it&#8217;s the simplest way to find out what you need to put in your CSS for styling some of the elements. This is particularly true when it comes to styling the sidebar &#8211; because the list tags for that are produced by WordPress and the only way to find out what they are is to view the source in your browser, to read the documentation at wordpress.org, or to use Aardvark or the Web Developer plugin to see what the element ids and classes are. The last option&#8217;s the easiest!</p>
<p>The final thing that you must do to make your theme work is to have a file called &#8216;style.css&#8217; and to put the following comment right at the top of it:</p>
<p><code>/*</code></p>
<p><code>Theme Name: Your Theme's Name Here</code></p>
<p><code>*/</code></p>
<p>Without that, it won&#8217;t show up in the &#8220;Manage Themes&#8221; page of your WordPress control panel. (You get to that page by clicking on &#8220;Themes&#8221; in the &#8220;Appearance&#8221; section of the main admin menu.) The theme files should be in a subdirectory in wp-content/themes in your WordPress installation. It&#8217;s worth putting a screenshot in there as well &#8211; called &#8216;screenshot.png&#8217; and about 300&#215;200 pixels &#8211; as that will show on the &#8220;Manage Themes&#8221; page.</p>
<p>This really has been the absolute rough and ready basics of creating a WordPress theme. I haven&#8217;t been building a theme while i&#8217;ve been writing it and i can&#8217;t guarantee that if you follow exactly what i&#8217;ve written here, your theme will work. It&#8217;s not intended to tell you everything you need to know, but i hope it&#8217;s given you a rough idea of how it all fits together.  To do the job properly, you&#8217;ll probably want to split your html up into at least 4 separate files &#8211; index.php, header.php, footer.php, and sidebar.php. WordPress has its own way of loading those files where they&#8217;re needed, and you&#8217;ll need to know how to organise that &#8211; having a look at the default theme should give you some clues.</p>
<p>Most importantly, there&#8217;s a vast amount of very good documentation at <a title="Wordpress documentation" href="http://codex.wordpress.org" target="_blank">http://codex.wordpress.org</a> &#8211; you should definitely start by reading the <a title="Wordpress theme development" href="http://codex.wordpress.org/Theme_Development" target="_blank">Theme Development</a> page.</p>
<p></code></code></p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090320-making-a-wordpress-theme/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Object Oriented PHP With CodeIgniter</title>
		<link>http://novemberechoromeodelta.com/20090312-object-oriented-php-with-codeigniter</link>
		<comments>http://novemberechoromeodelta.com/20090312-object-oriented-php-with-codeigniter#comments</comments>
		<pubDate>Thu, 12 Mar 2009 10:08:03 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[code igniter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/wordpress/?p=143</guid>
		<description><![CDATA[I think i had the basic idea about object oriented programming back in the early 80s &#8211; when i was an assembler programmer. Back then, i tried to make my code as modular and reusable as possible. But, in those days, at least, writing in assembly language didn&#8217;t give you much scope for optimising code [...]]]></description>
				<content:encoded><![CDATA[<p>I think i had the basic idea about object oriented programming back in the early 80s &#8211; when i was an assembler programmer. Back then, i tried to make my code as modular and reusable as possible. But, in those days, at least, writing in assembly language didn&#8217;t give you much scope for optimising code in that way &#8211; the best i could do was use lots of subroutines.<span id="more-143"></span></p>
<p>Since i started working with PHP, a year or so ago, i&#8217;ve been using OO concepts a bit. I&#8217;ve written a couple of classes to do things that seemed to require it, and i always use the object oriented style for functions if it&#8217;s available. However, that&#8217;s as far as it went. I understood the concepts of OOP, but i didn&#8217;t really understand its application.</p>
<p>A few days ago, however, i started playing around with <a title="CodeIgniter web site" href="http://codeigniter.com" target="_blank">CodeIgniter</a> and i was impressed. So i decided to rewrite a project i&#8217;m currently working on using the CodeIgniter framework. And now, as a result of using it, i think i really do finally <em>get</em> object oriented programming!</p>
<p>In the words of their web site, &#8220;CodeIgniter&#8217;s an Open Source Web Application Framework that helps you write kick-ass PHP programs&#8221;. It uses the &#8220;Model &#8211; View &#8211; Controller&#8221; approach, which separates logic from presentation and, if used properly, forces you to write code in an object oriented and modular way.</p>
<p><em>Controllers</em> are functions that run first when a URL is requested. They then load one or more <em>Views</em> &#8211; which is where all the HTML is. <em>Models</em> are where your database functions go &#8211; and they can be called from either a controller or a view. Keeping these aspects of code separate helps considerably with reusability and it also helps keep individual sections of code simple. For me, at least, this approach seems to noticeably reduce the number of errors in my code.</p>
<p>CodeIgniter comes with a lot of useful built-in functionality &#8211; although the framework&#8217;s filesystem footprint is surprisingly small (only about 3MB). The included libraries help with things like accessing a database, sending email, validating form data, maintaining sessions, manipulating images, working with XML-RPC data, etc &#8211; most of the functions that you need to use all the time when developing web applications. The database abstraction layer not only simplifies the code, but should help with portability.</p>
<p>One of the best things about it, from my point of view, is that there&#8217;s no fancy template stuff involved &#8211; you just use PHP.  Rewriting the project that i&#8217;m currently working on, to fit into the CodeIgniter framework, has proved to be relatively easy. Mostly, i can just cut and paste from the old php files into new ones &#8211; putting the relevant bits into either controllers, views, or models. I&#8217;ve had surprisingly few problems doing that &#8211; and i&#8217;m quite sure that&#8217;s because breaking the code down into smaller, more modular chunks has helped eliminate mistakes that would creep in otherwise.</p>
<p>I&#8217;m sure the work i&#8217;ve had to do rewriting this project will pay dividends in the time that i&#8217;ll save on the parts i&#8217;ve still got to do &#8211; and also in the added ease of maintenance and modification. And, as a bonus, i&#8217;m learning my way around a framework that i&#8217;m sure i&#8217;m going to be using a lot in future.</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090312-object-oriented-php-with-codeigniter/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Optimising Ajax Search Suggestions</title>
		<link>http://novemberechoromeodelta.com/20090304-optimising-ajax-search-suggestions</link>
		<comments>http://novemberechoromeodelta.com/20090304-optimising-ajax-search-suggestions#comments</comments>
		<pubDate>Wed, 04 Mar 2009 08:49:13 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/wordpress/?p=138</guid>
		<description><![CDATA[While i was watching Douglas Crockford&#8217;s talk on Ajax performance on the Yahoo developer network site yesterday, it occurred to me that the Ajax dropdown search suggestion list i wrote for a client&#8217;s site (mentioned in an earlier blog post) was rather inefficient in the way it handled the XMLHTTP requests. When a user typed [...]]]></description>
				<content:encoded><![CDATA[<p>While i was watching <a title="Ajax performance video" href="http://video.yahoo.com/watch/4141759/11157560" target="_blank">Douglas Crockford&#8217;s talk on Ajax performance</a> on the Yahoo developer network site yesterday, it occurred to me that the Ajax dropdown search suggestion list i wrote for a client&#8217;s site (mentioned in <a title="earlier post on search suggestions" href="http://novemberechoromeodelta.com/ajax-search-suggestions-dropdown-list">an earlier blog post</a>) was rather inefficient in the way it handled the XMLHTTP requests.<span id="more-138"></span></p>
<p>When a user typed two characters into the search input box, my script would fire off an ajax request to the server and get a list of all matching strings from the relevant database field. If they typed a third character, it would do the same thing again for that string. And so on. I didn&#8217;t bother getting suggestions for just one typed character, as there would be too many suggestions for the user to handle easily and the extra load on the server and network seemed unnecessary.</p>
<p>However, i realised yesterday that there&#8217;s no point doing any requests after the first one &#8211; so long as the first two characters of the search string stay the same &#8211; because we&#8217;ve already got all the suggestions we need. After the first request, subsequent requests for longer search strings only return a subset of the results for the first two characters. So all i needed to do was to keep that first set of results and narrow it down as more characters were added to the string it needed to match.</p>
<p>The decision to reuse the old results or retrieve a new set depends on whether the first two characters of the search string match the first two characters of the first result of the old result set. If they match, then we&#8217;ve already got the results we need &#8211; if they don&#8217;t, then we do an XMLHTTP request and get some new results.</p>
<p>This change should result in quite a considerable saving in http request overheads and server load if users type more than two characters into the search box. It should also mean responsiveness improves noticeably &#8211; particularly on slow network connections.</p>
<p>While i was making these changes, i realised the way the search suggestions were being sent from the server could be optimised too. To keep things simple, i was retrieving the data from the mysql database, putting it into an array, and then json_encode&#8217;ing it and returning it to the browser, without doing any other processing. This seemed most efficient at the time. However, because mysql was returning an associative array with the field name as the key, the field name was included with every record &#8211; which was quite a lot of redundant data.</p>
<p>Looking at it a bit more critically, i realised there was no need to return the field name at all, as it was never used in the search suggestions code (it&#8217;s already known by the browser) &#8211; and having it there made the code more complicated anyway. I could have used a numeric array, rather than an associative one, but the key would still have been redundant. So i rewrote it to just push the value from the result into the array to be json_encoded.</p>
<p>On average, this ought to knock about a third off the data that needs to be sent in the XMLHTTP request. It probably won&#8217;t make much difference over a fast network link, but it should be noticeable over a slow one.</p>
<p>This dropdown search suggestions system was my first Ajax project &#8211; and i was focussed more on getting it to work than on proper optimisation. Next time i&#8217;ll be thinking about optimisation from the outset.</p>
<p>Of course, while i was modifying my original code, i discovered a bug i hadn&#8217;t noticed before &#8211; so now i&#8217;m going to have to fix that too. Groan&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090304-optimising-ajax-search-suggestions/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Passing Variables From PHP To Javascript</title>
		<link>http://novemberechoromeodelta.com/20090219-passing-variables-from-php-to-javascript</link>
		<comments>http://novemberechoromeodelta.com/20090219-passing-variables-from-php-to-javascript#comments</comments>
		<pubDate>Thu, 19 Feb 2009 09:22:54 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/wordpress/?p=134</guid>
		<description><![CDATA[Sometimes you need to pass variables &#8211; probably URL parameters &#8211; to a JavaScript script in a separate file that&#8217;s being called from a web page. I looked at a few different solutions on the web, but i didn&#8217;t find anything i liked, so i worked out my own approach. Instead of calling my JavaScript [...]]]></description>
				<content:encoded><![CDATA[<p>Sometimes you need to pass variables &#8211; probably URL parameters &#8211; to a JavaScript script in a separate file that&#8217;s being called from a web page. I looked at a few different solutions on the web, but i didn&#8217;t find anything i liked, so i worked out my own approach.</p>
<p><span id="more-134"></span>Instead of calling my JavaScript script files &#8220;something.js&#8221;, i&#8217;ve started calling them &#8220;something.js.php&#8221; &#8211; so they&#8217;ll be parsed by the php interpreter. This allows me to dynamically create JavaScript scripts &#8211; for example, to attach a dynamically created dropdown list on a page when a user clicks on a link. The ability to create something like a dropdown list according to what else is happening on a dynamically generated page can be useful &#8211; but it can be a bit confusing to debug, because seeing the JavaScript file you generated isn&#8217;t straightforward. It can also require some mental gymnastics to work out whether a bug&#8217;s in the PHP or the JavaScript!</p>
<p>Anyway, i wanted to pass a parameter through from the page&#8217;s URL to the js script, in order to be able leave the subject of the current page out of the dropdown list. The first thing i tried was to include the following tag in the header, immediately before the tag calling the javascript file:</p>
<p><code>&lt;script type="text/javascript"&gt;var personId = &lt;?php echo $_GET['id'] ?&gt;;&lt;/script&gt;</code></p>
<p>This works ok, but it&#8217;s a bit messy and including it in the HTML goes against the principle of separating structure from function. So, instead of that, i changed the script tag which loads the javascript file to:</p>
<p><code>&lt;script type="text/javascript" src="person.js.php?id=&lt;?php echo $_GET['id'] ?&gt;"&gt;&lt;/script&gt;</code></p>
<p>The browser now gets the javascript file with that parameter, which i can easily access in the javascript file itself, thus:</p>
<p><code>var personId = &lt;?php echo $_GET['id'] ?&gt;;</code></p>
<p>To help debug this sort of script, i view the page source. Then i copy and paste the URL of the js.php file, along with any URL parameters, from the script tag in the page source into the browser&#8217;s address bar. Then i use &#8220;View Source&#8221; to look at the dynamically generated javascript.</p>
<p>I&#8217;m also going to start naming css files as &#8220;something.css.php&#8221; &#8211; so they, too, will be parsed by the php interpreter. I haven&#8217;t investigated the possibilities it opens up yet, but it would allow me to use variables in the CSS file and it would make it possible to set something (e.g., a colour) in one place, at the top of the file, which can recur wherever it&#8217;s needed (using php &#8216;echo&#8217; statements). This would mean i&#8217;d only have to change it once and changes would be propagated throughout the file.</p>
<p>However, i had a bit of struggle to get that to work with Firefox 3. It works fine in IE7, Safari and Opera &#8211; and i was puzzled about why it didn&#8217;t work in Firefox as well. After a bit of experimenting, i realised that apache sends a &#8220;Content-type: text/css&#8221; header if the filename suffix is &#8220;.css&#8221;, but a text/html content-type header if it&#8217;s &#8220;php&#8221;. Obviously the other browsers don&#8217;t worry about that &#8211; but Firefox does. So, to make .css.php files work (if you&#8217;re using apache), you have to put the following line at the top of the file:</p>
<p><code>&lt;?php header( 'Content-type: text/css' ); ?&gt;</code></p>
<p><strong>Note:</strong> this must be the very first line in the file. If there&#8217;s anything else before it &#8211; even a blank line &#8211; it won&#8217;t work, because once apache has sent anything to the browser it can&#8217;t send another header.</p>
<p>With this in mind, even though files with the .js.php suffix seem to work ok, it&#8217;s obviously a good idea to send an application/javascript header with js.php files, too &#8211; like this:</p>
<p><code>&lt;?php header( 'Content-type: application/javascript' ); ?&gt;</code></p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090219-passing-variables-from-php-to-javascript/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ajax Search Suggestions Dropdown List</title>
		<link>http://novemberechoromeodelta.com/20090131-ajax-search-suggestions-dropdown-list</link>
		<comments>http://novemberechoromeodelta.com/20090131-ajax-search-suggestions-dropdown-list#comments</comments>
		<pubDate>Sat, 31 Jan 2009 06:00:50 +0000</pubDate>
		<dc:creator>will</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://novemberechoromeodelta.com/wordpress/?p=129</guid>
		<description><![CDATA[I recently built a site for a client who sells records and CDs and wanted his catalogue of over ten thousand items available for purchase from his site. I used mysql and php for the database handling side of things and, naturally, i suggested a search box to make it easier for customers to find [...]]]></description>
				<content:encoded><![CDATA[<p>I recently built a site for a client who sells records and CDs and wanted his catalogue of over ten thousand items available for purchase from his site. I used mysql and php for the database handling side of things and, naturally, i suggested a search box to make it easier for customers to find what they were looking for.<span id="more-129"></span></p>
<p>But implementing a search system when you&#8217;re dealing with band names and record titles isn&#8217;t a simple matter. I considered mysql&#8217;s fulltext search methods, but they turned out to be useless for searching through this type of text. There were two main problems. Firstly, there&#8217;s a minimum length of words that will be indexed &#8211; this is only configurable at system level and, on a shared web hosting server, changing it wasn&#8217;t a viable option. The default minimum is 4 &#8211; which excludes band names like &#8220;yes&#8221; and &#8220;who&#8221;.</p>
<p>Mysql also has a &#8220;stopword&#8221; list, which contains words that don&#8217;t get indexed. The stopwords list includes words like &#8220;them&#8221;, &#8220;who&#8221;, and &#8220;yes&#8221; &#8211; all names of groups which appear in the database and need to appear in search results. Again, this list is a system variable and  it wasn&#8217;t viable for me to change it. So i had to give up on the idea of using fulltext searching and do it the hard way.</p>
<p>The &#8220;hard way&#8221; consisted of using the &#8220;<code>SELECT ... FROM ... WHERE ... LIKE %...%</code>&#8221; sql construction with the search string. But that wasn&#8217;t good enough on its own as , so i also split multi-word search strings into statements for the individual words and strung them together using &#8220;<code>AND</code>&#8221; operators &#8211; so the search should turn up what they were looking for even if they had the words in the wrong order.</p>
<p>This worked fairly well, but for some searches it threw up lots of results that weren&#8217;t really what you were looking for. For example, searching for &#8220;yes&#8221; produced results that included &#8220;Isaac Hayes&#8221; and &#8220;Eyes Adrift&#8221;. Not a particularly big deal, i guess, but when they come at the top of the list it&#8217;s a bit confusing. I could have added more code to make sure any results that contained the search string alone came at the top of the list, but it was getting fairly complicated already and i decided that a drop-down suggestion list containing relevant search terms would be a better option.</p>
<p>I hadn&#8217;t used ajax before &#8211; in fact, i hadn&#8217;t written much javascript at all &#8211; but i was surprised at how easy the ajax side of the job was. I decided to use JSON, rather than XML, to transport the search results from the server to the client, for two reasons. PHP has a nice function to convert an array into JSON which was neater than writing several lines of code to build the XML document &#8220;manually&#8221;. Also, JSON is a more efficient way of sending the search results &#8211; in terms of the number of bytes that it contains &#8211; which is important when you&#8217;re trying to get a feel that&#8217;s as close to realtime as possible.</p>
<p>Getting the user input from the input box in the search form proved to be an altogether trickier challenge. The only reason it was trickier was because i had trouble finding good documentation on the relevant DOM events. I knew i needed to use one of onKeyDown, onKeyPress, or onKeyUp in the html tag for that input, but working out which one would be best wasn&#8217;t easy. Some of documentation kicking around on the net is just plain wrong.</p>
<p>After a bit of experimentation, i settled on onKeyDown &#8211; as it seemed to work better for what i needed than onKeyPress. For some reason &#8211; possibly reading inaccurate documentation &#8211; i rejected onKeyUp as an option. The KeyDown event fires for more keys than the KeyPress event, which may be why i chose it &#8211; i don&#8217;t really remember.</p>
<p>Anyway, KeyDown fires before the current character has been written to the input field, so i wrote an input handler to construct a string from the contents of the search box plus the key that had just been pressed. This isn&#8217;t a trivial matter, as you have to take into account the cursor position, the delete and backspace keys, as well as any selection that may be in effect at the time.</p>
<p>I ended up with the following code to handle user input:</p>
<pre>var keynum;
/* Get key code depending on which browser it is. */
if ( keyevent.keyCode )
{
  keynum = keyevent.keyCode;
}
else if ( keyevent.which )
{
  keynum = keyevent.which
}
else if ( window.event.keycode )
{
  keynum = window.event.keycode;
}

/* Get the text that's already in the input field. */
var inputText = document.someform.searchstring.value;

/* Get the value from the select box. */
var field = document.someform.field.value;

/* Which key? */

switch( keynum )
{
  /* first - ones we ignore */
  case KEY.LEFT:
  case KEY.RIGHT:
  case KEY.UP:
  case KEY.DOWN:
  case KEY.ESC:
  case KEY.PAGEUP:
  case KEY.PAGEDOWN:
  break;

  default:
  {
    /* Get selection information */
    var selectionStart = getSelectionStart( document.someform.searchstring );
    var selectionEnd = getSelectionEnd( document.someform.searchstring );

    if (( keynum == KEY.BS ) || ( keynum == KEY.DEL ))
    {
      /* Backspace or delete - don't add it to the string, but delete
      whatever character(s) it relates to. */
      if ( selectionStart == selectionEnd )
      {
        /* There's no selection - just a cursor position. So delete one character
	- either before or after the cursor, depending on whether it's BS or DEL. */
        cursorPosition = selectionStart;

        if ( keynum == KEY.BS )
        {
          // backspace - delete char before cursor
          var searchString = inputText.slice( 0 , cursorPosition - 1 )
+ inputText.slice( cursorPosition );
        }
        else
        {
          // del - delete char after cursor
          var searchString = inputText.slice( 0 , cursorPosition )
+ inputText.slice( cursorPosition + 1 );
        }
      }
      else
      {
        /* There is a selection - delete the characters covered by it. */
        var searchString = inputText.slice( 0 , selectionStart )
+ inputText.slice( selectionEnd );
      }

    }
    else
    {
      /* Not deleting, so add character to search string, insert
      it in search string, or replace selection with it. */
      var searchString = inputText.slice( 0 , selectionStart ) + String.fromCharCode( keynum )
+ inputText.slice( selectionEnd );

    }
}</pre>
<p>[......]</p>
<pre>/* Functions to get the selection start and end positions. If this is IE,
we need to approach it in a bit of a roundabout way to find the positions.
If Mozilla etc, it's simple. */
function getSelectionStart( thisElement ) {
  if ( thisElement.createTextRange ) {
    var selectionRange = document.selection.createRange().duplicate()
    selectionRange.moveEnd( 'character', thisElement.value.length )
    if ( selectionRange.text == '' ) return thisElement.value.length
    return thisElement.value.lastIndexOf( selectionRange.text )
  } else return thisElement.selectionStart
}

function getSelectionEnd( thisElement ) {
  if ( thisElement.createTextRange ) {
    var selectionRange = document.selection.createRange().duplicate()
    selectionRange.moveStart( 'character', -thisElement.value.length )
    return selectionRange.text.length
  } else return thisElement.selectionEnd
}</pre>
<p style="font-size: 85%;"><em>[The last two functions were pinched from Diego Perini's script at </em><a title="Cursor Position Control Example" href="http://javascript.nwbox.com/cursor_position"><em>http://javascript.nwbox.com/cursor_position</em></a><em> - i didn't get round to rewriting them before i scrapped this approach.]</em></p>
<p>Of course, it took a while to get all this working properly. But as soon as i <em>had</em> got it working i discovered that there was a much easier way to do it!</p>
<p>I stumbled across Peter-Paul Koch&#8217;s excellent <a title="Quirksmode" href="http://quirksmode.org">Quirksmode</a> site and his <a title="Event Compatibility Tables" href="http://quirksmode.org/dom/events/index.html">Event Compatibility Tables</a>, which told me that &#8220;[the keyup] event fires after the keystroke has been processed; for instance after a character has been added to a 	text input.&#8221; Doh! That was what i needed to know <em>before</em> i wrote all that code above!</p>
<p>A minimal amount of experimentation told me that onKeyUp was what i should be using, so i scrapped all the code above and replaced it with:</p>
<pre>/* Get the text from the input field. */
var searchString = searchfield.value;</pre>
<p>which was much neater! I hadn&#8217;t wasted my time though, because i now had a good understanding of text input handling with javascript and the DOM.</p>
<p>There are several jQuery plugins for dropdown suggestion lists, but all the ones i looked at either seemed a bit buggy or didn&#8217;t work the way i wanted them to. Using one of them would also mean including the jQuery library in the page&#8217;s code &#8211; which adds a slight download overhead &#8211; so i decided against it. If i&#8217;d been using jQuery for anything else in the page, it probably would have been different but, as i wasn&#8217;t, writing my own code was easier and more efficient.</p>
<p>I was surprised at how easy it was to implement the dropdown search suggestions list. It&#8217;ll make searching easier for my client&#8217;s customers and hopefully it will help him sell more records. But i&#8217;m not sure if it will fix the problem with searching for &#8220;yes&#8221; &#8211; with short names like that, anyone who can type at a reasonable speed will have typed the whole thing into the search box before they see it in the suggestions. And unless the string comes from the suggestions, the search will be loose, rather than exact.</p>
<p>But <em>Yes</em> are crap anyway, so who cares? <img src='http://novemberechoromeodelta.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://novemberechoromeodelta.com/20090131-ajax-search-suggestions-dropdown-list/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
