<?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>James Tombs &#187; James</title>
	<atom:link href="http://jamestombs.co.uk/author/admin/feed" rel="self" type="application/rss+xml" />
	<link>http://jamestombs.co.uk</link>
	<description>Development blog from James Tombs about PHP, XHTML + CSS and Drupal</description>
	<lastBuildDate>Wed, 25 Aug 2010 21:51:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>How not to create a registration/login process &#8211; T-mobile UK</title>
		<link>http://jamestombs.co.uk/2010-07-16/how-not-to-create-a-registrationlogin-process-t-mobile-uk/1302</link>
		<comments>http://jamestombs.co.uk/2010-07-16/how-not-to-create-a-registrationlogin-process-t-mobile-uk/1302#comments</comments>
		<pubDate>Fri, 16 Jul 2010 17:04:22 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[accessibility]]></category>
		<category><![CDATA[user experience]]></category>
		<category><![CDATA[ux]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1302</guid>
		<description><![CDATA[I have just come across a great example of how not to deal with users logging in or registering for a site with T-Mobile (UK). I am on my second phone with them and had an account with them for the original phone, so I tried logging in using my username which I had in [...]]]></description>
			<content:encoded><![CDATA[<p><!--1fbd454703b24bd8a49817567c36e413--></p>
<p>I have just come across a great example of how not to deal with users logging in or registering for a site with T-Mobile (UK).</p>
<p>I am on my second phone with them and had an account with them for the original phone, so I tried logging in using my username which I had in an email and my password.  It wasn&#8217;t having it.</p>
<p>So I tried the forgotten password route.  This asked for my mobile number and my username.  Entered my original number and username. Nope. Entered my new number and username. Nope.</p>
<p>So I tried the forgotten username + password route. This asks for your name, phone number and email.  I entered all this information using my original phone number. Nope.  Tried again with my new phone number. Nope.</p>
<p><span id="more-1302"></span></p>
<p>At this point I guess that I may not have an account for my new phone and my old phone was removed even though the number is still on the go on a second phone I have.</p>
<p>This time I went to the registration form. Put in my new number and entered the captcha. I was presented with another screen asking if I was the account holder, what my email was, how I was paying for the number, and a password.  I filled all of this only at this point to be told that an account already existed for this number.  Why couldn&#8217;t this error be present after the first step rather than making me enter in loads of data which was redundant.</p>
<p>So I tried to register again using my original number, entered the captcha and on to step two.  This time I was asked for different information, I assume it recognised that this was a PAYG phone and not a contract phone so rather than being asked about how I paid for it, I was asked for my name address as well as my email, password. I filled this in, but the post code lookup didn&#8217;t recognise my post code, so I tried another post code, nope, and my works post code&#8230;nope. I carried on with the form assuming that it would present some more text fields to enter my address and pressed Submit.</p>
<p>&#8220;Please select your address before proceeding&#8221;</p>
<p>It wouldn&#8217;t let me proceed as I didn&#8217;t select my address which it wouldn&#8217;t find.  Being a developer, I thought I would disable javascript.  Obviously there was a problem, with their post code look up service and with javascript disabled the form would degrade nicely with all the address fields. Nope. The same form is displayed, still showing the Find address button which the href is set to javascript:; so the link wouldn&#8217;t do anything.</p>
<p>I am now in a situation where I can&#8217;t login to a pre-existing account or create a new account for not one but two phones.</p>
<h3>Fixes</h3>
<p>There are quite a few fixes that T-Mobile need to do to get their forms up to scratch.  I can&#8217;t really say much about the login process as it may just be that the accounts don&#8217;t exist for whatever reason, I will have to wait and hear back from T-Mobile.  But the registration form needs a lot of work.</p>
<p>When registering a new account and the number exists, throw an error straight away. Some inline validation would be great, at the very least throw up an error on submitting the form rather than getting the user to type another page of information before being told that the very first thing that did on the previous page was wrong.</p>
<p>Sort out the post code lookup service. I tried 3 different post codes. I know they exist. The look up service they are using just doesn&#8217;t work. A query is sent off by the javascript but there is no response (used Firebug).</p>
<p>Degrade the form if javascript is not available. Not everyone has javascript enabled, especially on some phones. Making sure an application degrades properly if javascript is absent is vital.  If the post code lookup did work, then I wouldn&#8217;t of found this problem, but it doesn&#8217;t work and as it is javascript only, you can&#8217;t go any further.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-16/how-not-to-create-a-registrationlogin-process-t-mobile-uk/1302/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Block API module changes coming soon</title>
		<link>http://jamestombs.co.uk/2010-07-16/block-api-module-changes-coming-soon/1299</link>
		<comments>http://jamestombs.co.uk/2010-07-16/block-api-module-changes-coming-soon/1299#comments</comments>
		<pubDate>Fri, 16 Jul 2010 10:39:16 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[block api]]></category>
		<category><![CDATA[drupal]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1299</guid>
		<description><![CDATA[After reviewing and updating Block API for Drupal 7, I saw that there were some fairly big changes made to the way the block system works from a code perspective which meant I have had to change a fair bit of the module for Drupal 7. So rather than having 2 quite distinct bits of [...]]]></description>
			<content:encoded><![CDATA[<p>After reviewing and updating Block API for Drupal 7, I saw that there were some fairly big changes made to the way the block system works from a code perspective which meant I have had to change a fair bit of the module for Drupal 7.  So rather than having 2 quite distinct bits of code, I will be updating the Drupal 6 version to work like the Drupal 7 version so that the documentation is the same.  This not only makes the module easier to maintain from my perspective but also anyone else using Block API.</p>
<p><span id="more-1299"></span></p>
<h3>So what has changed?</h3>
<p>hook_block() no longer exists in Drupal 7.  It has been split in to individual hooks for each $op.  So rather than hook_block() we now have:</p>
<ul>
<li>hook_block_info()</li>
<li>hook_block_configure()</li>
<li>hook_block_save()</li>
<li>hook_block_view()</li>
</ul>
<p>A few of these new hooks conflicted with the hooks put in place by the Block API module, so I have made a few changes to the way other modules hook in to it.</p>
<pre class="brush: php">function html_block_block($op = &#039;list&#039;, $delta = NULL, $edit = array()) {
  $function = &#039;block_api_block_&#039;. $op;
  return $function(&#039;html_block&#039;, $delta, $edit);
}</pre>
<p>The above has gone completely. Rather than passing the modules name to the core Blocks module, Block API will pass on it&#8217;s own name and handle the block management of modules using the API itself.  This reduces the amount of code needed (although it wasn&#8217;t that much to start off with) and also makes it easier to remember what you need to use to hook in to Block API.</p>
<p><em>hook_block_api_info()</em> has now changed to <em>hook_block_api_block_types()</em>, the code stays exactly the same. This was caused by the function name changes made in Drupal 7.</p>
<p><em>hook_block_api_view()</em> has changed to <em>hook_block_api_display()</em>, this was also due to the function change in Drupal 7.</p>
<p>Everything else stays the same.  The Block API has now been made slightly easier to use and hook in to thanks to Drupal 7.</p>
<p>The code on d.o should be updated soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-16/block-api-module-changes-coming-soon/1299/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>World of Warcraft &#8211; PHP Raider Block</title>
		<link>http://jamestombs.co.uk/2010-07-13/world-of-warcraft-php-raider-block/1289</link>
		<comments>http://jamestombs.co.uk/2010-07-13/world-of-warcraft-php-raider-block/1289#comments</comments>
		<pubDate>Tue, 13 Jul 2010 14:32:05 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[world of warcraft]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1289</guid>
		<description><![CDATA[This module adds the ability to have a block pulling out the upcoming raids from PHP Raider. Download: ZIP Last updated: 2010-07-13 18:30 The block displays however many raids you want to display and gives you more information which is available on mouseover. As well as the block configuration, the module has an admin form [...]]]></description>
			<content:encoded><![CDATA[<p>This module adds the ability to have a block pulling out the upcoming raids from <a href="http://www.phpraider.com/">PHP Raider</a>.</p>
<p><strong>Download:</strong> <a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/wow_phpraider.zip">ZIP</a> <strong>Last updated:</strong> 2010-07-13 18:30</p>
<p><span id="more-1289"></span></p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/raid_block.jpg" alt="" title="Raid Block" width="209" height="254" class="alignnone size-full wp-image-1291" /> <img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/raid_hover.jpg" alt="" title="Raid Block - Hover" width="396" height="265" class="alignnone size-full wp-image-1292" /></p>
<p>The block displays however many raids you want to display and gives you more information which is available on mouseover.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/raid_settings.jpg" alt="" title="Raider Block Settings" width="476" height="337" class="alignnone size-full wp-image-1293" /></p>
<p>As well as the block configuration, the module has an admin form that must be filled in before any blocks can be created.  This is to make sure that Drupal knows where PHP Raider is located and where the database is.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/raider_config.jpg" alt="" title="PHP Raider configuration screen" width="500" height="306" class="alignnone size-full wp-image-1294" /></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-13/world-of-warcraft-php-raider-block/1289/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>World of Warcraft Blocks for Drupal</title>
		<link>http://jamestombs.co.uk/2010-07-12/world-of-warcraft-blocks-for-drupal/1279</link>
		<comments>http://jamestombs.co.uk/2010-07-12/world-of-warcraft-blocks-for-drupal/1279#comments</comments>
		<pubDate>Mon, 12 Jul 2010 17:53:03 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1279</guid>
		<description><![CDATA[I have been working on a site for a World of Warcraft guild to get their frontpage up to scratch with their old site which was running the TinyPortal on SMF. With a server change and some mods becoming unsupported, the decision was made to switch to something else for the frontpage. I had only [...]]]></description>
			<content:encoded><![CDATA[<p>I have been working on a site for a World of Warcraft guild to get their frontpage up to scratch with their old site which was running the TinyPortal on SMF. With a server change and some mods becoming unsupported, the decision was made to switch to something else for the frontpage. I had only one thing on my mind which was Drupal.  But soon found that there didn&#8217;t appear to be many modules on Drupal.org for World of Warcraft.</p>
<p>So far I have created two blocks using the Block API module I developed and will release more when I have written and tested them.</p>
<p>Both blocks are set up in one module, which I have called wow_blocks. If you already have a module called wow_blocks, it may be a bit of a mission getting this to work, so you will have to chose one of the modules.</p>
<p>Download: <a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/wow_blocks.zip">ZIP</a>. <strong>Last updated:</strong> 2010-07-12 18:30</p>
<p><span id="more-1279"></span></p>
<h3>Block 1: Recruitment</h3>
<p>The first block is a block for recruitment.  An admin can set the roles and specs that the guild requires to be displayed in the block, so users know which areas the guild is recruiting in.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/recruitment_block.jpg" alt="" title="recruitment_block" width="199" height="497" class="alignnone size-full wp-image-1281" /></p>
<p>All the images are included in the ZIP file.</p>
<p>The admin screen, allows the admin to select the links to use for the Apply now and Recruitment details buttons as well as options for each individual role and spec.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/recruitment_settings_full.jpg" rel="shadowbox[post-1279];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/recruitment_settings_small.jpg" alt="" title="recruitment_settings_small" width="511" height="357" class="alignnone size-full wp-image-1283" /><br />Click for larger version</a></p>
<h3>Block 2: Progression</h3>
<p>This block shows the guilds progression against the bosses of the game.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/progression_view.jpg" alt="" title="progression_view" width="436" height="296" class="alignnone size-full wp-image-1284" /></p>
<p>The block features an expandable group of game zones with all the bosses in the zone.</p>
<p>All bosses from the following zones are in the module:</p>
<ul>
<li>&#8216;Icecrown Citadel</li>
<li>Argent Coliseum</li>
<li>Ulduar</li>
<li>Eye of Eternity</li>
<li>Obsidian Sanctum</li>
<li>Naxxramas</li>
<li>Vault of Archavon</li>
</ul>
<p>Admins have full control over which zones are available and shown in the block as well as selecting which bosses have been defeated.</p>
<p>If you have any requests for World of Warcraft related blocks, let me know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-12/world-of-warcraft-blocks-for-drupal/1279/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding additional form elements using ahah_helper in Drupal 6</title>
		<link>http://jamestombs.co.uk/2010-07-08/adding-additional-form-elements-using-ahah_helper-in-drupal-6/1276</link>
		<comments>http://jamestombs.co.uk/2010-07-08/adding-additional-form-elements-using-ahah_helper-in-drupal-6/1276#comments</comments>
		<pubDate>Thu, 08 Jul 2010 10:41:42 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ahah]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1276</guid>
		<description><![CDATA[This tutorial will show you how to add new form elements which will be available in $form_state['values'] once the form has been submitted using a submit button by taking advantage of the AHAH helper module. The AHAH helper module does provide a demo, but the demo shows how to change a few fields depending on [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will show you how to add new form elements which will be available in $form_state['values'] once the form has been submitted using a submit button by taking advantage of the <a href="http://drupal.org/project/ahah_helper">AHAH helper module</a>.</p>
<p>The AHAH helper module does provide a demo, but the demo shows how to change a few fields depending on a selection made from a select element.  The tutorials I looked at online either didn&#8217;t cover the issue properly or just didn&#8217;t work.<br />
<span id="more-1276"></span><br />
Currently the 6.x-2.0 release throws up errors if you are using certain PHP versions, but these are gone in the 6.x-2.x-dev release.</p>
<h3>Scenario</h3>
<p>You want the user to enter in some data, lets say their favourite car.  But you want the ability for them to add as many cars as they want if they have more than one.</p>
<h3>Code</h3>
<p>Firstly you will need to set up a menu callback for your form, but I will assume you know how to do this if you are looking at this tutorial.</p>
<p>We will set up the basic form first, this includes one textfield and a submit button to submit the form with the textfield in a wrapper (this is important later on for the ahah_helper module).</p>
<pre class="brush: php">function test_form($form_state = NULL) {
  $form[&#039;cars&#039;] = array(
    &#039;#type&#039; =&gt; &#039;fieldset&#039;,
    &#039;#title&#039; =&gt; t(&#039;Favourite cars(s)&#039;),
    &#039;#prefix&#039; =&gt; &#039;&lt;div id=&quot;favourite-cars-wrapper&quot;&gt;&#039;,
    &#039;#suffix&#039; =&gt; &#039;&lt;/div&gt;&#039;,
  );
  $form[&#039;cars&#039;][&#039;car&#039;] = array(
    &#039;#type&#039; =&gt; &#039;textfield&#039;,
    &#039;#title&#039; =&gt; t(&#039;Favourite car&#039;),
    &#039;#size&#039; =&gt; 36,
    &#039;#default_value&#039; =&gt; $form_state[&#039;values&#039;][&#039;car&#039;],
  );
  $form[&#039;submit&#039;] = array(
    &#039;#type&#039; =&gt; &#039;submit&#039;,
    &#039;#value&#039; =&gt; t(&#039;Submit&#039;),
  );
  return $form;
}</pre>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>This is very basic and allows the user to enter one car and submit the form.  We now need to add in the extra functionality of ahah_helper to be able to add mulitple fields.</p>
<pre class="brush: php">function test_form($form_state = NULL) {

  ahah_helper_register($form, $form_state); // Absolutely vital for ahah_helper to do it&#039;s job

  // We check to see if quantity has been set, ie if the form has been submitted yet.  If not, we show 1 field, you can change this to however many fields you want to show up as default.
  if (!isset($form_state[&#039;storage&#039;][&#039;quantity&#039;])) {
    $quantity = 1;
  }
  else {
    // If the form has been submitted we get the quantity that was stored.
    $quantity = $form_state[&#039;storage&#039;][&#039;quantity&#039;];
    // We then do a check to see if the user has clicked the &quot;Add another car&quot; button, if they have we increase the amount by 1.
    if (isset($form_state[&#039;values&#039;][&#039;cars&#039;][&#039;add_more&#039;]) &amp;&amp; $form_state[&#039;values&#039;][&#039;op&#039;] == &#039;Add another car&#039;) {
      $quantity++;
    }
  }

  // We create a hidden form element to store the amount of fields that the user has added.
  $form[&#039;quantity&#039;] = array(
    &#039;#type&#039; =&gt; &#039;value&#039;,
    &#039;#value&#039; =&gt; $quantity,
  );

  $form[&#039;cars&#039;] = array(
    &#039;#type&#039; =&gt; &#039;fieldset&#039;,
    &#039;#title&#039; =&gt; t(&#039;Favourite cars(s)&#039;),
    &#039;#prefix&#039; =&gt; &#039;&lt;div id=&quot;favourite-cars-wrapper&quot;&gt;&#039;,
    &#039;#suffix&#039; =&gt; &#039;&lt;/div&gt;&#039;,
    &#039;#tree&#039; =&gt; TRUE // This is important for ahah_helper.
  );
  // We now do a simple loop, creating however many textfields are defined by $form_state[&#039;storage&#039;][&#039;quantity&#039;]
  for ($i = 1; $i &lt;= $quantity; $i++) {
    // The element name needs to be different for each textfield, otherwise we will only get one value after the form is submitted.
    $form[&#039;cars&#039;][&#039;car_&#039;. $i] = array(
      &#039;#type&#039; =&gt; &#039;textfield&#039;,
      &#039;#title&#039; =&gt; t(&#039;Favourite car&#039;),
      &#039;#size&#039; =&gt; 36,
      &#039;#default_value&#039; =&gt; $form_state[&#039;values&#039;][&#039;cars&#039;][&#039;car_&#039;. $i],
    );
  }

  // We add in a button with the #ahah element which will handle all our work for us.
  $form[&#039;cars&#039;][&#039;add_more&#039;] = array(
    &#039;#type&#039; =&gt; &#039;submit&#039;,
    &#039;#value&#039; =&gt; t(&#039;Add another car&#039;),
    &#039;#ahah&#039; =&gt; array(
      &#039;event&#039; =&gt; &#039;click&#039;, // When the button is &quot;clicked&quot;, AHAH will do it&#039;s job
      &#039;path&#039; =&gt; ahah_helper_path(array(&#039;cars&#039;)), // The array features the wrapper form field. So our form wrapper is $form[&#039;cars&#039;], so we set this to array(&#039;cars&#039;). If your form was $form[&#039;cars&#039;][&#039;another_wrapper&#039;], the path would be array(&#039;cars&#039;, &#039;another_wrapper&#039;).
      &#039;wrapper&#039; =&gt; &#039;favourite-cars-wrapper&#039;, // We then define the wrapper which will be changed.
    ),
  );
  $form[&#039;submit&#039;] = array(
    &#039;#type&#039; =&gt; &#039;submit&#039;,
    &#039;#value&#039; =&gt; t(&#039;Submit&#039;),
  );
  return $form;
}</pre>
<p>So what have we done&#8230;first we added the following line:</p>
<pre class="brush: php">ahah_helper_register($form, $form_state);</pre>
<p>This is a vital function that needs to be present in your form for ahah_helper to do it&#8217;s job.</p>
<p>Next we check to see if the form has been submitted before and if it has, get the amount of textfields that the form had by storing it in a hidden field.  We then do a further check to find out what button was clicked.  If the &#8220;add more&#8221; button was clicked, then we add another textfield by increasing the value of the quantity variable.</p>
<p>A minor, but very important change we make is adding &#8216;#tree&#8217; => TRUE to our wrapper element, this is a requirement for ahah_helper to do it&#8217;s job properly.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>Next we use a for loop, to add all our textfields into the form.  This should be self-explanitory but will go in to a bit more depth further on when we talk about the #ahah element.</p>
<p>We added an additional button to the form, this is so that the user can add another field to the form. You don&#8217;t need to worry about javascript degradation as ahah_helper takes care of this.</p>
<p>One attribute of #ahah on the button that isn&#8217;t listed in the form, but is very important, is the &#8220;method&#8221;.  The default value of this is replace, which is what we want. This replaces the whole contents of the wrapper which we define with the data from the path which we defined.  This is why we needed the for loop to recreate the textfields.</p>
<p>To take care of the form when javascript is disabled, you must check which button was pressed when the form was submitted.</p>
<pre class="brush: php">function test_form_submit($form, $form_state) {
  if ($form_state[&#039;values&#039;][&#039;op&#039;] == &#039;Submit&#039;) {
    drupal_set_message(&#039;Submit button clicked&#039;);
  }
  else {
    drupal_set_message(&#039;Add more button clicked&#039;);
  }
}</pre>
<p>With javascript enabled, when clicking the Add more button, Drupal will perform validation on the form, but will not submit the form.  Whereas clicking the submit button will perform validation and submit the form.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-08/adding-additional-form-elements-using-ahah_helper-in-drupal-6/1276/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Display iframed content as a block using Block API</title>
		<link>http://jamestombs.co.uk/2010-07-05/display-iframed-content-as-a-block-using-block-api/1270</link>
		<comments>http://jamestombs.co.uk/2010-07-05/display-iframed-content-as-a-block-using-block-api/1270#comments</comments>
		<pubDate>Mon, 05 Jul 2010 13:21:47 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[block api]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1270</guid>
		<description><![CDATA[This will give a quick look over the code needed to create a block type using Block API to allow users to create new blocks which use an iframe to display content from external sites. This can be useful for widgets that the user wants to display but doesn&#8217;t know HTML, or if the admin [...]]]></description>
			<content:encoded><![CDATA[<p>This will give a quick look over the code needed to create a block type using Block API to allow users to create new blocks which use an iframe to display content from external sites.  This can be useful for widgets that the user wants to display but doesn&#8217;t know HTML, or if the admin wants to add a bit more control rather than allowing too much HTML.</p>
<p>Not every user will understand this:</p>
<pre class="brush: html">&lt;iframe src=&quot;http://drupal.org/&quot; width=&quot;100%&quot; height=&quot;500px&quot; frameborder=&quot;1&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;</pre>
<p>And will find this much simpler and easier to use:</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/iframe_block_settings.jpg" alt="" title="iframe_block_settings" width="502" height="551" class="alignnone size-full wp-image-1271" /></p>
<p><span id="more-1270"></span></p>
<p>First off, you need to create a module like you normally would with your .info and .module files.</p>
<p>My module is going to be called iframe_block, so you will need to change this in certain cases if you use a different name.</p>
<pre class="brush: php">name = Iframe Block
description = Add new blocks which contain an iframe of a specified URL.
core = 6.x
dependencies[] = block_api</pre>
<p>That is for the .info file which sets the dependency on block_api.  If block_api isn&#8217;t available then this module can&#8217;t be used.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>Our .module file is going to be fairly simple and just hooks in to Block API, using three of the available hooks. But before we use any of the Block API hooks, we need to forwards the Drupal block related calls to the Block API module.</p>
<pre class="brush: php">function iframe_block_block($op = &#039;list&#039;, $delta = 0, $edit = array()) {
  $function = &#039;block_api_block_&#039;. $op;
  return $function(&#039;iframe_block&#039;, $delta, $edit);
}</pre>
<p>This will pass any calls to iframe_block_block() to the Block API module which in turn will add it&#8217;s own hooks which we can take advantage of.</p>
<p>The first one and most important is hook_block_api_info(), which we use to tell Drupal about our block type.</p>
<pre class="brush: php">function iframe_block_block_api_info() {
  $types[&#039;iframe_block&#039;] = array(
    &#039;title&#039; =&gt; t(&#039;Iframe Block&#039;),
    &#039;description&#039; =&gt; t(&#039;Create a block from with content from a specified URL using an iframe.&#039;),
    &#039;storage&#039; =&gt; BLOCK_API_STORAGE_DATABASE,
  );
  return $types;
}</pre>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/iframe_block_selection.jpg" alt="" title="iframe block selection" width="559" height="454" class="alignnone size-full wp-image-1272" /></p>
<p>Next we define our form for the user to fill in. The attributes we require are the source (the URL), the height and the width.  I am also going to provide the user the option of overriding the frameborder and scrolling attributes.</p>
<pre class="brush: php">function iframe_block_block_api_form($config, $edit) {
  if ($config[&#039;block_type&#039;] == &#039;iframe_block&#039;) {
    $form[&#039;url&#039;] = array(
      &#039;#type&#039; =&gt; &#039;textfield&#039;,
      &#039;#title&#039; =&gt; t(&#039;URL&#039;),
      &#039;#description&#039; =&gt; t(&#039;The URL of the page you would like to use as the source of the iframe.&#039;),
      &#039;#required&#039; =&gt; TRUE,
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;url&#039;],
    );
    $form[&#039;width&#039;] = array(
      &#039;#type&#039; =&gt; &#039;textfield&#039;,
      &#039;#title&#039; =&gt; t(&#039;Iframe width&#039;),
      &#039;#description&#039; =&gt; t(&#039;Enter the width of the iframe. Include the measurement type (px, em or %)&#039;),
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;width&#039;] ? $config[&#039;settings&#039;][&#039;width&#039;] : &#039;100%&#039;,
      &#039;#required&#039; =&gt; TRUE,
      &#039;#size&#039; =&gt; 10,
    );
    $form[&#039;height&#039;] = array(
      &#039;#type&#039; =&gt; &#039;textfield&#039;,
      &#039;#title&#039; =&gt; t(&#039;Iframe height&#039;),
      &#039;#description&#039; =&gt; t(&#039;Enter the height of the iframe. Include the measurement type (px, em or %)&#039;),
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;height&#039;] ? $config[&#039;settings&#039;][&#039;height&#039;] : &#039;300px&#039;,
      &#039;#required&#039; =&gt; TRUE,
      &#039;#size&#039; =&gt; 10,
    );
    $form[&#039;frameborder&#039;] = array(
      &#039;#type&#039; =&gt; &#039;select&#039;,
      &#039;#title&#039; =&gt; t(&#039;Iframe border&#039;),
      &#039;#description&#039; =&gt; t(&#039;Select whether you want to show a border around the iframe.&#039;),
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;frameborder&#039;] ? $config[&#039;settings&#039;][&#039;frameborder&#039;] : 0,
      &#039;#required&#039; =&gt; TRUE,
      &#039;#options&#039; =&gt; array(1 =&gt; t(&#039;Show border&#039;), 0 =&gt; t(&#039;Don\&#039;t show a border&#039;)),
    );
    $form[&#039;scrolling&#039;] = array(
      &#039;#type&#039; =&gt; &#039;select&#039;,
      &#039;#title&#039; =&gt; t(&#039;Scrolling&#039;),
      &#039;#description&#039; =&gt; t(&#039;Select whether the iframe should be scrollable or not&#039;),
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;scrolling&#039;] ? $config[&#039;settings&#039;][&#039;scrolling&#039;] : &#039;auto&#039;,
      &#039;#required&#039; =&gt; TRUE,
      &#039;#options&#039; =&gt; drupal_map_assoc(array(&#039;yes&#039;, &#039;no&#039;, &#039;auto&#039;)),
    );
  }
  return $form;
}</pre>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>This will allow the user to set up their iframe by entering the required information. </p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/iframe_block_settings.jpg" alt="" title="Iframe block settings" width="502" height="551" class="alignnone size-full wp-image-1271" /></p>
<p>Finally, we need to hook in to hook_block_api_view() to be able to display our iframe using the users input.</p>
<pre class="brush: php">function iframe_block_block_api_view($config) {
  if ($config[&#039;block_type&#039;] == &#039;iframe_block&#039;) {
    $output = &#039;&lt;iframe src=&quot;&#039;. $config[&#039;settings&#039;][&#039;url&#039;] .&#039;&quot; width=&quot;&#039;. $config[&#039;settings&#039;][&#039;width&#039;] .&#039;&quot; height=&quot;&#039;. $config[&#039;settings&#039;][&#039;height&#039;] .&#039;&quot; frameborder=&quot;&#039;. $config[&#039;settings&#039;][&#039;frameborder&#039;] .&#039;&quot; scrolling=&quot;&#039;. $config[&#039;settings&#039;][&#039;scrolling&#039;] .&#039;&quot;&gt;&#039;. $config[&#039;settings&#039;][&#039;no_iframes&#039;] .&#039;&lt;/iframe&gt;&#039;;
  }
  return array(&#039;content&#039; =&gt; $output);
}</pre>
<p>Very simply we are taking the users input and entering it in to some HTML code to give us the desired output.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/iframe_block_view.jpg" rel="shadowbox[post-1270];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/iframe_block_view-300x257.jpg" alt="" title="Iframe Block View" width="300" height="257" class="alignnone size-medium wp-image-1273" /><br /><small>Click for larger version</small></a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-05/display-iframed-content-as-a-block-using-block-api/1270/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Displaying nodes as blocks using Block API</title>
		<link>http://jamestombs.co.uk/2010-07-05/displaying-nodes-as-blocks-using-block-api/1252</link>
		<comments>http://jamestombs.co.uk/2010-07-05/displaying-nodes-as-blocks-using-block-api/1252#comments</comments>
		<pubDate>Mon, 05 Jul 2010 10:31:47 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[block api]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1252</guid>
		<description><![CDATA[Recently I wrote a new module called Block API which allows other modules writers to create modules to develop templates for users to easily create new blocks rather than relying on copying and pasting HTML. The example module included copies the functionality of the core block module. Below I will show how to use Block [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I wrote a new module called <a href="http://jamestombs.co.uk/2010-06-30/new-drupal-module-block-api/1245">Block API</a> which allows other modules writers to create modules to develop templates for users to easily create new blocks rather than relying on copying and pasting HTML.</p>
<p>The example module included copies the functionality of the core block module.  Below I will show how to use Block API to display a specific node as a block with further configuration options available to the user to choose from.<br />
<span id="more-1252"></span><br />
First off, if you just want to download this module to use, you can do so by <a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/node_block.zip">clicking here</a>.</p>
<p>As with any other module, create an info file using whatever module name you want.  The module name I will be using is node_block.</p>
<pre class="brush: php">name = Node Block
description = Add new blocks by using pre-existing nodes.
core = 6.x
dependencies[] = block_api</pre>
<p>In your .module file, we need to first set up the hook to allow Block API to do it&#8217;s job. So our first function will be the following:</p>
<pre class="brush: php">function node_block_block($op = &#039;list&#039;, $delta = 0, $edit = array()) {
  $function = &#039;block_api_block_&#039;. $op;
  return $function(&#039;node_block&#039;, $delta, $edit);
}</pre>
<p>This passes all the hook_block calls through the Block API which then allows users to select your block types through a single interface.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/module_block.jpg" alt="" title="Module Block selection through Block API" width="560" height="442" class="alignnone size-full wp-image-1257" /></p>
<p>Next, we need to define our block types that we will provide users.  To do this we use hook_block_api_info().</p>
<pre class="brush: php">function node_block_block_api_info() {
  $types[&#039;node_block&#039;] = array(
    &#039;title&#039; =&gt; t(&#039;Node Block&#039;),
    &#039;description&#039; =&gt; t(&#039;Create a block from a pre-existing node.&#039;),
    &#039;storage&#039; =&gt; BLOCK_API_STORAGE_DATABASE,
  );
  return $types;
}</pre>
<p>This is very simple, and defines the block type.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>For this module we are going to allow the user to select a node to display and choose whether to display the full node or just the teaser.  As well as this, we are going to give the administrator the choice of which node types are available to the user to chose nodes from as well as selecting whether users can use unpublished nodes or not.</p>
<p>First we will define the administration form to chose which content types are available.  To do this, we need to use hook_menu() to define our menu item pointing to our form.</p>
<pre class="brush: php">function node_block_menu() {
  $items[&#039;admin/settings/node_block&#039;] = array(
    &#039;access callback&#039; =&gt; &#039;user_access&#039;,
    &#039;access arguments&#039; =&gt; array(&#039;administer blocks&#039;),
    &#039;page callback&#039; =&gt; &#039;drupal_get_form&#039;,
    &#039;page arguments&#039; =&gt; array(&#039;node_block_admin_form&#039;),
    &#039;title&#039; =&gt; &#039;Node Block Configuration Settings&#039;,
    &#039;description&#039; =&gt; &#039;Set the configuration options for Node Blocks.&#039;,
    &#039;type&#039; =&gt; MENU_NORMAL_ITEM,
  );
  return $items;
}</pre>
<p>There is nothing complex here, just a standard menu item.  We now have to create the form node_block_admin_form().</p>
<pre class="brush: php">function node_block_admin_form() {
  $types = node_get_types(&#039;names&#039;);
  $form[&#039;node_block_content_types&#039;] = array(
    &#039;#type&#039; =&gt; &#039;checkboxes&#039;,
    &#039;#title&#039; =&gt; t(&#039;Node types available to create blocks&#039;),
    &#039;#description&#039; =&gt; t(&#039;Set the node types that are allowed to be displayed as blocks.&#039;),
    &#039;#required&#039; =&gt; TRUE,
    &#039;#options&#039; =&gt; $types,
    &#039;#default_value&#039; =&gt; variable_get(&#039;node_block_content_types&#039;, &#039;&#039;),
  );
  $form[&#039;node_block_published_only&#039;] = array(
    &#039;#type&#039; =&gt; &#039;checkbox&#039;,
    &#039;#title&#039; =&gt; t(&#039;Only allow published nodes to be shown as blocks.&#039;),
    &#039;#description&#039; =&gt; t(&#039;By checking this box only published nodes will be available for selection and appear as blocks.&#039;),
    &#039;#default_value&#039; =&gt; variable_get(&#039;node_block_published_only&#039;, 1),
  );
  $form[&#039;node_block_sql_order&#039;] = array(
    &#039;#type&#039; =&gt; &#039;select&#039;,
    &#039;#title&#039; =&gt; t(&#039;Order autocomplete results by&#039;),
    &#039;#description&#039; =&gt; t(&#039;Select the column name to order the autocomplete results by.&#039;),
    &#039;#default_value&#039; =&gt; variable_get(&#039;node_block_sql_order&#039;, &#039;nid&#039;),
    &#039;#required&#039; =&gt; TRUE,
    &#039;#options&#039; =&gt; array(&#039;nid&#039; =&gt; t(&#039;Node ID&#039;), &#039;title&#039; =&gt; t(&#039;Node title&#039;), &#039;type&#039; =&gt; t(&#039;Node type&#039;)),
  );
  $form[&#039;node_block_sql_sort&#039;] = array(
    &#039;#type&#039; =&gt; &#039;select&#039;,
    &#039;#title&#039; =&gt; t(&#039;Order of autocomplete results&#039;),
    &#039;#description&#039; =&gt; t(&#039;The order in which autocomplete results will be ordered.&#039;),
    &#039;#default_value&#039; =&gt; variable_get(&#039;node_block_sql_sort&#039;, &#039;ASC&#039;),
    &#039;#options&#039; =&gt; array(&#039;ASC&#039; =&gt; t(&#039;Ascending&#039;), &#039;DESC&#039; =&gt; t(&#039;Descending&#039;)),
    &#039;#required&#039; =&gt; TRUE,
  );
  $form[&#039;node_block_autocomplete_limit&#039;] = array(
    &#039;#type&#039; =&gt; &#039;textfield&#039;,
    &#039;#title&#039; =&gt; t(&#039;Amount of results to display in autocomplete&#039;),
    &#039;#description&#039; =&gt; t(&#039;Enter the amount of results to appear in the autocomplete when selecting a node.&#039;),
    &#039;#required&#039; =&gt; TRUE,
    &#039;#default_value&#039; =&gt; variable_get(&#039;node_block_autocomplete_limit&#039;, 25),
    &#039;#size&#039; =&gt; 5,
  );
  return system_settings_form($form);
}</pre>
<p>To get a list of nodes types, you can run your own custom SQL query, but it is a lot easier to use Drupal&#8217;s built in node_get_types() function. If you pass along &#8216;types&#8217; as the first argument, you will get a lot more information, but all we need is the node type machine name and the display name.  node_get_types(&#8216;names&#8217;) does exactly this with an associative array with the key being the machine name and the value being the display name.</p>
<p>The rest of the form is very simple, giving the administrator full control over the ordering of the autocomplete which users will select their node from.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/admin_settings.jpg" alt="" title="Administration form" width="560" height="601" class="alignnone size-full wp-image-1259" /></p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>We now have our admin form set up, so now it is time to create the configuration form for the users when adding a new block. Again we hook in to the Block API, this time using hook_block_api_form($config, $edit).</p>
<pre class="brush: php">function node_block_block_api_form($config, $edit) {
  if ($config[&#039;block_type&#039;] == &#039;node_block&#039;) {
    $form[&#039;nid&#039;] = array(
      &#039;#type&#039; =&gt; &#039;textfield&#039;,
      &#039;#title&#039; =&gt; t(&#039;Node ID&#039;),
      &#039;#description&#039; =&gt; t(&#039;Start typing the title of the node and select it from the autocomplete list.&#039;),
      &#039;#required&#039; =&gt; TRUE,
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;nid&#039;],
      &#039;#autocomplete_path&#039; =&gt; &#039;js/node_block/autocomplete&#039;,
    );
    $form[&#039;teaser&#039;] = array(
      &#039;#type&#039; =&gt; &#039;select&#039;,
      &#039;#title&#039; =&gt; t(&#039;Show the Teaser or full node&#039;),
      &#039;#description&#039; =&gt; t(&#039;Select whether you would like just the teaser displayed in the block or the full node.&#039;),
      &#039;#default_value&#039; =&gt; $config[&#039;settings&#039;][&#039;teaser&#039;],
      &#039;#required&#039; =&gt; TRUE,
      &#039;#options&#039; =&gt; array(0 =&gt; t(&#039;Full node&#039;), 1 =&gt; t(&#039;Teaser&#039;)),
    );
  }
  return $form;
}</pre>
<p>Here we give the user two options.  The first is an autocomplete field to select the node and the second being a simple checkbox allowing the user to select whether they want to show the teaser of the node or the full node.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/block_settings.jpg" alt="" title="Block API - Block settings form" width="544" height="432" class="alignnone size-full wp-image-1258" /></p>
<p>To get the autocomplete working, we need to set up our autocomplete menu item and function to run the search query.</p>
<p>In your existing hook_menu(), add the following to create a menu callback for our autocomplete textfield.</p>
<pre class="brush: php">$items[&#039;js/node_block/autocomplete&#039;] = array(
    &#039;page callback&#039; =&gt; &#039;node_block_js_autocomplete&#039;,
    &#039;access callback&#039; =&gt; TRUE,
    &#039;type&#039; =&gt; MENU_CALLBACK,
  );</pre>
<p>A very simple callback, no need for a title or description and access is open to everyone, although you could limit it to the users who are able to create blocks.</p>
<p>Next we need to set up the SQL query that will fetch the nodes based on the users input.</p>
<pre class="brush: php">function node_block_js_autocomplete() {
  $str = $_POST[&#039;nid&#039;];
  $sql = &quot;SELECT nid, title FROM {node} WHERE LOWER(title) LIKE LOWER(&#039;%%%s%%&#039;)&quot;;
  foreach (variable_get(&#039;node_block_content_types&#039;, &#039;&#039;) as $type =&gt; $value) {
    if (strlen($value) &gt; 1) $types[] = &#039;&quot;&#039;. $type .&#039;&quot;&#039;;
  }
  $sql .= &quot; AND type IN (&quot;. implode(&quot;, &quot;, $types) .&quot;)&quot;;
  if (variable_get(&#039;node_block_published_only&#039;, 1) == 1) {
    $sql .= &quot; AND status = 1&quot;;
  }
  $sql .= &quot; ORDER BY &quot;. variable_get(&#039;node_block_sql_order&#039;, &#039;nid&#039;) .&quot; &quot;. variable_get(&#039;node_block_sql_sort&#039;, &#039;ASC&#039;);
  $sql .= &quot; LIMIT 0, &quot;. variable_get(&#039;node_block_autocomplete_limit&#039;, 25);
  $query = db_query($sql, filter_xss($str));
  $results = array();
  while ($data = db_fetch_object($query)) {
    $results[$data-&gt;nid] = check_plain($data-&gt;title);
  }
  print drupal_to_js($results);
}</pre>
<p>We get the users current inputted text from $_POST and set up the basic SQL. As we gave the administrator the chance to limit the options available, we must now apply those filters. First we make sure the query only gets results for the right content types, then check for only published nodes if defined by the administrator. The next few lines are for the autocomplete ordering and limiting the amount of results.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>We now have our two admin forms configured, the only bit remaining is showing the block on the page.  This is done by using hook_block_api_view().</p>
<pre class="brush: php">function node_block_block_api_view($config) {
  if ($config[&#039;block_type&#039;] == &#039;node_block&#039;) {
    $node = node_load($config[&#039;settings&#039;][&#039;nid&#039;]);
    if ($node-&gt;status == 0 &amp;&amp; variable_get(&#039;node_block_published_only&#039;, 1) == 1) return FALSE;
    $output = node_view($node, $config[&#039;settings&#039;][&#039;teaser&#039;] == 1 ? TRUE : FALSE);
  }
  return array(&#039;content&#039; =&gt; $output);
}</pre>
<p>First, we load the node using the NID saved from our form by Block API.  It is probably best to add some code in to make sure that a node ID has been saved either at view stage or when saving the block.</p>
<p>Next we make sure the node is not unpublished if the administrator has defined that only published nodes can be shown as blocks.</p>
<p>Then we use the function node_view() to display the node. The second argument is the $teaser argument. If TRUE it will display the teaser of the node, otherwise the full node will be published.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/07/block_view.jpg" rel="shadowbox[post-1252];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/07/block_view-300x163.jpg" alt="" title="Block API - Block View" width="300" height="163" class="alignnone size-medium wp-image-1260" /><br /><small>Click for larger image</small></a></p>
<p>You may also want to hide the node block if you are viewing the node page itself, so adding a line after the status line such as:</p>
<pre class="brush: php">if (arg(0) == &#039;node&#039; &amp;&amp; arg(1) == $config[&#039;settings&#039;][&#039;nid&#039;]) return FALSE;</pre>
<p>And that is it.  You will now be able to create blocks </p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-07-05/displaying-nodes-as-blocks-using-block-api/1252/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a multi-step moderation process in Drupal 6</title>
		<link>http://jamestombs.co.uk/2010-06-30/create-a-multi-step-moderation-process-in-drupal-6/1189</link>
		<comments>http://jamestombs.co.uk/2010-06-30/create-a-multi-step-moderation-process-in-drupal-6/1189#comments</comments>
		<pubDate>Wed, 30 Jun 2010 14:02:25 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1189</guid>
		<description><![CDATA[This will guide you through creating a multi-step process of content moderation in Drupal 6. This is a follow on to the guide on Drupal.org about creating a revisioning system and the follow on, on creating a revisioning system with state-based access. Both of which only allow a single step revisioning sytem, i.e. Author creates [...]]]></description>
			<content:encoded><![CDATA[<p>This will guide you through creating a multi-step process of content moderation in Drupal 6. This is a follow on to the guide on Drupal.org about creating a <a href="http://drupal.org/node/408968">revisioning system</a> and the follow on, on creating a <a href="http://drupal.org/node/408052">revisioning system with state-based access</a>. Both of which only allow a single step revisioning sytem, i.e. Author creates content, moderator either edits and publishes or sends back to author to edit.</p>
<h3>Scenario</h3>
<p>A user submits a piece of content, we will refer to this user as the author. The content is not published and is sent to another user for moderation, we will refer to this user as the moderator.</p>
<p>The moderator can then either set the content from a moderation state back to a draft state for the author to amend or through to a &#8220;to be published state&#8221;.</p>
<p>Once the moderator has checked the content and made amends they can mark the content as ready for publishing.  At which point a third user which we will refer to as the publisher, can make further amends to the content and publish it, make further amends and send back to the moderator to check through the changes or mark the content as back to draft to allow the author to change it.<br />
<span id="more-1189"></span></p>
<h3>Required modules</h3>
<p>A few contributed modules are required to get this process in place as well as a couple of core modules.</p>
<ul>
<li>Trigger (Core, optional)</li>
<li>Profile (Core)</li>
<li><a href="http://drupal.org/project/module_grants">Module Grants</a> (Contrib)</li>
<li><a href="http://drupal.org/project/smart_menus">Smart tabs</a> (Contrib)</li>
<li><a href="http://drupal.org/project/revisioning">Revisioning</a> (Contrib)</li>
<li><a href="http://drupal.org/project/token">Token</a> (Contrib)</li>
<li><a href="http://drupal.org/project/workflow">Workflow</a> (Contrib)</li>
<li><a href="http://drupal.org/project/diff">Diff</a> (Contrib, optional)</li>
</ul>
<p>The <a href="http://drupal.org/project/diff">Diff module</a> is optional, but can be useful to easily see what parts of the content have changed from each revision.</p>
<h3>Enable modules</h3>
<p>Some of the modules have sub-modules which come with the main module, so be sure to check all the required modules, which are:</p>
<ul>
<li>Module Grants</li>
<li>Module Grants Monitor (Optional)</li>
<li>Node Tools</li>
<li>User Tools</li>
<li>Profile</li>
<li>Trigger (Optional)</li>
<li>Smart tabs</li>
<li>Diff (Optional)</li>
<li>Revisioning</li>
<li>Token</li>
<li>Token actions</li>
<li>Workflow</li>
<li>Workflow access</li>
</ul>
<p>If you already have content on your site, you will also need to download and install <a href="http://drupal.org/project/workflow_post_install">Workflow Post Install</a>, otherwise all old content may only be accessible by administrator.</p>
<h3>Create user roles</h3>
<p>You can have as many different roles to allow more fine grained control over who can create what content types, but to try and keep this tutorial as simple as possible, I will stick to the three main roles defined in the scenario.</p>
<ul>
<li>Author</li>
<li>Moderator</li>
<li>Publisher</li>
</ul>
<p>It may be best to give your author role a different role name as the Workflow module automatically adds a line in the admin for &#8220;author&#8221; which applies to any role creating content.</p>
<p>Go to Administer &gt; User management &gt; Roles (admin/user/roles).</p>
<p>Then add your three roles, I will be using author role, moderator role and publisher role.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/roles.jpg" alt="" title="User roles" width="470" height="198" class="alignnone size-full wp-image-1194" /></p>
<h3>Set up workflow settings</h3>
<p>Go to Administer &gt; Site building &gt; Workflow (admin/build/workflow).</p>
<p>Create a new Workflow and call it <strong>Moderation</strong>. </p>
<p>In the <strong>State name</strong> box, enter <em>in draft</em> and set the <strong>weight</strong> to <em>-10</em>. Save the state.</p>
<p>Once the state has saved, click the <strong>List</strong> tab and click the <strong>Add state</strong> link.</p>
<p>Add the following states:</p>
<ul>
<li>in moderation (weight: -2)</li>
<li>is moderated (weight: 2)</li>
<li>live (weight: 10)</li>
</ul>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow_states.jpg" alt="" title="Workflow states" width="428" height="238" class="alignnone size-full wp-image-1197" /></p>
<p>Underneath your states, you can apply the workflow to separate content types. I will be applying it to both the default content types (Page and Story).</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow_content-types.jpg" alt="" title="Workflow content types" width="470" height="181" class="alignnone size-full wp-image-1198" /></p>
<p>Next to the Moderation workflow, click the <strong>Edit</strong> link.</p>
<p>This page may seem a little daunting at first, but don&#8217;t panic. The first set of checkboxes allow you to set out which roles can transition the node between certain states. You will also see the extra &#8220;author&#8221; role that I refered to earlier.</p>
<p>The first row is for the original creation of the node.  This is the transition from the <strong>(creation)</strong> state to the <strong>in draft</strong> state. The only role we are giving access to this is the Workflow defined author, note that this is not the author role that we created.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-creation_to_draft.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-creation_to_draft-300x64.jpg" alt="" title="Workflow: Creation to draft" width="300" height="64" class="alignnone size-medium wp-image-1206" /><br /><small>Click for larger version</small></a></p>
<p>The next transition is from being <strong>in draft</strong> to <strong>in moderation</strong>. For this transition, we want to set this to our author role as opposed to the workflow defined author.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-draft_to_moderation.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-draft_to_moderation-300x64.jpg" alt="" title="Workflow: Draft to moderation" width="300" height="64" class="alignnone size-medium wp-image-1207" /><br /><small>Click for larger version</small></a></p>
<p>The next transition is from <strong>in moderation</strong> to <strong>is moderated</strong>.  This is our moderation step where the content is moderated prior to being sent back to the author for further amends or to the publisher for final approval and publishing. We want to set the moderator role under <strong>in draft</strong> and <strong>is moderated</strong>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-moderation_to_moderated.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-moderation_to_moderated-300x64.jpg" alt="" title="Workflow: Moderation to moderated" width="300" height="64" class="alignnone size-medium wp-image-1208" /><br /><small>Click for larger version</small></a></p>
<p>Next is the step from being moderated to going to the publisher.  There are some optional transitions that you can put in here, depending on how you want to work.  The one that everyone would need is the transition from <strong>is moderated</strong> to <strong>live</strong>. The one that will differ is for rejections. Some people will want it to go back to draft, whereas others will want it to go back to moderator, others will want both options. This way if there isn&#8217;t a major problem, the content can be sent back to the moderator for further moderation rather than having to go back to the author only to be sent back to the moderator.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-moderated_to_live.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-moderated_to_live-300x64.jpg" alt="" title="Workflow: Moderated to live" width="300" height="64" class="alignnone size-medium wp-image-1209" /><br /><small>Click for larger version</small></a></p>
<p>The final transition is from the <strong>live</strong> state. The only role that needs this is our author role (not the workflow author role) to be able to take the content back to <strong>in draft</strong>. This will not change the live copy, but create an unpublished revision which we will set up in the next part of the tutorial.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-live.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-live-300x64.jpg" alt="" title="Workflow: Live" width="300" height="64" class="alignnone size-medium wp-image-1210" /><br /><small>Click for larger version</small></a></p>
<p>After the checkboxes, in the Comment for Workflow Log section, make sure both boxes are ticked to show a comment form in the Workflow and node edit screens to allow the roles to add their comments for the next role to read to understand why the amends were rejected or what was changed.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-comments.jpg" alt="" title="Workflow: Comments" width="507" height="214" class="alignnone size-full wp-image-1213" /></p>
<p>In the <strong>Workflow tab permissions</strong>, check our three roles.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-tab_permissions.jpg" alt="" title="Workflow: Tab permissions" width="507" height="250" class="alignnone size-full wp-image-1214" /></p>
<p>Next we have the Access control section.  These permissions allow you to set permissions to certain roles based on the state of the content (in draft, in moderation, is moderated, live). Take in to account that these permissions will be overridden by some of the permissions in the User management &gt; Permissions page which we will get on to later.</p>
<p>In the sections for each state, the <em>anonymous user</em> and <em>authenticated user</em> should stay ticked under <strong>Roles who can view posts in this state</strong>.</p>
<p>Under <strong>in draft</strong>, check our <strong>author role</strong> for <strong>Roles who can edit posts in this state</strong>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-in_draft.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-in_draft-300x118.jpg" alt="" title="Workflow: Access control: In draft" width="300" height="118" class="alignnone size-medium wp-image-1215" /><br /><small>Click for larger version</small></a></p>
<p>Under <strong>in moderation</strong>, check our <strong>moderator role </strong>for <strong>Roles who can edit posts in this state</strong>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-in_moderation.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-in_moderation-300x118.jpg" alt="" title="Workflow: Access control: In moderation" width="300" height="118" class="alignnone size-medium wp-image-1216" /><br /><small>Click for larger version</small></a></p>
<p>Under <strong>is moderated</strong>, check our <strong>publisher role</strong> for <strong>Roles who can edit posts in this state</strong>.<br />
<a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-is_moderated.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-access-is_moderated-300x118.jpg" alt="" title="Workflow: Access control: Is moderated" width="300" height="118" class="alignnone size-medium wp-image-1217" /><br /><small>Click for larger version</small></a></p>
<p>Leave the live state with only the default view options checked.</p>
<p>Press <strong>Save</strong>.<br />

<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Configure content types</h3>
<p>Go to Administer &gt; Content management &gt; Content types (admin/content/types).</p>
<p>Click the <strong>Edit</strong> link next to the content type you wish you apply the moderation workflow.</p>
<p>Under the <strong>Workflow settings</strong>, uncheck the <strong>Published</strong> box as we don&#8217;t want to publish the content until it has been moderated and approved.</p>
<p>Check both the <strong>Create new revision</strong> and <strong>New revision in draft, pending moderation (requires &#8220;Create new revision&#8221;)</strong> boxes to create a revision for each modification of the content.</p>
<p>Under <strong>Create new revision</strong>, it is up to you what setting you use, but remember to read the description text below the options.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-settings.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/workflow-settings-300x217.jpg" alt="" title="Content types: Workflow settings" width="300" height="217" class="alignnone size-medium wp-image-1218" /><br /><small>Click here for larger version</small></a></p>
<p>If you have the Diff module enabled, you will get the additional option <strong>Show Preview changes button on node edit form</strong> which will allow you to see the difference between the current edits and the current revision.</p>
<p>Repeat this step for all content types that you wish to have moderation enabled for.<br />

<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Set up user permissions</h3>
<p>Go to Administer &gt; User management &gt; Permissions (admin/user/permissions).</p>
<p>Under the <strong>module_grants_monitor module</strong> section. Tick the boxes <strong>access All tab</strong>, <strong>access I Can Edit tab</strong> and <strong>access I Can View tab</strong> for the <strong>moderator role</strong>. For the publisher role, you can tick the same boxes plus <strong>access Published tab</strong> and <strong>access Unpublished tab</strong>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-module_grants_monitor.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-module_grants_monitor-300x109.jpg" alt="" title="Permissions: Module_grants_monitor" width="300" height="109" class="alignnone size-medium wp-image-1221" /><br /><small>Click for larger version</small></a></p>
<p>Under <strong>node module</strong>, make sure <strong>anonymous user</strong> and <strong>authenticated user</strong> are both checked for <strong>access content</strong>.</p>
<p>For <strong>author role</strong>, tick the boxes to allow them to create content of selected content types as well as being able to edit their own content.</p>
<p>For the <strong>moderator</strong> and <strong>publisher roles</strong>, allow them to edit any content as well as view or revert any revisions, but if you want further control over this, you can set this later on in the revisioning section.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-node.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-node-300x215.jpg" alt="" title="Permissions: Node" width="300" height="215" class="alignnone size-medium wp-image-1222" /><br /><small>Click for larger version</small></a></p>
<p>Under <strong>revisioning module</strong>, give the <strong>author role</strong> the ability to <strong>view revision status messages</strong> and to <strong>edit revisions of their own content</strong>. Moderators should have permission to <strong>access Pending tab</strong>, <strong>edit revisions</strong> and <strong>view revision status messages</strong>. The <strong>publisher role</strong> should have the same permissions as the <strong>moderator role</strong>, but should also have <strong>unpublish current revisio</strong>n and <strong>publish revisions</strong>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-revisioning.jpg" rel="shadowbox[post-1189];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/permissions-revisioning-300x173.jpg" alt="" title="Permissions: Revisioning" width="300" height="173" class="alignnone size-medium wp-image-1226" /><br /><small>Click for larger version</small></a></p>
<p>Press Save.</p>
<h3>Set up email triggers</h3>
<p>For information on setting up and using <a href="http://drupal.org/node/199254">Triggers and Actions in Drupal 6</a>, it is best to read the excellent page on the Drupal.org website at <a href="http://drupal.org/node/199254">http://drupal.org/node/199254</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-30/create-a-multi-step-moderation-process-in-drupal-6/1189/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>New Drupal module &#8211; Block API</title>
		<link>http://jamestombs.co.uk/2010-06-30/new-drupal-module-block-api/1245</link>
		<comments>http://jamestombs.co.uk/2010-06-30/new-drupal-module-block-api/1245#comments</comments>
		<pubDate>Wed, 30 Jun 2010 13:25:31 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[block api]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1245</guid>
		<description><![CDATA[I have created a new module for Drupal 6 called Block API which is available on Drupal.org. Block API is a new module I have developed for Drupal 6 which gives greater control over block templates much like you do with nodes. More information is available on my Block API page under Projects. Developer information [...]]]></description>
			<content:encoded><![CDATA[<p>I have created a new module for Drupal 6 called <a href="http://drupal.org/project/block_api">Block API</a> which is available on <a href="http://drupal.org/project/block_api">Drupal.org</a>.</p>
<blockquote><p>Block API is a new module I have developed for Drupal 6 which gives greater control over block templates much like you do with nodes.</p></blockquote>
<p>More information is available on my <a href="http://jamestombs.co.uk/projects/block-api-module-drupal">Block API</a> page under <a href="http://jamestombs.co.uk/projects">Projects</a>.</p>
<p>Developer information on how to use the module is available on the <a href="http://jamestombs.co.uk/projects/block-api-module-drupal/block-api-developers-information">Block API Developer information</a> page.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-30/new-drupal-module-block-api/1245/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New Hosting</title>
		<link>http://jamestombs.co.uk/2010-06-25/new-hosting/1187</link>
		<comments>http://jamestombs.co.uk/2010-06-25/new-hosting/1187#comments</comments>
		<pubDate>Fri, 25 Jun 2010 22:11:51 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1187</guid>
		<description><![CDATA[If you are seeing this post, it means you are being served through the new hosting from DamnVPS soon to be ThrustVPS. They offer very good VPS packages which are very fast for a very good price and allow a lot of customisation with some excellent backend configuration options.]]></description>
			<content:encoded><![CDATA[<p>If you are seeing this post, it means you are being served through the new hosting from <a href="https://clients.damnvps.com/aff.php?aff=043">DamnVPS</a> soon to be <a href="https://clients.damnvps.com/aff.php?aff=043">ThrustVPS</a>.</p>
<p>They offer very good VPS packages which are very fast for a very good price and allow a lot of customisation with some excellent backend configuration options.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-25/new-hosting/1187/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a burst of light in Photoshop using filters</title>
		<link>http://jamestombs.co.uk/2010-06-23/create-a-burst-of-light-in-photoshop-using-filters/1174</link>
		<comments>http://jamestombs.co.uk/2010-06-23/create-a-burst-of-light-in-photoshop-using-filters/1174#comments</comments>
		<pubDate>Wed, 23 Jun 2010 15:33:17 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[photoshop]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1174</guid>
		<description><![CDATA[This tutorial will show you how to create a burst of light in Photoshop using the basic filters provided with Photoshop. Step 1: Create a new canvas and fill the background with black (#000000) Open Photoshop and create a new canvas, whatever dimensions you want to use, I am using 500&#215;500. Fill the background layer [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will show you how to create a burst of light in Photoshop using the basic filters provided with Photoshop.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/resutl1-150x150.jpg" alt="" title="Final - Blue" width="150" height="150" class="alignnone size-thumbnail wp-image-1182" /> <img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/burst-150x150.jpg" alt="" title="Final" width="150" height="150" class="alignnone size-thumbnail wp-image-1179" /></p>
<p><span id="more-1174"></span></p>
<h3>Step 1: Create a new canvas and fill the background with black (#000000)</h3>
<p>Open Photoshop and create a new canvas, whatever dimensions you want to use, I am using 500&#215;500.</p>
<p>Fill the background layer with black (#0000000).</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Step 2: Create the initial burst of light</h3>
<p>Set the foreground colour to white (#ffffff) (you can do this by pressing <strong>d</strong> on the keyboard to reset the foreground and background colours then pressing <strong>x</strong> to switch the foreground and background).</p>
<p>Now select the <strong>Gradient tool</strong> and set the gradient to be foreground to transparent and set to a radial gradient.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/gradient.jpg" alt="" title="Gradient tool options" width="268" height="125" class="alignnone size-full wp-image-1175" /></p>
<p>Now draw a radial gradient from the center of the document on a new layer.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/radial-gradient.jpg" alt="" title="Radial gradient" width="500" height="500" class="alignnone size-full wp-image-1176" /></p>
<p>Next create another layer. Go to <strong>Filters</strong> &gt; <strong>Render</strong> &gt; <strong>Clouds</strong>. Set the layer blend mode in the layers panel to <strong>Soft Light</strong>.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/layers-panel.jpg" alt="" title="Layers panel" width="236" height="196" class="alignnone size-full wp-image-1177" /></p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>With the same layer still selected, go to <strong>Filters</strong> &gt; <strong>Artistic</strong> &gt; <strong>Plastic Wrap</strong>. You will need to play around with the settings here to get your desired result, I will leave them as the defaults.</p>
<p>Next, go to <strong>Filters</strong> &gt; <strong>Blur</strong> &gt; <strong>Radial Blur</strong>. Set the <strong>Amount</strong> to <em>100</em> and the <strong>Blur Method</strong> to <em>Zoom</em>.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/radial-blur.jpg" alt="" title="Radial Blur Settings" width="317" height="261" class="alignnone size-full wp-image-1178" /></p>
<p>Click OK to apply the blur.<br />

<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Step 3: Add colour to the burst</h3>
<p>Create another layer and fill it with whatever colour you want the burst to be. I am using #8dc63f. Set the layers blend mode in the layers panel to <strong>Colour</strong>. Lower the opacity to 60-80% to get more detail from the burst.</p>
<p><strong>Result</strong></p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/burst.jpg" alt="" title="Final" width="500" height="500" class="alignnone size-full wp-image-1179" /></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-23/create-a-burst-of-light-in-photoshop-using-filters/1174/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a glossy button in Photoshop</title>
		<link>http://jamestombs.co.uk/2010-06-23/create-a-glossy-button-in-photoshop/1161</link>
		<comments>http://jamestombs.co.uk/2010-06-23/create-a-glossy-button-in-photoshop/1161#comments</comments>
		<pubDate>Wed, 23 Jun 2010 10:11:38 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[photoshop]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1161</guid>
		<description><![CDATA[This tutorial will teach you how to create a glossy button that is reusable by using Layer styles. Layer styles are not available in some older versions of Photoshop and Photoshop Elements. Step 1: Create a new canvas and create a new layer In Photoshop, create a new canvas and add a layer. In this [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will teach you how to create a glossy button that is reusable by using <strong>Layer styles</strong>. Layer styles are not available in some older versions of Photoshop and Photoshop Elements.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/glossy-final.jpg" alt="" title="Finished result" width="300" height="120" class="alignnone size-full wp-image-1162" /><br />
<span id="more-1161"></span></p>
<h3>Step 1: Create a new canvas and create a new layer</h3>
<p>In Photoshop, create a new canvas and add a layer. In this layer draw a rectangular shape using the marquee tool while leaving a small space around the canvas border.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/marquee.jpg" alt="" title="Select a rectangle using the marquee tool" width="167" height="88" class="alignnone size-full wp-image-1163" /></p>
<p>Fill this shape with white on the new layer.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Step 2: Set the layer styles</h3>
<p>Right click the layer and select <strong>Blending Options</strong>.</p>
<p>Tick <strong>Outer Glow</strong> and set the <strong>Blend Mode</strong> to <em>Normal</em> and the <strong>Colour</strong> to <em>black (#000000)</em> and lower that <strong>Opacity</strong> to <em>10%</em>. In the <strong>Elements</strong> section, change the <strong>Size</strong> to <em>10px</em>.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/outerglow.jpg" alt="" title="Outer Glow Blending Options" width="600" height="441" class="alignnone size-full wp-image-1164" /></p>
<p>Next tick <strong>Inner Glow</strong> and set the <strong>Blend Mode</strong> to <em>Normal</em> and the <strong>Colour</strong> to <em>white (#ffffff)</em> and set the <strong>Opacity</strong> to <em>40%</em>. In the <strong>Elements</strong> section, change the <strong>Size</strong> to <em>15px</em>.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/innerglow.jpg" alt="" title="Inner Glow Blending Options" width="600" height="441" class="alignnone size-full wp-image-1165" /></p>
<p>Next select <strong>Gradient Overlay</strong>, leave all the settings at their defaults, but change to the <strong>Gradient</strong> to the colour you want.  In this example I have chosen #ec2f03 to #c02502.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/gradientoverlay.jpg" alt="" title="Gradient Overlay Blending Options" width="600" height="441" class="alignnone size-full wp-image-1166" /></p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>Finally, tick the <strong>Stroke</strong> checkbox, and lower the <strong>Size</strong> to <em>2px</em> and the <strong>Position</strong> to <em>Inside</em>. Set the <strong>Colour</strong> of the stroke to something slightly different than the gradient.  I chose #ed1c24.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/stroke.jpg" alt="" title="Stroke Blending Options" width="600" height="441" class="alignnone size-full wp-image-1167" /></p>
<h3>Step 3: Add a slight shine to the button</h3>
<p>Create another layer on top of the button and select the <strong>Eliptical Marquee Tool</strong> and draw an elipse covering the top half of the button.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/elipse-selection.jpg" alt="" title="Elipse selection" width="177" height="92" class="alignnone size-full wp-image-1169" /></p>
<p>With the selection active, press and hold <strong>Ctrl, Alt and Shift</strong> and left click the layer preview of the button. This should limit the selection just to the area of where the selection meets the button.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/elipse-selection-refined.jpg" alt="" title="Elipse Selection Refined" width="177" height="92" class="alignnone size-full wp-image-1168" /></p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<p>On the new layer, <strong>Fill</strong> this with <em>white (#ffffff)</em> and set the <strong>Opacity</strong> of the layer to <em>15%</em>.</p>
<h3>Result</h3>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/finished-button.jpg" alt="" title="Finished Button" width="140" height="60" class="alignnone size-full wp-image-1171" /></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-23/create-a-glossy-button-in-photoshop/1161/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a Drupal multisite enviroment using Drupal 6</title>
		<link>http://jamestombs.co.uk/2010-06-22/creating-a-drupal-multisite-enviroment-using-drupal-6/1135</link>
		<comments>http://jamestombs.co.uk/2010-06-22/creating-a-drupal-multisite-enviroment-using-drupal-6/1135#comments</comments>
		<pubDate>Tue, 22 Jun 2010 09:35:27 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1135</guid>
		<description><![CDATA[This guide will show you how to create a multisite environment using a shared user system with the user only needing to log in once, to be logged in to all the sites. I will be doing this using WAMP on a Windows XP machine, so some of the steps won&#8217;t work if you are [...]]]></description>
			<content:encoded><![CDATA[<p>This guide will show you how to create a multisite environment using a shared user system with the user only needing to log in once, to be logged in to all the sites.</p>
<p>I will be doing this using WAMP on a Windows XP machine, so some of the steps won&#8217;t work if you are using IIS or will differ if you are using a different setup.</p>
<p>The result we will be aiming for is a shared user system allowing the user to log in/out of 3 sites which I will use the following domains:</p>
<ul>
<li>http://www.local.com</li>
<li>http://community.local.com</li>
<li>http://support.local.com</li>
</ul>
<p><span id="more-1135"></span></p>
<h3>WAMP installation</h3>
<p>Download and install the latest version of <a href="http://www.wampserver.com/en/download.php">WAMP</a> from the <a href="http://www.wampserver.com/en/download.php">WAMP website</a>. The latest version comes with PHP 5.3 which has problems with Drupal 6, so you will also need to download and install PHP 5.2.x from the <a href="http://www.wampserver.com/en/addons_php.php">WAMP Addons page</a> once WAMP is installed.</p>
<p>Once WAMP and PHP 5.2.x have been installed and WAMP has restarted, left click the WAMP icon in the system tray and go to PHP > PHP Version and select the 5.2.x version you downloaded.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/06/php5.jpg" alt="" title="Select PHP 5.2.x from the versions list" width="312" height="240" class="alignnone size-full wp-image-1136" /></p>
<p>Left click the WAMP icon again and this time select <strong>Apache</strong> > <strong>Apache Modules</strong> and scroll down and select <strong>rewrite_module</strong> and <strong>vhost_alias_module</strong>.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>WAMP Virtual Hosts set up</h3>
<p>Again, left click the WAMP icon and go to Apache then select <strong>httpd.conf</strong>.</p>
<p>Scroll down to the bottom of this file and look for the following lines:<br />
<code># Virtual hosts<br />
# Include conf/extra/httpd-vhosts.conf</code></p>
<p>Remove the comment from the beginning of the second line to end up with this:<br />
<code># Virtual hosts<br />
Include conf/extra/httpd-vhosts.conf</code></p>
<p>Save and close the file.</p>
<p>Now in Explorer, navigate to the <em>WAMP directory\bin\bin\apache\Apache2.2.11\conf\extra\</em> directory.</p>
<p>Open the <strong>httpd-vhosts.conf</strong> file with your favourite text editor.</p>
<p>Replace the contents of this file with the following:</p>
<p><code>NameVirtualHost *:80<br />
#<br />
# VirtualHost example:<br />
# Almost any Apache directive may go into a VirtualHost container.<br />
# The first VirtualHost section is used for all requests that do not<br />
# match a ServerName or ServerAlias in any &lt;VirtualHost&gt; block.<br />
#<br />
&lt;VirtualHost *:80&gt;<br />
    ServerAdmin webmaster@localhost<br />
    DocumentRoot &quot;c:/wamp/www/&quot;<br />
    ServerName www.local.com<br />
    ErrorLog &quot;logs/local-www-error.log&quot;<br />
    CustomLog &quot;logs/local-www-access.log&quot; common<br />
    &lt;directory &quot;c:/wamp/www/&quot;&gt;<br />
        Options Indexes FollowSymLinks<br />
        AllowOverride all<br />
        Order Deny,Allow<br />
        Deny from all<br />
        Allow from 127.0.0.1<br />
    &lt;/directory&gt;<br />
&lt;/VirtualHost&gt;<br />
&lt;VirtualHost *:80&gt;<br />
    ServerAdmin webmaster@localhost<br />
    DocumentRoot &quot;c:/wamp/www/&quot;<br />
    ServerName community.local.com<br />
    ErrorLog &quot;logs/local-com.localhost-error.log&quot;<br />
    CustomLog &quot;logs/local-com.localhost-access.log&quot; common<br />
    &lt;directory &quot;c:/wamp/www/&quot;&gt;<br />
        Options Indexes FollowSymLinks<br />
        AllowOverride all<br />
        Order Deny,Allow<br />
        Deny from all<br />
        Allow from 127.0.0.1<br />
    &lt;/directory&gt;<br />
&lt;/VirtualHost&gt;<br />
&lt;VirtualHost *:80&gt;<br />
    ServerAdmin webmaster@localhost<br />
    DocumentRoot &quot;c:/wamp/www/&quot;<br />
    ServerName support.local.com<br />
    ErrorLog &quot;logs/local-sup.localhost-error.log&quot;<br />
    CustomLog &quot;logs/local-sup.localhost-access.log&quot; common<br />
    &lt;directory &quot;c:/wamp/www/&quot;&gt;<br />
        Options Indexes FollowSymLinks<br />
        AllowOverride all<br />
        Order Deny,Allow<br />
        Deny from all<br />
        Allow from 127.0.0.1<br />
    &lt;/directory&gt;<br />
&lt;/VirtualHost&gt;</code></p>
<p>This sets up 3 virtual hosts all using the same directory for the files, as we are using a shared codebase. This is also set up to only allow traffic from the localhost. To make the site public to all, change the line:</p>
<p><code>Allow from 127.0.0.1</code></p>
<p>To:</p>
<p><code>Allow from all</code></p>
<p>Save and close the file.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>HOSTS set up</h3>
<p>The local.com domain already exist, so we need to overwrite the IP address where it points to be the local computer in the HOSTS file. We do this by editing the HOSTS file which on Windows is located in the following directory:</p>
<p><em>C:\WINDOWS\system32\drivers\etc</em></p>
<p>The HOSTS file has no file extension. So open it up in Notepad and add the following line at the very bottom:</p>
<p><code>127.0.0.1 www.local.com community.local.com support.local.com</code></p>
<p>Save the file, but make sure you don’t add a .txt extension.</p>
<p>You will need to close all your browser windows and in some cases restart the computer for the changes to take effect.</p>
<p>Open a new browser window and try to navigate to www.local.com, you should now get the WAMP welcome screen.</p>
<h3>Create a database in MySQL</h3>
<p>Using which ever MySQL admin tool you prefer, create a new database to use for Drupal. If using WAMP, you can use PHPMyAdmin by navigating to http://localhost/phpmyadmin/</p>
<p>By default MySQL has no password in WAMP.</p>
<h3>Download and set up Drupal</h3>
<p>Download the latest version of Drupal 6 which at the time of writing is <a href="http://drupal.org/drupal-6.17">Drupal 6.17</a>.</p>
<p>Extract the files and subfolders to the <em>C:\wamp\www</em> directory overwriting the existing <strong>index.php</strong> when asked. If you are not asked to overwrite the <strong>index.php</strong> file, you have tried to extract the files at the wrong directory level.</p>
<p>Navigate to the <em>/sites/</em> directory and copy the default directory twice and rename the 2 new directories <strong>support.local.com</strong> and <strong>community.local.com</strong>.</p>
<p>Navigate in your browser to <em>www.local.com</em>, you should get the Drupal installation screen. Follow the screens through and install Drupal how you normally would. Once installation has finished and you are at the Welcome screen, navigate to <em>support.local.com</em>.</p>
<p>During installation, add a database prefix as <strong>support_</strong> and continue with installation.</p>
<p>Once at the welcome screen, do the same with <em>community.local.com</em> but this time using the prefix <strong>comm_</strong>.</p>
<h3>Configure Drupal for multisite by modifying settings.php</h3>
<p>In the /sites/ directory there are now 4 directories.</p>
<p>- all<br />
- community.local.com<br />
- default<br />
- support.local.com</p>
<p>The default directory is used for www.local.com, the other 2 xxx.local.com directories should be self explanitory and the all directory is present for modules and themes.</p>
<p>Open up the settings.php file in the default directory.</p>
<p>Around a quater of the way down the file (around line 93 for most people) there is a line for $db_prefix, if you didn’t set one it should just say:</p>
<p><code>$db_prefix = '';</code></p>
<p>Scroll 3 quaters down (around line 169) and uncomment the line:</p>
<p><code># $cookie_domain = 'example.com';</code></p>
<p>And change to:</p>
<p><code>$cookie_domain = '.local.com';</code></p>
<p>This will share the session cookie across all subdomains of local.com</p>
<p>Save and close the file.</p>
<p>Now open up <strong>settings.php</strong> from within the community.local.com directory.</p>
<p>Scroll down to line 93 and replace with the following:</p>
<p><code>$db_prefix = array(<br />
  'default' => 'comm_',<br />
  'users' => '',<br />
  'sessions' => '',<br />
  'role' => '',<br />
  'authmap' => '',<br />
  'users_roles' => '',<br />
  'profile_fields' => '',<br />
  'profile_values' => '',<br />
);</code></p>
<p>Save and close the file.</p>
<p>And again, scroll 3 quaters down (around line 169) and uncomment the line:</p>
<p><code># $cookie_domain = 'example.com';</code></p>
<p>And change to:</p>
<p><code>$cookie_domain = '.local.com';</code></p>
<p>Repeat the same for support.local.com, although this time set the default $db_prefix to <strong>support_</strong>.</p>
<p>Save and close the file.</p>
<p>Navigate to each site in the browser and log out of each site. Now log in to <em>www.local.com</em>. Now if you navigate to <em>support.local.com</em>, you should be logged in, same with <em>community.local.com</em>.</p>
<p>We now have 3 sites with a shared user base and a single signon. As you may be able to tell from the $db_prefix array above, we are sharing the users table as well as sessions which keeps the user data and log in data the same across all the sites. We also share the role and users_roles tables to be able to set multi-sitewide roles as well as the profile tables so that the user doesn’t have to type any information over and over again.</p>
<p>
<!-- Begin Google Adsense code -->
<script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<!-- End Google Adsense code -->
</p>
<h3>Cleaning up unneeded MySQL tables</h3>
<p>Now in our database, we have redundant tables which aren’t doing anything and aren’t being used. We can now delete these to keep the database a bit tidier. Delete the following tables:</p>
<ul>
<li>support_users</li>
<li>support_sessions</li>
<li>support_role</li>
<li>support_authmap</li>
<li>support_users_roles</li>
<li>support_profile_fields</li>
<li>support_profile_values</li>
<li>comm_users</li>
<li>comm_sessions</li>
<li>comm_role</li>
<li>comm_authmap</li>
<li>comm_users_roles</li>
<li>comm_profile_fields</li>
<li>comm_profile_values</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-06-22/creating-a-drupal-multisite-enviroment-using-drupal-6/1135/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Finding a string in any file with a subdirectory in linux</title>
		<link>http://jamestombs.co.uk/2010-05-24/finding-a-string-in-any-file-with-a-subdirectory-in-linux/1134</link>
		<comments>http://jamestombs.co.uk/2010-05-24/finding-a-string-in-any-file-with-a-subdirectory-in-linux/1134#comments</comments>
		<pubDate>Mon, 24 May 2010 15:36:38 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1134</guid>
		<description><![CDATA[Nothing new or major but something that I keep forgetting. find . -exec grep -l "string to find" {} \; This will search all subdirectories from the current directory for the &#8220;string to find&#8221;.]]></description>
			<content:encoded><![CDATA[<p>Nothing new or major but something that I keep forgetting.</p>
<p><code>find . -exec grep -l "string to find" {} \;</code></p>
<p>This will search all subdirectories from the current directory for the &#8220;string to find&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-05-24/finding-a-string-in-any-file-with-a-subdirectory-in-linux/1134/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create your own simple grid system in CSS</title>
		<link>http://jamestombs.co.uk/2010-04-05/create-your-own-simple-grid-system-in-css/1129</link>
		<comments>http://jamestombs.co.uk/2010-04-05/create-your-own-simple-grid-system-in-css/1129#comments</comments>
		<pubDate>Sun, 04 Apr 2010 23:57:57 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[css]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1129</guid>
		<description><![CDATA[This tutorial will outline the steps required to create your own grid system like the 960.gs or Blueprint CSS frameworks. Step 1: The basics behind grid systems Grid systems allow you to create a quick framework using HTML and set CSS styles to set up div tags in to a grid like formation which saves [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will outline the steps required to create your own grid system like the <a href="http://960.gs/">960.gs</a> or <a href="http://blueprintcss.org/">Blueprint CSS</a> frameworks.</p>
<p><span id="more-1129"></span></p>
<h4 class="step">Step 1: The basics behind grid systems</h4>
<p>Grid systems allow you to create a quick framework using HTML and set CSS styles to set up div tags in to a grid like formation which saves you from having to worry about floating elements and margins etc.</p>
<p>This tutorial is going to focus on a very basic grid that allows you to easily create 1, 2, 3, 4 column layouts.  If you are looking for something that has more depth to it and more flexibility, it will be better to look at <a href="http://960.gs/">960.gs</a> or <a href="http://blueprintcss.org/">Blueprint CSS</a>, as they will provide you with a lot more options on how you want to display your content.</p>
<h4 class="step">Step 2: The start of the CSS</h4>
<p>We need to set up some basic CSS rules to set up our grid elements or cells so that they line up in a grid like we want them to.</p>
<pre class="brush: css">.cell, .cell-2, .cell-3 {
  float: left;
  display: inline;
  margin: 0 10px;
  position: relative;
}
.alpha { margin-left: 0; }
.omega { margin-right: 0; }
</pre>
<p>Our first rule is setting the cell to float and display inline with a 10px margin on the left and right.  The next two rules allow us to remove the margin if we need to from the first rule.  So with the following HTML, the second cell would have no right margin.</p>
<pre class="brush: html">&lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;cell omega&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;</pre>
<p>To make sure our cells line up properly on different rows we need to wrap them with another div which we will give the class <em>grid</em>.</p>
<pre class="brush: css">.grid, .grid-2, .grid-3, .grid-4 {
  clear: both;
  overflow: hidden;
  margin-bottom: 1.5em;
}</pre>
<p>This makes sure that the div is a new row if the row above doesn&#8217;t use the full width.</p>
<h4 class="step">Step 3: The mathematics</h4>
<p>The basis of grid systems is some simple mathematics.  If you look at the 960.gs size and the column counts available, you can see that they are divisable to a whole number. 960/12 = 80 and 960/16 = 60.</p>
<p>To be able to start off with the maths, you need to decide on the width of the wrapper of the whole page.  Take in to account the different resolutions that people use.  At the moment the majority of users are using 1024&#215;768, so the width shouldn&#8217;t be any more than 1000px wide (also take in to account a scrollbar on the right).</p>
<p>For this tutorial I am going to show the maths for a grid system with a width of 960px.</p>
<p>So we need to set the CSS for this:</p>
<pre class="brush: css">.container {
  width: 960px;
  margin: 0 auto;
}</pre>
<p>To work out the width of a single cell that fills the full width of the wrapper we need to divide the width of the container by the number of columns (in this case 1) then minus 20 (due to the 10px margin on both the left and right).</p>
<p>So; (960 / 1) &#8211; 10 &#8211; 10 = 940</p>
<pre class="brush: css">.grid .cell { width: 940px; }</pre>
<p>That is the most basic cell in the grid which will fill up the whole width of the container with the margins.</p>
<p>Now lets work out the width needed for a 2 column layout.</p>
<p>(960 / 2) &#8211; 10 &#8211; 10 = 460</p>
<pre class="brush: css">.grid-2 .cell { width: 460px; }</pre>
<p>This would be displayed using the following HTML:</p>
<pre class="brush: html">&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;grid-2&quot;&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre>
<p>Let&#8217;s work through it backwards to make sure the maths works out. 460 + 460 = 920.  That is the total width of the available content areas.  But on top of that we need to add our margins in, we have the 10px on the far left, then there are 2 lots of 10px margins in the very centre of the grid and the last 10px at the very far right side of the grid making a total of 960px.</p>
<p>A 3 column layout can container 3 cells or 2 cells where one of the cells is the size of 2 single cells.  So lets see how that works.</p>
<p>(960 / 3) &#8211; 10 -10 = 300</p>
<pre class="brush: css">.grid-3 .cell { width: 300px; }</pre>
<p>So, 3 x 300px = 900px + (20px x 3) = 960px.  That is the CSS needed for 3 single cells.</p>
<pre class="brush: html">&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;grid-3&quot;&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre>
<p>There are 2 easy ways to find out the width of the 2 cell.</p>
<p>One way, is to take the result of the single cell which in this case is 300, then add that on again to make 600.  We then need to add 20 to that to take in to account the margin that is no longer needed between the cells.</p>
<p>((960 / 3) &#8211; 20) + ((960 / 3) &#8211; 20) + 20 = 620</p>
<p>The other way is to do the original sum without taking the margins off until you have the full width of 2 cells, like so:</p>
<p>((960 / 3) * 2) &#8211; 20 = 620</p>
<p>So the CSS would like this:</p>
<pre class="brush: css">.grid-3 .cell-2 { width: 620px; }</pre>
<p>With the HTML like this:</p>
<pre class="brush: html">&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;grid-3&quot;&gt;
    &lt;div class=&quot;cell-2&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre>
<p>We then use exactly the same principles for the 4 column layout.</p>
<p>Single cell: (960 / 4) &#8211; 10 &#8211; 10 = 220<br />
Double cell: (220 + 220) + 20 = 460<br />
Triple cell: (460 + 220) + 20 = 700</p>
<pre class="brush: css">.grid-4 .cell { width: 220px; }
.grid-4 .cell-2 { width: 460px; }
.grid-4 .cell-3 { width: 700px; }</pre>
<p>Which would give you the following combinations available:</p>
<pre class="brush: html">&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;grid-4&quot;&gt;
    &lt;div class=&quot;cell-3&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;grid-4&quot;&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;grid-4&quot;&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
    &lt;div class=&quot;cell-2&quot;&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre>
<h4 class="step">Step 4: The result</h4>
<p>The result should be the following:</p>
<pre class="brush: css">.container {
  width: 960px;
  margin: 0 auto;
  padding: 1.5em 0;
}
.grid, .grid-2, .grid-3, .grid-4 {
  clear: both;
  overflow: hidden;
  margin-bottom: 1.5em;
}
.cell, .cell-2, .cell-3 {
  float: left;
  display: inline;
  margin: 0 10px;
  position: relative;
}
.alpha { margin-left: 0; }
.omega { margin-right: 0; }
.grid .cell { width: 940px; }
.grid-2 .cell, .grid-4 .cell-2 { width: 460px; }
.grid-3 .cell { width: 300px; }
.grid-3 .cell-2 { width: 620px; }
.grid-4 .cell { width: 220px; }
.grid-4 .cell-3 { width: 700px; }</pre>
<p>I have tidied up the code slightly, as the width for a 2 column cell is the same as a double cell in a 4 grid system.</p>
<p>If you look at the source code for this site, you will see that there are 2 sets of widths defined.  This is to cater for larger screens. A piece of javascript is triggered as soon as the page has finished loading and any resizing of the browser window which applies a class called wide to the body of the HTML.  If the window width is larger than 1200px then the site will be displayed in a larger grid system.  You could do the same using a stylesheet switcher to be able to change from a narrow to wide theme.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-04-05/create-your-own-simple-grid-system-in-css/1129/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Photoshop Tutorial &#8211; Dark Modern Header</title>
		<link>http://jamestombs.co.uk/2010-04-04/photoshop-tutorial-dark-modern-header/1122</link>
		<comments>http://jamestombs.co.uk/2010-04-04/photoshop-tutorial-dark-modern-header/1122#comments</comments>
		<pubDate>Sun, 04 Apr 2010 00:06:56 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[photoshop]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1122</guid>
		<description><![CDATA[This tutorial with guide you through how to make a dark modern header for your website: Step 1 Open Photoshop and create a new image how ever big you want it. Step 2 Create a black bar using the rectangular marquee tool on a new layer. Step 3 Using the same selection go to the [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial with guide you through how to make a dark modern header for your website:</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/example.jpg" alt="" title="example" width="400" height="150" class="alignnone size-full wp-image-1127" /></p>
<p><span id="more-1122"></span></p>
<h4 class="step">Step 1</h4>
<p>Open Photoshop and create a new image how ever big you want it.</p>
<h4 class="step">Step 2</h4>
<p>Create a black bar using the rectangular marquee tool on a new layer.</p>
<h4 class="step">Step 3</h4>
<p>Using the same selection go to the Select menu and select feather, set to 10px. On a new layer fill this with white.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/1.jpg" alt="" title="1" width="400" height="150" class="alignnone size-full wp-image-1123" /></p>
<h4 class="step">Step 4</h4>
<p>Press Ctrl + T to transform the layer. Drag the bottom slider up to the top to shrink the layer.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/2.jpg" alt="" title="2" width="421" height="162" class="alignnone size-full wp-image-1124" /></p>
<h4 class="step">Step 5</h4>
<p>Move the layer in to place and set the opacity to 30%.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/3.jpg" alt="" title="3" width="400" height="150" class="alignnone size-full wp-image-1125" /></p>
<h4 class="step">Step 6</h4>
<p>Select the Single Row Marquee tool and create a selection, press and hold Ctrl + Alt + Shift and click on the preview area of the black box in the layers panel.</p>
<p>On a new layer fill with #00adef do this again and make sure they are one on top of the other so it&#8217;s 2px high.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/4.jpg" alt="" title="4" width="400" height="150" class="alignnone size-full wp-image-1126" /></p>
<h4 class="step">Step 7</h4>
<p>Now we will add some shading over the clue bar so it isn&#8217;t so bright.</p>
<p>Press and hold Ctrl and left click the preview area of the blue bar in the layers panel.</p>
<p>On a new layer fill the selection with black.</p>
<p>Press Ctrl + D to deselect the selection.</p>
<p>Go to Filter » Blur » Gaussian Blur and set to 1px.</p>
<p>Set the layer opacity to 60%.</p>
<p>Press V and move up 1px.</p>
<h4 class="step">Step 8</h4>
<p>Add extra details to it such as text and reflection and you are finished.</p>
<p><img src="http://jamestombs.co.uk/wp-content/uploads/2010/04/example.jpg" alt="" title="example" width="400" height="150" class="alignnone size-full wp-image-1127" /></p>
<div class="note">
<p>Note: This tutorial was original posted on <a href="http://www.skeletorscorpse.com/photoshop-web-graphics/163-dark-modern-header">Skeletorscorpse</a> on 01 December 2006.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-04-04/photoshop-tutorial-dark-modern-header/1122/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Create stepped navigation with arrows using HTML + CSS</title>
		<link>http://jamestombs.co.uk/2010-03-30/create-stepped-navigation-with-arrows-using-html-css/1107</link>
		<comments>http://jamestombs.co.uk/2010-03-30/create-stepped-navigation-with-arrows-using-html-css/1107#comments</comments>
		<pubDate>Tue, 30 Mar 2010 18:50:55 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1107</guid>
		<description><![CDATA[In this tutorial I will show you how to create a stepped navigation with arrows using HTML and CSS which works in all major browsers. It is useful to show a user a stepped process such as a multi part form where there is more than one step that needs to be filled in. View [...]]]></description>
			<content:encoded><![CDATA[<p>In this tutorial I will show you how to create a stepped navigation with arrows using HTML and CSS which works in all major browsers. It is useful to show a user a stepped process such as a multi part form where there is more than one step that needs to be filled in.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/03/final-wide.jpg" rel="shadowbox[post-1107];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/03/final-small.jpg" alt="" title="Final result" width="400" height="42" class="aligncenter size-full wp-image-1113" /></a></p>
<div class="demo-block">
<div class="demo">
<p><a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/steppednav.html'>View demo</a></p>
</div>
<div class="source">
<p><a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/source.txt'>View sourcecode</a></p>
</div>
</div>
<p><span id="more-1107"></span></p>
<h3>Step 1: The HTML</h3>
<p>For the HTML we will use an unordered list so the navigation is accessible and will still partly work without the CSS file such as in text browsers.</p>
<pre class="brush: html">
&lt;div class=&quot;steps&quot;&gt;
  &lt;ul&gt;
    &lt;li class=&quot;step step-1&quot;&gt;
      &lt;a href=&quot;#&quot;&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br /&gt;Some random text that describes the step&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class=&quot;step step-2&quot;&gt;
      &lt;a href=&quot;#&quot;&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;br /&gt;Some random text that describes the step&lt;/a&gt;
    &lt;/li&gt;
    &lt;li class=&quot;step step-3&quot;&gt;
      &lt;a href=&quot;#&quot;&gt;&lt;strong&gt;Step 3&lt;/strong&gt;&lt;br /&gt;Some random text that describes the step&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>This will leave us with the following &#8211; <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/step-1.html'>view step 1 result</a>.</p>
<h3>Step 2: Style with CSS</h3>
<p>We now need to make it pretty, firstly we reset the default CSS rules applied to unordered lists by the browsers.</p>
<pre class="brush: css">
.steps ul, .steps li {
  margin: 0;
  padding: 0;
  list-style: none;
}
</pre>
<p>This resets the margins and padding around each the list itself and each list element within the list as well as removing the list-style (i.e. the bullet).</p>
<p>To make the elements appear side-by-side rather than on top of one another, we need to float the list elements.</p>
<pre class="brush: css">
.steps ul { float: left; }
.steps li {
  float: left;
}
</pre>
<p>This will leave you with your list elements side-by-side. <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/step-2.html'>View the result of step 2</a>.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
/* 336x280, created 3/31/10 */
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h3>Step 3: Make the steps in to arrows</h3>
<p>The next step is to add in our arrows to be background images.</p>
<pre class="brush: css">.steps li a {
  display: block;
  padding: 15px 20px;
  color: #fff;
  line-height: 1.5em;
  text-decoration: none;
}</pre>
<p>This makes the anchor tags act like block level elements so that they fill out in to their parent item which is the &lt;li&gt;. We also add some padding and set the line-height to make it look nicer.</p>
<p>Next we add in the background images for our list elements. You can use these images for the time being to speed up the process, just right click them then save them in the same folder as your CSS file.  <a href="http://jamestombs.co.uk/wp-content/uploads/2010/03/step.png" rel="shadowbox[post-1107];player=img;">Normal</a> &amp; <a href="http://jamestombs.co.uk/wp-content/uploads/2010/03/step_over.png" rel="shadowbox[post-1107];player=img;">Hover</a>. The images are basic PNGs with transparent sections on the end of arrow. There is also a 1px stroke to the right which gives you the seperator between the steps. The images should be as wide as your container, the reason for this is mentioned in step 5.</p>
<pre class="brush: css">.steps li.step a { background: transparent url(step.png) center right no-repeat; }
.steps li.step a:hover { background: transparent url(step_over.png) center right no-repeat; }</pre>
<p>This adds in the images to our steps with the hover state. <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/step-3.html'>View result of step 3</a></p>
<h3>Step 4: Setting the width and aligning the steps</h3>
<p>As you can tell from the result of step 3, we have a bit of a mess now.  So now we can clear it up.  My example is wrapped in a container which is 960px wide, so what I am going to do, is divide that by 3 as I have 3 steps.  That means each step should be 320px wide. So alter the CSS for .steps li to the following:</p>
<pre class="brush: css">
.steps li {
  float: left;
  width: 320px;
}
</pre>
<p>This now lines our steps side-by-side again with the text wrapped to fit in the width, but the arrows are stop start and aren&#8217;t covering each other.</p>
<p>To get around this, we use a negative margin to pull the element to the left, although we only apply this to the 2nd and 3rd steps.</p>
<pre class="brush: css">.steps li.step-2, .steps li.step-3 { margin-left: -30px; }</pre>
<p>Now you will notice a new problem.  The later steps are covering the earlier steps so the arrow isn&#8217;t visible.  To get around this, we will use the CSS property z-index to change the layering on the z-axis.</p>
<p>For z-index to be effective though, we also need to change the positioning type of the list element and child anchor.</p>
<pre class="brush: css">.steps li.step, .steps li.step a {
  position: relative;
  z-index: 3;
}
.steps li.step-2, .steps li.step-2 a { z-index: 2; }
.steps li.step-3, .steps li.step-3 a { z-index: 1; }</pre>
<p>Once again we have created more problems.  The first one being that some of the text is now hidden beneath the arrow of the preceeding step.  We can get around this by adding some extra padding.</p>
<pre class="brush: css">.steps li.step-2 a, .steps li.step-3 a { padding-left: 50px; }</pre>
<p>The 50px comes from the -30px which is the left negative margin + the extra 20px of padding we defined earlier on for each anchor element.</p>
<p>The negative margins also made the total width of our stepped element less than 960px so we have a gap at the end. With some simple maths we can work out the new width that each list element must be to fit the 960px width. We have a 960px container with 2 elements with negative margins of 30px, so 960px + 60px = 1020px.  Now we divide that by 3 to get our new width which is 340px.</p>
<pre class="brush: css">.steps li {
  float: left;
  width: 340px;
}</pre>
<p>This then leaves us a lot closer to our goal. <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/step-4.html'>View result of step 4</a>.</p>
<h3>Step 5: Fix the background position of the last step</h3>
<p>The arrow is showing on the 3rd step although it doesn&#8217;t go anywhere, it is the end.  To fix this, we just need to change the background position for step 3, this is the reasoning for our images being long.</p>
<pre class="brush: css">.steps li.step-3 a { background-position: center left; }
.steps li.step-3 a:hover { background-position: center left; }</pre>
<p>We change the background image to be aligned to the left so it is solid colour, as we made the images longer than the content, unless there is only 1 step (why would you be doing this tutorial if you only had 1 step?) the arrow won&#8217;t be seen.</p>
<p>Then you have a finished stepped navigation. <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/step-5.html'>View result of step 5</a>.</p>
<p>Then with a little extra CSS for text formatting and some borders on the parent element you are left with the <a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/steppednav.html'>final result</a>.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/03/final-wide.jpg" rel="shadowbox[post-1107];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/03/final-small.jpg" alt="" title="Final result" width="400" height="42" class="aligncenter size-full wp-image-1113" /></a></p>
<div class="demo-block">
<div class="demo">
<p><a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/steppednav.html'>View demo</a></p>
</div>
<div class="source">
<p><a href='http://jamestombs.co.uk/wp-content/uploads/2010/03/source.txt'>View sourcecode</a></p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-03-30/create-stepped-navigation-with-arrows-using-html-css/1107/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating a grid of images for an album in Drupal 6 with pagination</title>
		<link>http://jamestombs.co.uk/2010-03-10/creating-a-grid-of-images-for-an-album-in-drupal-6-with-pagination/1106</link>
		<comments>http://jamestombs.co.uk/2010-03-10/creating-a-grid-of-images-for-an-album-in-drupal-6-with-pagination/1106#comments</comments>
		<pubDate>Wed, 10 Mar 2010 13:12:27 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1106</guid>
		<description><![CDATA[Following on from the original tutorial on creating a grid of images for an album in Drupal 6, a few people asked how to add pagination on to this for large albums. Unfortunately from what I can tell Drupal&#8217;s pagination function only works with SQL queries so we are unable to use the existing data [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from the original tutorial on <a href="http://jamestombs.co.uk/2009-06-25/creating-a-grid-of-images-for-an-album-in-drupal/1046">creating a grid of images for an album in Drupal 6</a>, a few people asked how to add pagination on to this for large albums.</p>
<p>Unfortunately from what I can tell Drupal&#8217;s pagination function only works with SQL queries so we are unable to use the existing data available in the node object.  But due to Drupal&#8217;s nice database schema, it is very simple to write some simple SQL to give us the pager.</p>
<p><span id="more-1106"></span></p>
<p>Below is the full code and below the code I will explain what each part does.</p>
<pre class="brush: php">&lt;?php
$count = count($node-&gt;field_images);
if ($count &gt; 0):
	$images_per_page = 9;
	$sql = &quot;SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = &quot;. $node-&gt;nid;
	$count = &quot;SELECT COUNT(f.fid) FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = &quot;. $node-&gt;nid;
	$query = pager_query($sql, $images_per_page, 0, $count);
	while ($data = db_fetch_object($query)) {
		$images[$data-&gt;fid] = array(
			&#039;filepath&#039; =&gt; $data-&gt;filepath,
			&#039;data&#039; =&gt; unserialize($data-&gt;field_images_data),
		);
	}
	$rows = array();
	$images_per_row = 3;
	$i = 0;
	$row = 0;
	foreach ($images as $image) {
		$rows[$row][$i] = &#039;&lt;a class=&quot;gallery-thumbs&quot; title=&quot;&#039;. htmlspecialchars($image[&#039;data&#039;][&#039;description&#039;]) .&#039;&quot; rel=&quot;lightbox[photo_gallery-&#039;. $node-&gt;nid .&#039;]&quot; href=&quot;&#039;. imagecache_create_url(&#039;lightbox&#039;, $image[&#039;filepath&#039;]) .&#039;&quot;&gt;&#039;. theme(&#039;imagecache&#039;, &#039;thumbnail&#039;, $image[&#039;filepath&#039;], $image[&#039;data&#039;][&#039;title&#039;], $image[&#039;data&#039;][&#039;title&#039;]) .(trim($image[&#039;data&#039;][&#039;description&#039;]) != &#039;&#039; ? &#039;&lt;br /&gt;&lt;small&gt;&#039;. $image[&#039;data&#039;][&#039;description&#039;] .&#039;&lt;/small&gt;&lt;/a&gt;&#039; : &#039;&#039;);
		$i++;
		if ($i == $images_per_row) {
			$row++;
			$i = 0;
		}
	}
	?&gt;
  &lt;table class=&quot;views-view-grid&quot;&gt;
    &lt;tbody&gt;
      &lt;?php foreach ($rows as $row_number =&gt; $columns): ?&gt;
        &lt;?php
          $row_class = &#039;row-&#039; . ($row_number + 1);
          if ($row_number == 0) {
            $row_class .= &#039; row-first&#039;;
          }
          elseif (count($rows) == ($row_number + 1)) {
            $row_class .= &#039; row-last&#039;;
          }
        ?&gt;
        &lt;tr class=&quot;&lt;?php print $row_class; ?&gt;&quot;&gt;
          &lt;?php foreach ($columns as $column_number =&gt; $item): ?&gt;
            &lt;td class=&quot;&lt;?php print &#039;col-&#039;. ($column_number + 1); ?&gt;&quot;&gt;
              &lt;?php print $item; ?&gt;
            &lt;/td&gt;
          &lt;?php endforeach; ?&gt;
        &lt;/tr&gt;
      &lt;?php endforeach; ?&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
  &lt;?php print theme(&#039;pager&#039;, array(), $images_per_page, 0); ?&gt;
&lt;?php else: ?&gt;
  &lt;p&gt;No images in album&lt;/p&gt;
&lt;?php endif; ?&gt;</pre>
<p>First thing we do is check to see if there are any images.  Rather than doing a SQL query to get the result, I have chosen to use the already existing array of images in the node object.</p>
<pre class="brush: php">$count = count($node-&gt;field_images);</pre>
<p><script type="text/javascript"><!--
google_ad_client = "pub-8190774722923642";
/* 336x280, created 3/31/10 */
google_ad_slot = "1689935941";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script><br />
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>Then as before we check to make sure we have images, then create our query to generate the pager.</p>
<pre class="brush: php">$images_per_page = 9;
	$sql = &quot;SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = &quot;. $node-&gt;nid;
	$count = &quot;SELECT COUNT(f.fid) FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = &quot;. $node-&gt;nid;
	$query = pager_query($sql, $images_per_page, 0, $count);
	while ($data = db_fetch_object($query)) {
		$images[$data-&gt;fid] = array(
			&#039;filepath&#039; =&gt; $data-&gt;filepath,
			&#039;data&#039; =&gt; unserialize($data-&gt;field_images_data),
		);
	}</pre>
<p>In the query, we are gathering the file id (fid) of each individual image, the field_images_data which is a serializd array of the title, description and alt text of the image from when it was uploaded and the filepath of the image.  The count isn&#8217;t necessarily needed, but I have found the pager can act oddly when the $count part of <em>pager_query()</em> is missing.</p>
<p><em>pager_query()</em> also requires 2 other elements. The first after $sql, is the amount of rows to be taken out the database.  The next number is the element number.  This is needed for pages with multiple pagers on them.  If you have got multiple pagers and experience trouble then you will need to change this.</p>
<p>Then from this we recreate the $images array that we had before, although it is missing some information which is provided through the $node object, it provides everything that we need to display the image on the page.</p>
<p>The whole table HTML section remains untouched, but it is followed by an extra line:</p>
<pre class="brush: php">&lt;?php print theme(&#039;pager&#039;, array(), $images_per_page, 0); ?&gt;</pre>
<p>This prints out the Drupal pager below out table of images.  This can be used multiple times on a page, so you can have some pagination below and above the table of images.</p>
<p>If the page you are displaying the albums on already has pagers, you may need to change the 0 in both the <em>theme_pager()</em> and <em>pager_query()</em>.</p>
<p>You should now have a fully working grid with pagination.</p>
<p><strong>Edit:</strong> As pointed out by dukat in the comments, you can change the original SQL query to the following to keep the images in the order defined in the node.</p>
<pre class="brush: php">$sql = &quot;SELECT f.fid, i.field_images_data, f.filepath FROM content_field_images i JOIN files f ON f.fid = i.field_images_fid WHERE nid = &quot;. $node-&gt;nid .&quot; ORDER BY i.delta ASC&quot;;</pre>
<p>Obviously you can change the order between ASC or DESC.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-03-10/creating-a-grid-of-images-for-an-album-in-drupal-6-with-pagination/1106/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Bobby Kotick &#8211;  &#8220;I took a look at World of Warcraft and I thought, &#8216;Who would want to buy a subscription to that?&#8217;&#8221;</title>
		<link>http://jamestombs.co.uk/2010-02-19/bobby-kotick-i-took-a-look-at-world-of-warcraft-and-i-thought-who-would-want-to-buy-a-subscription-to-that/1105</link>
		<comments>http://jamestombs.co.uk/2010-02-19/bobby-kotick-i-took-a-look-at-world-of-warcraft-and-i-thought-who-would-want-to-buy-a-subscription-to-that/1105#comments</comments>
		<pubDate>Fri, 19 Feb 2010 12:15:31 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Gaming]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1105</guid>
		<description><![CDATA[This is from Bobby Kotick speach as DICE this year (CEO of Activision Blizzard) Kotick was also offered the chance to buy Blizzard in the 1990s for $7 million, and then in the early 2000s for $700 million. [12:10] &#8220;I took a look at World of Warcraft and I thought, &#8216;Who would want to buy [...]]]></description>
			<content:encoded><![CDATA[<p>This is from <a href="http://en.wikipedia.org/wiki/Robert_Kotick">Bobby Kotick</a> speach as <a href="http://www.dicesummit.org/">DICE</a> this year (CEO of Activision Blizzard)</p>
<p>Kotick was also offered the chance to buy Blizzard in the 1990s for $7 million, and then in the early 2000s for $700 million.</p>
<p>[12:10] &#8220;I took a look at World of Warcraft and I thought, &#8216;Who would want to buy a subscription to that?&#8217;&#8221;</p>
<p>[12:10] &#8220;So, of course we ended up merging with them in 2008 when they were worth $7 billion.&#8221;</p>
<p>You can buy <a href="http://www.amazon.co.uk/gp/product/B000197Z30?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000197Z30">World of Warcraft</a> for just £4.99 from <a href="http://www.amazon.co.uk/gp/product/B000197Z30?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000197Z30">Amazon</a>.</p>
<p><span id="more-1105"></span></p>
<p>Activision Blizzard owns the following gaming brands:</p>
<p><a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D15%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D23%26field-keywords%3DCrash%2520Bandicoot%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Crash Bandicoot series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D16%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D13%26field-keywords%3DGuitar%2520Hero%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Guitar Hero series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D5%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D21%26field-keywords%3DCall%2520of%2520Duty%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Call of Duty series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D29%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D18%26field-keywords%3DTony%2520Hawk%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Tony Hawk franchise</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D27%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D21%26field-keywords%3DSpider-Man%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Spider-Man series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D19%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D17%26field-keywords%3DSpyro%2520the%2520Dragon%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Spyro the Dragon series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D0%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D0%26field-keywords%3DWarcraft%2520%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Warcraft series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D3%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D10%26field-keywords%3DStarCraft%2520%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">StarCraft series</a><br />
<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2Fs%3Fie%3DUTF8%26x%3D18%26ref_%3Dnb%5Fsb%5Fnoss%26y%3D17%26field-keywords%3DDiablo%2520%26url%3Dsearch-alias%253Dvideogames&#038;tag=skeletorscorp-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=19450">Diablo series</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-02-19/bobby-kotick-i-took-a-look-at-world-of-warcraft-and-i-thought-who-would-want-to-buy-a-subscription-to-that/1105/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Review] Microsoft Sidewinder X8 Mouse</title>
		<link>http://jamestombs.co.uk/2010-01-28/microsoft-sidewinder-x8-mouse/1101</link>
		<comments>http://jamestombs.co.uk/2010-01-28/microsoft-sidewinder-x8-mouse/1101#comments</comments>
		<pubDate>Thu, 28 Jan 2010 21:46:42 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Gaming]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1101</guid>
		<description><![CDATA[Just received my Microsoft Sidewinder X8 mouse as a replacement to my aging Logitech G7. Both mice are wireless gaming mice relying on batteries for power, but both go different ways to making sure you can always use your mouse. The Logitech G7 went down the route of 2 seperate batteries that could only be [...]]]></description>
			<content:encoded><![CDATA[<p>Just received my <a href="http://www.amazon.co.uk/gp/product/B001DCELH2?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B001DCELH2">Microsoft Sidewinder X8</a> mouse as a replacement to my aging <a href="http://www.amazon.co.uk/gp/product/B000ETTH88?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000ETTH88">Logitech G7</a>. Both mice are wireless gaming mice relying on batteries for power, but both go different ways to making sure you can always use your mouse.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/sidewinder-x8.jpg" rel="shadowbox[post-1101];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/sidewinder-x8-300x239.jpg" alt="" title="sidewinder-x8" width="300" height="239" class="alignnone size-medium wp-image-1103" /></a></p>
<p><span id="more-1101"></span></p>
<p>The Logitech G7 went down the route of 2 seperate batteries that could only be used in the G7.  Only one battery could be used at a time, so while that was in use the other could be recharged in the charging dock, which also had a USB port for the USB receiver.  It worked well, but could be a bit annoying when the battery ran out of juice mid-way through a game or work, but it only took a couple of seconds to swap.  At first the batteries lasted around 7-8 hours each between charges which was more than enough generally for 2-3 days of use.  But over the years the battery life has shrunk to less than an hour on both which made the mouse more and more frustrating. Unfortunately as good as the mouse was, very comfortable and with a relatively good sensitivity (2000dpi), new batteries for the mouse would of cost around the same as what the moues is worth second hand.  So for the second time since owning the G7 I went out looking for a new mouse.  My first outing resulted in buying the corded <a href="http://www.amazon.co.uk/gp/product/B000X8G0D0?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000X8G0D0">Razer Lachesis</a>.  That didn&#8217;t last long though, the feel of the mouse was wrong, the mouse was too light and the shape of the buttons never felt right as well some issues with the mouse not being usable upon Windows start up which I imagine was down to drivers.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/microsoft_sidewinder_x8_2.jpg" rel="shadowbox[post-1101];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/microsoft_sidewinder_x8_2-300x181.jpg" alt="" title="microsoft_sidewinder_x8_2" width="300" height="181" class="alignnone size-medium wp-image-1104" /></a></p>
<p>So now the <a href="http://www.amazon.co.uk/gp/product/B001DCELH2?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B001DCELH2">Microsoft Sidewinder X8</a> is in, same price as both the <a href="http://www.amazon.co.uk/gp/product/B000X8G0D0?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000X8G0D0">Razer Lachesis</a> and the  <a href="http://www.amazon.co.uk/gp/product/B000ETTH88?ie=UTF8&#038;tag=skeletorscorp-21&#038;linkCode=as2&#038;camp=1634&#038;creative=19450&#038;creativeASIN=B000ETTH88">Logitech G7</a> but is packed with a lot more features.</p>
<p>It comes with one standard rechargable AA battery, so the battery can be charged using a standard battery recharger or the more useful and usable charger that also acts as a receiver. In what looks like a hockey puck is a small wire wrapped around the middle with a small pad with 3 metal elements on it. This attaches magnetically to the bottom of the mouse but in such a way as not to pull off easily.  This provides a charging facility over USB which is great as when the battery is running low, you can just plug the cable in and carry on as normal, then when the battery is charged up, just take the cable out and carry on, no changing batteries required here.</p>
<p>Another nice touch is that in the hockey puck like receiver is a set of 2 feet for the mice with different levels of slipperiness to go with the standard feet on the mice, so you have 3 sets of feet.</p>
<p>The mouse has different resolution settings like the G7 and Lachesis but like the Lachesis goes all the way to 4000dpi. The Lachesis and G7 have 2 buttons below the scroll wheel to go up and down the sensitivity settings, the X8 offers 3 buttons allowing 3 different settings. The X8 also features a nice LED screen next to the thumb which tells you the DPI as well as the battery charge state, I feel it would of been better to be more like the G7 and allow more than 3 settings and to be able to scroll through as you would easily be able to tell which sensitivity you are on by looking at the LED screen.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/Mo-MSX8.jpg" rel="shadowbox[post-1101];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/Mo-MSX8-300x241.jpg" alt="" title="Mo-MSX8" width="300" height="241" class="alignnone size-medium wp-image-1102" /></a></p>
<p>The scroll wheel on the X8 feels very solid with a textured metal finish allowing good grip which although I think it shouldn&#8217;t, actually feels better than the rubber used on both the Lachesis and G7 and gives a reassuring click sound when pressed.</p>
<p>So far I highly recommend the X8 at the moment I would say it is a better mouse than the G7 and definately better than the Lachesis from my experiences, but only time will tell.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-28/microsoft-sidewinder-x8-mouse/1101/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a cartoon style cloud in Photoshop</title>
		<link>http://jamestombs.co.uk/2010-01-27/create-a-cartoon-style-cloud-in-photoshop/1095</link>
		<comments>http://jamestombs.co.uk/2010-01-27/create-a-cartoon-style-cloud-in-photoshop/1095#comments</comments>
		<pubDate>Tue, 26 Jan 2010 23:39:09 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1095</guid>
		<description><![CDATA[This tutorial will teach you how to make a basic cartoon cloud in Photoshop. The tutorial should be suitable for beginners. The result Tutorial Step 1: Create new document Open Photoshop and create a new document at whatever size you wish, I will be creating mine at 400&#215;240. Step 2: Set the background colour Set [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will teach you how to make a basic cartoon cloud in Photoshop. The tutorial should be suitable for beginners.</p>
<p><span id="more-1095"></span></p>
<h2>The result</h2>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/cloud_result.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/cloud_result-300x180.jpg" alt="" title="Finished Cloud" width="300" height="180" class="alignnone size-medium wp-image-1096" /></a></p>
<h2>Tutorial</h2>
<h3>Step 1: Create new document</h3>
<p>Open Photoshop and create a new document at whatever size you wish, I will be creating mine at 400&#215;240.</p>
<h3>Step 2: Set the background colour</h3>
<p>Set your foreground colour to #b7e0ff and fill the background by either pressing Alt + Backspace or going to Edit > Fill (Shift + F5) and selecting the foreground colour.</p>
<h3>Step 3: Create the cloud shape</h3>
<p>Select the elliptical marquee tool and draw multiple circles on the canvas, creating the shape of the cloud.  To add to the initial selection, hold Shift while drawing the additional circles.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/shape.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/shape-300x180.jpg" alt="" title="Cloud shape" width="300" height="180" class="alignnone size-medium wp-image-1100" /></a></p>
<p>Create a new layer and fill the cloud selection with #79b4e0. With the selection still active, create another layer and fill with #cde9ff.  Move this layer up 3 or 4 pixels.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/double-layer.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/double-layer-300x180.jpg" alt="" title="Colour" width="300" height="180" class="alignnone size-medium wp-image-1097" /></a></p>
<h3>Step 4: Add some additional depth to the cloud</h3>
<p>With the selection still active, create another layer. This time select the gradient tool and set the foreground colour to white. Then for your gradient settings, set the gradient to go from foreground to transparent.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/gradient.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/gradient.jpg" alt="" title="Select gradient" width="267" height="182" class="alignnone size-full wp-image-1098" /></a></p>
<p>Go to Select -> Modify -> Contract and set to 2 or 3px, press OK.</p>
<p>Now draw a gradient from just above the top of your cloud shape to the bottom of the cloud shape.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/gradient_draw.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/gradient_draw-300x180.jpg" alt="" title="Draw gradient" width="300" height="180" class="alignnone size-medium wp-image-1099" /></a></p>
<p>You cloud is now complete.</p>
<h2>Result</h2>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/cloud_result.jpg" rel="shadowbox[post-1095];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/cloud_result-300x180.jpg" alt="" title="Finished Cloud" width="300" height="180" class="alignnone size-medium wp-image-1096" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-27/create-a-cartoon-style-cloud-in-photoshop/1095/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a basic layout using HTML &amp; CSS</title>
		<link>http://jamestombs.co.uk/2010-01-26/create-a-basic-layout-using-html-css/1086</link>
		<comments>http://jamestombs.co.uk/2010-01-26/create-a-basic-layout-using-html-css/1086#comments</comments>
		<pubDate>Tue, 26 Jan 2010 17:03:01 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1086</guid>
		<description><![CDATA[Following on from the Guide to classes and ids in HTML and CSS, we will create this basic 2 column layout. Before we delve in to HTML and CSS, you need to understand the basic structure of the page to know how to write your HTML. To do this, on paper or Photoshop draw out [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from the <a href="http://jamestombs.co.uk/2010-01-26/guide-to-classes-and-ids-in-html-css/1085">Guide to classes and ids in HTML and CSS</a>, we will create this basic 2 column layout.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/main.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/main-300x207.jpg" alt="" title="2 Column Layout" width="300" height="207" class="alignnone size-medium wp-image-1092" /></a></p>
<p>Before we delve in to HTML and CSS, you need to understand the basic structure of the page to know how to write your HTML.  To do this, on paper or <a href="http://www.amazon.co.uk/Adobe-Photoshop-Elements-PC-DVD/dp/B002OB5G6G/ref=sr_1_1?ie=UTF8&#038;s=software&#038;qid=1264522453&#038;sr=1-1">Photoshop</a> draw out the basic layout.</p>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/layout.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/layout-300x207.jpg" alt="" title="Wireframe" width="300" height="207" class="alignnone size-medium wp-image-1093" /></a></p>
<p>With the basic wireframe of the site you can now write out the basic HTML.</p>
<p><span id="more-1086"></span></p>
<pre class="brush: html">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
  &lt;title&gt;2 Column Layout&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div id=&quot;wrap&quot;&gt;
    &lt;div id=&quot;header&quot;&gt;
    	&lt;h1&gt;Site name&lt;/h1&gt;
    &lt;/div&gt;
    &lt;div id=&quot;navigation&quot;&gt;
      &lt;ul&gt;
      	&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
    &lt;div id=&quot;content_area&quot;&gt;
      &lt;div id=&quot;content&quot;&gt;
        &lt;h2&gt;Heading&lt;/h2&gt;
        &lt;p&gt;Mauris sit amet lectus at sem fringilla tincidunt. Phasellus ornare mollis egestas. Donec a sapien metus, sit amet faucibus dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc nec tortor nec velit dapibus elementum. Fusce blandit accumsan sagittis. Suspendisse sodales gravida risus rutrum facilisis. Vestibulum at velit id arcu egestas condimentum. Aenean laoreet leo sit amet eros eleifend pretium condimentum ac arcu. Vestibulum volutpat hendrerit urna, sit amet laoreet eros volutpat et.&lt;/p&gt;
      &lt;/div&gt;
      &lt;div id=&quot;sidebar&quot;&gt;
        &lt;div class=&quot;block&quot;&gt;
          &lt;h3&gt;Block header&lt;/h3&gt;
          &lt;ul&gt;
            &lt;li&gt;Item 1&lt;/li&gt;
            &lt;li&gt;Item 2&lt;/li&gt;
            &lt;li&gt;Item 3&lt;/li&gt;
            &lt;li&gt;Item 4&lt;/li&gt;
            &lt;li&gt;Item 5&lt;/li&gt;
            &lt;li&gt;Item 6&lt;/li&gt;
            &lt;li&gt;Item 7&lt;/li&gt;
            &lt;li&gt;Item 8&lt;/li&gt;
            &lt;li&gt;Item 9&lt;/li&gt;
            &lt;li&gt;Item 10&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div id=&quot;footer&quot;&gt;
    	&lt;p&gt;Copyright somerandomsite 2010&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>This gives the bare markup needed for the layout.</p>
<p>For the CSS we will go through each separate HTML element.</p>
<h3>Wrapper</h3>
<p>We start the document off with a div with an id of wrap.  This gives us a container that we can set a width to as we can&#8217;t set a width to the body tag.</p>
<pre class="brush: css">#wrap {
  width: 980px;
  margin: 0 auto;
}</pre>
<p>This sets the width of the container to 980px. Setting the margin to <em>0 auto</em> means that the top and bottom margins are set to 0 and the left and right margins are set to automatically generate.  The browser will then set the left and right margins to be the same which results in the container being centered in the body.</p>
<h3>Header</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_header.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_header-300x207.jpg" alt="" title="Header" width="300" height="207" class="alignnone size-medium wp-image-1089" /></a></p>
<p>For the header, we will need to style the header div itself as well as the h1 tag inside it.</p>
<pre class="brush: css">#header { background: #c00; }
#header h1 {
  color: #fff;
  margin: 0;
  padding: 30px 10px 10px 30px;
  font-size: 6em;
  font-weight: normal;
}</pre>
<p>With this CSS we are making the background color of the div with id header to #c00 which is a dark red.  As divs are block level elements it will automatically fill the width of it&#8217;s parent which is our div with the id wrap. So we have a div with a red background which is 980px wide.</p>
<p>Within our header div we have an h1 tag.  For this we change it to white by using <em>color: #fff</em>. We then remove any margins on the h1 tag which are applied automatically by the browser then set some padding around the text so that it doesn&#8217;t touch the edge of the div.  To make it stand out we make the font-size 6x bigger than the standard font-size of the page which you can specify in the body CSS, and make the font-weight normal rather than bold.</p>
<h3>Navigation bar</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_navigation.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_navigation-300x207.jpg" alt="" title="Navigation Bar" width="300" height="207" class="alignnone size-medium wp-image-1090" /></a></p>
<p>The navigation bar is made from an unordered list which allows internet robots (search engines) and screen readers (browsers for blind/hard of sight users) to navigate the site properly.  You could make it using a p tag with spaces between the links but that wouldn&#8217;t be good for accessibility or SEO.</p>
<pre class="brush: css">#navigation ul {
  margin: 0;
  padding: 0;
  list-style: none;
  float: left;
  background: #00c;
  width: 100%;
}
#navigation ul li {
  float: left;
  width: auto;
}
#navigation ul li a {
  display: block;
  padding: 10px 20px;
  color: #fff;
  text-decoration: none;
  font-size: 1.4em;
  font-weight: bold;
}
#navigation ul li a:hover {
  color: #00c;
  background: #fff;
}</pre>
<p>The first thing we do is to reset the default styling given to unordered lists (the bullet points etc) by resetting the margin, padding and list-style (bullet points). Then we float the whole list to the left so that the ul element takes the height of the children list elements.  We also set the background colour and set the width to 100% so that it takes the whole width of the container, otherwise the background colour would stop after the last list element.</p>
<p>Each list element within the unordered list is floated to the left so they all line up next to each other.  We also define the width as <em>auto</em>, if you don&#8217;t do this the CSS validator will mark your code as invalid CSS.</p>
<p>Each anchor tag with in the list is giving some padding to give space to each link.  We have to define the display of each anchor tag as block so that we can apply vertical padding to each link, this also allows better hover styling as the cursor doesn&#8217;t have to be on the text and can be anywhere within the padded area.  As well as the padding the colour is changed to make the text contrast the background and we remove the default text-decoration of anchor tags which is the underline by setting it to none. I also made the font slightly bigger and bold.</p>
<p>As well as the default state of the anchor tags, we can also define the hover attribute using a pseudo class called :hover.  When the user hovers their mouse over the HTML element defined by the selector the browser will pick up on these CSS changes and will be reverted as soon as the mouse stops hovering over the element.  Here we are just changing the colour and background so that the user can see that it has a click-able action.</p>
<h3>Content area</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_content_area.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_content_area-300x207.jpg" alt="" title="Content Area" width="300" height="207" class="alignnone size-medium wp-image-1094" /></a></p>
<p>Our content area div is a minor container div to enclose the main content and sidebar. You don&#8217;t have to use this, but it makes it a lot easier to style and line up elements in all the browsers.</p>
<pre class="brush: css">#content_area {
  clear: both;
  padding-top: 10px;
}</pre>
<p>The clear attribute makes sure that any floating elements are cleared, so essentially the div will appear on the next free line below any floating elements and allows us to put some padding between the navigation and our content.  With out the clear attribute, the padding would have no effect.</p>
<h3>Content</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_content.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_content-300x207.jpg" alt="" title="Content" width="300" height="207" class="alignnone size-medium wp-image-1087" /></a></p>
<pre class="brush: css">#content {
  float: left;
  width: 75%;
}
#content h2, #content p {
  padding: 0 10px 0 20px;
}
#content h2 {
  font-size: 3.0em;
  margin: 0;
}
#content p {
  font-size: 1.2em;
}</pre>
<p>The first thing we do is set the width of our content div and float it to the left, this allows the sidebar to go along side it.</p>
<p>We also apply some standard CSS rules to add padding and change the font size of elements within the content div.</p>
<h3>Sidebar</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_sidebar.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_sidebar-300x207.jpg" alt="" title="Sidebar" width="300" height="207" class="alignnone size-medium wp-image-1091" /></a></p>
<pre class="brush: css">#sidebar {
  margin-left: 75%;
}
#sidebar h3 {
  font-size: 1.6em;
  margin: 0;
}
#sidebar li {
  font-size: 1.2em;
}
.block {
  border: 1px solid #000;
  padding: 10px;
  margin: 5px;
}</pre>
<p>To get the sidebar to move up to the right of the content we need to make sure that it isn&#8217;t trying to display on top or behind it.  To do this, we apply a left margin to the sidebar, the left margin should be the same or bigger (if you want to include a space between your sidebar and content) than your content width. You can also do this by setting the width and floating it to the left or right, but this can cause complications especially when you have more than 2 columns.</p>
<p>As with the content we apply some basic styling to the elements within the sidebar.</p>
<h3>Footer</h3>
<p><a href="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_footer.jpg" rel="shadowbox[post-1086];player=img;"><img src="http://jamestombs.co.uk/wp-content/uploads/2010/01/highlight_footer-300x207.jpg" alt="" title="Footer" width="300" height="207" class="alignnone size-medium wp-image-1088" /></a></p>
<pre class="brush: css">#footer {
  clear: both;
  background: #aaa;
}
#footer p {
  padding: 10px 20px;
  color: #fff;
  font-size: 1.3em;
}</pre>
<p>Much like the content area we need to clear any floating elements above it.  I have also change the background colour to a light grey.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-26/create-a-basic-layout-using-html-css/1086/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guide to classes and id&#8217;s in HTML &amp; CSS</title>
		<link>http://jamestombs.co.uk/2010-01-26/guide-to-classes-and-ids-in-html-css/1085</link>
		<comments>http://jamestombs.co.uk/2010-01-26/guide-to-classes-and-ids-in-html-css/1085#comments</comments>
		<pubDate>Tue, 26 Jan 2010 16:09:04 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1085</guid>
		<description><![CDATA[Classes A class can be applied to any HTML element to allow you to easily target it using CSS to add styling and change the way it is presented to the user. In CSS classes are selected using a full stop followed by the name of the class. HTML &#60;div class=&#34;classname&#34;&#62; &#60;p&#62;This is some text [...]]]></description>
			<content:encoded><![CDATA[<h2>Classes</h2>
<p>A class can be applied to any HTML element to allow you to easily target it using CSS to add styling and change the way it is presented to the user.  In CSS classes are selected using a full stop followed by the name of the class.<br />
<span id="more-1085"></span></p>
<h3>HTML</h3>
<pre class="brush: html">&lt;div class=&quot;classname&quot;&gt;
  &lt;p&gt;This is some text in a paragraph tag.&lt;/p&gt;
&lt;/div&gt;</pre>
<h3>CSS</h3>
<pre class="brush: css">p { font-size: 12px; }
.classname { border: 1px solid #ddd; }
.classname p { font-size: 14px; }</pre>
<p>This would display like this:</p>
<div style="border: 1px solid #ddd;">
<p style="font-size: 14px;">This is some text in a paragraph tag.</p>
</div>
<p>The original <em>p</em> selector in the CSS is overwritten by <em>.classname p</em>, so the font size of any <em>p</em> tag within a parent with a class of <em>classname</em> will be 14px.</p>
<p>If you were to have two paragraph tags within the div but wanted them styled slightly differently, then you could add a class to one of the paragraph tags.</p>
<h3>HTML</h3>
<pre class="brush: html">&lt;div class=&quot;classname&quot;&gt;
  &lt;p class=&quot;large&quot;&gt;This is slightly larger text.&lt;/p&gt;
  &lt;p&gt;This is some text in a paragraph tag.&lt;/p&gt;
&lt;/div&gt;</pre>
<h3>CSS</h3>
<pre class="brush: css">p { font-size: 12px; }
.classname { border: 1px solid #ddd; }
.classname p.large { font-size: 14px; }</pre>
<div style="border: 1px solid #ddd;">
<p style="font-size: 14px;">This is slightly larger text.</p>
<p>This is some text in a paragraph tag.</p>
</div>
<p>As you can see the first paragraph is larger than the second paragraph.  This is because the second paragraph is picking up the default font-size that we specified in the CSS file.  The first paragraph is using a larger font size due to the CSS rule <em>.classname p.large</em>.</p>
<p>Classes can be reused as many times as you like in an HTML document. If you have a constant style that you wish to apply on elements through the page, you can create a single CSS class and reuse it.</p>
<h2>Id&#8217;s</h2>
<p>Id&#8217;s can be styled in much the same way a class can, but rather than using a full stop as a selector, we use the hash tag (#).  Unlike CSS classes though, an Id can only be used <strong>once</strong> per page. The benefit of using Id&#8217;s is that you can link to them with anchor tags.</p>
<h3>HTML</h3>
<pre class="brush: html">&lt;div id=&quot;tut_header&quot;&gt;&lt;p&gt;Site name&lt;/p&gt;&lt;/div&gt;
&lt;!-- Insert random HTML --&gt;
&lt;p&gt;&lt;a href=&quot;#tut_header&quot;&gt;Back to header&lt;/a&gt;&lt;/p&gt;</pre>
<p>So if you had a long page of content, clicking the link will make the page move up so that the div with the id tut_header will be the top most point. Using ids can be useful for creating &#8216;Back to Top&#8217; buttons.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-26/guide-to-classes-and-ids-in-html-css/1085/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Open source intranet solution &#8211; Open Atrium</title>
		<link>http://jamestombs.co.uk/2010-01-13/open-source-intranet-solution-open-atrium/1084</link>
		<comments>http://jamestombs.co.uk/2010-01-13/open-source-intranet-solution-open-atrium/1084#comments</comments>
		<pubDate>Wed, 13 Jan 2010 21:15:59 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1084</guid>
		<description><![CDATA[Open Atrium is an open source intranet package that uses Drupal as it&#8217;s underlying framework. As Open Atrium is a Drupal installation profile, it runs using PHP and MySQL, which means other than hardware cost it is free to get started and run. It features a few familar modules to any Drupal user such as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://openatrium.com/">Open Atrium</a> is an open source intranet package that uses Drupal as it&#8217;s underlying framework.</p>
<p>As <a href="http://openatrium.com/">Open Atrium</a> is a <a href="http://drupal.org">Drupal</a> installation profile, it runs using PHP and MySQL, which means other than hardware cost it is free to get started and run. It features a few familar modules to any <a href="http://drupal.org">Drupal</a> user such as <a href="http://drupal.org/project/views">Views</a> and <a href="http://drupal.org/project/og">Organic Groups</a> but also introduces some lesser known modules such as <a href="http://drupal.org/project/features">Features</a> and <a href="http://drupal.org/project/spaces">Spaces</a>.</p>
<p>It is currently in beta and is currently at beta 3.2 which can be downloaded the from <a href="http://openatrium.com/download">Open Atrium</a> website.</p>
<p>You can install it like you would any <a href="http://drupal.org/">Drupal</a> installation, but during installation you are given the choice to install Drupal standalone or <a href="http://drupal.org/">Drupal</a> with <a href="http://openatrium.com/">Open Atrium&#8217;s</a> modules and configuration preinstalled.</p>
<p>Features include a blog for updates, a calendar for events, documents which uses the books module to produce a hierachial display of all the documents you want to store, a shoutbox and a case tracker which is ideal for development teams.  Each feature can be turned on or off within each organic group which means you can easily divide internal teams in to different groups to keep the intranet a bit tidier than it would if it was all in one place.</p>
<p><object width="400" height="225"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5579829&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5579829&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="225"></embed></object>
<p><a href="http://vimeo.com/5579829">Introducing Open Atrium</a> from <a href="http://vimeo.com/developmentseed">Development Seed</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-13/open-source-intranet-solution-open-atrium/1084/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create a Drupal 6 theme based on the Zen starter theme</title>
		<link>http://jamestombs.co.uk/2010-01-11/create-a-drupal-6-theme-based-on-the-zen-starter-theme/1083</link>
		<comments>http://jamestombs.co.uk/2010-01-11/create-a-drupal-6-theme-based-on-the-zen-starter-theme/1083#comments</comments>
		<pubDate>Mon, 11 Jan 2010 21:08:55 +0000</pubDate>
		<dc:creator>James</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[drupal planet]]></category>

		<guid isPermaLink="false">http://jamestombs.co.uk/?p=1083</guid>
		<description><![CDATA[What is Zen? Taken from the Zen project page: Zen is the ultimate starting theme for Drupal. If you are building your own standards-compliant theme, you will find it much easier to start with Zen than to start with Garland or Bluemarine. This theme has fantastic online documentation and tons of code comments for both [...]]]></description>
			<content:encoded><![CDATA[<h3>What is Zen?</h3>
<p>Taken from the <a href="http://drupal.org/project/zen">Zen project page</a>:</p>
<blockquote><p><strong>Zen is the ultimate <em>starting theme</em> for Drupal.</strong> If you are building your own standards-compliant theme, you will find it much easier to start with Zen than to start with Garland or Bluemarine. This theme has <a href="http://drupal.org/node/193318">fantastic online documentation</a> and tons of code comments for both the PHP (template.php) and HTML (page.tpl.php, node.tpl.php).</p>
</blockquote>
<h3>Why use Zen?</h3>
<p>Zen gives a great framework for you to work from as a lot of the hard work in making the default Drupal CSS rules easier to customise as well as having a starter kit for you to modify giving you the basics to create your own theme without needed to mess around with the in&#8217;s and out&#8217;s of Drupals theming system.<br />
<span id="more-1083"></span></p>
<h3>Where do I get Zen?</h3>
<p>You can download Zen from the project page on <a href="http://drupal.org/project/zen">Drupal.org</a>. As of writing there are 2 versions available for Drupal 6; Zen 6.x-1.1 and Zen 6.x-2.0-beta1.  We will be using Zen 6.x-1.1 as it isn&#8217;t a good idea to use modules or themes that are in alpha, beta or RC on a production site.</p>
<h3>How do I install Zen?</h3>
<p>Once you have downloaded the file from Drupal.org you will need to extract the zen folder and place it in your /sites/all/themes directory.  You will need to create a directory called themes within the /sites/all directory if it doesn&#8217;t already exist. </p>
<p>If you need a program to extract the file from Drupal.org, I recommend you use <a href="http://www.7-zip.org/download.html">7-zip</a> which is a freeware application.</p>
<h3>How do I start using Zen?</h3>
<p>Within the Zen directory is a directory called STARTERKIT.  Copy this folder and return to the /sites/all/themes directory.  Paste the STARTERKIT directory from your clipboard into this directory. You should have a tree structure like the below:</p>
<pre>+ sites
|-+ all
| |-+ themes
| | |-- zen
| | |-- STARTERKIT</pre>
<p>Rename the STARTERKIT directory to the name you wish to give your theme.  This is the machine name that is used in the backend so you have to use lowercase characters and use underscores (_) instead of spaces.</p>
<p>For this tutorial we will name the theme drupal_theme, which gives us the following tree structure.</p>
<pre>+ sites
|-+ all
| |-+ themes
| | |-- zen
| | |-- drupal_theme</pre>
<p>Navigate within your drupal_theme directory and rename the file STARTERKIT.info.txt to yourthemename.info, in my case it will be drupal_theme.info.</p>
<p>Open the file in your editing program.</p>
<p>Change the name from <em>name = Zen Sub-theme Starter Kit</em> to <em>name = Your Theme Name</em> and change the description to a description of your theme.</p>
<p>Also change the <em>STARTERKIT.css</em> text to <em>yourthemename.css</em>, in my case it will be drupal_theme.css.</p>
<p>Save and close the file.</p>
<p>You need to make a choice as to whether you would like your theme to be a liquid layout, i.e. it will stretch the width of the browser so there is no whitespace on either side of the site or a fixed layout site where the site is a fixed width dependant of the browser window.</p>
<blockquote><p><strong>Liquid/adaptive width</strong></p>
<p>Copy the file <em>layout-liquid.css</em> from the /sites/all/themes/zen/zen directory to the /sites/all/themes/yourthemename directory. Then rename the file <em>layout.css</em></p>
<p><strong>Fixed width</strong></p>
<p>Copy the file <em>layout-fixed.css</em> from the /sites/all/themes/zen/zen directory to the /sites/all/themes/yourthemename directory. Then rename the file <em>layout.css</em></p></blockquote>
<p>Copy over the following CSS files from /sites/all/themes/zen/zen to your /sites/all/themes/yourthemename directory.</p>
<ul>
<li>zen.css</li>
<li>print.css</li>
<li>html-elements.css</li>
</ul>
<p>Rename the <em>zen.css</em> to <em>yourthemename.css</em>, in my case it will be <em>drupal_theme.css</em>.</p>
<p>In your theme folder, open and edit the files template.php and theme-settings.php, replacing all instanced of <em>STARTERKIT</em> with your theme name, so I replaced all instances of <em>STARTERKIT</em> with <em>drupal_theme</em>.</p>
<p>While logged in as a user with rights to the admin pages, navigate to Administer > Site building > Themes (admin/build/themes) and set your theme to default and save.</p>
<h3>How do I customise the theme?</h3>
<p>The structure of the page as in the way the sidebar, header, content, footer is layed out is mostly in the php files within the Zen theme and the CSS files we copied over to our theme folder allows us to change the styling of these items to make them appear the way we want.</p>
<h4>Change the font size</h4>
<p>The default font size is defined in the <em>html-elements.css</em> file.</p>
<pre class="brush: css">
  #page
  {
    /*
     * To use a 12px font size on the page, delete the 14px declarations.
     * to use a 14px font size on the page, delete the 12px declarations.
     */

    /* Use a 12px base font size with a 16px line height */
    font-size: 0.75em; /* 16px x .75 = 12px */
    line-height: 1.333em; /* 12px x 1.333 = 16px */

    /* Use a 14px base font size with a 18px line height */
    font-size: 0.875em; /* 16px x .875 = 14px */
    line-height: 1.286em; /* 14px x 1.286 = 18px */
  }
</pre>
<p>The #page rule is the wrapper that surrounds all the code.  So anything we apply to this will be applied to all elements under it unless they are overwritten later on in the CSS file.  By default the font size is set to 14px as it is the latter rule of the two. If you wish to reduce the font size to 12px, simply delete the last three lines (you can also delete the additional comments at the top of the rule), so you get the following:</p>
<pre class="brush: css">
  #page
  {
    /* Use a 12px base font size with a 16px line height */
    font-size: 0.75em; /* 16px x .75 = 12px */
    line-height: 1.333em; /* 12px x 1.333 = 16px */
  }
</pre>
<h4>How do I change the background colour?</h4>
<p>In the <em>yourthemename.css</em> file, change the body rule from:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
  }</pre>
<p>To:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
    background-color: #c00;
  }</pre>
<p>Where you change the colour to what ever you want. If you don&#8217;t know the hex value for the colour you want to use, you can use the RGB colour in the following format:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
    background-color: rgb(204, 0, 0);
  }</pre>
<p>Or you can find the hex colour in this <a href="http://www.webmonkey.com/reference/Color_Charts">hex colour reference chart</a>.</p>
<h4>How do I add an image to use as my background?</h4>
<p>In the <em>yourthemename.css</em> file, change the body rule from:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
  }</pre>
<p>To:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
    background: #fff url(background.jpg) top center repeat;
  }</pre>
<p>Place the image in your theme folder.  Alternatively if you want to keep your theme folder as tidy as possible, you can create a folder called images within your theme folder and change the CSS code to:</p>
<pre class="brush: css">
body
  {
    margin: 0;
    padding: 10px;
    background: #fff url(images/background.jpg) top center repeat;
  }</pre>
<p>If you chose a background image that makes the text hard to read, you can change the background colour of the #main element, which is the wrapper of all the main content excluding the header and footer, to white.</p>
<pre class="brush: css">
#main
  {
    background-color: #fff;
  }</pre>
<p>You can continue editing your theme by editing the CSS rules within the main CSS file (<em>yourthemename.css</em>).  For more references on CSS, check out the <a href="http://jamestombs.co.uk/2010-01-07/top-htmlcss-resources-for-beginners/1066">Top HTML/CSS resources for beginners</a> post.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamestombs.co.uk/2010-01-11/create-a-drupal-6-theme-based-on-the-zen-starter-theme/1083/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
