Hello World
If a cenotaph contains no bodies, then logically a xenotaph must have no aliens - so please note, this site does not contain aliens, which must be a relief for all you alien allergy sufferers out there!
You know, I think at one time or another I've written Hello World's for:
- HTML
- JavaScript
- ASP
- VB
- PHP
- Perl
- Python*
- Java
- C#
- and C++
... I could have nightmares about the words "Hello World".
* granted, I think I only tinkered with Python because it was either Civ4 or Paintshop Pro's native scripting language.
Please note: this site makes use of the Gothikka and Braeside Lumberboy (on the Terran Derelict theme) fonts for the headers and it does look just that little bit nicer with them installed - they're both free fonts so you may as well install them ;)
June 21, 2011
Nested Navigation
This is something that's niggled me for literally years... nesting data in a database. Here's the problem:
You've got a navigation system of undefined depth that you want the user to be able to drill down through, so something like products » electronics » audio » MP3 players. So you set up a database for the navigation system and to keep it nice and clean you can effectively minimise it to something like (a very simplified version of what I'm actually doing):
Table: nav
id | parent_id | page_id | text |
---|---|---|---|
1 | 0 | 1 | Products |
2 | 1 | 2 | Electronics |
3 | 2 | 3 | Audio |
4 | 3 | 4 | MP3 Players |
This gives you a nice structure where all your navigation items have parents (or not if they're top level) and, as long as you're drilling down it's fine... the problem comes when you want to "drill up"!
See, to keep the URI clean you only really want to pass in the navigation id and use that to build up your page - so if you're URI passing a variable like ?nav=4 then the system has to know that to navigation items visible will be navigation item 4, the parent (and siblings) of nav 4, the parent and siblings of that nav and so on all the way down the tree to the root level items.
I've seen this done in a dozen different ways - most involve horrible recursive loops and I've always thought there has to be a better way.
One alternative is to store the "path" in the database for each navigation item. It's nicely efficient, you just add in a VARCHAR field and store the path to the nav item as a serialised string... something like "1;2;3;4". However, and this is probably just me, but that's never "sat right" with me. It just seems wrong to store the structure of the data that way when it's already there - in the form of the parent_id. It breaks the relational aspect of your data because if you move a navigation item you've got to not only reassign the parent_id but also rebuild that path - say you wanted to drop the Audio sub-category and just move MP3 Players into the Electronics category. With the basic database structure you just drop nav.id = 3, reassign the parent_id and jobsagoodun. If you're storing the path however you also need to update that path so that instead of "1;2;3;4" it now reads "1;2;4".
From the point of view of maintaining the relational integrity of the data, this has always seemed like a bad idea to me.
The solution
Now, I'm not sure this is a great or efficient solution but it sits right with me!
Since we want to store the data in a structured fashion - why not convert it to a structured fashion? XML.
First off we map the entire navigation system to XML - so we need to select it first.
SELECT nav.id, nav.parent_id, nav.page_id, nav.text FROM nav
Now we need to loop through that data and map it to an XML structure - I'm using PHP but there no reason you couldn't do the same thing in C# for instance. I'm using a database abstraction object so assume a read method executes a SELECT query on the database and returns an associative array like:
array (
[0] => array (
'id' => 1,
'parent_id' => 0,
'page_id' => 1,
'text' => "Products"
),
[1] => array (
'id' => 2,
'parent_id' => 1,
'page_id' => 2,
'text' => "Electronics"
),
... and so on
);
So if you do a for loop on that array, every instance will be an associative array holding the navigation item data ... now to structure it.
$xml = new DOMDocument();
$xmlRoot = $xml->createElement('root');
$xml->appendChild($xmlRoot);
//order by the parent ID so that when attaching nodes the parents will exist first
$aNavList = $db->read("SELECT nav.id, nav.parent_id, nav.page_id, nav.text FROM nav ORDER BY nav.parent_id ASC");
foreach($aNavList as $aNavItem) {
$iParentID = (int) $aNavItem['parent_id'];
//create the 'nav' node containing the text: e.g. <nav>Products</nav>
$xmlNav = $xml->createElement('nav', $aNavItem['text']);
//assign attributes to the nav node to store the data
// XML IDs can't start with numbers
$xmlNav->setAttribute('id', "nav_{$aNavItem['id']}");
$xmlNav->setIdAttribute('id', true);
// the pure database ID
$xmlNav->setAttribute('db_id', $aNavItem['id']);
// the page ID (example data)
$xmlNav->setAttribute('page_id', $aNavItem['page_id']);
//Attach the nodes to the XML document
// If the parent ID of this node is 0, attach to the 'root' element
// Otherwise attach to the element with the ID "nav_{this parent id}"
$xmlParentNode = $iParentID == 0 ?
$xmlRoot :
$xml->getElementById("nav_{$aNavItem['parent_id']}");
$xmlParentNode->appendChild($xmlNav);
}
The $xml variable should now hold a structured version of your navigation data, thus:
<root>
<nav id="nav_1" db_id="1" page_id="1">Products
<nav id="nav_2" db_id="2" page_id="2">Electronics
<nav id="nav_3" db_id="3" page_id="3">Audio
<nav id="nav_4" db_id="4" page_id="4">MP3 Players</nav>
</nav>
</nav>
</nav>
</root>
I'll admit that's not terribly exciting but it does mean that you can use standard DOM navigation techniques to run through your nav system. Remember, we've only got the ID of the LAST node in that branch of the navigation tree but now that node is nested within all its ancestors. Now we can navigate through that data upwards!
Say we've got a huge, nested navigation system and we want to make a breadcrumb trail all we need is the node we're looking for and any direct ancestors of that node - so that we end up with something like the aforementioned:
Products » Electronics » Audio » MP3 Players
We can now do this without an unknown quantity or recursive loops using the DOMDocument stored in $xml and the nav variable from the address - e.g. products.php?nav=4
$iNavSoughtID = (int) $_GET['nav'];
$htmlBreadcrumb = "";
$xmlNodeSought = $xml->getElementById("nav_{$iNavSoughtID}");
while($xmlNodeSought->nodeName != 'root') {
$htmlBreadcrumb .= '<a href="/products.php?nav='
. $xmlNodeSought->getAttribute('db_id') . '">'
. $xmlNodeSought->firstChild->nodeValue
. '</a>';
$xmlNodeSought = $xmlNodeSought->parentNode;
}
That's a really simple example without any security or sanity checks in but it does give you a working breadcrumb trail where you've just started with the node identified in the address and worked your way down the xml tree until you've hit the root - without any horrible recursive loops or questionable path data in the database.
If you store your navigation system in XML you need only perform the one single database query at the start to build the document and then you can perform all the navigation views through simple DOM manipulation. You could even have the CMS actually write (and update) a navigation XML document and use JavaScript (AJaX) to build the website navigation system on the fly (you could probably even do it in CSS with :hover and display if you parsed the XML to HTML first) then you'd only be performing database queries on the nav system as and when it changes!
Even with the DOM manipulation, that's got to be more efficient, especially with large navigation systems, than nested SQL queries or recursive loops, surely.
May 16, 2011
C# ActiveControl
Having just spent about an hour trying to work this out... All I'm trying to do is add focus to a list (ListView type) that's inside a tab (contained within a TabPage). Something that, on the face of it, should be incredibly simple.
Let's say the ListView is called something like lvAllBadgers and contains a lovely list of badgers, when they were born, their names, sex and so on. There are 3 ways in which you should be able to activate your badger list so that it gains focus when you change to the "Badgers" tab.
this.lvAllBadgers.Focus();
this.lvAllBadgers.Select();
ActiveControl = this.lvAllBadgers;
Any of those should work (the one that the documentation tends to lean towards is .Select() btw). However - could I get any of them to work? Could I buggery.
Now here's what they don't tell you - if you want to activate a control make sure it has the property TabStop = true otherwise you can't activate the damned thing without clicking on it!
Sheesh!
February 9, 2011
Columnar layout with CSS
OK - this works but I don't understand why it works; if someone would care to explain it to me I'd be grateful. It's the old nutshell of trying to get a columnar layout in HTML using only div tags and CSS and getting it to work like a table, so that whichever column is the tallest determines the height of the containing element.
For instance - to replicate a layout like this:
<table cellpadding="0" cellspacing="0">
<tr>
<td>
<ul>
<li><a href="/page_1/">Page 1</a></li>
<li><a href="/page_2/">Page 2</a></li>
<li><a href="/page_3/">Page 3</a></li>
<li><a href="/page_4/">Page 4</a></li>
<li><a href="/page_5/">Page 5</a></li>
</ul>
</td>
<td>
<h1>A Page Header Here</h1>
<p>Some page content here</p>
...
</td>
</tr>
<table>
To create a simple equivalent using only divs would be something more like this:
<div id="container">
<div id="menu">
<ul>
<li><a href="/page_1/">Page 1</a></li>
<li><a href="/page_2/">Page 2</a></li>
<li><a href="/page_3/">Page 3</a></li>
<li><a href="/page_4/">Page 4</a></li>
<li><a href="/page_5/">Page 5</a></li>
</ul>
</div>
<div id="content">
<h1>A Page Header Here</h1>
<p>Some page content here</p>
...
</div>
</div>
The easy way to do this is to just set the display types for "menu" and "content" in the CSS to be either inline-block or table-cell and this will work fine ... as long as you don't have to support any version of Internet Explorer older than version 8 - and that's the problem!
If however you have to support IE7 (or older) then you'll find those requisite CSS display values aren't supported - bugger. So, you might think, I know, we'll simply set the width of the "menu" and float it to the left - which is fine as long as your content is taller than your menu - otherwise you'll find the menu will overflow its parent container like this:
There is a solution though - it seems to work but the reason for it escapes me currently. To create your normal columnar layout as above the CSS would look something like this:
body {
color: #000000;
background-color: #f7f7f7;
padding: 10px;
margin: 0px;
}
#container {
position: relative;
padding: 10px;
margin: 0px;
border: 1px solid #666666;
color: #000000;
background-color: #ffffff;
}
#menu {
position: relative;
width: 120px;
padding: 5px;
margin: 0px;
border: 1px solid #ff0000;
color: #000000;
background-color: #ffffff;
float: left;
}
#content {
position: relative;
padding: 5px;
margin: 0px 0px 0px 140px;
border: 1px solid #0000ff;
}
Now - here's the bit that makes it work, simply add overflow: hidden; to the container, like so:
#container {
position: relative;
padding: 10px;
margin: 0px;
border: 1px solid #666666;
color: #000000;
background-color: #ffffff;
overflow: hidden;
}
And now your menu will also scale the container!
Of course if you want a different coloured background for the menu you may need to add an absolutely positioned div behind it and set the top and bottom attributes to 0px. So what you actually end up with is something more like this:
body {
color: #000000;
background-color: #f7f7f7;
padding: 10px;
margin: 0px;
}
#container {
position: relative;
padding: 10px;
margin: 0px;
border: 1px solid #666666;
color: #000000;
background-color: #ffffff;
overflow: hidden;
}
#menu_bg {
position: absolute;
top: 0px;
bottom: 0px;
width: 130px;
color: #000000;
background-color: #e1e1e1;
z-index: 1;
}
#menu {
position: relative;
width: 120px;
padding: 5px;
margin: 0px;
float: left;
z-index: 2;
}
#content {
position: relative;
padding: 5px;
margin: 0px 0px 0px 140px;
border: 1px solid #0000ff;
z-index: 2;
}
<div id="container">
<div id="menu_bg"> </div>
<div id="menu">
<ul>
<li><a href="/page_1/">Page 1</a></li>
<li><a href="/page_2/">Page 2</a></li>
<li><a href="/page_3/">Page 3</a></li>
<li><a href="/page_4/">Page 4</a></li>
<li><a href="/page_5/">Page 5</a></li>
</ul>
</div>
<div id="content">
<h1>A Page Header</h1>
</div>
</div>
September 17, 2010
.htacces, mod_rewrite and SetEnv
I just came across this interesting foible.
I wanted to do a conditional URI rewrite based upon an environment variable defined in Apache's <VirtualHost> directive. According to the documentation mod_rewrite can pick up environment variables by using %{ENV:VARIABLE_NAME}.
So for instance, if you'd defined an environment variable called TestServer with a value of 1, like so:
SetEnv TestServer 1
You'd imagine that you'd be able to pick that up with mod_rewrite and allow it to redirect you to a development server - maybe doing something like:
RewriteEngine On
RewriteCond %{ENV:TestServer} 1
RewriteRule ... (rule goes here)
Or something to that effect. However, that won't work. The reason it won't work is a bit annoying. It won't work because of the order in which Apache processes things. mod_rewrite is processed before SetEnv; therefore any environment variables you set with SetEnv won't exist at the time mod_rewrite executes!
The way around it is to use mod_rewrite to set your environment variable thus:
RewriteEngine On
RewriteRule .* - [E=TestServer:1] [L]
Put that inside your VirtualHost directive and Bingo! Everything works was you'd expect - you can now use %{ENV:TestServer} inside your .htaccess files to create conditional rewrites based on environment variables set on a per-VirtualHost basis!
June 29, 2010
JavaScript Events
JavaScript is all well and good - great for just hacking together small dynamic elements in your web pages. It does object orientation and DOM manipulation and all the kinds of things you need to make a dynamic web page work - lovely.
Where it falls down however, especially the Event handler, is when you try to use Internet Explorer's implementation of JavaScript... then it all gets tricky. I'm not trying to get everthing working in every web browser ever created you understand, not even every version of Internet Explorer, just Firefox 3, Internet Explorer 8, Opera 10 and Chrome (version 5 I think - whatever the latest one is anyway). Everything I wrote initially worked fine in everything except IE - no surprise there. What was interesting was what broke in IE and why.
For instance - I'm generating an "object" on the fly - a collection of HTML Elements which I will later append to the page, so:
var container = document.createElement('div');
var firstImage = new Image();
var secondImage = new Image();
var thirdImage = new Image();
Well, that nicely creates up my HTML Elements - and it works in everything, so far so good. Now I've set up classes for all this stuff in the stylesheet so I set those and append the images to the container:
container.className = 'wrapper';
firsImage.className = 'wrapper_img_1';
secondImage.className = 'wrapper_img_2';
thirdImage.className = 'wrapper_img_3';
container.appendChild(firstImage);
container.appendChild(secondImage);
container.appendChild(thirdImage);
... And we're still good. Some other formatting is done with element.style and the like and it's all hunky dory. Now to attach some Event listeners. This is the first part where IE diverges from the standard but I'm aware of this and I know the workarounds - so I have a function:
//cross browser addEventListener
function listenForEvent(DOMElement, sEvent, pCallback, bRunIt) {
if(bRunIt === undefined) bRunIt = false;
//Internet Explorer
if(DOMElement.addEventListener === undefined) {
var sMSIEEvent = 'on' + sEvent;
return DOMElement.attachEvent(sMSIEEvent, pCallback);
}
//everything else
else return DOMElement.addEventListener(sEvent, pCallback, bRunIt);
}
This means I can attach Events to Elements without worrying about which browser I'm dealing with - and the function returns true or false depending on whether the Event Listener was successully attached or not.
Say I wanted to add a mouseover event to the firstImage I send the Image object, the name of the event and the callback function like so:
listenForEvent(firstImage, 'mouseover', imageHover);
//callback function
function imageHover(e) {
/* ... functionality goes here ... */
}
Unlike older versions of Internet Explorer, IE8 does actually seem to pass through the Event, automatically, to the e parameter just like every other web browser - but I still have a tendency to put the IE event capture in. So if we take a closer look at that callback function:
//callback function
function imageHover(e) {
if(e === undefined) e = window.event;
/* ... functionality goes here ... */
}
Right, that ensures that I've got an event. Now, this is a simple image rollover script - it changes the src attribute of the image when you mouse over it. However, since the imageHover function is supposed to be generic it will allow me to change the src of any given image passed to the listenForEvent function that uses this callback (I was actually changing an arrow symbol to a plus symbol when the user moused over it - and there were several arrow symbols but I just wanted the one function. I was also adding onclick events and calling some other functions which is why I didn't just use a background image and change it in the CSS with a :hover pseudo-attribute, smarty pants!)
What I needed to do was be able to access the Element that triggered the function - with most browsers this is easy since the callback function is essentially attached to the Element and therefore the properties of that Element can be accessed via this.
//callback function
function imageHover(e) {
if(e === undefined) e = window.event;
this.src = '/some/other/image.ext';
}
Marvellous... except it doesn't work in IE8 of course because the Event belongs to the window not the calling Element - sort of. To get the Element that called the Event you need to use IE's srcElement property... so the workaround is to alias this to be either this or e.srcElement:
//callback function
function imageHover(e) {
if(e === undefined) e = window.event;
this.sourceElement = e.srcElement ? e.srcElement : this;
this.sourceElement.src = '/some/other/image.ext';
}
That actually works! The trick is realising how Internet Explorer scopes its Events - that's what I found interesting/annoying anyway.
Although this example is a massive simplification of what I was actually doing, I hope it explains the weirdness of Internet Explorer's Event model to anyone trying to create a dynamic page using JavaScript.
The actual HTML on my page was about a dozen lines from the <html> tag to the </html> tag - the content was largely created on-the-fly, from the database, using PHP, AJaX, JSON and JavaScript. It would fail badly on the Search Engines but it was for part of a Content Management System so that's OK :)
February 4, 2010
Rammstein
Epic as always - what would have been good would have been me realising my camera phone had a zoom... hey ho :)
Combichrist were an absolutely brilliant support act - I'm a little biased here as I actually prefer Combichrist - but they came on all guns blazing and got the place jumping... which is what you want from a support act really.
November 22, 2009
Arrrrrrrrrrggggggggggggghhhhhhhh!
Oki - I'm just trying to make a little "Image loaded" type event listener in JavaScript - something fairly simple so that a function is triggered when an image is loaded.
In Firefox/Opera et al, this is no problem, just create add an event listener and away you go.
var theImage = new Image();
theImage.addEventListener('load', someFunction, false);
Jobsagoodun... now, you're going to point out the obvious that IE uses attach event and all's well and good, right? Well... yes, up to a point.
var theImage = new Image();
if(theImage.attachEvent) {
theImage.attachEvent('onload', someFunction());
}
else {
theImage.addEventListener('load', someFunction, false);
}
Yes, there are some slight differences, but nothing insurmountable... however - this is what I was actually doing. Can you spot the obvious mistake (it's taken me 2 hours - *sigh*)
var theImage = new Image();
theImage.src = 'someURI';
if(theImage.attachEvent) {
theImage.onload = function() { someFunction(); }
}
else {
theImage.addEventListener('load', someFunction, false);
}
...
...
...
...
...
Have you spotted the blatant error yet?
...
...
...
No, it's not that I'm using theImage.onload instead of an attachEvent handler... that's a perfectly reasonable hack and wasn't causing everything to fall over...
...
...
...
Well, here it is, by assigning the .src to the image before adding the onload event handler then, if the image is in the cache, it may well have "loaded" before the event handler is attached (in Internet Explorer anyway) - this means the image is loaded before the 'onload' listener is attached and therefore it never gets called!
Gads - that was a hellish couple of hours
July 28, 2009
Actionscript 3
So I've just upgraded from Flash MX 2004 pro to CS4 at work, only on a trial basis at the moment but it looks as though they'll fork out for the update. I'm monkeying around with a banner advert for a Danish advert and I need to add in, well, a button - nice and simple, yes? ... no. Not really.
Now this isn't a huge gripe but I just find the logic distinctly peculiar. In Flash MX 2004 to create a button, you'd have your image, convert it to a symbol and set the type to be "button". Logically this makes a button. It's not a very useful button as it doesn't link to anything. So you have to assign some ActionScript to the button thus:
on(release) {
getURL('http://www.example.com', '_self');
}
And there you go - that's a button. However, with Flash CS4 you can't do that - you can only assign ActionScript to frames it seems and not the actual buttons themselves. This means you then have to be able to locate your button before you can assign the action to it. Not a huge problem, just give your button an "instance" and then assign the attributes to that instance... a bit like adding an event handler to an Element that you've assigned an id to with JavaScript. This gives you something like this:
var sURIHompage:String = 'http://www.example.com';
//using a button with the instance id of btn1
btn1.addEventListener(MouseEvent.MOUSE_UP, linkMain);
//callback function
function linkMain(e:MouseEvent):void {
var requestURI:URLRequest = new URLRequest(sURIHompage);
navigateToURL(requestURI, '_self');
}
OK what's good about this? Well - it's all nicely ECMAScripty, it's got an Event handler and type-casting it looks almost like proper grown-up code... but...
This is quite a big but if you ask me and no, it's not a whinge about it being more code to write. In an attempt to make it seem a bit more grown up, a bit more OOP perhaps it's somehow managed to miss the whole entire point of Object Oriented Programming, Objects.
Put it this way, Flash is a good visual tool for understanding objects - if you draw a button on the screen that's obviously an object. It's actually a special type of mini Flash movie all to itself, it's got three specific frames which relate to mouse events which allow you to create different visual effects based on what the mouse is doing. Now, if Button is a prototype (class) then any "button" you create is an instance of that prototype and should inherit all the properties of Button - this should include relevant Script Event Handlers for a button (as opposed to just the animation handlers it has)... which logically would include mouse down, up, and click events. I mean, what's the point of a button that doesn't have the ability to take you to another part of the movie or load an external URI? Being able to change colour when you put the mouse over it is all well and good... but a bit flipping pointless if that is all it does!
Flash always used to understand that visible entities, such as buttons, are as much code objects as they are visual or animation objects and, that being the case, could have ActionScript assigned to them rather than having to assign it to them from outside the object, from a frame in the movie for instance. It's all a bit procedural.
Flash CS4 (AS3 engine) compiles all the ActionScript into the .swf file anyway so surely this is entirely an issue with the GUI? Somebody thought it would be a good idea to totally separate out the AS from the visual objects - in essence prevent them from being actual objects in the code as well as "symbols" in the animation - to me this seems like a bit of programmer's ego masturbation; we can't possibly allow anyone outside the inner circle to visualise code objects in such a blatant way! No! That would be like exposing the secrets of the Magic Circle and fire will rain down from the sky and the six headed beast will rise from the oceans ridden by the whore of Babylon... or something bad anyway.
meh
January 23, 2009
The Hobbycraft Nativity nuthouse
Hmmm k; well over Chrimbo someone thought it would be a good idea to cobble together a home-made nativity - bits and pieces from various family members to make a new nativity scene for Vic's nan... We were tasked with making some sheep, a sheepdog, a shepherd and one of the wise men. I, of course, went for the easier bits, namely some sheep. I mean how hard can it be to make a cloud with a head and some legs, right?
Off we toddled to Hobbycraft as we seemed to, for some strange reason, have a lack of anything to make the required sheep, shepherd, wise-man and so on from. Funny that.
After much rummaging we found several bits and pieces - some polystyrene balls, wooly fluff and some modelling clay type stuff called Fimo. Vic picked up various shinies for making jewellery for her wise man and we were both completely stumped on how the hell to make a sheepdog - hey ho.
Anyway, after much fiddling, knitting, baking and generally gluing ourselves to the table, chairs, bits of sheep - possibly even each other (Superglue - a substance possibly more evil than the blackened lumps of "pure evil" in the microwave at the end of "Time Bandits") - we did eventually come out with some reasonable looking bits and bobs.
It was all put together with the parts from Vic's rellies and to be honest, I kinda like the look of it; not for the professional polish, but just because it's somehow honest and very, very silly - as the result of an exercise in utter daftness it's not bad. Oh well, it was all good fun... :D
June 28, 2008
Dawn of War Banners - updated
Been a while (as I completely forgot I'd done this) but I've completed the badges and banners for another two Ork clans for Dawn of War - namely the Blood Axes and the Snake Bites.
So I've updated the badges and banners download archive (zip) and the downloads page - enjoy.