This site is a self-contained low down on what's going on in my life, what I'm working on, what I'm thinking about, and how I'm feeling about life in general.
Monday, 19 May 2008
From brain surgery to killing someone with your little finger, it's possible to teach yourself anything if you approach it in a structured manner.
My personal experience comes from what I've done in IT and how I've taught myself to do numerous things from 3D Design to PHP Programming. There is a definite and easy structure to follow.
Learning technical subjects in an educational institution occurs as part of a curriculum, nothing more, so the skills you are taught, and hopefully taught well, will no doubt be severely depleted when you actually come to use them. The best time to learn any IT skill is when you need it.
The best learning is born out of necessity, it ensures you're 100% focused on what you're about to learn, and will remember it better because you're putting it straight into practice.
When it's time for you to learn something, and you're going to teach yourself, you need to do some initial homework on the subject. The internet is a great resource for training, but it can be difficult to find consistent material. Personally, I love lynda.com, their training is top notch and the basics are free, which is what you're concerned with at the outset.
Alternatively, find a book that gives a beginners approach to your particular subject. You'll need to ensure you have the fundamentals nailed, this usually only takes a few hours to get through though.
Once you have a foundational understanding of the subject, you need to define what it is you’re trying to do. Once you know what the task is, you need to break it down into real world actions. For illustrative purposes, let’s imagine we’re creating a web application. Firstly, break the project into its high level sections, which may be:
Now pick the area you want to focus on first and break that up into its major parts, lets choose administration:
Again, pick a section and drill down on it, let’s take the add user path. Because this section has tangible flow, with actions and results, we will look at the actions that occur in the flow:
Doing this is half the battle because now you’re in a situation to start programming. For our example, Page 1 requires the creation of a html form. Page 2 requires a database connection, and Page 3 a simple HTML written confirmation of the action.
Because of our analysis, we now have some research to do, how to insert data into the database from a submitted form using x language, how to redirect to another page once that is done.
Most people start their search for answers at Google. Search for what you need rather than how you think it would be written, so if you need to insert into an sql database using asp, search for “Insert into an sql database using asp”. This will yield the results you need. Failing that you could try either Yahoo! or Google answers, although, if you don’t mind paying a small premium, Experts Exchange is always my destination of choice for fast, accurate responses.
Once you’ve complete one task, move through the entire project in this way and take it one step at a time. The old adage of breaking your problems into smaller pieces to make them easier to manage is applicable to most things in life and is just as relevant to programming.
Friday, 25 April 2008
I recently wrote about how to create a bar graph using the <canvas> tag in html. This was more of a theory article, so as promised, here is the substance.

Start by creating your html body as follows:
<body onload="buildChart();">
<div class="chart">
<div id="label_container" style="position: relative; margin: 20px auto; display: inline-block;">
<canvas id="canvas" width="400" height="200"></canvas>
</div>
</div>
<table id="mydata">
<tr> <th>Customers</th><th>Value</th> </tr>
<tr><td>Design</td> <td>2</td> </tr>
<tr><td>Enquiries</td> <td>5</td> </tr>
<tr><td>Home Screen</td> <td>1</td> </tr>
<tr><td> Navigation</td> <td> 4</td> </tr>
<tr><td> Projects</td> <td> 6</td> </tr>
<tr><td> To-do</td> <td> 9</td> </tr>
</table>
</body>
The table contains the data used to build the chart, this can be built dynamically which is really useful for reports etc.
Now lets start on the javascript to build our chart. Firstly, lets start working with our buildChart function.
function buildChart(){
// source data table and canvas tag
var data_table = document.getElementById('mydata');
var canvas = document.getElementById('canvas');
var td_index = 1; // which TD contains the data
var max_value = 0;
var ySegmentCount = 5;
Here, we've defined our variables for the table, the canvas and specified the column that contains the values for our graph. max_value will be set to the largest of the values, and ySegmentCount contains the number of values to be listed horizontally.
I've defined a fixed pallet for this example, however you can easily adapt this to use a dynamic pallet, I just like to control the colours used.
var myPallet = new Array();
myPallet[0] = "#2A416A";
myPallet[1] = "#39588E";
myPallet[2] = "#4572AD";
myPallet[3] = "#688BC3";
myPallet[4] = "#8EA6D2";
myPallet[5] = "#B2C3DF";
myPallet[6] = "#CCD8EA";
myPallet[7] = "#DDDBFB";
myPallet[8] = "#F0F0F0";
myPallet[9] = "#2A416A";
myPallet[10] = "#39588E";
myPallet[11] = "#4572AD";
myPallet[12] = "#688BC3";
myPallet[13] = "#8EA6D2";
myPallet[14] = "#B2C3DF";
myPallet[15] = "#CCD8EA";
myPallet[16] = "#DDDBFB";
myPallet[17] = "#F0F0F0";
Next we retrieve the chart values and calculate some parameters.
var tds, data = [], color, colors = [], value = 0;
var trs = data_table.getElementsByTagName('tr'); // all TRs
for (var i = 0; i < trs.length; i++) {
tds = trs[i].getElementsByTagName('td'); // all TDs
if (tds.length === 0) continue; // no TDs here, move on
// get the value, update total
value = parseFloat(tds[td_index].innerHTML);
if(value > max_value){ max_value = value; }
data[data.length] = value;
// Assign color
color = myPallet[i];
colors[colors.length] = color; // save for later
trs[i].style.backgroundColor = color; // color this TR
}
var itemCount = trs.length-1;
var yIncrement = max_value / ySegmentCount; //determine increment between y axis increments
var barWidth = (canvas.width - (10 * (itemCount * 2))) / itemCount;
var yIncrementPixels = (canvas.height - (2 * (ySegmentCount * 2))) / ySegmentCount;
We now know how wide to make the bars based on the canvas width and number of items, and also the distance between value markers.
We now need to prepare to draw our bar graph, we start by preparing the variables.
var ctx = canvas.getContext('2d');
var canvas_size = [canvas.width, canvas.height];
var backSoFar = 2;
var ySpanPosition = 0;
var yTotal = max_value;
backSoFar contains the vertical (y) start position of each background block. This starts at 2 to create a slight gap at the top. ySpanPosition contains the vertical position of the span containing the axis value.
Lets render the background.
for(i=0; i<ySegmentCount+1; i++){
if(i==ySegmentCount){
yTotal = canvas.height-8;
var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode('0');
oSpan.setAttribute('style','left: -50px; top: '+yTotal+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: 45px; display: block; text-align: right;');
oSpan.appendChild(oLabelText);
labelContainer.insertBefore(oSpan, labelContainer.lastChild);
}else{
backSoFar += 2;
ySpanPosition = backSoFar -8;
ctx.fillStyle = '#E7EEF6';
ctx.fillRect(0,backSoFar,canvas.width,yIncrementPixels);
var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode(yTotal.toFixed(2));
//var oLabelText = document.createTextNode('sdfsg');
oSpan.setAttribute('style','left: -50px; top: '+ySpanPosition+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: 45px; display: block; text-align: right;');
oSpan.appendChild(oLabelText);
labelContainer.insertBefore(oSpan, labelContainer.lastChild);
yTotal += -yIncrement;
backSoFar += yIncrementPixels;
backSoFar += 2;
}
}
Change the value of ctx.fillStyle to set the background colour. Now for our final block for javascript in this function, we render the bars themselves.
var sofar = 0; // keep track of progress
// loop the data[]
for (var piece in data) {
var percentHeight = (data[piece]/max_value)*100;
var pixelHeight = (canvas.height-4)*(percentHeight/100);
var barFloor = canvas.height - pixelHeight; //subtract bar height from canvas height to get ground level;
sofar += 10; //add left margin
//ctx.beginPath();
ctx.fillStyle = colors[piece]; // color
ctx.lineWidth = 4;
ctx.strokeStyle = '#FFF';
ctx.shadowBlur = 3;
ctx.shadowColor = "#999";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.strokeRect(sofar,barFloor,barWidth,pixelHeight);
ctx.shadowBlur = 0;
ctx.shadowColor = "#333";
ctx.fillRect(sofar,barFloor,barWidth,pixelHeight);
//Add labels
var xLabelPosition = sofar;
var yLabelPosition = canvas.height + 10; //add span height
var labelContainer = document.getElementById('label_container');
var oSpan = document.createElement('span');
var oLabelText = document.createTextNode(data[piece]);
//var oLabelText = document.createTextNode('sdfsg');
oSpan.setAttribute('style','left: '+xLabelPosition+'px; top: '+yLabelPosition+'px; position: absolute; font-size: 60%; z-index: 100; background: none; width: '+barWidth.toFixed(0)+'px; display: block; text-align: center;');
oSpan.appendChild(oLabelText);
labelContainer.insertBefore(oSpan, labelContainer.lastChild);
sofar += barWidth;
sofar += 10;
}
}
After calculating the positioning of the bar, we create 2 rectangles, the first is white and has drop shadow, the second is the coloured bar. Then we access the DOM to create the span labels and position them appropriately. The 10 value added to the sofar variable spaces the bars 10 pixels.
Finally, some css to make sure everything displays as required.
canvas { background: #fff; border-bottom: 1px solid #ccc; }
.chart {
position: relative;
display: block;
text-align: center;
background: #FFF;
padding-bottom: 10px;
padding-top: 10px;
}
span { font-family: Arial, Helvetica, sans-serif;}
So there we have it, a low bandwidth bar graph that looks great and is totally dynamic. I haven't had time to make the code as efficient as possible but it definitely does the job. I hope you find this useful.
Sunday, 13 April 2008
In any information-based website, it's important to remember that people will possibly want to print your information off.
This could be for any number of reasons, passing to a friend, saving for your own purposes, or supporting a business case to buy a product.
When they do, they will get a mess, bits of navigation, images, cut off text. The end result is you or your customer lose business, or look unprofessional.
To fix this, use a print stylesheet. A print stylesheet is used only when printing and lets you sweep navigation and other unwanted information under the carpet.

If you're viewing this article on it's own, go to print preview and see what happens. All the navigational elements go and you're left with a nicely formatted document ready to print (Aside from the google ads which I haven't hidden yet).
Creating a print stylesheet should be the last thing you do, that way you're not constantly changing it through the project lifecycle.
When you are ready to implement your stylesheet you can add it in one of two ways. To include the stylesheet using the LINK object:
<link href="css/print.css" rel="stylesheet" type="text/css" media="print" />
Or to use inline styles use:
@media print {
/* style sheet for print goes here */
}
Either way achieves the same result. When compiling your print stylesheet, use display:none; to hide individual elements.
Ensure any content containing div's are set to full width so that the full page is utilised.
Finally, consider colours, not all browsers allow background printing, you should bear this in mind. Minimise the use of colours in your page to improve the reproduction on laser printers.
Providing a drastic change from screen to page can set you apart from competitors and give you that slight edge. It's a little detail that can make a big difference.
Friday, 11 April 2008
When building an accessible standards-based website, many developers feel it is sufficient to pass their pages through the w3c page checkers for xhtml etc. It is fairly important for your pages to pass these tests as much as possible, however, I believe that you need to go beyond the standards and look at whether or not your markup is suitable for purpose.
What I mean by this is that you need to look at each element on your rendered webpage and ask yourself if you've used the correct markup to display it. Often, designers will use spans to list items, instead of a list object, or div tags to display tabulated data instead of a table.
Whenever you want to display tabulated data, do not be afraid to use a table. The witch hunts of the CSS revolution focused on the use of tables for page layout and structure, but used correctly they are still the most effective way of displaying your data in a flexible grid layout. The question is are you coding your tables correctly? The traditional method of creating a table was as follows:
<table>
<tr><td>Header 1</td><td>Header 2</td></tr>
<tr><td>Metric 1</td><td>100</td></tr>
<tr><td>Metric 2</td><td>200</td></tr>
<tr><td>Metric 3</td><td>300</td></tr>
</table>
This works, but the best practice for creating data tables is:
<table>
<thead>
<tr><th>Header 1</th><th>Header 2</th></tr>
</thead>
<tbody>
<tr><td>Metric 1</td><td>100</td></tr>
<tr><td>Metric 2</td><td>200</td></tr>
<tr><td>Metric 3</td><td>300</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>600</td></tr>
</tfoot>
</table>
This approach makes your code easier to understand by both screen readers and developers alike, plus when css is turned off, your data retains it's structure.
When you cast a critical eye over your site, you might notice that many of your page elements are actually lists. Site navigation is a list of destinations, likewise site maps are better displayed in a list object, about us pages often list statistics. These are all comment situations where list object should be used but are not.
You can craft an effect top level navigation using an unordered list:
<ul>
<li><a href="home.php">Home</a></li>
<li><a href="blog.php">Blog</a></li>
<li><a href="contact.php">Contact Us</a></li>
<li><a href="links.php">Links</a></li>
</ul>
The magic then happens within the CSS.
ul {
display: block;
width: 100%;
overflow: hidden;
list-style: none;
margin: 0px;
padding: 0px;
}
ul li{
display: block;
float: left;
overflow: hidden;
margin: 2px;
padding: 0px;
}
ul li a:link, ul li a:visited {
display: block;
margin: 0px;
padding: 15px;
}
ul li a:hover {
display: block;
margin: 0px;
padding: 15px;
background-color: #CCC;
}
These are just two common areas of markup that are overlooked, but there are many more, It's worth brushing up on the markup available to you so that you can ensure you always choose the best markup for the purpose.
Tuesday, 19 February 2008
I wanted to create a tag cloud, and looked at Cal Evans's Cloud Generator, which to me seemed overly complex, though very stable I'm sure. I just thought that it would be easier to work it out myself and tailor the solution to my needs.
It was actually easier to do than I thought.
Click here for the source code.
Monday, 11 February 2008
This series of articles will cover the theory behind creating a simple eCommerce system.
Of all the components of an eCommerce site, the shopping cart will be the hardest to develop.
We will store an md5 session key that will link back to databased transactions.
It's easier than you think to build an eCommerce site, sometimes it's just having that guidance on process to complete it.
Below is some example code you can use to create and store your MD5 key.
session_start();
if($cartID == ''){
if(isset($_SESSION['cartID'])) {
$cartID = $_SESSION['cartID'];
echo 'Loaded from session: Cart ID: '.$cartID;
} elseif(isset($_COOKIE['cartID'])) {
$cartID = $_COOKIE['cartID'];
$_SESSION['cartID'] = $cartID;
echo 'Loaded from cookie: Cart ID: '.$cartID;
} else {
$cartID = md5(uniqid(rand(),true));
$_SESSION['cartID'] = $cartID;
setcookie('cartID', $cartID, time() +432000);
echo 'Created md5 key: '.$cartID;
}
}