<?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>Otaqui.Com &#187; webdev</title>
	<atom:link href="http://otaqui.com/blog/tag/webdev/feed/" rel="self" type="application/rss+xml" />
	<link>http://otaqui.com/blog</link>
	<description>Pete Otaqui's blog about web development and everything else</description>
	<lastBuildDate>Wed, 23 Jun 2010 09:55:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Adobe CS3 &#8220;licensing for this product has stopped working&#8221; fix</title>
		<link>http://otaqui.com/blog/699/adobe-cs3-licensing-for-this-product-has-stopped-working-fix/</link>
		<comments>http://otaqui.com/blog/699/adobe-cs3-licensing-for-this-product-has-stopped-working-fix/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 09:55:00 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=699</guid>
		<description><![CDATA[After getting a new computer, and restoring my old system from a Time Machine backup, I found my Adobe Web Premium CS3 stopped working. Every application I started (Photoshop, Fireworks, Flash, etc) gave the error message: Licensing for this product has stopped working. After following every suggestion I could find in Adobe&#8217;s knowledge base and [...]]]></description>
			<content:encoded><![CDATA[<p>After getting a new computer, and restoring my old system from a Time Machine backup, I found my Adobe Web Premium CS3 stopped working.  Every application I started (Photoshop, Fireworks, Flash, etc) gave the error message:</p>
<blockquote><p>Licensing for this product has stopped working.</p></blockquote>
<p>After following every suggestion I could find in Adobe&#8217;s knowledge base and various online articles, I still couldn&#8217;t get any of the applications to start.</p>
<p>As a final act of complete desperation, after many rounds of removal-reboot-reinstall, I finally ran the installer and chose a product that I had not installed before (Contribute).  Once that was done I started up the new app, and it asked me for my license key &#8211; which I entered and the app started.  Then I tried Photoshop and it started up fine!</p>
<p>So &#8211; if you didn&#8217;t do a complete install int he first place, one of the easiest things could be to add a new app to your install, and get that to reset your licensing for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/699/adobe-cs3-licensing-for-this-product-has-stopped-working-fix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>If We Had A Web Of Data I Would Build &#8230;</title>
		<link>http://otaqui.com/blog/643/if-we-had-a-web-of-data-i-would-build/</link>
		<comments>http://otaqui.com/blog/643/if-we-had-a-web-of-data-i-would-build/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 14:24:45 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[linked-data]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=643</guid>
		<description><![CDATA[Georgi Kobilarov has a post up asking what would you build with a function web of data and I have a few ideas. These all need fleshing out (and probably spell-checking ;), but if I didn&#8217;t post them now I might never get round to it! Shopping I think there are a few ways you [...]]]></description>
			<content:encoded><![CDATA[<p>Georgi Kobilarov has a post up asking <a href="http://blog.georgikobilarov.com/2010/04/with-a-web-of-data-what-would-you-do/">what would you build with a function web of data</a> and I have a few ideas.  These all need fleshing out (and probably spell-checking ;), but if I didn&#8217;t post them now I might never get round to it!</p>
<p><strong>Shopping</strong></p>
<p>I think there are a few ways you could use a web of linked data to make online grocery shopping better &#8211; comparing prices across stores, create shopping lists from recipes, and get recipes from lists of goods.</p>
<p><strong>Recruitment</strong></p>
<p>With jobs and resumés available as linked data, recruitment could become much more machine-enabled, giving managers better abilities to find people themselves rather than relying on agents who don&#8217;t always understand their clients&#8217; business or industry.  It could also help people looking for work in a similar way.  Types of skill, training and qualification could also be linked in, as could &#8220;linkedin&#8221; style personal recommendations.</p>
<p><strong>E-Learning</strong></p>
<p>Serious attempts have been made at making learning materials shareable and reusable.  As part of the data web, finding and consuming these materials becomes easier but more than that we could build a development plan generator.  Competency can be aligned to skills or training received, something that could be useful to government departments, schools, universities and business.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/643/if-we-had-a-web-of-data-i-would-build/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BBC Fisheye Greasemonkey Script</title>
		<link>http://otaqui.com/blog/646/bbc-fisheye-greasemonkey-script/</link>
		<comments>http://otaqui.com/blog/646/bbc-fisheye-greasemonkey-script/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 09:15:08 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[greasemonkey]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=646</guid>
		<description><![CDATA[Greasemonkey script to reformat &#8220;Author&#8221; select elements on the BBC&#8217;s Fisheye repository browser, which are ridiculously long (because they contain a considerable chunk of certificate data) which messes with the whole page layout. Shrinking the selects to a more reasonable width fixes this and makes the site more usable. http://otaqui.com/code/bbc-fisheye/bbc-fisheye.user.js // ==UserScript== // @name BBC [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.greasespot.net/">Greasemonkey</a> script to reformat &#8220;Author&#8221; select elements on the BBC&#8217;s Fisheye repository browser, which are ridiculously long (because they contain a considerable chunk of certificate data) which messes with the whole page layout.  Shrinking the selects to a more reasonable width fixes this and makes the site more usable.</p>
<p><a href="http://otaqui.com/code/bbc-fisheye/bbc-fisheye.user.js">http://otaqui.com/code/bbc-fisheye/bbc-fisheye.user.js</a></p>
<pre class="brush: javascript">
// ==UserScript==
// @name           BBC FishEye
// @namespace      http://otaqui.com/code/bbc-fisheye
// @description    Make BBC&#039;s Fisheye look more like it should
// @include        https://fisheye.dev.bbc.co.uk/*
// ==/UserScript==
var elems = document.evaluate(
    &#039;//select[@name=&quot;wbauthor&quot;]&#039;,
    document,
    null,
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
    null
);
var i=0;
var sel;
while ( sel = elems.snapshotItem(i++) ) sel.style.width = &#039;200px&#039;;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/646/bbc-fisheye-greasemonkey-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash Script for Serving Multiple Trac Projects and Sharing Authentication</title>
		<link>http://otaqui.com/blog/600/bash-script-for-serving-multiple-trac-projects-and-sharing-authentication/</link>
		<comments>http://otaqui.com/blog/600/bash-script-for-serving-multiple-trac-projects-and-sharing-authentication/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 08:55:25 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=600</guid>
		<description><![CDATA[I use Trac for personal projects, and I share some of these out with people as required. I use tracd (TracStandalone) for this, rather than a full-blown apache setup, since it serves my needs quite nicely and is a lot easier to turn on and off as required without tweaking apache config and rebooting the [...]]]></description>
			<content:encoded><![CDATA[<p>I use Trac for personal projects, and I share some of these out with people as required.  I use tracd (TracStandalone) for this, rather than a full-blown apache setup, since it serves my needs quite nicely and is a lot easier to turn on and off as required without tweaking apache config and rebooting the whole webserver.</p>
<p>All my projects live under a single parent directory, and I prefer to share a single users digest file between them all &#8211; so ideally I wanted to share a single tracd to run all my projects.  This is fairly straightforward on the command line:</p>
<pre class="brush: bash">
tracd --hostname=webhost.com -p 9876 \
--auth=&quot;*,/path/projects/people.htdigest,Realm&quot; \
/path/projects/p1 \
/path/projects/p2
</pre>
<p>That is &#8230;.<br />
Line 1 &#8211; start tracd for a given hostname and port,<br />
Line 2 &#8211; specify auth for all projects (*), the auth file and the &#8220;Realm&#8221; you specified when creating the file with apache&#8217;s htdigest command<br />
Lines 3+ &#8211; specify as many projects as you want to run</p>
<p>This is ok with a couple of projects, but gets unwieldy quite quickly.  What I needed was a little shell script to open up all projects under a given directory quickly.  Here&#8217;s what I came up with:</p>
<pre class="brush: bash">
#!/bin/bash

# make / truncate a temp file to store names:
temp=/tmp/tracdpaths
&gt; $temp

# specify base directory:
base=/path/projects/

# output all subdirectories to temp file:
find $base -maxdepth 1 -mindepth 1 -type d \
-exec echo -n &quot;{} &quot; &gt; $temp \;

# now start tracd
tracd --hostname=webhost.com -p 9876 \
--auth=&quot;*,/path/projects/people.htdigest,Realm&quot; \
`cat $temp`
</pre>
<p>Essentially this script uses &#8216;find&#8217; to get all of the directories exactly 1 level down from your projects directory, and will echo their paths to a temp file (suppressing the newlines).  It will then run run tracd, appending the contents of this file to the end of the call.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/600/bash-script-for-serving-multiple-trac-projects-and-sharing-authentication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom User Agent with Cucumber Tests and Webrat in Mechanize Mode</title>
		<link>http://otaqui.com/blog/541/custom-user-agent-with-cucumber-tests-and-webrat-in-mechanize-mode/</link>
		<comments>http://otaqui.com/blog/541/custom-user-agent-with-cucumber-tests-and-webrat-in-mechanize-mode/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 12:08:50 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=541</guid>
		<description><![CDATA[It&#8217;s pretty straightforward to set a custom user agent with mechanize if you&#8217;re using it directly, KickAssLabs has a good example. If you&#8217;re using Mechanize through Webrat though, things are a little different. The nice thing though, is that you can do this in a step definition &#8211; allowing features to be based on different [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s pretty straightforward to set a custom user agent with mechanize if you&#8217;re using it directly, <a href="http://www.kickasslabs.com/2009/03/31/quick-hits-setting-the-user-agent-header-in-webrat/">KickAssLabs has a good example</a>.</p>
<p>If you&#8217;re using Mechanize through Webrat though, things are a little different.  The nice thing though, is that you can do this in a step definition &#8211; allowing features to be based on different browser scenarios (this is great if you&#8217;re developing across devices).</p>
<p>First off there are two accessors of interest in mechanize, &#8220;user_agent&#8221; and &#8220;user_agent_alias&#8221;.  The former is fairly self evident and lets you define the user agent at will, the latter gives you shortcut access to a list of common user agents baked into mechanize.  You can see that list in <a href="http://github.com/tenderlove/mechanize/blob/master/lib/mechanize.rb#L48">the mechanize.rb source</a>.  It contains some desktop browsers, the iPhone and the default Mechanize UA strings.</p>
<p>If you&#8217;re happy with the default alias list, you can just write a step definition like this:</p>
<pre class="brush: ruby">
Given /^I am using the &quot;(.*)&quot; browser$/ do |browser|
  webrat.adapter.mechanize.user_agent_alias = browser
end
</pre>
<p>And then you can use this in your features:</p>
<pre class="brush: text">
Given I am using the &quot;iPhone&quot; browser
When I visit the home page
Then I should see &quot;You are using an iPhone!&quot;
</pre>
<p>If you want to be able to specify your own UA strings, and as I said this is especially likely if you are developing cross-device applications where capabilities are important, then you can just use your own hash instead, and set &#8220;user_agent&#8221; rather than &#8220;user_agent_alias&#8221;:</p>
<pre class="brush: ruby">
Given /^I am using the &quot;(.*)&quot; browser$/ do |browser|
  UA_ALIASES = {
    &quot;Nokia N95&quot; =&gt; &quot;Mozilla/5.0 (SymbianOS/9.2; .....&quot;,
    &quot;Palm Pre&quot; =&gt; &quot;Mozilla/5.0 (webOS/1.0; .....&quot;
  }
  webrat.adapter.mechanize.user_agent = UA_ALIASES[browser]
end
</pre>
<p>With a little tweaking you could use both the included list and, if the string from your feature isn&#8217;t there, look in a custom list too.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/541/custom-user-agent-with-cucumber-tests-and-webrat-in-mechanize-mode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Complete List of Special Google Chrome URLs</title>
		<link>http://otaqui.com/blog/539/complete-list-of-special-google-chrome-urls/</link>
		<comments>http://otaqui.com/blog/539/complete-list-of-special-google-chrome-urls/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 20:12:54 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=539</guid>
		<description><![CDATA[Google Chrome has quite a lot of special URLs. Some of these are covered over at Lifehacker in their post on Chrome&#8217;s about pages, but the meta &#8220;about:&#8221; protocol isn&#8217;t the only one that Chrome uses. Waha, a user on the chromeplugins.org site posted a much more complete list of URL schemes that Chrome uses. [...]]]></description>
			<content:encoded><![CDATA[<p>Google Chrome has quite a lot of special URLs.  Some of these are covered over at Lifehacker in their <a href="http://lifehacker.com/5045164/google-chromes-full-list-of-special-about-pages">post on Chrome&#8217;s about pages</a>, but the meta &#8220;about:&#8221; protocol isn&#8217;t the only one that Chrome uses.</p>
<p>Waha, a user on the chromeplugins.org site posted <a href="http://www.chromeplugins.org/google/chrome-tips-tricks/about-chrome-more-internal-urls-7793.html">a much more complete list of URL schemes</a> that Chrome uses.  Waha was looking at the <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/url_constants.cc">url_constants.cc</a> source file, along with some other stuff, to work this list out.</p>
<p>I&#8217;ve ignored the virtually universal set of protocols that are in just about every browser: http, https, ftp, file, data, feed and javascript, and also the URLs that cannot be entered into the address bar (not using Chrome 5 on OS X Snow Leopard anyway).</p>
<p>Without further ado, here&#8217;s the list:</p>
<ul>
<li><a href="about:blank">about:blank</a> &#8211; the empty page</li>
<li><a href="about:cache">about:cache</a> &#8211; disk and memory cache information</li>
<li><a href="about:net-internals">about:net-internals</a> &#8211; network information including Proxy, HostResolver, URLRequest, HTTPCache and SocketStream</li>
<li><a href="about:crash">about:crash</a> &#8211; the page shown when a tab process crashes</li>
<li><a href="about:credits">about:credits</a> &#8211; list of libraries and other code used in Chrome, with links</li>
<li>about:hang &#8211; this seems to kill a tab for me (I haven&#8217;t linked for that reason &#8211; use at your own risk)</li>
<li><a href="about:memory">about:memory</a> &#8211; memory usage of the various processes</li>
<li>about:shorthang &#8211; see about:hang above</li>
<li><a href="about:terms">about:terms</a> &#8211; Google Chrome Terms of Service</li>
<li>about:inducebrowsercrashforrealz &#8211; not many lolz here</li>
<li><a href="chrome://extensions/">chrome://extensions/</a> &#8211; installed extensions</li>
<li><a href="chrome://history/">chrome://history/</a> &#8211; your browsing history</li>
<li><a href="chrome://newtab">chrome://newtab</a> &#8211; the new tab page</li>
<li><a href="chrome://thumb/http://www.google.com/">chrome://thumb/http://www.google.com/</a> &#8211; thumbnail for a page you&#8217;ve visited</li>
<li><a href="chrome://favicon/http://www.google.com/">chrome://favicon/http://www.google.com/</a> &#8211; favicon for a page you&#8217;ve visited</li>
<li><a href="view-source:http://otaqui.com/blog/539/complete-list-of-special-google-chrome-urls">view-source:http://otaqui.com/blog/539/complete-list-of-special-google-chrome-urls</a> &#8211; view the source of a web page</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/539/complete-list-of-special-google-chrome-urls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BBC Standards Ruby Gem</title>
		<link>http://otaqui.com/blog/526/bbc-standards-ruby-gem/</link>
		<comments>http://otaqui.com/blog/526/bbc-standards-ruby-gem/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 22:19:52 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[bbc]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=526</guid>
		<description><![CDATA[Thanks to some brilliant tidying up of my work by my good friend <a href="http://www.metade.org/">Patrick</a>, there is now a <a href="http://github.com/metade/bbc_standards">bbc_standards ruby gem</a> which you can use to validate pages against some of the <a href="http://www.bbc.co.uk/guidelines/futuremedia/technical/">BBC Technical Guidelines</a>]]></description>
			<content:encoded><![CDATA[<p>Thanks to some brilliant tidying up of my work by my good friend <a href="http://www.metade.org/">Patrick</a>, there is now a <a href="http://github.com/metade/bbc_standards">bbc_standards ruby gem</a> which you can use to validate pages against some of the <a href="http://www.bbc.co.uk/guidelines/futuremedia/technical/">BBC Technical Guidelines</a> (more specifically the &#8220;Semantic Mark-up&#8221; and &#8220;XHTML Integrity&#8221; standards).</p>
<p>This gem was originally designed to work with Cucumber, and initially was intended to just validate pages against the XHTML Strict doctype that BBC pages are usually required to use.  Since it uses Nokogiri for validation &#8211; against the XML Schema rather than the Doctype for what it&#8217;s worth &#8211; the testing is a) strict and b) *fast*.  There are no external webservice calls, so it is fine to test all page loads within Cucumber, even testing the same URI many times over (since the bottleneck will almost certainly be your app by some margin.</p>
<p>I&#8217;m currently working on a post about using the gem for the <a href="http://www.bbc.co.uk/blogs/webdeveloper/">BBC Web Developer blog</a>, but I thought I&#8217;d point any interested parties at the code here and now.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/526/bbc-standards-ruby-gem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create A Custom CakePHP Console Application Using Shells, Tasks, Models and Controllers</title>
		<link>http://otaqui.com/blog/448/create-a-custom-cakephp-console-application-using-shells-tasks-models-and-controllers/</link>
		<comments>http://otaqui.com/blog/448/create-a-custom-cakephp-console-application-using-shells-tasks-models-and-controllers/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 14:43:54 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=448</guid>
		<description><![CDATA[CakePHP doesn&#8217;t just come with its own console applications for baking code, managing ACL, inspecting classes, manipulating the schema, internationalisation and running the testsuite (whew!) it also lets you write your own console applications. [NB: I always have an external cake core directory, for easy swapping. The code examples all assume you have done this, [...]]]></description>
			<content:encoded><![CDATA[<p>CakePHP doesn&#8217;t just come with its own console applications for baking code, managing ACL, inspecting classes, manipulating the schema, internationalisation and running the testsuite (whew!) it also lets you write your own console applications.</p>
<p><em>[NB: I always have an external cake core directory, for easy swapping.  The code examples all assume you have done this, or at least created an alias in your terminal to point to the core cake directory with something like: alias cake='../cake/console/cake'</em></p>
<p>First off, to find out about the current console applications you are running jump into a terminal and cd to your app directory, then simple run the &#8220;cake&#8221; command to see what you have available:</p>
<pre class="brush: bash">
app_dir $ cake
</pre>
<p>This will output a list of available shells in the core cake library and the two &#8220;vendors&#8221; directories.</p>
<p>So how do you go about creating your own?  The <a href="http://book.cakephp.org/view/110/Creating-Shells-Tasks">CakePHP documentation on creating Shells &amp; Tasks</a> is a good place to start.</p>
<p>An application I&#8217;ve needed to automate with a cron-job, and also have available as an in-app, on-demand function is the sending of emails.  I&#8217;m not talking about writing a mass mailer here, but rather just sending out course information to users who are booked to attend &#8211; and doing so both automatically and on-demand when an administrator decides it is necessary.  This is an obvious instance where you don&#8217;t want to duplicate the code in the controller and the shell.</p>
<p>In my case, I have several kinds of email I want to send, so I set up a generalised Task, used by several different Shells.  The advantage of doing things this way around is that any other Shells can also make use of the emailer Task in the fututre.</p>
<p>Here&#8217;s some simplified code from one of the Shells, a &#8220;booking reminder&#8221; for delegates:</p>
<pre class="brush: php">
// file app/vendors/shells/booking_reminder.php
&lt;?php
class BookingReminderShell extends Shell {
  var $uses = array(&quot;Booking&quot;,&quot;User&quot;,&quot;Course&quot;);
  var $tasks = array(&quot;Emailer&quot;);
  public function main() {
    // use $this-&gt;Booking etc as if we were in a controller
    // use $this-&gt;Emailer for the task
  }
}
</pre>
<p>And then we have the Task:</p>
<pre class="brush: php">
// file app/vendors/shells/tasks/emailer.php
&lt;?php
class Emailer extends Shell {
  public function execute() {
    // this method is called when the task is instantiated,
    // gives you a chance to setup
  }
  public function send($to,$from,$subject,$message,$attachments=null) {
    // called from shell with: $this-&gt;Emailer-&gt;send();
  }
}
</pre>
<p>Note how both Shells and tasks extend from the base &#8220;Shell&#8221; class.  Also note how Shells use a method called &#8220;main()&#8221; when they are run, whereas Tasks use &#8220;execute()&#8221; when they are created.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/448/create-a-custom-cakephp-console-application-using-shells-tasks-models-and-controllers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using a Proxy with Cucumber, Webrat and Mechanize</title>
		<link>http://otaqui.com/blog/458/using-a-proxy-with-cucumber-webrat-and-mechanize/</link>
		<comments>http://otaqui.com/blog/458/using-a-proxy-with-cucumber-webrat-and-mechanize/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 08:15:36 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=458</guid>
		<description><![CDATA[If you&#8217;re writing Cucumber tests using Webrat and Mechanize to test a site, and you are behind a proxy server, you can do something like this to tell mechanize about it in your webrat_steps.rb file: When /^I am on (.+)$/ do &#124;page_name&#124; webrat.adapter.mechanize.set_proxy('proxy.host.com',8080) visit path_to(page_name) end I&#8217;m sure there&#8217;s a tidier way to do this, [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re writing Cucumber tests using Webrat and Mechanize to test a site, and you are behind a proxy server, you can do something like this to tell mechanize about it in your webrat_steps.rb file:</p>
<p><code><br />
When /^I am on (.+)$/ do |page_name|<br />
    webrat.adapter.mechanize.set_proxy('proxy.host.com',8080)<br />
    visit path_to(page_name)<br />
end<br />
</code></p>
<p>I&#8217;m sure there&#8217;s a tidier way to do this, but it&#8217;s quick and it works with the following gem versions:</p>
<p>Cucumber 0.3.11<br />
Webrat 0.5.3<br />
Mechanize 0.9.3</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/458/using-a-proxy-with-cucumber-webrat-and-mechanize/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Disable Debug Output for Ajax in CakePHP</title>
		<link>http://otaqui.com/blog/430/disable-debug-output-for-ajax-in-cakephp/</link>
		<comments>http://otaqui.com/blog/430/disable-debug-output-for-ajax-in-cakephp/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 09:15:46 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=430</guid>
		<description><![CDATA[If you are developing a CakePHP application and you have the debug value set to anything greater than 0 in your config/core.php file, you will find that Ajax requests will also get the extra information appended to the output. In order to circumvent this add this to your &#8220;app_controller.php&#8221; file (which sits directly inside the [...]]]></description>
			<content:encoded><![CDATA[<p>If you are developing a <a href="http://cakephp.org">CakePHP</a> application and you have the debug value set to anything greater than 0 in your config/core.php file, you will find that Ajax requests will also get the extra information appended to the output.</p>
<p>In order to circumvent this add this to your &#8220;app_controller.php&#8221; file (which sits directly inside the &#8220;app/&#8221; dir, rather than in &#8220;app/controllers&#8221;):</p>
<pre class="brush: php">
&lt;?php
class AppController extends Controller {
  var $components = array(&#039;RequestHandler&#039;);
  var $helpers = array(&#039;Html&#039;,&#039;Form&#039;,&#039;Ajax&#039;);
  function beforeFilter() {
    if ( $this-&gt;RequestHandler-&gt;isAjax() ) {
      Configure::write(&#039;debug&#039;,0);
    }
  }
}
?&gt;
</pre>
<p>Note that while this will disable the debugging output, it will also have other affects too (for the life of the Ajax Request) like extending the length of time that the &#8220;schema&#8221; is cached.  This should make little or no difference, but is worth remembering.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/430/disable-debug-output-for-ajax-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mozilla Fennec Alpha 2 Release</title>
		<link>http://otaqui.com/blog/428/mozilla-fennec-alpha-2-release/</link>
		<comments>http://otaqui.com/blog/428/mozilla-fennec-alpha-2-release/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 20:29:29 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[links]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/428/mozilla-fennec-alpha-2-release/</guid>
		<description><![CDATA[Mozilla has released the second alpha of Fennec, their mobile browser. There&#8217;s a short but sweet overview of Fennec on Vimeo which is worth checking out. I think almost regardless of it&#8217;s performance improvements the real game-changing potential here is the inevitable swathe of add-ons and extensions that will be, and in some cases such [...]]]></description>
			<content:encoded><![CDATA[<p>Mozilla has <a href="http://blog.mozilla.com/blog/2008/12/23/fennec-alpha-2-released/">released the second alpha of Fennec</a>, their mobile browser.  There&#8217;s a short but sweet <a href="http://www.vimeo.com/2577978">overview of Fennec on Vimeo</a> which is worth checking out.</p>
<p>I think almost regardless of it&#8217;s <a href="http://starkravingfinkle.org/blog/2008/12/fennec-alpha2-performance/">performance improvements</a> the real game-changing potential here is the inevitable swathe of add-ons and extensions that will be, and in some cases such as <a href="http://hackademix.net/2008/12/23/noscript-for-fennec-update/">NoScript</a> already are, available.</p>
<p>I don&#8217;t think that any web developer who has used it would want to go back to a world without <a href="http://getfirebug.com/">Firebug</a> and I also think that it&#8217;s influence on <a href="http://webkit.org">WebKit</a>&#8216;s developer tools is fairly clear to see.</p>
<p>So I really hope that support for Fennec spreads beyond the Nokia 810 soon, and that it&#8217;s as instrumental as Firefox was in re-igniting browser development, especially from a developer-tool perspective.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/428/mozilla-fennec-alpha-2-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Page Optimisation Technique &#8211; Build Two Rows For The Fold</title>
		<link>http://otaqui.com/blog/415/page-optimisation-technique-build-two-rows-for-the-fold/</link>
		<comments>http://otaqui.com/blog/415/page-optimisation-technique-build-two-rows-for-the-fold/#comments</comments>
		<pubDate>Sat, 07 Feb 2009 14:01:07 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[page-optimisation]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=415</guid>
		<description><![CDATA[Despite suggestions to the contrary, we web developers still very much have to work with the concept of a &#8220;fold&#8221; &#8211; that is the part of the page that is immediately visible when a user visits your site. This is usually considered to mean &#8220;before the user has to scroll down&#8221; but can also just [...]]]></description>
			<content:encoded><![CDATA[<p>Despite suggestions to the contrary, we web developers still very much have to work with the concept of a &#8220;fold&#8221; &#8211; that is the part of the page that is immediately visible when a user visits your site.</p>
<p>This is usually considered to mean &#8220;before the user has to scroll down&#8221; but can also just mean &#8220;the stuff they look at first&#8221; even if they have a really big monitor.  This gives us a slightly more useful thing to think about &#8211; the first &#8220;batch&#8221; of content that will be at the top of the page, and incidentally will be the entirety of what a considerable portion of our users see first.</p>
<p>So, I have a suggestion to all the web *designers* out there to mull over: introduce the idea of &#8220;Two Rows&#8221; in your design.  By having a single row that is for content &#8220;above the fold&#8221; and a second one for everything below, we can get the absolute minimum &#8220;perceived load time&#8221; of the page.</p>
<p>Let&#8217;s have a look at a fairly standard wireframe of a page:</p>
<div id="attachment_416" class="wp-caption aligncenter" style="width: 430px"><a href="http://otaqui.com/blog/wp-content/uploads/layout_normal.png"><img src="http://otaqui.com/blog/wp-content/uploads/layout_normal.png" alt="&quot;Normal&quot; three column page layout" title="Normal three column page layout" width="420" height="420" class="size-full wp-image-416" /></a><p class="wp-caption-text">Normal three column page layout</p></div>
<p>This will be more or less as you expect, a header and footer with 3 (or however many) columns in between.</p>
<p>Now let&#8217;s have a look at a wireframe designed for the fold:</p>
<div id="attachment_417" class="wp-caption aligncenter" style="width: 430px"><a href="http://otaqui.com/blog/wp-content/uploads/layout_optimised.png"><img src="http://otaqui.com/blog/wp-content/uploads/layout_optimised.png" alt="Optimised For the Fold Layout" title="Optimised For the Fold Layout" width="420" height="420" class="size-full wp-image-417" /></a><p class="wp-caption-text">Optimised For the Fold Layout</p></div>
<p>As you can see, I&#8217;ve changed the structure to split the main content completely into two distinct rows.</p>
<p>The advantage here is that we developers can do several things to make the first row appear as quickly as possible:</p>
<ol>
<li>Firstly we don&#8217;t have to do anything.  The source order itself will mean that the content of the first row is loaded first, meaning that you won&#8217;t have that all-to-common &#8220;pause for the right-hand-column&#8221; to load.</li>
<li>Place all styles at the top of the page, and all required scripts between the two rows &#8211; this will make the page appear correctly styled and have javascript-driven functionality available.</li>
<li>Taking the point above to a further degree, we could in fact *split* the javascript (and possibly even css) files, which is normally a abad idea, to provide only the functionality required for the &#8220;first row&#8221;, and then load other resources afterwards.  This is a rather extreme approach, but could help if your site really needs the content &#8220;above the fold&#8221; to be absolutely as fast as possible even at the cost of overall page performance.</li>
<li>With a dynamic site, we can flush the buffer after the first row, and leave any further processing overhead to happen after that much of the page has been sent to the browser.</li>
</ol>
<p>There is no real need for the actual design to exagerate the rows in the same way that the wireframe does &#8211; but you would need a horizontal split of the content at that point to make things as easy and flexible as possible.  This limitation can be overcome with CSS, and possibly javascript, but this will rapidly become fiddly and hard to maintain.</p>
<p>To demonstrate what I mean, I took the Guardian&#8217;s homepage, and reworked it (as a graphic) to have the horizontal split required for Two Rows, without really appearing much different to the current, pure-column structure.</p>
<p>Before:<br />
<div id="attachment_423" class="wp-caption aligncenter" style="width: 310px"><a href="http://otaqui.com/blog/wp-content/uploads/guardian_original.jpg"><img src="http://otaqui.com/blog/wp-content/uploads/guardian_original-300x231.jpg" alt="Original Guardian Homepage" title="Guardian Original" width="300" height="231" class="size-medium wp-image-423" /></a><p class="wp-caption-text">Original Guardian Homepage</p></div></p>
<p>And after (with the &#8220;second row&#8221; being slightly greyed out):<br />
<div id="attachment_422" class="wp-caption aligncenter" style="width: 310px"><a href="http://otaqui.com/blog/wp-content/uploads/guardian_modified.jpg"><img src="http://otaqui.com/blog/wp-content/uploads/guardian_modified-300x231.jpg" alt="Modified Guardian Page" title="Guardian Modified" width="300" height="231" class="size-medium wp-image-422" /></a><p class="wp-caption-text">Modified Guardian Page</p></div></p>
<p>This example worked fairly well in terms of &#8220;hiding&#8221; the row lines since some things are bumped right up to them and others have varying amounts of whitespace either side.</p>
<p>I must admit that I&#8217;ve never implemented this technique, but I certainly believe that it could have significant impact for a site like the Guardian that has a large amount of content &#8220;below the fold&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/415/page-optimisation-technique-build-two-rows-for-the-fold/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Model and Field Result Set in CakePHP</title>
		<link>http://otaqui.com/blog/402/custom-model-and-field-result-set-in-cakephp/</link>
		<comments>http://otaqui.com/blog/402/custom-model-and-field-result-set-in-cakephp/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 17:22:44 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=402</guid>
		<description><![CDATA[If you&#8217;re using CakePHP and want to perform a custom SQL query while forcing your results into an arbitrary Model-based array when they are given back to you, you could do a lot worse than using grigri&#8217;s (who is a fellow South Westerner and therefore obviously a good bloke ;) DboMysqlEx (Mysql Extended) Class, or [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re using CakePHP and want to perform a custom SQL query while forcing your results into an arbitrary Model-based array when they are given back to you, you could do a lot worse than using grigri&#8217;s (who is a fellow South Westerner and therefore obviously a good bloke ;) DboMysqlEx (Mysql Extended) Class, or at least this particular part of it:</p>
<pre class="brush: php">&lt;?php
require_once (LIBS . &#039;model&#039; . DS . &#039;datasources&#039; . DS . &#039;dbo&#039; . DS . &#039;dbo_mysql.php&#039;);
class DboMysqlEx extends DboMysql {
   var $description = &quot;MySQL DBO Driver - Extended&quot;;
   // Override resultSet to allow for Model__field type aliases
   function resultSet(&amp;$results) {
		if (isset($this-&gt;results) &amp;&amp; is_resource($this-&gt;results) &amp;&amp; $this-&gt;results != $results) {
			mysql_free_result($this-&gt;results);
		}
       $this-&gt;results =&amp; $results;
       $this-&gt;map = array();
       $num_fields = mysql_num_fields($results);
       $index = 0;
       $j = 0;
       while ($j &lt; $num_fields) {
           $column = mysql_fetch_field($results,$j);
           if (!empty($column-&gt;table)) {
               $this-&gt;map[$index++] = array($column-&gt;table, $column-&gt;name);
           } else {
               if (strpos($column-&gt;name, &#039;__&#039;)) {
                   $parts = explode(&#039;__&#039;, $column-&gt;name);
                   $this-&gt;map[$index++] = array($parts[0], $parts[1]);
               } else {
                   $this-&gt;map[$index++] = array(0, $column-&gt;name);
               }
           }
           $j++;
       }
   }
}
?&gt;
</pre>
<p>This code, which overrides the default MySQL DBO, allows you to SELECT something AS Modelname__Fieldname (with a double underscore) and will end up populating your result set as you would like it to ($results['Modelname']['Fieldname']).</p>
<p>In order to use a custom datasource, copy the code and save it as &#8220;/cake_dir/app/models/datasources/dbo/dbo_mysqlex.php&#8221; and edit your &#8220;/cake_dir/app/config/database.php&#8221; file so that it uses the &#8220;mysqlex&#8221; driver instead of plain old &#8220;mysql&#8221;.</p>
<p>This all came from a discussion on the excellent <a href="http://groups.google.com/group/cake-php/browse_thread/thread/f823cc7f168cd619?hl=en">CakePHP Google Group</a></p>
<p>Grigri posted <a href="http://bin.cakephp.org/view/1781729779">a copy of his modified MySQL Extended DBO</a> online if you want some more of his nice features like backtracing.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/402/custom-model-and-field-result-set-in-cakephp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Selecting a Different Table Column if the Original Record is NULL in MYSQL Using IFNULL</title>
		<link>http://otaqui.com/blog/398/selecting-a-different-table-column-if-the-original-record-is-null-in-mysql-using-ifnull/</link>
		<comments>http://otaqui.com/blog/398/selecting-a-different-table-column-if-the-original-record-is-null-in-mysql-using-ifnull/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 13:31:13 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=398</guid>
		<description><![CDATA[MySQL&#8217;s documentation is OK, but it&#8217;s examples are sometimes quite poor. I have a particular setup where values across two tables &#8211; a course table and a schedule table which relates to it &#8211; can be effectively &#8220;overridden&#8221;. The idea is that for any given course, one can set &#8220;default&#8221; values, and then these can [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL&#8217;s documentation is OK, but it&#8217;s examples are sometimes quite poor.</p>
<p>I have a particular setup where values across two tables &#8211; a course table and a schedule table which relates to it &#8211; can be effectively &#8220;overridden&#8221;.  The idea is that for any given course, one can set &#8220;default&#8221; values, and then these can be overridden every time a course is actually scheduled to happen.</p>
<p>The courses table looks something like this:</p>
<p>COURSES<br />
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY<br />
title VARCHAR(255) NOT NULL<br />
subtitle VARCHAR(255) NOT NULL<br />
description TEXT NOT NULL</p>
<p>SCHEDULES<br />
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY<br />
course_id INT(11) NOT NULL<br />
subtitle VARCHAR(255) NULL<br />
description TEXT NULL</p>
<p>Hopefully you can see what I would want during a SELECT &#8211; to get the values from the schedules table if they aren&#8217;t null, or otherwise get the value from the courses table if they are.</p>
<p>This is achieved with the IFNULL built in function in MySQL.  IFNULL takes two arguments, and returns the first argument if it (the first argument that is) is not null, or the second argument if it is.  The actual SQL for my example looks like this:</p>
<p>SELECT courses.title, IFNULL(schedules.subtitle,courses.subtitle) AS subtitle, IFNULL(schedules.description,courses.description) AS description FROM schedules LEFT JOIN courses ON schedule.course_id=course.id;</p>
<p>This will give you the &#8220;subtitle&#8221; and &#8220;description&#8221; values from the linked table (schedules) if they exist, or the default values from the original table (courses) if they don&#8217;t.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/398/selecting-a-different-table-column-if-the-original-record-is-null-in-mysql-using-ifnull/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MySQL Data Files In MAMP Pro</title>
		<link>http://otaqui.com/blog/341/mysql-data-files-in-mamp-pro/</link>
		<comments>http://otaqui.com/blog/341/mysql-data-files-in-mamp-pro/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 07:32:21 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/blog/?p=341</guid>
		<description><![CDATA[It took me a little searching to find where MAMP Pro (I couldn't say whether MAMP is the same) puts its MySQL data files, so I thought I'd blog it]]></description>
			<content:encoded><![CDATA[<p>It took me a little searching to find where MAMP Pro (I couldn&#8217;t say whether MAMP is the same) puts its MySQL data files, so I thought I&#8217;d blog it:</p>
<p><code>
<pre>/Library/Application Support/living-e/MAMP PRO/db/mysql</pre>
<p></code></p>
<p>I had been looking in my User directory&#8217;s version of the same path (which is where MAMP Pro stores config files), but it makes perfect sense in this context that databases are shared while configuration isn&#8217;t.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/341/mysql-data-files-in-mamp-pro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing with Mono and MonoDevelop on OS X</title>
		<link>http://otaqui.com/blog/101/developing-with-mono-and-monodevelop-on-os-x/</link>
		<comments>http://otaqui.com/blog/101/developing-with-mono-and-monodevelop-on-os-x/#comments</comments>
		<pubDate>Thu, 26 Jun 2008 13:12:59 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/wp/2008/06/developing-with-mono-and-monodevelop-on-os-x/</guid>
		<description><![CDATA[Having just downloaded and installed MonoDevelop for OS X I can say that the process of getting up and running is an absolute breeze &#8211; only involving the normal mac &#8216;download, unpack and drop into Applications&#8217; routine. MonoDevelop (and indeed Mono itself) allows you to build several types of application &#8211; C++, C#, ASP.Net and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.monodevelop.com/"><img src="http://otaqui.com/wp/wp-content/uploads/mono-logo.png" alt="MonoDevelop" style="float:left; margin-right:10px; margin-bottom:10px;border:0px;"></a></p>
<p>Having just downloaded and installed <a href="http://www.monodevelop.com/">MonoDevelop</a> for OS X I can say that the process of getting up and running is an absolute breeze &#8211; only involving the normal mac &#8216;download, unpack and drop into Applications&#8217; routine.</p>
<p>MonoDevelop (and indeed <a href="http://www.mono-project.com/">Mono</a> itself) allows you to build several types of application &#8211; C++, C#, ASP.Net and the like.  You can build cross-platform executables &#8211; either console-based or with a GUI (the application comes with quick-start project templates for the Gnome# and GTK# tookits) &#8211; and also web-based projects.  MonoDevelop comes with the xsp server built-in so the code-compile-debug cycle is only a single click away (as a bonus it even opens your browser for you).</p>
<p>MonoDevelop is a Gnome application, so a minor annoyance when using it with OS X is the key-binding setup which requires you to use Ctrl over the Apple key for things like copy, paste and save.</p>
<p>I&#8217;m hoping to do some work on a mono-driven ASP.Net application, so I may be posting more on that in the future. For now though &#8211; I&#8217;d like to give a big thanks (and say congratulations) to the MonoDevelop team.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/101/developing-with-mono-and-monodevelop-on-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dojo Toolkit Book Reviews &#8211; &#8216;Dojo: The Definitive Guide&#8217;, &#8216;Mastering Dojo&#8217; and &#8216;Dojo: Using The Dojo Javascript Library To Build Ajax Applications&#8217;</title>
		<link>http://otaqui.com/blog/96/dojo-toolkit-book-reviews-dojo-the-definitive-guide-mastering-dojo/</link>
		<comments>http://otaqui.com/blog/96/dojo-toolkit-book-reviews-dojo-the-definitive-guide-mastering-dojo/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 14:55:42 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/wp/2008/06/dojo-toolkit-book-reviews-dojo-the-definitive-guide-mastering-dojo/</guid>
		<description><![CDATA[Having been working extensively with the Dojo Toolkit, and found their documentation to be extremely useful &#8211; but not exhaustive. I was happy therefore to be able to get hold of the following of pre-release books about the toolkit: Dojo: The Definitive Guide Mastering Dojo Dojo: Using the Dojo JavaScript Library to Build AJAX Applications [...]]]></description>
			<content:encoded><![CDATA[<p>Having been working extensively with the <a href="http://dojotoolkit.org">Dojo Toolkit</a>, and found their <a href="http://doojtoolkit.org/docs">documentation</a> to be extremely useful &#8211; but not exhaustive. I was happy therefore to be able to get hold of the following of pre-release books about the toolkit:</p>
<ul>
<li><a href="http://oreilly.com/catalog/9780596516482/">Dojo: The Definitive Guide</a></li>
<li><a href="http://pragprog.com/titles/rgdojo/mastering-dojo">Mastering Dojo</a></li>
<li><a href="http://safari.oreilly.com/9780321563132">Dojo: Using the Dojo JavaScript Library to Build AJAX Applications</a></li>
</ul>
<p>All three books cover the core dojo library and dijit gui controls and also associated tools like the build system.</p>
<h3>Dojo: The Definitive Guide</h3>
<p><img src="http://otaqui.com/wp/wp-content/uploads/dojo_tdg.jpg" alt="Dojo: The Definitive Guide" style="float:left; margin-right:10px; margin-bottom:10px;" /></p>
<p>If I ever want to get a book on a subject and there is an O&#8217;Reilly Definitive Guide, I will choose that one &#8211; mostly based on having the Javascript and Actionscript equivalents.  I have to say though that I felt a bit let down with this version, as <acronym title="Dojo: The Definitive Guide">DTDG</acronym> isn&#8217;t as comprehensive as I&#8217;m used to from the series.  While the coverage is broad (more so than the other books in this review), it isn&#8217;t all that deep in some key areas &#8211; missing out on some of the gotcha&#8217;s that I have found indispensable when working with Dojo.</p>
<p>I should make it clear that book is very clearly written with clean and helpful examples.  It is also written with the clear intention of readers people build solid web applications beyond using Dojo.</p>
<p>DTDG does go into excellent detail about the Dojo environment &#8211; bootstrapping, the build system, the dijit life-cycle, browser utilities, OOP with Dojo, Event management and the Publish / Subscribe mechanism, Ajax / JSON / JSONP / JSON-RPC, and more besides.  I think few people who aren&#8217;t Dojo committers could read and grok the book without gaining considerable insight.
<p>This puts the book in context &#8211; it isn&#8217;t really for the average developer who wants to get an application up-and-running with Dojo.  I would say it is for someone who wants a deeper understanding of the structure of the library, rather than how to hack something together with it.  A good example is the explanation of dojo.byId(), a clear detailing of the vagaries of document.getElementById() &#8211; and why the former is more useful (however I&#8217;ll leave you to go and buy the book to find out the specifics ;).</p>
<h3 style="clear:left;">Mastering Dojo</h3>
<p><img src="http://otaqui.com/wp/wp-content/uploads/mastering_dojo.jpg" alt="Mastering Dojo" style="float:left; margin-right:10px; margin-bottom:10px;" /></p>
<p>I would recommend this book without hesitation.  I found it informative, helpful and really on-point while trying to create a fairly heavy application on top of Dojo.  Written in the usual Pragmatic Programmer style, it is as easy to read through a chapter as it is to dig into for a specific answer.</p>
<p>Perhaps one omission is the <acronym title="Dojo Objective Harness">DOH</acronym> (which the book incorrectly refers to as the Dojo Object Handler) &#8211; perhaps correctly citing the fact that it is out of it&#8217;s own scope.  Given that DOH is dojo agnostic (your project does need to use Dojo to be tested with DOH) I suppose that is fair enough, but I would love to have seen even an introductory chapter on it.</p>
<p>Mastering Dojo is structured in a slightly confusing way &#8211; confusing at least if you are used to The Book Of Dojo and it&#8217;s well worth searching for terms in the index (unless you&#8217;re reading a PDF!) when the chapter titles don&#8217;t look as though they contain what you need.</p>
<h3 style="clear:left;">Dojo: Using the Dojo JavaScript Library to Build AJAX Applications</h3>
<p><img src="http://otaqui.com/wp/wp-content/uploads/dojo_utdjsltbaa.jpg" alt="Dojo: Using the Dojo JavaScript Library to Build AJAX Applications" style="float:left; margin-right:10px; margin-bottom:10px;" /></p>
<p>I&#8217;m afraid to say that I wasn&#8217;t especially enamored of this book &#8211; from its tongue-tangling and strangely-chosen title onwards.  I felt that it missed a considerable amount about the basics of dojo &#8211; which is understandable given its title &#8211; without really giving enough detail or insight into building an RIA &#8211; which is not.</p>
<p>Using Dojo (the best shortening I can come up with) does give a reasonable introduction to dojo, and covers some of the fundamental forms of usage, but it really isn&#8217;t comparable to either of the previously covered titles.</p>
<p><em>Update 2008-07-03 : </em> Alex Russell, one of the core dojo committers has also <a href="http://alex.dojotoolkit.org/?p=682">reviewed these books</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/96/dojo-toolkit-book-reviews-dojo-the-definitive-guide-mastering-dojo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Reacting To Events with the Dojo Dijit Editor</title>
		<link>http://otaqui.com/blog/95/reacting-to-events-with-the-dojo-dijit-editor/</link>
		<comments>http://otaqui.com/blog/95/reacting-to-events-with-the-dojo-dijit-editor/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 15:15:47 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/wp/2008/06/reacting-to-events-with-the-dojo-dijit-editor/</guid>
		<description><![CDATA[I was writing a custom set of validation routines for a form, and using Dojo&#8217;s Dijit.Editor component &#8211; and having some trouble attaching my &#8220;invalid&#8221; class and a tooltip to a &#8216;required&#8217; editor. There were several parts to the problem: Iframe Transparency in IE Targeting the containing div node, the editor&#8217;s iframe tag, and that [...]]]></description>
			<content:encoded><![CDATA[<p>I was writing a custom set of validation routines for a form, and using Dojo&#8217;s Dijit.Editor component &#8211; and having some trouble attaching my &#8220;invalid&#8221; class and a tooltip to a &#8216;required&#8217; editor.</p>
<p>There were several parts to the problem:</p>
<ul>
<li>Iframe Transparency in IE</li>
<li>Targeting the containing div node, the editor&#8217;s iframe tag, and that iframe&#8217;s body node</li>
<li>Ignoring the weird default content that Dojo, or possibly the browser itself, adds to the Editor (a &lt;br /&gt; tag, but with a special attribute in Mozilla browsers)</li>
<li>Removing the class once the user makes a change to the content</li>
</ul>
<p>Ignoring all the rest, and a lot of the specifics (since I&#8217;m sure there are better ways to achieve all this) I&#8217;m just going to note how to get use dojo.connect to respond to a &#8216;click&#8217; inside the editor area.  It&#8217;s worth noting that using the normal method&#8217;s you would expect <em>sort of</em> work &#8211; but only when you click on the Editor&#8217;s toolbar rather than the inside the editable area.  That being said, here you go:</p>
<p><code><br />
&lt;textarea dojoType="dijit.Editor" id="dijitEditor">Click Me&lt;/textarea&gt;<br />
&lt;script&gt;<br />
dojo.addOnLoad(function() {<br />
&nbsp;var dijitEditor = dijit.byId('dijitEditor');<br />
&nbsp;var eBody = dijitEditor.iframe.contentDocument.body;<br />
&nbsp;dojo.connect(eBody,'click',onEditorClick);<br />
});<br />
function onEditorClick() {<br />
&nbsp;alert('you clicked the editor window');<br />
}<br />
&lt;/script&gt;<br />
</code></p>
<p><strong>NB &#8211; Not IE-friendly</strong>.  This won&#8217;t work in IE because of the contentDocument property, which it doesn&#8217;t support &#8211; but you could use the document.frames[] array instead.  Note that the iframe&#8217;s id is widgetid+&#8217;_iframe&#8217; in all except Mozilla.  So something like this:</p>
<p><code><br />
dojo.addOnLoad(function() {<br />
&nbsp;var dijitEditor = dijit.byId('dijitEditor');<br />
&nbsp;var eBody;<br />
&nbsp;if ( dojo.isIE ) {<br />
&nbsp;&nbsp;eBody = document.frames['dijitEditor_iframe'].body;<br />
&nbsp;} else {<br />
&nbsp;&nbsp;eBody = dijitEditor.iframe.contentDocument.body;<br />
&nbsp;}<br />
&nbsp;dojo.connect(eBody,'click',onEditorClick);<br />
});<br />
</code></p>
<p>I really went down the rabbit hole for while chasing &#8216;ondijitclick&#8217; and the &#8216;events&#8217; / &#8216;captureEvents&#8217; properties of the Dijit.Editor, but ended up using this fairly straightforward custom method.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/95/reacting-to-events-with-the-dojo-dijit-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Transparent IFrames in Internet Explorer using Javascript</title>
		<link>http://otaqui.com/blog/93/transparent-iframes-in-internet-explorer-using-javascript/</link>
		<comments>http://otaqui.com/blog/93/transparent-iframes-in-internet-explorer-using-javascript/#comments</comments>
		<pubDate>Tue, 10 Jun 2008 14:04:18 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/wp/?p=93</guid>
		<description><![CDATA[In order to have an IFrame with a transparent background in Internet Explorer, you need to add an &#8220;allowtransparency&#8221; attribute, like so: &#60;iframe src="iframe_source.html" id="iframe_id" allowtransparency="true" /&#62; However, if you want to set the transparency with Javascript via the DOM, you must camelCase the property: document.getElementById('iframe_id').allowTransparency = true; Note &#8211; you must also make sure [...]]]></description>
			<content:encoded><![CDATA[<p>In order to have an IFrame with a transparent background in Internet Explorer, you need to add an &#8220;allowtransparency&#8221; attribute, like so:</p>
<p><code>&lt;iframe src="iframe_source.html" id="iframe_id" allowtransparency="true" /&gt;</code></p>
<p>However, if you want to set the transparency with Javascript via the DOM, you must camelCase the property:</p>
<p><code>document.getElementById('iframe_id').allowTransparency = true;</code></p>
<p>Note &#8211; you must also make sure that &lt;body&gt; tag in the document contained by the iframe is also transparent in order for the parent&#8217;s colours to show through.</p>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/93/transparent-iframes-in-internet-explorer-using-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firefox 3 RC1 Extensions</title>
		<link>http://otaqui.com/blog/92/firefox-3-rc1-extensions-2/</link>
		<comments>http://otaqui.com/blog/92/firefox-3-rc1-extensions-2/#comments</comments>
		<pubDate>Thu, 29 May 2008 15:21:27 +0000</pubDate>
		<dc:creator>pete</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[downloads]]></category>
		<category><![CDATA[links]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://otaqui.com/wp/2008/05/firefox-3-rc1-extensions-2/</guid>
		<description><![CDATA[Now that Firefox 3 Release Candidate 1 is out, I&#8217;ve decided to give it a proper trial. I had tried running Firefox 2 and 3 in parallel on my macbook, but found that 3 would always try and become the default browser, which annoyed me enough to get rid of it. Now though I&#8217;ve gone [...]]]></description>
			<content:encoded><![CDATA[<p>Now that <a href="http://www.mozilla.com/en-US/firefox/all-rc.html">Firefox 3 Release Candidate 1</a> is out, I&#8217;ve decided to give it a proper trial.</p>
<p>I had tried running Firefox 2 and 3 in parallel on my macbook, but found that 3 would always try and become the default browser, which annoyed me enough to get rid of it.  Now though I&#8217;ve gone the whole hog and, while I do have FF 2 hanging around, I&#8217;m using 3 full time.  The upshot is that I&#8217;ve been poking around at what extensions are available for average everyday webmonkey (btw &#8211; did you see that <a href="http://www.webmonkey.com/">webmonkey is back</a>?) and have been updated to work with FF 3 RC 1.  Here&#8217;s my current list of installed extensions.</p>
<p><i>Update: 7th May 2008:</i> these all work for Firefox 3 RC 2</p>
<dl>
<dt><a href="http://adblockplus.org/en/">AdBlock Plus</a></dt>
<dd>A pre-requisite for surfing the public web.  Ads are so 20th century!</dd>
<dt><a href="http://www.iosart.com/firefox/colorzilla/">ColorZilla</a></dt>
<dd>Advanced Eye Dropper, Colour Picker and more.  Brilliant stuff.</dd>
<dt><a href="http://blog.delicious.com/blog/2008/04/firefox-3-delicious-and-you.html">Delicious Bookmarks</a></dt>
<dd>Plugs your browser nicely into your delicious account.</dd>
<dt><a href="http://www.getfirebug.com/releases/">Firebug 1.2 Beta</a></dt>
<dd>Indispensable.  Nuff said.</dd>
<dt><a href="http://www.borngeek.com/firefox/googlebarlite/">Googlebar Lite</a></dt>
<dd>Ahhh, so much nicer than the big G&#8217;s own attempt.</dd>
<dt><a href="http://amb.vis.ne.jp/mozilla/scrapbook/">Scrapbook</a></dt>
<dd>Sort of like your bookmarks, but actually saves the pages down to your hard drive for offline viewing.  You can edit-before-capture and even spider whole sites (or sections thereof).  Really quite nice.</dd>
<dt><a href="http://tamperdata.mozdev.org/">TamperData</a></dt>
<dd>TamperData is to HTTP what Firebug is to the DOM.</dd>
<dt><a href="http://chrispederick.com/work/web-developer/">Web Developer Toolbar</a></dt>
<dd>An oldie but a VERY goodie!  Manage CSS, find stuff and another hot tip &#8211; until <a href="http://addons.mozilla.org/firefox/addon/539">MeasureIt</a> is updated for FF 3, it also has it&#8217;s own ruler system (in the Miscellaneous menu).</dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://otaqui.com/blog/92/firefox-3-rc1-extensions-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
