Pages: << 1 2 3 4 5 6 7 8 9 10 11 ... 15 >>

05/28/08

11:30:34 am, by robertc Email , 544 words, 5059 views   en-UK
Categories: Front End Web Development, Semantic Web and Microformats

Microformats vEvent

It's London Web Week, which means there are lots of events on. I plan to go to three of them myself, the first of which was last night's Microformats vEvent.

Review: Microformats vEvent at The Yorkshire Grey, Holborn, London 19:00 to 21:30

The venue was a function room in a pub which wasn't ideal - there weren't enough seats for everybody and, since I was a bit late arriving, I had to stand through both presentations which made it a bit awkward to make notes.

Putting microformats on the Semantic Web with GRDDL (Tom Morris) - Tom started off by talking about "Descriptive Markup", an alternate term for semantic markup to avoid "semantic" being every third word that would come out of his mouth. He then moved on to GRDDL and it's potential for creating a decentralised data web out of any HTML pattern you use on your website. An HTML pattern doesn't have to be a Microformat, it can be any HTML as long as it's used consistently on your site and you can provide an XSL transform to turn that pattern into useful semantic data. You can then write your own GRDDL profile to allow the data to be automatically extracted. He also discussed that the output from a GRDDL transform needn't be RDF, it could be anything you want such as RSS or JSON, which would allow you to very easily create an API for your website with nothing more than a few transforms. In the questions at the end he compared GRDDL to CSS and Javascript, except where CSS was for presentation and Javascript is for behaviour GRDDL would be for data. For an example of the potential he suggested we checkout triplr.org. Tom finished off with some "Design Patterns for the Web of Data":

  • Give everything a URI - your website, your house, your car, your pets etc.
  • Things (ie. URIs) linked together with meaning
  • Small vocabularies loosely joined - don't try and describe the whole world, stay focussed on your target domain
  • Do the right thing - practice wisdom
  • "Pragmatic" usually means you're doing it wrong
  • Don't mandate, don't limit - the less you restrict, the more room there is for freedom of expression

One Big Happy Family: Practical Collaboration on Meaningful Markup (Dan Brickley) - Dan's talk was a bit more political than technical and addressed the antagonistic attitudes which are sometimes displayed by Semantic Web folk towards Microformats folk and vice versa. Through a discussion of some of the history behind the current Semantic Web specifications at the W3C, a history which is largely obscured by the specs in their current state, he demonstrated that the two communities have far more commonalities than differences. Both communities are converging on the same goal but are taking very different routes to get there, and a bit more respect on both sides could allow each to learn from the other. That was a high level summary, the way Dan said it took longer but was also funnier with a liberal sprinkling of anecdotes &amp;#58;&amp;#41;

The talks themselves were very good, but I didn't enjoy the environment much - apart from the standing, the TV screen was a bit hard to read so 3.5 out of 5 overall.

Technorati tags for this review:    

Tweet this!

05/27/08

05:10:00 pm, by robertc Email , 558 words, 24970 views   en-UK
Categories: Web Develop, Front End Web Development

Building a compressed prototype + scriptaculous with YUI Compressor

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 1.6.0.2 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',
  REQUIRED_PROTOTYPE: '1.6.0.2',
  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) <
        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
        Scriptaculous.REQUIRED_PROTOTYPE);
  }
};
 
Scriptaculous.load();

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!

04/26/08

06:28:15 pm, by robertc Email , 133 words, 2049 views   en-UK
Categories: Linux, SuSE

Mugshot 1.1.45 on SuSE 10.3

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!

04/22/08

10:46:43 pm, by robertc Email , 933 words, 9147 views   en-UK
Categories: Front End Web Development

Adobe onAIR London 2008 (Afternoon)

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!

04/19/08

07:53:14 pm, by robertc Email , 890 words, 8222 views   en-UK
Categories: Front End Web Development

Adobe onAIR London 2008 (Morning)

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!

03/08/08

10:32:29 pm, by robertc Email , 243 words, 1454 views   en-UK
Categories: Linux, SuSE

openSUSE 10.3 on a Toshiba SatellitePro 6000 (upgrade)

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!

03/06/08

11:58:47 am, by robertc Email , 974 words, 24275 views   en-UK
Categories: General, Product Reviews

IE8 Beta 1 - A Review

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 msn.com. 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"/>
<![endif]-->

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!

03/03/08

11:37:49 pm, by robertc Email , 846 words, 54623 views   en-UK
Categories: Server Side Web Development

Fixing Jack's formmail.php for register_globals = off

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");
   exit; 

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']);
   exit;

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!

01/21/08

11:41:55 pm, by robertc Email , 1706 words, 9037 views   en-UK
Categories: Usability & Accessibility, Front End Web Development

Web Development for the Blackberry Pearl

We had a potential client which wanted to use our web application on their Blackberry Pearl devices. I figured "How hard can it be?", downloaded an emulator and got cracking &amp;#58;&amp;#41; I wanted to make the standard pages support the Pearl, I didn't want to write a whole new web app, without changing how they worked on desktop browser to avoid confusing existing customers.

The tips below are things I specifically ran into on the Pearl, I imagine they'll apply pretty well to any low end mobile browsing device.

Tables make layout inflexible - the Blackberry has a fairly narrow screen when compared to a desktop. If your form laid out is in a table which is several hundred pixels wide the chances are it's not going to fit in the width. Since your page is most likely already too long for the display this is going to leave users having to scroll in two axes to complete the form. To avoid this I changed all the forms I expected to get used on the Pearl into a tableless layout which then used CSS to achieve the same display on the desktop, and then add a mobile stylesheet to override this:

<link rel="stylesheet" href="style/handheld.css" media="handheld" type="text/css">

This meant they lay out in a grid on a desktop browser but in a linear column on mobile devices

No javascript by default - the web app I was working with has been in production for more than five years, so it has it's share of hairy code particularly in the javascript department - a mixture of inline and external. One of the main issues for me was that so much of the supporting functionality depended on JS - for instance the search form could be filled out and submitted, but the functionality for scrolling through the results depended on onclick events on buttons. I re-wrote the forward and back buttons to be wrapped in little forms of their own which submitted to the correct URLs to solve that fairly easily (and that worked just as well for full desktop browsers too).

The more difficult situation was the input form, which, although it allows free text input, also allows you to select from a list of available options. Unfortunately the way this has always worked is for users to click on a button which launches a pop-up window, then double click on the item they want out of the resulting select list. The value is then inserted into the main form and the window closed, and the whole process is driven by javascript.

So, obviously it's not going to work at all without any javascript. I should point out this represents a bad design decision, I should have started with a form which worked without javascript and layered the enhanced behaviours on top (a technique known as progressive enhancement, but way back when the decisions were made I didn't know any better and neither did anyone I worked with. So I was re-writing the page in my ASP era web app, but I wanted to keep visually identical (close enough, at least) to the previous version. Here's an example of what the form components looked like before I started (names have been changed to protect the innocent):

<tr>
<td>
  <input class="standardWidth" value="Service Group" onclick="openPopup('Default.asp?WCI=listItems','PopUp','300','680');" type="button">
</td>
<td>
  <input autocomplete="off" name="txtITEM" id="txtITEM" size="25" maxlength="20" title="Click button to display list" value="" type="text">
<div style="display: none;" class="auto_complete" id="txtITEM_complete">
</div>
<script type="text/javascript">
new Ajax.Autocompleter('txtITEM', 'txtITEM_complete', 'Default.asp?WCI=listItemUL', {minChars: 2});
</script>
</td>
</tr>

A quick note here so you don't get lost - I'm using scriptaculous for the auto complete, openPopup is a fairly standard popup function, all the server side functionality is encapsulated in a WebClass, basically a VB6 DLL embedded in an ASP page, so different pages are called up by varying the WCI= parameter.

After I'd switched to a tableless layout (see above), my first step was to comment out all the javascript, this broke everything &amp;#58;&amp;#41; Next, I changed the input element to be a submit. Every button on the form would submit it and I planned to then detect which button had been clicked on the server side. This is relatively straightforward, just give all your submit buttons a common name (but a unique id so you can reference them individually in script):

<div>
    <span class="colLeft">
        <input type="submit" name="butLogForm" id="subITEM" class="standardWidth" value="ITEM">
    </span>
    <span class="colRight">
        <input type="text" name="txtITEM" id="txtITEM" size="25" maxlength="25" value="" title="Click button to display list">
    </span>
</div>

Then, on the form target page you check the value of butLogForm, so in VB6/ASP it's Request( "butLogForm" ), and its value will be the whatever you assigned to the button which was clicked (ITEM in the above example). So if a button other than the 'main' submit button has been pressed it's easy to detect this and redirect to the appropriate selection page for the field (which would be the same page as was originally appeared in the popup window summoned by clicking the button). I then added some plumbing to direct the popup page to either submit the value as a form or populate with javascript into opener depending on how it was called and to capture all the values behind the scenes once the user had selected them.

So now the form worked fine with javascript disabled, the only task left was to make it work as it did before in a desktop browser, popup windows and auto-completes, when javascript was enabled. This was slightly complicated by the need for the javascript to know the URLs for all the pages, and these could be changed at runtime, so I decided to pass them all in as parameters to the onload function (there is a URLFor) utility function available within the webclass which calculates them). To reduce the number of URLs to be passed in I used a naming convention so that the URL for the auto-complete function could be easily generated from the popup URL by appending 'UL' to it:

if ($('subITEM')) {
    $('subITEM').onclick = function () {openPopup(urlITEM + '&IsForPage=Log','PopUp',width,height); return false;};
    if (!$('txtITEM').readOnly) {
        var elTxtITEM = $('txtITEM');
        acDiv = document.createElement('div');
        acDiv.className = "auto_complete";
        acDiv.id = "txtITEM_complete";
        elTxtITEM.parentNode.appendChild(acDiv);
        new Ajax.Autocompleter('txtITEM', 'txtITEM_complete', urlITEM + 'UL', {minChars: 2});
    }
}

The code is fairly simple. First I check to see if the relevant submit button actually exists (there are configuration settings in the app to turn each field on and off) and, if it does, adds the old popup code to the button. Next I check to see if the text field is editable (another configurable option) and add both the div required by the Ajax.Autocompleter and then initialise the control itself.

The <button> element is useless - well it might not be completely useless, I didn't try too hard, but I decided I was only using it in the first place to show off my l33t HTML skills so I just switched them back to regular input elements.

No CSS by default - the browser on the Blackberry Pearl will not use CSS by default, though you can change the configuration to enable it and it will then respect the mobile stylesheet. The main problem this posed for me was that, in a lot of places, I was relying on padding and borders to provide spacing between text elements, eg:

<div><span><strong>Status:</strong></span><span>Active</span></div>

So when CSS is turned off you end up with tall the text running together with no spaces in between, making it hard to read. Since in this situation it's impossible to control the presentation with CSS I resorted to using markup for it and added &nbsp; glyphs inside the spans in every place where the text needed a space.

Turning on javascript leads to memory errors (slowly) - just like CSS, the browser on the Blackberry Pearl will not use javascript by default. This leads to the issues I already covered above, but a more amusing issue occurs if the user happens to enable javascript. The Pearl is a low memory device, even compared to other smart phones, and if your web app has several hundred kilobytes of javascript for it to download it will use up all of that memory in a vain attempt to parse the file. Since all the javascript gets downloaded in a standard header this led to a long wait and then an error message when you even tried to access the login page on my app. I made an extremely cut down javascript file, basically the standard field validation and date formatting functions, the openPopup function and some empty function stubs for all the onload functions (to avoid error messages). Since I didn't have the time or resources to implement WURFL or DeviceAtlas and this is only ever likely to be used in controlled corporate environments, I made a user configuration setting in order to send the cut down version to the Blackberry instead of the regular JS .

Only onchange on inputs, no onblur or onfocus - the final thing that caught me out was to do with my validation and formatting helpers on text inputs, these were all hanging off onblur and were not getting fired on the Pearl. The quick solution was to change everything to onchange instead, though the reason I'd used onblur in the first place was because I'd experienced some unreliability in the desktop browsers so this was not ideal. Unfortunately I had to wrap up this project before I had chance to get into it in more detail.


Tweet this!

11/25/07

10:37:40 pm, by robertc Email , 1120 words, 5041 views   en-UK
Categories: Web Develop

DDD 6

Review: DDD6 at Microsoft UK Campus, Building 3, Thames Valley Park, Reading, Berkshire. RG6 1WG. 08:45 to 17:00

I'm more of a web developer than a 'Microsoft developer', but I use a lot of the MS stuff at work and I really enjoyed WebDD last February so I thought I'd give the more .Net focussed parent event a try.

Why IronRuby? (Presentation) Dave Verwer - I'd been to a couple of Dave's talks at the WebDD event and enjoyed them tremendously, so I went in to this one with high expectations. The talk started with some of the benefits of Ruby - a dynamic language with elegant syntax designed for simplicity and productivity, before going on to discuss how IronRuby and the DLR are implemented in .Net. The DLR is basically a layer for dynamic languages on top of the standard CLR, it is an abstraction of the what was developed in the course of getting IronPython up and running. At this point Dave admitted that IronRuby wasn't yet ready for use, so the rest of his talk would be about (C based) Ruby 1.8 - which IronRuby is targeting for compatibility. This was a bit of a disappointment for me, because really I was after a more practical demonstration of IronRuby than another presentation on Ruby - but it's possible I was in the minority given the audience. Check out the IronRuby website if you want to learn more.

Entity Framework (Presentation) James Winters - I had no idea what this was before the talk, but the title sounded more interesting than the others available in this slot, and it saved me leaving the room when I knew I wanted to see the talks either side. In the event, I was glad I stayed. To give a simple sound bite - Entity Framework is like an ORM on steroids, which will allow transparent mapping to non-relational stores, such as LDAP, as well as the more usual SQL stuff. The plan is for all MS server products to move to Entity Framework for their data access, though at the time of the talk the only backend available was SQL Server and all the examples were basic ORM stuff. The logical model of Entity Framework is made up of three levels:

  • O-SPACE - the object model, eg. LINQ
  • C-SPACE - the conceptual model, eg. Entity Client
  • S-SPACE - the store - eg. ADO.Net.SqlProvider

All levels are scoped by an entity container, which defines a namespace and an object model, and the goal of the MS Visual Studio team is to be able to generate the lower levels using visual tools.

Entity Framework supports multiple querying methods:

  • ESQL - very similar to HQL in Hibernate
  • Object Query - a generic object interface with caching and lazy loading, which can either be read only or mergeable
  • Use Entities directly
  • LINQ

There are some limitiation, there is no locking by default and, while it's going to be possible to map stored procedures the visual tools aren't going to support it for some time so you have to write up the XML manually. Generally, though it has a slight whiff of the architecture astronaut, it looks like an interesting addition to the .Net toolbox (Slides available here).

Why do I need an Inversion of Control Container? (Presentation) Mike Hadlow - I'd heard of Inversion of Control (IoC), but hadn't really understood what it was for. The presenter, Mike, had been in a similar position until he started studying it seriously, and now he was here to share his epiphany. The main problems IoC is trying to address is that the relationship between component size and complexity is not linear - double the size of your components and you quadruple the complexity - but breaking components into smaller pieces tends to lead to increased dependencies. Inversion of control reduces the complexity of large components and manages the dependencies between them. The principals of inversion of control (paraphrased from Robert Martin) are:

  • High level modules should not depend on low level modules
  • Abstractions should not depend on details
  • Details should not depend on abstractions
Typical problems of OO code without IoC are:

Inversion of control helps with all these by allowing constructor injection and property injection. If these can be injected into components at runtime, rather than hard-wired into the components, then it becomes possible to modify the behaviour of components without having to modify the components thus satisfying the open/closed principal and reducing the coupling (property injection) and also to easily mock objects for unit testing (constructor injection). Mike then moved on to some detailed demonstrations using the Windsor component from the Castle project, before concluding that IoC is really just the thorough application of design patterns and other OOP best practices. Therefore you should only start considering inversion of control once you're already familiar with these and have already implemented things like unit testing (Slides available here).

Dynamic Languages on .NET (Presentation) Michael Foord - My first session of the afternoon and by this point I was flagging a bit after having to get up early and make the trip out to Reading. Michael is one of the authors of Resolver, a spreadsheet based application environment, aimed at the financial markets and written in IronPython. The app is approximately 30000 lines of code, thus refuting the myth that it's impossible to write large applications in a dynamic language, and it's spreadsheet model is implemented in a Python hash table, making it very easy to extend Resolver with new types and operators. After a discussion of what constitutes a 'dynamic language' and the overall benefits of Python and IronPython in particular, Michael moved on to some practical examples based on his IronPython Web IDE (Slides available here)

Testing Your Applications With MbUnit Gallio (Presentation) Ben Hall - unit testing is a popular topic on programmer blogs these days, and this was reflected in a fairly full room for one of the 'minor' talks (ie. we weren't in one of the big rooms). Ben covered some best practices of automating unit testing on .Net with MbUnit and Gallio, starting at the database layer (use transactions and rollbacks or COM+ transactions), the business object layer (mocking and inversion of control) and the user interface (don't try and automate it!). An interesting if slightly hurried talk which I was unfortunately too tired to pay full attention too (Slides available here)

Overall a good day, I definitely learned more than one new thing per talk and the Microsoft conference room facility is a good venue for these sorts of things, so 4 out of 5, and I'll almost certainly try and get to the next one.

Technorati tags for this review:  

Tweet this!
Permalink: DDD 6Leave a comment »

11/16/07

07:32:19 pm, by robertc Email , 227 words, 2698 views   en-UK
Categories: Front End Web Development

IE6 & 7 Up/Down Keypress Issues with Ajax.Autocompleter in Scriptaculous 1.8.0

I started a new project at work today, adding some ajaxy interactivity to a slightly long in the tooth web application. In a previous iteration I'd plugged prototype.js 1.5.1 into this app, now I wanted snazzy effects and autocomplete fields. Figuring it was a good time to move up to the latest version of scriptaculous, I downloaded the recently released 1.8.0 version (which includes prototype 1.6.0).

I had to do some hacking around in my 'legacy' javascript to get things working in Firefox (that's how long in the tooth this application is), and then I added my Ajax.Autocompleters, got my afterUpdateElement callbacks working and was starting to feel generally quite chuffed with myself at how well it was all going. Then I thought I'd give it a quick check in IE...

In IE7 the up and down arrows didn't scroll up and down the autocomplete list, which made the whole thing kind of useless. A quick check in IE6 confirmed the same issue there, so I immediately resorted to Google. Unfortunately the answer wasn't immediately apparent in the search results and it was only when I started searching the Ruby on Rails Trac directly I finally homed in on the answer. Hoping that I can help future searchers home in on this more quickly, here's the defect: "some keypress events don't work in IE6/7"; and here's the fix.


Tweet this!

<< 1 2 3 4 5 6 7 8 9 10 11 ... 15 >>