ColdFusion, WordPress, Flash & other web things


May 02

Faviconed!

Today, I finally got round to creating a favicon for 1 Pixel Out. I googled “favicon” and the second result pointed me to this nifty online tool. The whole process took under 2 minutes. I love it when things just work!

Apr 28

Another Mach-II site

Back in January this year, we launched version 3 of the Beaverbrooks website. The new site is another successful implementation of the Mach-II framework. We followed OO concepts when designing the back-end and stuck to web standards for the front-end. This enabled us to achieve huge improvements in user experience, SEO and performance. We also had a go at AJAX for the advanced search functionality.

Beaverbrooks screenshot

Apr 28

SQL Server & IDENTITY

I’ve been using the @@IDENTITY keyword for years now to retrieve the ID of a newly created record in SQL Server but we discovered the other day that its behaviour is not always as straight forward as we thought.

The problem

If you run the statement below, in most cases you get the ID of the newly inserted row.

INSERT INTO table_name( ... )
VALUES( ... )

SELECT @@IDENTITY AS newID

The problem arises when your insert statement fires a trigger that performs more inserts to a table with an IDENTITY column. This is the behaviour of the @@IDENTITY keyword according to the Microsoft docs:

If the statement fires one or more triggers that perform inserts that generate identity values, calling @@IDENTITY immediately after the statement returns the last identity value generated by the triggers.

This means that in the situation described above, you wouldn’t get the ID of the new record but the ID of the last record inserted by the trigger.

The solution

Note: Patrick McElhaney commented that this is not the best solution. See the update below.

Use IDENT_CURRENT() instead:

INSERT INTO table_name( ... )
VALUES( ... )

SELECT IDENT_CURRENT('table_name') AS newID

Credit goes to Stuart Miller for pointing this one out as well as finding the solution.

Update

According to Patrick McElhaney’s comment below, SCOPE_IDENTITY() is a better solution. I checked the docs and he’s absolutely right.

Apr 19

Cross-window Javascript communication

This solution is now officially obsolete. A much nicer and simpler solution is available here.

This is a solution to a problem that I’ve come accross several times before but never really had a go at solving. This time, I just had to get it right or we would have had to use a nasty system of hidden frames. Yuk!

The problem

Right, so you have this page you want to open in a popup and you want to be able to call JS functions defined in the popup from the main window. Nothing revolutionary here. When you create a popup with the window.open method, you can specify a name for the new window object and use it to reference the popup from the main window.

// Create a new popup window
var popupWin = window.open( url, "popupWin" );

// To call functions defined in the popup:
popupWin.doSomething();

Now, when the user navigates to another page in the main window, the reference to the popup window object is lost and you cannot communicate with the popup anymore. This can be problematic if you need the popup to stay open. You can re-create the popup with the open method but this always reloads the page and when your popup is a music player, you get a very rubbish user experience indeed.

So, using the music player as an example, what we would need is a way to maintain a persistent link between the player and its opener so that the main window can call methods to control the player.

The solution

What we need to do is get the popup to broadcast its existence to the main window. Fortunately, the popup is not as forgetful as our main window and still has a reference to its creator: self.opener. We can get the popup to remind the opener at regular intervals with this code:

function notifyOpener() {
	if(self.opener || !self.opener.popupWin) self.opener.popupWin = self;
}

setInterval( notifyOpener, 200 );

This ensures that any page opened in the main window gets notified. The interval time should be short enough for the window to be notified before the user gets a chance to click any links. Now, the main window can call functions of the popup:

// Initialise popup pointer
var popupWin = null;

function doSomething() {
	if( popupWin && !popupWin.closed ) {
		popupWin.doSomething();
	}
}

Initialising the popupWin variable ensures that the script doesn’t break if the popup is closed. Before making the call to the popup, we can also check the closed property of the popup window. When true, this property indicates that the popup window was closed by the user (hardly rocket science, heh?).

So, if we combine the code above with the open routine we get this for the main window:

// Initialise popup pointer
var popupWin = null;

function openPopup() {
	var url = "the_url_to_your_popup.htm"
	if( !popupWin || popupWin.closed ) {
		popupWin = window.open( url, "popupWin" );
	} else popupWin.focus();
}

function doSomething() {
	if( popupWin && !popupWin.closed ) {
		// The popup is open so call it
		popupWin.doSomething();
	} else {
		// The popup is closed so open it
		openPopup();
	}
}

And in the popup:

function notifyOpener() {
	if(self.opener || !self.opener.popupWin) self.opener.popupWin = self;
}

setInterval( notifyOpener, 200 );

self.focus();

function doSomething() {
	alert("I'm doing something");
}

That’s it. Well, actually no, there is one more thing: the popup script will start throwing errors if the user closes the main window or navigates to a page on a different domain. To prevent any unnecessary errors, we add the following lines to the popup script:

function handleError() { return true; }
window.onerror = handleError;

Download an example

Oct 22

appConstants plugin: New version improved

I have fixed and improved the appConstants plugin. Here are a list of fixes/improvements:

  1. The constantsFile parameter now defaults to "/config/constants.xml" if it isn’t defined in mach-ii.xml
  2. Lists of server names are now comma-delimited.
  3. Error handling has been improved.
  4. The code is now properly commented.