Belfry Images

Deleting items in a table with AJAX via JQuery

This is a very straight-forward tutorial on implementing a jQuery-driven ‘delete via AJAX’ feature. Say we have a plain HTML table containing a list of items and a ‘Remove’ link. I’m not going to describe the back-end, but I’m assuming something groovy like CakePHP or ASP.NET MVC. I’ve also assumed that the delete request always succeeds and never returns an error, which may not be the case. The script itself is a more than required but is my preferred method as I can extend the elements in the UI fairly easily.

<table>
    <tr><td>Chickpeas</td>      <td><a href="/items/delete/1" class="delete">Delete</a>    </td></tr>
    <tr><td>Garlic</td>         <td><a href="/items/delete/2" class="delete">Delete</a></td></tr>
    <tr><td>Olive oil</td>      <td><a href="/items/delete/3" class="delete">Delete</a></td></tr>
    <tr><td>Tahini</td>         <td><a href="/items/delete/4" class="delete">Delete</a></td></tr>
    <tr><td>Cumin</td>          <td><a href="/items/delete/5" class="delete">Delete</a></td></tr>
    <tr><td>Lemon juice</td>    <td><a href="/items/delete/6" class="delete">Delete</a></td></tr>
</table>

The delete hrefs (/items/delete/XX) link to an action or page that deletes the specified item and returns a HTTP status of 200 (OK). If the action just redirected to the current page then this table should work as it stands, which is probably a good way to check that everthing works as expected without involving AJAX features. If you just want to set up the client side without implementing any server-side code, create the following in delete_test.php and use it for the delete links:

<?php header('HTTP/1.1 200 OK'); ?>

Make sure that jQuery 1.3+ has been included in the page and add the following:

<script type="text/javascript">
$(function(){
    var ui = {
        init: function(){
            $('a.delete').live('click', ui.delete_click);
        },

        delete_click: function(){
            link = this;
            $.get(link.href, function(data, status) {
                $(link).parents('tr').remove();
            });
            return false;
        }
    };

    ui.init();
});
</script>

Very basic stuff but it works. It could be jazzed up by fading out the items first or updating a status label. If there is a significant delay between calling the delete action and getting a response the user may not think anything has happened, so perhaps the delete link should change or be disabled.

Declaring a class with inheritance and a generic type constraint in C#

I’m writing a generic class that inherits from a base class, implements an interface, and has a type constraint on the generic class. The class inheritance and interface are straightforward, as is the type constraint, but combined together it’s not obvious how to write this. Any examples of type constraints I could find don’t have inheritance or interfaces as well. So, via a bit of trail and error, here is a right way to declare such a class:

public class MyClass<T> :
    BaseClass<T>, IMyInterface
    where T : ClassOfT
{...}

Subversion on a USB stick

I use Subversion for version control at work, so I wanted to use it for a couple of websites and projects that I play with at home. I’ve been thinking about buying a cheap server or NAS that I could set up but couldn’t justify the cost and electricity just for want of version control.

As it happens, my Subversion client of choice TortoiseSVN can create and access local Subversion repositories. Probably all SVN clients can do this, and this is just a feature of the system, but when I’m used to seeing the version control purely as a client/server configuration this was a bit of a surprise. TortoiseSVN integrates nicely with Windows Explorer which makes it extremely easy to work with. If I had to load a seperate SVN client just to commit changes I would most likely put it off and/or forget about it. TortoiseSVN makes working with Subversion so easy that it is the main reason I keep giving up on Linux for my development machines.

One of the attractions of version control is that the project is portable – I can check out (make a local copy of) a website on my home PC, make changes, commit the changes to the server, then update the site on my laptop, without having to worry about copying files (and having different versions of files in the one place). That requires the Subversion server to be accessible on both machines, and if I don’t happen to have internet access for any reason that may not be possible.

Setting up a repository on a USB stick gives me most of the benefits of the typical client/server setup. The biggest downside is a lack of backups, which is something that needs to be maintained on a server anyway, and should be worked around by making backups of the repositories on the USB stick. In any case even if the repository fails I still should have multiple working copies on various machines. Not ideal but at least the files won’t be lost.

So how to do this? First install TortoiseSVN. I’m going to assume familiarity with SVN, and with TortoiseSVN in particular.

On the USB stick, make a folder to store the repositories. I called my folder svnrepos. Inside that folder, make another folder for the first repository. This is the name of the repository so call it something sexy, like bentest. Right click the folder, go to TortoiseSVN, and Create repository here. Wheels will turn, and a message should appear saying the repository was created.

Now go to your development folder, or wherever you want to check out a working copy of the project. Right-click the development folder (eg C:\Development\www) and select SVN Checkout.

The URL of repository is the path to the local repository that you created, as a file URL. Mine is file:///E:/svnrepos/bentest (note there are three slashes after the file: part). The checkout directory is where the working copy will be created. It should be automatically filled in when editing the repository URL, but can be changed. Mine is C:\Development\www\bentest. Click OK and you should have revision 0 of the repository ready to create trunk, branch and tag folders and add content.

Version control. Distributed backups of your precious work. No reliance on internet access and access to private Subversion server. Beautiful.

I haven’t experimented with this so far but I suspect there may be issues if the USB drive comes up on another driver letter. The repository url will probably need to be changed in the working copy. That should be possible via the Relocate command in TortoiseSVN’s context menu.

UPDATE: Relocate is indeed the command to use. TortoiseSVN throws up a warning about corrupting your working copy, but as long as the path entered is the new path to the same place in the repository (eg from file:///H:/svnrepos/bentest/trunk to file:///F:/svnrepos/bentest/trunk) this is the best/only method.

Tip: list all actively listening ports on a Windows machine

Finding out what ports are open on a machine is something I often need to do, and I usually stuff around for ages trying to figure out whether a particular port is open. The fastest way I’ve (just) found is by opening a console and running netstat -a, or netstat -an to show IP and port numbers rather than machine and service names.

Now that I know that the port’s definitely open, I’ve just got to figure out why the service still isn’t working…

ORDER BY items must appear in the select list if the statement contains a UNION operator

Is a very annoying error message that you get when writing above average complexity SELECT statements. I’m not sure if it only applies to queries against SQL Server, but it can be very difficult to debug if you haven’t come across it before (or come across so many things in a day that they all blur into one big problem).

For me at least it happens like this:

  1. Ben writes a big meaty query, tests it, all ok
  2. Ben writes query #2, which has the same SELECTed columns as the first query, tests also, also ok
  3. Ben sticks a UNION ALL between the two queries, thus making Das Uberquery™ and securing his employment
  4. Ben executes said query and gets cryptic error message, spends rest of day tring to debug 300 lines of SQL, goes home with migraine.

It sounds like one of the queries has an ORDER BY clause but of course I’ve taken all of the ORDER BYs out when joining them, and I’m ordering the UNION as a whole!

The issue is that one or more of the big mutha queries that are being UNION ALLed together contain a subquery that contains a ORDER BY clause. Something like this:

SELECT t1.A, t2.B
FROM t1, (SELECT TOP 1 * FROM Foo ORDER BY Bar) t2
UNION ALL
SELECT t3.A, t3.B
FROM t3

It’s that ORDER BY Bar part that gives grief. I can’t see why it’s an issue, but this is what to look out for. Replace the subquery with a view or find some other way to do it without the ORDER BY clause.

External graphics in XSL:FO not sizing correctly

I’m using Apache FOP to generate PDFs from XSL:FO, and an external graphic (think the <img> tag in HTML) kept being resized incorrectly. Another image (different size) was the correct size on the page. Turns out I was using height and width attributes in the fo:external-graphic element, when I should have been using content-height and content-width. Somehow the second image respected the height and width I wanted. Possibly this has something to do with the stored DPI of the images (since XSL:FO is a specification for printed documents), but in any case content-width and content-height is the way to go. Way to go, Ben :P

Editing past log comments in Subversion

Subversion is my source version control software of choice, but it’s not immediately obvious how to edit the log comment of a past commit (such as after adding a particularly scathing remark that may not be a wise career move). A caveat is that you need to have administrator access to the Subversion repository.

In the repository directory (wherever you created the repository) is a hooks folder (on my system this is H:\IT\svnrepos\pas\hooks). This folder contains scripts that are called by Subversion when various events occur (hooks). The files that are created in a repository’s hooks folder by default are templates of hooks designed for Linux etc. On a Windows server they need to be created as batch files (*.bat) to be executed.

What you need to do is create a hook that will run prior to changing a revision property (such as a log comment) and let Subversion know that changing the comment is permitted. By default changing the log comment is disabled (obviously, or you wouldn’t be reading this). Make a new file in the hooks folder called pre-revprop-change.bat and write the following into it:

if "%4" == "svn:log" exit 0
echo Property '%4' cannot be changed >&2
exit 1

The %4 argument contains which operation is being performed. If the operation is svn:log we indicate success, which is a return code of 0. Otherwise it prints an error and exits with a non-zero, which indicates an error (and that the operation shouldn’t be allowed). Once that is saved, you should be able to use your to Subversion client to edit the comment. Be careful with what you do, as revision properties aren’t versioned, and you won’t be able to undo your changes. You should also probably rename pre-revprop-change.bat to pre-revprop-change.bat.bak once finished.

Logical XOR operator in C#

For reference the logical XOR operator in C# is the same as the bitwise XOR operator: ^. This always gets me because usually the logical boolean operators are like && and || versus the bitwise operators (& and |). I guess it’s the same thing anyway, just a bitwise XOR operation on two booleans. Fascinating.

Could not find resources exception when modifying a form class in Visual Studio .NET 2003

I changed the name of a form class and added a new class at the top of the class file with the same name of the old form class, descending from the renamed class to avoid breaking old code. Then when I ran the app I got an exception saying that the form’s resources couldn’t be loaded. When I had a look at the resources file for the form (<project folder>\obj\Debug) a resources file was still being created for the old class name instead of the new one. Since this resources file is the one that gets linked into the DLL or exe, this meant that the new form class couldn’t find its resources. According to Microsoft KB318603 this is because other class definitions located before the form class definition will be picked up when naming the resources file. So if this happens, move the other class to after the form class (ie the MyForm.cs file should contain first the MyForm class then any other classes).

Of course the best thing would be to move the other classes into another file but that sounds like work :-)