dynamically loading external scripts in Safari

I was just given a loan of a MacOSX box in order to debug some parts of our CMS.

After a bit of digging, I found that the biggest bug was that you cannot dynamically add script tags to the document in Safari and expect them to run. This includes external scripts.

For example, here is my usual loadExternalScript() function:

function loadExternalScript(url){
	for(i in loadedScripts)if(loadedScripts[i]==url)return 0;
	loadedScripts.push(url);
	var el=newEl('script');
	el.type="text/javascript";
	if(sajax_is_loaded&&/\\.php/.test(url))url+=(/\\?/.test(url)?'&':'?')+'sajax_is_loaded';
	el.src=url;
	getEls('head')[0].appendChild(el);
	return 1;
}

This works in everything except Safari.

One fairly obvious solution to this is to grab the contents of the requested file with XMLHttpRequest and eval() it.

Sample code to demonstrate this:

function loadExternalScript(url){
	for(i in loadedScripts)if(loadedScripts[i]==url)return 0;
	loadedScripts.push(url);
	if(sajax_is_loaded&&/\\.php/.test(url))url+=(/\\?/.test(url)?'&':'?')+'sajax_is_loaded';
	var x=new XMLHttpRequest();
	x.open('GET',url,true);
	x.onreadystatechange=function(){
		if(x.readyState!=4)return;
		eval(x.responseText);
	}
	x.send(null);
	return 1;
}

Anyone spot the subtle bug above?

The bug is that the resultant code will be run only within the scope of the anonymous function created by the XMLHttpRequest callback.

A lengthy solution to this would be to parse the code and add “window.” in front of all functions and variables, but that’s ugly.

A more pretty solution is to run the resulting code with setTimeout() instead, which allows it to be written directly to the global scope.

function loadExternalScript(url){
	for(i in loadedScripts)if(loadedScripts[i]==url)return 0;
	loadedScripts.push(url);
	if(sajax_is_loaded&&/\\.php/.test(url))url+=(/\\?/.test(url)?'&':'?')+'sajax_is_loaded';
	var x=new XMLHttpRequest();
	x.open('GET',url,true);
	x.onreadystatechange=function(){
		if(x.readyState!=4)return;
		var t=x.responseText.replace(/\\\\/g,'\\\\\\\\').replace(/"/g,'\\\\"').replace(/\\n/g,"\\\\n");
		setTimeout('eval("'+t+'");',0);
	}
	x.send(null);
	return 1;
}

Of course, the original DOM insertion is the preferred method, but the above function should be used for Safari.

resizing and rotating in FCKeditor

On the heels of yesterday’s work, I’ve added some further features to the file manager.

Some of our clients upload images from their cameras, only to realise they took the images with the camera tilted 90 degrees to either side. So, we have a new Rotate function.

Also, a resize function has been added, for reducing the size of images that you accidentally uploaded too large.

I rewrote the code to use GD instead of Pear, as the Pear library was giving some people trouble (and the Rotate function in Image_Transform produces cack results).

Also, I’ve added some icons.

the example – click the Image icon, then click “Browse Server”.

image previews for the FCKeditor file manager

This week, I’ve been tackling a huge number of work, upgrading our in-house CMS to bring it up to a “Product” status. A lot of the work is internal, and will probably not be open-sourced for a while, which is a pity. This work included a lot of AJAX work – changing all our menu systems to load on the fly, adapting our Pages menu so we can re-order pages by simply dragging them around. A lot of work.

The first piece of OS to come out of this is a previewer for FCKeditor. In the file manager, if you don’t know what an image looks like, you now just have to hover over the filename, and half a second later, a small info-window will appear with a generated thumbnail.

The example is here. Click the image icon, then the browse server button. when you hover over an image link for .5 seconds, a small image preview box pops up with some info.

You can download the changed files here.

This is really just a base for tomorrow, when I write an image manipulator so you can resize, rotate, etc, online, instead of needing a graphics editor.

burning down the house

Got up this morning, fed the guinea pig, rabbit and dog. Bronwyn fed the cats. Did the dishes, got the kid dressed, and went for the front door.

Bronwyn reminded me that I hadn’t lit the fire yet.

So, I raked the remainging ashes in to the tray below the grate, put a small piece of firelighter on, lit it, added three sticks and a piece of scrap plank, then covered with coal, and headed for the front door.

Bronwyn asked me to clear out the ashes.

*sigh* – so, I opened the fireguard, and removed the tray. The tray was okay to the touch, so I carried it with bare hands out the back, and dumped it on the compost heap. Then I put the tray back, and headed for the front door.

Twenty minutes later, Bronwyn called me in a panic and said “The shed’s on fire!”. I replied, relaxed, “So put it out!”. She demanded that I get back, and said that it was my responsibility.

I turned around, and started the twenty minute walk back home, cursing what was probably just a few flames.

I got to the house just after two fire brigade trucks turned up. Both of the sheds had burned to the ground.

I was a bit dismayed, to say the least. Bronwyn was in shock. After the brigade had reduced the flames to barely a smoulder, I thanked them, sent an email to my landlord (it honestly didn’t occur to me to pick up the phone), and took Bronwyn to the doctor.

Later, while digging through the rubble, trying to bring some sense of order to the chaos, I found the bodies of the guinea pig and the rabbit. I removed them for later burial.

The dog had run straight into the house at first chance, but all the cats had run off. Beethoven (our white cat) turned up when the fire brigade were almost done, but the others were still missing hours later.

It’s now almost half five, and one of the missing cats just turned up, sans fur and whiskers, and limping on burned pads. I had to brush her hair for five-ten minutes just to get rid of most of the crusty burned hair.

I think there are two ways in which she could have gotten damaged. Either she was asleep in the shed and didn’t feel the heat until too late, or she had panicked and run for “safety”, under the shed.

This was my fault. I have accidentally killed at least two of Bronwyn’s pets, as well as seriously burning one other, and destroying property of the landlord. It’s embarassing to think how stupid the cause of this whole thing was – basically, an ember which I had not noticed, must have blown onto the first shed, setting off the bone-dry wood.

I think this will cost me a bit – I need to replace two sheds, a petrol lawnmower, a kerosene tank (which luckily wasn’t full at the time!), and some windows, which cracked in the heat. That was the landlord’s stuff.

Personally, I lost a load of magazines, including a fifteen year archive of Dragon magazine (including the special edition #200 with the hologram on the front cover). I also lost the Linux Format edition which mentioned the ILUG. Also, I lost all of my tools, some of which were quite expensive. Damn…

Let this be a lesson to you all – dispose of your ashes carefully!

moved house

Well, I type this article with painful fingers. Yesterday, at 7am, I started the hard work of finishing off all the packing in the house. We finally got just about everything out of the house by 7pm. There were a few things left behind, though, as we could only get three runs out of my neighbour before he had to head off to a wake (his brother died that day). Thanks, Sean – I owe you a few pints.

Today, I decided to get the network up and running. Scrounged around and couldn’t find the power supply for my ADSL router, so I was a bit screwed. Then, it occured to me that eircom has been doing a lot of marketing for their wireless broadband access, so it was very likely that someone around me had it set up.

So, I booted up my lappie, ran iwlist scan, found an unprotected router, and changed my config to use it. I feel fairly guilty “stealing” bandwidth like that, although a ping -b 192.168.1.0 didn’t show any other computers on the network, so I guess the owner of the router is off working or something.

Anyway… right now, I’m discussing an empty naggin of vodka which Bronwyn just found in my laptop case – nyeh, what can I say? Sometimes I need a drink. It relaxes me.

So anyway – new house, with a good garden. The rent is somewhat higher, but at least there is working heating here (my last house was heated by judicial application of coal and space heaters – expensive).

I’m half an hour closer to work, which means an hour less walking, and an hour more sleeping 🙂

Right – off to finish unpacking, set up my own ADSL network, find the owner of this one, apologise, and help secure it.

depression lifting?

I’m feeling cautiously optimistic that I am getting a handle on my depression.

Last week, there was a massive crisis in the office, when our server was suddenly flooded with 1.6 million junk emails. This slowed down our email throughput to basically a standstill, for two days, causing huge headaches in the company, and lots of anger from our poor clients, who had to suffer with us.

Some of the symptoms of my depression is a feeling of responsibility for everything, and massive paranoia when things go wrong. Last week was a real test for this, as I was put under a lot of strain while we tried to get this sorted.

Thankfully, we finally got through it all, with the help of our good buddy Brian of Synergy Int, but it left the whole company in a state of strain.

The reason I say I am optimistic that I’m getting a handle on my depression is that, even though I felt at many times during the week that it was time that I took up my life-long dream of becoming a farmer, I recognised the hopeless despair as simply a response to the stress that I was under. Also, when I felt extremely paranoid that fingers were being pointed at me, I recognised that this was also stress talking.

I am very proud that I managed to recognise these symptoms for what they were, and to continue working despite them.

In total, I lost about two days work last week, but was able to start up again very quickly after the crisis was past.