boogdesign posts

Longer posts on standards based web design, portable web development and Linux, intermingled with some stuff on my other nerd interests.

Rob Crowther, London, UK based Blogger, Web Developer, Web Designer and System Administrator - read my Curriculum Vitae

Buy my book!

Book CoverHello! HTML5 and CSS3 available now

Buy my other book!

Book CoverEarly access to HTML5 in Action available now


05:10:00 pm Permalink Building a compressed prototype + scriptaculous with YUI Compressor

Categories: Web Develop, Front End Web Development

A newer version of protoaculous is available from Inderpreet Singh, skip the reading and download protoaculous 1.9 directly.

A while back I started using protoaculous.js, a combined and compressed version of the Prototype.js and Scriptaculous in a single file. Unfortunately, as time went by and both Prototype and Scriptaculous got updated, it didn't seem like anyone was updating protoaculous in sync, so a few months ago I decided to build my own.

Of course, a day or so after I did that, John-David Dalton released a more up to date and far more complete set of files in his 'protopack', but I know some folks were already using my version because I got a request the other day to update it to use of prototype.js. I figured this was a good opportunity to try and be a bit more organised about building it, plus I like being in the situation where I don't have to rely on anyone else for my updates, hence this mini-tutorial blog post.

Before starting we'll need the YUI Compressor (get the yuicompressor-x.y.z.jar file out of the build sub-directory), which itself needs a version of the Java runtime installed. The below assumes you're running on Windows, have Java setup, and have the YUI Compressor .jar file in your working directory. You'll also need a set of scriptaculous and prototype source files (the prototype.js file is in the 'lib' sub-folder, everything else is in 'src').

OK, so assuming we've got all the relevant stuff from the previous paragraph downloaded into your working directory, building the combined and compressed protoaculous.js is two fairly easy steps. First off, scriptaculous loads it's dependent scripts dynamically by inserting <script> elements into the document head, since we're not going to have the separate scripts in the combined file we need to stop it doing that. I create a file v_scriptaculous.js where I've removed lines 46 to 54:

    var js = /scriptaculous\.js(\?.*)?$/;
    $$('head script[src]').findAll(function(s) {
      return s.src.match(js);
    }).each(function(s) {
      var path = s.src.replace(js, ''),
      includes = s.src.match(/\?.*load=([a-z,]*)/);
      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
       function(include) { Scriptaculous.require(path+include+'.js') });

And also lines 26-29:

  require: function(libraryName) {
    // inserting via DOM fails in Safari 2.0, so brute force approach
    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');

If you end up working with a newer version the procedure should be similar, though the line numbers may be different, just look for any functions which try to dynamically insert script tags. With the above two sections removed I end up with a v_scriptaculous.js file 46 lines long, which, disregarding comments, looks like this:

var Scriptaculous = {
  Version: '1.8.1',
  load: function() {
    function convertVersionString(versionString) {
      var v = versionString.replace(/_.*|\./g, '');
      v = parseInt(v + '0'.times(4-v.length));
      return versionString.indexOf('_') > -1 ? v-1 : v;
    if((typeof Prototype=='undefined') ||
       (typeof Element == 'undefined') ||
       (typeof Element.Methods=='undefined') ||
       (convertVersionString(Prototype.Version) <
       throw(" requires the Prototype JavaScript framework >= " +

Now we need to combine all the files together and feed them into the YUI Compressor. To do this I've created a batch file build.bat:

@echo off
copy prototype.js + v_scriptaculous.js + builder.js + effects.js + dragdrop.js + controls.js + slider.js + sound.js c.js /b
java -jar yuicompressor-2.3.5.jar -o protoaculous.1.8.1.min.js c.js
del c.js

This creates a temporary file, c.js, which is a combination of all the javascript files, uses the YUI Compressor to build the output file, then deletes the temporary file. I found I had to use the /b (binary) switch on the copy command otherwise I got junk at the end of the file which caused errors in the compressor. After running the batch file we should end up with protoaculous.1.8.1.min.js sitting in our working directory.

Tweet this!
13 feedbacks »PermalinkPermalink


06:28:15 pm Permalink Mugshot 1.1.45 on SuSE 10.3

Categories: Linux, SuSE

Previously I produced an RPM for Mugshot 1.1.40 for SuSE 10.1. I could never get a more recent version to build on SuSE 10.1, but since I recently upgraded to 10.3 I decided to have another go.

It seems the most recent Linux version is 1.1.45, whereas the Windows version is up to 1.1.93. I'm not sure if the Linux version is just not getting developed anymore, but I decided to stick to 1.1.45 for now as I'm not a C developer and I wouldn't be able to patch the newer version if it didn't work on Linux. If anyone knows what's going on, please post a comment.

So, I've built a new RPM (and here's the updated spec file). I think I've fixed the MIME type stuff now, but you might still have to right click and 'save as'.

Tweet this!
Send feedback »PermalinkPermalink


10:46:43 pm Permalink Adobe onAIR London 2008 (Afternoon)

Categories: Front End Web Development

Review: onAIR London 2008 - Afternoon Sessions at onAIR London 2008, The Brewery in London, 52 Chiswell Street, London 12:15 to 17:00

Deploying and Updating AIR Applications (Serge Jespers) - Serge covered the nuts and bolts of deploying AIR applications. He demonstrated the user experience of installing signed vs unsigned applications, and the $299 dollars a year for a code signing certificate is probably worth it if you're going to develop AIR apps regularly. Next he talked about deployment, which involved a discussion of 'Install Badges' - basically flash movies embedded in a web page. The basic one will just run the installer, but there's a more advanced one available, in beta form, on Adobe Labs which adds functionality to check and see if your app is already installed, and tries an update instead of an install if so.

Adobe AIR API Overview (Daniel Dura) - Daniel took us on a potted tour of the AIR API, highlighting some of the 'cool bits'. He started off in the Window API and discussed transparency - so you can create irregularly shaped windows with custom controls - and he demonstrated that it was 'real' transparency by interacting with the desktop through the gap. He then talked about the SQLite API, which lets you achieve Google Gears type things within your app before concluding with some discussion of the integration between AIR and the native OS drag and drop mechanisms.

Extreme AIR development: From concept to TechCrunch in 5 Days (Jeremy Baines) - On to the first lightning talk, Jeremy talked about the rapid development of his AIR app, Alert Thingy, unfortunately the demo went a bit pear shaped.

Developing Secure AIR Applications (Oliver Goldman) - This was one of the more important talks of the day. All the cool apps and transparent windows are fun and shiny, but you want to be fun and shiny while not simultaneously turning your user's machine into a node in a giant spam botnet. The AIR runtime has two security domains - the one where your application code runs, the Application Security Domain, has certain 'dynamic' features, such as eval, innerHTML and <script> elements, disabled to help you avoid shooting yourself in the foot with any imported content (which runs with the loader's privileges). Loaded content, in frames or iframes or loaded by loader.load in a Flash movie, runs in a sandbox by default, the Remote Security Domain. This means it does have eval and friends enabled, but it doesn't have access to all the cool AIR desktop integration stuff. In order to give your loaded content access to those features you have to use the sandbox bridge functions to explicitly make methods available. The final point the Oliver made is that an update function should be part of your security strategy - if security holes are found in your AIR application you've got to have a reliable method for pushing the fixes out to your users, therefore 'check for updates' and associated logic should be included in your first release.

Using JavaScript Frameworks in AIR Applications (Andre Charland) - We were on to the 'short talks' now. Andre discussed how you could easily adapt most popular AJAX/Javascript libraries for us in AIR apps and discussed some of the things they were good for (keyboard shortcuts, activity indicators, window operations when chromeless, mouse hints and tooltips).

BBC News & Sport on Air (BBC) - Three guys from the BBC gave a quick overview of their corporation's history of desktop applets for easy access to website updates and contents, and how the early clients had evolved into the current/new AIR prototype application, which looked quite neat.

Google Analytics on AIR (Nicolas Lierman) - Nicolas has reverse engineered Google Analytics (though now in full co-operation with Google) to produce an AIR desktop analytics application. Quite interesting as an intellectual exercise, I didn't see any clear advantages over the web interface though, and it seems you have to have it on blue gradient background instead of a nice clean white.

Why an Ajax Guy is Excited About AIR (Dion Almaer) - Dion talked about the future of the web and how AIR and Google Gears are complementary technologies. Contrary to popular belief, Google Gears is not "all about offline" - it is a collection of small improvements to the browser API and a testing/proving ground for some HTML 5 APIs. Basically a way of making parts of tomorrow's world wide web available for web developers to use today.

AIR Conditioning (Lee Brimelow) - the day ended on a light hearted note as Lee gave a lot of amusing examples of applications you shouldn't create in AIR just because you can. My favourites were the world's smallest video player and the little app which moved the window out from under the mouse so you couldn't close it. Not much in the way of technical content, but an enjoyable way to end nonetheless.

I didn't enjoy the afternoon so much, and at the time I felt like it was a bit lightweight compared to the morning, and also that the presenters were starting to repeat stuff from earlier in the day. However, looking back in review I think my perception was mostly due to the later afternoon where the flow was lost a bit with all the shorter presentations - it maybe would have been better to spread the shorter talks out among the longer ones rather than clumping them all together like that (ie. one long and one short talk per session between coffee breaks). Still plenty of good stuff, and more free food at the end &amp;#58;&amp;#41; so 4.5 out of 5.

Technorati tags for this review:    

Tweet this!
1 feedback »PermalinkPermalink


07:53:14 pm Permalink Adobe onAIR London 2008 (Morning)

Categories: Front End Web Development

Review: onAIR London 2008 - Morning Sessions at onAIR London 2008, The Brewery in London, 52 Chiswell Street, London 10:00 to 12:15

Free stuff and breakfast - Everyone who attended got a free t-shirt and an O'Reilly Shortcut, Flex 3 Early Evaluation: Assessing Flex and Your Project Needs. Not bad swag (or schwag, as they insisted on calling it), especially when considering this is the first of these sort of things I've been to where they had free t-shirts in XXL. There was also a lot of high value (and some not so high value...) giveaways throughout the day on a raffle type system (no prizes for me, though &amp;#58;&amp;#40; ). Breakfast was tea, coffee, juice and sugary donut things to be consumed while playing with the XBox or Wii.

Keynote - Andrew Shorten presented AIR as the latest in a long line of 'disruptive innovation' from Adobe (and Macromedia), it was marketing hype but I'm sure we can let them off. He listed the key use cases for AIR applications (as opposed to web apps):

  • Applications without persistent connections
  • 'Branded' experiences
  • When desktop functionality was required
  • Local data access scenarios
  • Efficient development

There was mention of a few apps which demonstrated the above features, but not enough time to go into details.

Building your first Adobe AIR application with Adobe Flex (Mike Chambers) - This talk used FlexBuilder, the Eclipse based IDE for Adobe's Flex framework. We were shown actual code examples, a common theme throughout the day, rather than pictures of what to do and, despite my having done no Flex before, it all looked easy enough (which I'm sure was the point). There was some discussion of application signing, and Mike also mentioned two books which are being published with a Creative Commons license: Adobe AIR for JavaScript Developers Pocketguide and the ActionScript reference for RIA development.

Building your first AIR application with HTML and JavaScript (Kevin Hoyt) - After the first talk demonstrated building AIR apps with Adobe's commercial tools, this talk swung things around to show how it was just as easy to build stuff with the free SDK, a text editor and a good knowledge of standard front end web technology. He started off with a few samples, MapCache and SimpleTasks, both implemented using only HTML and Javascript. Again we were treated to live examples with real code in an editor, the key first step is to import the AIRAliases.js which gives you access to the OS integration features through references like air.File.desktopDirectory.resolvePath (resolves the file path to the user's desktop) and air.File.FileStream (the main way to read and write files). Kevin also discussed the Application and Non-Application Sandbox: in the Application Sandbox (where you have access to the AIR APIs) the features in Javascript relating to dynamic code execution are disabled for security (because you have file system access with the user's privileges); you can create a IFRAME in the Non-Application Sandbox which runs like normal JS, with eval and dynamic content creation, but with no direct access to the AIR API, then talk to your Application Sandbox through the SandboxBridge.

Leveraging HTML and JavaScript within Adobe AIR (Kevin Hoyt) - After a break we were back with Kevin for a talk on how to get the Flash and ActionScriptparts of an application to talk to the HTML and Javascript parts. This talk was mostly code rather than slides, and I present a much compressed version here from the (hopefully) salient points I scribbled down in my notes. First off, calling ActionScript from Javascript: create an external interface in your Flash file ExternalInterface.addCallback and then use document.getElementById from your Javascript to reference the Flash object and call the method directly. Also from ActionScript you can reach directly into the HTML DOM with a browser.window.document reference. From what I understand this is fairly standard for Flash and HTML without AIR being involved, what AIR adds is a greater consistency and closer integration. In an AIR app you can reach inside the Flash runtime from JS using a window.runtime.flash reference which allows you to take advantage of SWF components. Kevin demonstrated a Zip viewer in Javascript which used David Chang?s Zip utility (fully detailed on his excellent blog).

Lunch - it's my policy never to complain about a free lunch, fortunately in this case I had no desire to &amp;#58;&amp;#41; Serving staff came to us with trays of finger snacks while we were queuing for the food table, and later came around with little bowls of hot food. I had a lamb and potatoes thing. The only vaguely confusing thing was they seemed to expect me to eat gravy with a fork, but it all tasted good.

I'm going to stop here, since it's taken me over a week already and I'm only half way through the day. The morning by itself definitely deserves a 5 out of 5, if you're still wavering about whether or not to go to any of the events on the second half of the European tour I'd say it's well worth a day out. A few other folk have been a lot quicker off the mark than me - Remy Sharp and James Ford are two I've come across (you can even see me in one of the pictures in the second one).

Technorati tags for this review:    

Tweet this!
Send feedback »PermalinkPermalink


10:32:29 pm Permalink openSUSE 10.3 on a Toshiba SatellitePro 6000 (upgrade)

Categories: Linux, SuSE

A mere five months after the release of SuSE 10.3 I finally got round to upgrading my aging laptop. Of course, I was still on 10.1, so I'd already waited ten months before that &amp;#58;&amp;#41;

I downloaded the main ISO and the extras one, and booted off the CD. Encountered a slight problem getting it to boot initially, but when I clicked for 'view details' in the boot process I saw a helpful message about adding brokenmodules to the boot options. I also had to disable acpi, so I ended up with these options:

acpi=off brokenmodules=pata_ali

The next issue was I had a load of extra repositories enabled on 10.1, and it turned out the Guru repo is now part of Packman so you have to disable it before starting the upgrade, otherwise the upgrade hangs.

After that it was more time consuming than complicated, I had a load of package conflicts to resolve, and for a time it seemed like I was going round in circles with that. Then I just had to wait overnight while it did the actual upgrade, and now I have it all installed and working.

The default KDE theme is a bit different, lots of faux transparency, and there's a new, more compact, application menu which is quite nice, but otherwise not massively different from the end user point of view. With some updated underlying packages I'm hoping I'll now have a better chance of installing more recent software.

Tweet this!
Send feedback »PermalinkPermalink


11:58:47 am Permalink IE8 Beta 1 - A Review

Categories: General, Product Reviews

Product Review: Internet Explorer 8 Beta 1

Microsoft released the first Beta for Internet Explorer 8 the other day, so I downloaded it and installed it on a virtual machine so I could test it out. This post records my first impressions, even if it took me two weeks to actually finish it off and publish it &amp;#58;&amp;#41;

First stage was the install, which looks much the same as the installer for IE7, I selected 'Choose my settings' to make sure I didn't miss anything.

The first option is also familiar from IE7, nice of it not to change my default search provider to Live anyway.

Next was 'Select activity providers' - this is a new feature in IE8, more on this below.

The 'Safety filter' - much the same as in IE7.

Finally, because I'd selected 'Go online and select more activity providers,' I got to the activity providers page.

Although all the options come from Microsoft, there were a few examples which weren't driven from Microsoft's data. I selected Yahoo! as my mapping provider as well as a few other non-standard ones.

So the first test, how does IE8 render my website? Answer, quite well actually!

The home page looks a lot more like it does in Firefox than it does in IE7 (below). Though a visual test of one web page is hardly thorough, it does seem likely that this will be MS's most standards compliant browser yet.

The blog itself also looks OK, no major issues for me so far!

However, on the JS front, things were not quite so rosy, mostly thanks to some of the many 'blog decorators' I've got going on in the sidebar. But this gives me an opportunity to show off one of the first things I really liked about IE8 - the new 'done with errors' dialogue.

You can expand to see all the errors in a list (in IE7, only one error shows at a time) and it also has that very convenient 'Copy details to clipboard' button.

That's not all on the error handling front, I got to see the other neat new feature, which seemed mostly to get caused by The initial error message is much like before:

But what it does after that is a bit more clever. Each tab in IE8 runs in a separate process, a feature known as LCIE, so a crash is not fatal to the browser. As you can see in the image below, when a tab crashes it is simply restarted and the rest of the tabs are unaffected.

There's also a whole collection of (very Firebug like) developer tools built in to the browser, allowing JScript debugging without installing one of MS's Visual Studio variants. The tools menu as also had a bit of an update, to emphasise the privacy features.

Activities are a major new feature of IE8, it's basically a way of taking advantage of other resources on the internet to enhance the information you can see on your current page, similar to the way the Firefox Operator Add-on is supposed to work with Microformats. For example, below I have selected the post code on my 'About Us' page and then right clicked - I get a choice of 'activities' for my selection.

I select 'Map with Yahoo!' and a map appears in a floating frame.

There is apparently a more direct interface than right clicking, but I couldn't get it to appear reliably. Selecting some text sometimes causes a little button with an arrow on it to appear:

So enough praise, there are several things I didn't like so much. First up, WebSlices - basically a sort of single item RSS feed embedded in a web page. This is quite exiting for the Microformats community because the format for embedding the item is based on hAtom. Unfortunately it isn't actually valid hAtom, and also seems to be solving the exact same problem as Microsummaries which has been in Firefox for over a year. So with two existing (though admittedly de-facto) standards to choose from, Microsoft chose to implement neither of them and go their own way. There may be very good reasons for this, of course, but it's the sort of thing that makes you wonder how serious they really are about following web standards.

The next point of complaint is the IE7 mode. Generally a good idea - switch the browser back to an older rendering engine so that any pages which are seriously broken by IE8's new standards compliance have a chance of working, users have a simple 'make this site work' button to press. The implementation, however, is just plain bad. They've gone to all the trouble of making their browser crash proof with the LCIE stuff, but then have a feature as important as 'Emulate IE7' force you to restart the whole browser before it has any effect. So if you have eight tabs open, and only one website which doesn't work, you still have to close all seven other tabs to get that one page to work.

As a web developer you can trigger the IE7 rendering mode from your web page by either sending an HTTP header, or using an http-equiv meta element in your HTML:

<meta http-equiv="X-UA-Compatible" content="IE=7" />

Be warned however, the browser, even in 'IE7 mode', still believes it's IE8 in my (limited) testing. So if you're using conditional comments like these, they won't be picked up:

<!--[if IE 7]>
<link rel="stylesheet" href="/styles/ie7.css" type="text/css"/>

Overall then, I'm quite impressed. The activities stuff is quite smoothly implemented, the improvements for web developers are excellent and the move towards standards compliance is commendable - 4 out of 5. I hope they continue to make improvements before the final release.
Technorati tags for this review:  

Tweet this!
1 feedback »PermalinkPermalink


11:37:49 pm Permalink Fixing Jack's formmail.php for register_globals = off

Categories: Server Side Web Development

For many years now, I've used various versions of Jack's FormMail.php to handle simple form submissions on various websites, mostly 'contact us' forms. The script has gotten a little more sophisticated with time, but it's still one of the simpler ways of making a website 'interactive.'

The website at work uses it to send the marketing department emails when someone fills in the contact us form. The form is somewhat sophisticated, in that it presents different information depending on a few parameters in the URL, and passes formmail.php a different subject for the email depending on what configuration it's in. It also passes a redirect URL in a hidden field, so the user is redirected to a 'thanks for contacting us' page after submitting the form. Google Analytics is set up so that any hits on the 'thanks' page after viewing the contact page counts as a Goal. And this is where I spotted the problem - as I checked through the Analytics stats I noticed we hadn't achieved any goals since the middle of last week, although a day or two here and there without any is fairly common five on the trot is pretty rare.

My first step was to go to the contact form and try submitting it, the email duly arrived in the correct mailbox but the script didn't redirect to the thanks page. So first mystery solved, no hits on the thanks page means no goals on Analytics, but the marketing department hadn't noticed because they were still getting emails. I messed around with some of the different configurations of the contact page but none of them redirected as intended. Then I realised that all the emails had the same subject, and that was the default one given by formmail.php when it doesn't get passed a subject, though the values in the form fields were appearing in the email correctly, so it wasn't like the information wasn't getting passed though.

I checked the web host's page and discovered that they had recently updated the PHP config on the server, this in order to support PHP v5. There was a new option in CPanel to select the default version of PHP, so I went and set it to v4 in case formmail was incompatible with the newer release. It didn't make any difference though, so I started looking at formmail.php itself in detail.

The first thing I noticed was that the redirect functionality required register_globals to be enabled. Although my PHP configuration page claimed that register_globals was enabled, the behaviour of the script indicated that it wasn't. Unsurprisingly, the subject field also expected register_globals to be enabled, as did several other fields which I wasn't using, but the code which builds the email uses $HTTP_POST_VARS so works fine without.

If you've managed to read this far without falling asleep and you know what register_globals is, then you now have enough information to fix the problem yourself and there's no need to torture yourself any further. If you currently have no idea what I'm on about, I'm now going to try and explain and then show you how to edit your script to fix the problem. register_globals is a configuration setting for the PHP interpreter, if it's set to on then PHP will helpfully make any parameters passed into the script global variables. Parameters are the bits in the URL after the question mark, or fields in a form. This can be quite handy when you're slapping together a quick script, but is also very dangerous because, if you're not careful, you can create easy opportunities for hackers to do nasty things. For this reason, register_globals = on has long been discouraged in the PHP community, unfortunately many useful scripts were written in the days before anyone realised it was an issue, so web hosts usually provide a way turn it back on even if it's not enabled by default.

However, today we're going to make formmail.php work properly with register_globals = off. You're going to need to open the formmail.php script in a text editor - Notepad will do fine. First we shall fix the redirect issue, find the following lines near the end of the file:

if ($redirect) {
   header("Location: $redirect");

We're going to replace $redirect, which is trying to access the global variable, with $_POST['redirect'], like so:

if (isset($_POST['redirect'])) {
   header("Location: ". $_POST['redirect']);

The same trick works with the subject and email address, scroll up a few lines and find this:

mail_it(stripslashes($content), ($subject)?stripslashes($subject):"Form Submission", $email, $recipient); 

Replace it with:

mail_it(stripslashes($content), isset($_POST['subject'])?stripslashes($_POST['subject']):"Form Submission", $_POST['email'], $recipient);

Now upload your new version to the server and you should find things start working as before. As you can see the general rule is to replace $variable with $_POST['variable'], notice that I didn't change $recipient because I always hard code that value at the top of the script as a security precaution.

Tweet this!
59 feedbacks »PermalinkPermalink