The Scriptalizer

November 6th, 2008

Given the extended use of Javascript in today’s web applications, one of the best ways to improve site performance is to obfuscate your javascript before it is loaded into the browser.

Trimming white space and new lines can shave as much as 50% from your script file sizes, which can make as significant difference to the initial load delay of your site.

http://www.scriptalizer.com is as good a solution as I have found for this.

You upload your files, hit the button, and wham, all your beautifully formed javascript is compressed into a congealed, but wonderfully efficient, blob in a single file.

Only thing is that you have to insert a bit of logic into your code to load your human readable files in development and the single obfuscated file in Production, because you don’t wanted to have to repeat the obfuscation process every time you want to test a new piece of code, and you certainly don’t want to try and edit the obfuscated file by hand.

PLESK, vhost.conf and vhost_ssl.conf

September 25th, 2008

I recently had cause to run 2 websites under different domains from the same code base. I wanted to do this using my PLESK server, and provide for SSL connectivity to both domains.

I set up the 2 domains under PLESK as normal. To get the 2nd domain to run from the codebase for the first domain, I created a vhost.conf in the conf dir for the 2nd domain. This sets the DocumentRoot of the 2nd domain to the DocumentRoot of the 1st domain, and adds the home directory of the 1st domain to the open_basedir directive for the 2nd domain.

ie

the 2nd domain nows picks up its code from the home directory of the 1st domain, and the 2nd domain is now allowed refer to and write to the home directory of the 1st domain.

Next bit was the Digital Certs.

I installed these as normal under PLESK, then set up SSL support for both domains, and specified that both domains should use single directory for both SSL and non-SSL content.

This adds 2 Virtualhost directives to the http.include file (the one you should never edit) for both domains.

Now, to get the 2nd domain to refer to the code base of the 1st domain for SSL content, I copy my vhost.conf file to vhost_ssl.conf, and run

/usr/local/psa/admin/bin/websrvmng -a

This causes an Include statement to be written in both Virtualhost directives in the relevant the http.include file for the 2nd domain, allowing the vhost.conf and vhost_ssl.conf files to be read so that the 2nd domain uses the code base from the first domain for both SSL and non-SSL content.

The result?

https://www.textatrack.co.uk/

and

https://www.downloadmusic.ie

Same code base, but different domains and certs. Neat.

AJAX Character Encoding in Internet Explorer

July 16th, 2008

Is there no end to the woes of IE?

I’ve just spent 3 hours trying to find out why IE 7 won’t encode my form inputs in UTF-8 before sending them off in an XMLHttpRequest package to my server.

Here’s what is supposed to happen:

I send the page to the browser with UTF-8 character encoding, so the browser is supposed to use this encoding in whatever it does.

This is fine when sending form inputs back to the server with a straight-forward FORM Action routine, but when you use XMLHttpRequest in IE7, IE7 insists on sending the form input in ISO-8859-1.

So if someone enters Ø in one of my form inputs, IE7 sends this off to the server as ‘\xd8′ rather than as ‘%C3%98′ as it should.

The result is that garbage goes into my DB which then invalidates any XML that uses that garbage.

Thankfully, I found a solution.

When I take the form input value from my DOM, I pass it through the Javascript encodeURIComponent function before passing it to the XMLHttpRequest object.

var new_value = document.getElementById(”text_input”).value;
//CONVERT FORM INPUT TO UTF-8 FOR IE 7
new_value = encodeURIComponent(new_value);

XMLHttpRequest is supposed to use UTF-8 by default. There may be something wrong with my set up, but for the life of me I couldn’t get it to use UTF-8 (I’ve checked all my HTTP headers and everything is UTF-8; my server also uses UTF-8 by default, and everything works fine in FF) so this was the only solution that worked.

Another day lost to IE7.

Grrrrr.

Dynamic creation of Flash content

March 13th, 2008

Here’s a subject that gets a lot of press in the web development world.

Given the popularity of music and movies on the web, developers need to be able to deliver dynamically created and configured players as a matter of course.

There are a couple of challenges in this. For instance, creating DOM Objects with Javascript isn’t too hard, but creating DOM Embeds is a real nightmare, not least because IE won’t let you append an Embed to any other element, and because IE likes you to re-initialise these objects when you update their parameters.

Then you have the Eolas v. Microsoft issue, which is why you have to click twice on Flash objects in IE before they work.

Finally, you have to deal with all the various browser plugins that attempt to act on media content before any of their competitors, which makes them get up to all sorts of crazy behaviour.

From what I’ve seen, developers approach the dynamic Flash conundrum in one of two ways: they either try and accomplish everything with very long, hopelessly complex innerHTML strings, or they use the SWFObject Javascript library kindly provided by Geoff Stearns who is a Flash engineer with Youtube.

http://blog.deconcept.com/swfobject/

Having tried both myself, I would have to say that SWFObject is the only way to fly.

Its simple to use, its free, its stable in pretty much every browser and it starts Flash objects with a single click in IE, which is really sweet.

You can see it in action on the homepage of www.downloadmusic.ie.

All of the music buttons in the chart are created with SWFObject, but better still, the music buttons in the BATTLE BOX are dynamically created with AJAX and SWFObject. Creating Flash objects with AJAX is all but impossible without SWFObject.

Use it and spend more time with your kids (and thanks to Geoff).

Multidimensional arrays in form data

February 19th, 2008

Readers are probably aware that you can pass an array to a script from a HTML form.

For instance, if you want to pass multiple checkbox items, or data from a SELECT where the user can select more than one option:

<INPUT TYPE=checkbox VALUE=1 NAME=myData[]>
<INPUT TYPE=checkbox VALUE=2 NAME=myData[]>
<INPUT TYPE=checkbox VALUE=3 NAME=myData[]>

or

<SELECT NAME=myData[] MULTIPLE>

will appear in the PHP Superglobal $_GET/$_POST arrays as an array:

$_GET[’myData’] or $_POST[’myData’]

What users may not know is that you can also pass a multi-dimensional array from a form. This is particularly handy if your form is dynamically created with a variable input names.

For instance, if you want to create a checkbox that a user can tick and then add data that is associated with that checkbox.

Say you have a property website, and you allow a seller to specify that a property is close to the airport (checkbox) and then allow the seller to specify the distance in km and miles from the airport using 2 SELECTs.

Your checkbox would form the first layer of the array:

<INPUT TYPE=checkbox VALUE=1 NAME=myData[x]>

Where x = discreet data that refers to a property being ‘close to an airport’.

Your 2 SELECTS would then be:

<SELECT NAME=myData[x][0]>
<SELECT NAME=myData[x][1]>

This will place the multi-dimensional array $myData in either $_GET or $_POST, which you can use like any other multi-dimensional array.

IE 6 and 7 Imagemap crash issue

December 21st, 2007

Imagemaps are a bit old hat these days, but they still have their uses and this IE bug can be a real killer.

If you dynamically create an Imagemap using Javascript, IE has a problem with polygon areas that have different number of co-ordinates. Basically, IE will crash if you click on an area that has fewer co-ordinates than a previous area.

To get around this, don’t use DOM element properties to create your Imagemap:

Don’t use:

map_image.isMap = ‘ismap’;
map_image.useMap = ‘#layer0′;

etc

Put your IMG tag inside a SPAN instead, and update it using the innerHTML property.

Firefox, Imagemaps and Float DIVs

December 9th, 2007

Here is some curious Firefox behaviour I’ve recently discovered. It took me several hours to figure out what was happening.

If you place an imagemap inside a DIV in Firefox, it works fine.

However, if you then float that DIV, Firefox moves the image with the DIV, but leaves behind the imagemap where the DIV would have been had it not been floated.

IE doesn’t repeat this behaviour. It moves the imagemap with the image. I’m not sure which is the standardised behaviour, but if you want to place imagemaps in columns on a page, and you want this to work in Firefox, you have to use tables. DIVs won’t cut it.

Parsing the attributes of XML elements

November 5th, 2007

PHP 5.0 contains some excellent functions for parsing XML into arrays and objects, but that isn’t much good to you if you have to used PHP 4.0.

That said, it is relatively straightforward to extract the data from between XML tags in PHP 4.0, but the particular problem I came across was having to extract attribute values from the tags themselves. This arose in relation to exchange rate data published by the ECB, which you can view here:

http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

As you can see, the data we really want (the exchange rate and currency name) is an attribute value rather than raw data between the tags.

Anyway, to get at this data you need to look at the $attrs associative array that is passed to whatever ’start element’ function you are using. This will work (CUBE is the tagname we want in the ECB feed):

function startElement($parser, $name, $attrs) {
global $insidecube, $tag;

if ($insidecube) {
$tag = $name;
} elseif ($name == “CUBE”) {
foreach ( $attrs as $name => $value ) {
echo $name . ” ” . $value . “\n”;
}
$insidecube = true;
}

}

This just prints the attribute keys and values on your screen, but you get the idea.

What form am I?

October 19th, 2007

Its nice to have a single piece of Javascript that you can use on all the forms you have in an application, but it can be difficult between browsers to get your Javascript to recognise what form it has been called from.

Here’s a simple solution.

Give your form a numeric ID. That way, you can pass the ID to a function that can then do whatever it is you need to do with the form.

For example:

<FORM ID=100 NAME=registration_form ACTION=index.php METHOD=get>

<INPUT TYPE=text NAME=user_name>

<INPUT TYPE=button VALUE=submit_button onClick=’submitMe(100);’>

</FORM>

Your submitMe() function then looks like this:

function submitMe(formID) {

document.getElementById(formID).submit;

}

And if you have more than 1 form in a page, you can use different numeric IDs for each form: 100,101,102 etc

Finally, you can of course give your form a contextual name as well as an numeric ID (eg. “registration_form”) so that you can also access the form components and values through the DOM, ie:

var userName = document.registration_form.user_name.value;

Sweet.

Refreshing an image when filename is the same

September 19th, 2007

Here’s a nifty little trick that might get you out of a bind:

Say you have a web app in which the user can change the images by uploading new image files. Say then that the application requires that the image filename remain the same. See the problem?

The image may have changed but your browser is still looking at the same filename, so it will display its cached image. Of course, you could try an edit your HTML to that caching doesn’t occur, but we like caching, so here’s a better solution.

An image file, like a script file, can accept an argument when requested with HTTP. For instance, the image below is requested so:

<IMG src=/blog/wp-content/pottery-main.thumbnail.jpg?foo>

The cool thing about this is that you attach random arguments to your image calls, either in HTML or in Javascript, which will cause the browser to reload that image every time it is called. Hence, when your user loads a new image, and this image has the same file name as the old image, this method will allow the user to view the new image without having to do a manual refresh.

In Javascript, you can create a random argument using time and date functions. e.g.

my_image.src=”images/pottery.jpg?” + (new Date()).getTime();

or

image_td.innerHTML = “<IMG src=images/pottery.jpg?” + (new Date()).getTime() + “</IMG>”;