Settled in Leeds

After my little blogging hiatus, there’s too much news to catch up on. But the biggest is that we all moved to Leeds, England and are settling into a new (to us) house in Meanwood (if you happen to know the area).

The kids are in school, Kelley is well, I’m still with Sitepen doing much of the same old.

airport cmdline tool

In the notes-to-self category, turns out apple ships a tool called

1
airport
in leopard.
Following this article’s suggestion, I linked it like so:

cd /usr/sbin
sudo sudo ln -s /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport
1
airport -h
shows me that I can do
1
airport -I
to see my current status

BarCampLeeds 08

What a day. Who knew that Leeds was this nascent tech hub. I had a hunch of course (and followed it by moving back here), but there's enery and talent oozing out the edges here, and its surely only a matter of time before it reaches critical mass and becomes a real tech ecosystem.

What'd I learn? I started the day with an into to geocaching. Which I'd of course heard of, but somehow had lumped it in my mind with orienteering and other things which I'm not likely to ever do regularly if at all. But I'm sold - what fun, and the kids will love it - a modern day treasure hunt.

While I held onto a vain hope that I might get my demo done in time for my talk in the afternoon, I stuck around in the main hall half-listening, half working. There was the beginnings of an interesting discussion around usability and (graphic) design, but the crowd didnt really bite. I also was treated to a crash course in viral something.. marketing? self-promotion? mostly how to have a laugh on the web it seemed, and share it with as many people as possible. That I didnt quite see the point I'm sure says more about me than the speaker - who did a great job.

I missed what looked like an interesting sessison on the success of wikis, but caught a great session discussing SAAS (Software as a Service). That looks like a big slice of pie for the taking, if you can get it right.

I was introduced to the lazy web, and a clearing house kind of offering (vagueware.com) by the presenter. I was trying to remember the other site I used a while back - it was a more general (i.e. non-tech) ideas/inventions site, but its gone.

My talk was on building desktop apps with Dojo and AIR. There wasnt really enough time to dig in so I was left skimming over materials and gesturing vaguely at examples I pulled up. "Dojo" on AIR was a little arbitrary - Dojo /is/ a good fit, and does give you a real leg up when developing an html/js based AIR app. But not to the exclusion of all other libraries. Its good for the same reason Dojo is good on the web, and that there's a couple specific affordances for AIR (e.g. dojox.storage.AirFileStorageProvider) is nice, but not in and off itself a reason to switch. The compelling case for AIR is that you dont have to re-learn anything to start developing desktop apps, and from that point of view if you're already comfortable with javascript library, you should probably stick with it. Anyhow, I hope folks took something away from it.

Finally I caught 2 great sessions on a a more business slant. The first was tips on dealing with large organizations as a small vendor/contractor, and negotiating the beaurocratic hazards organizations of a size seem to favor. It is so easy to get burnt as these cultures crash, and it was great food for thought. And right on its heels was a discussion on preparing proposals, RFP responses. Stand-out points for me where - ask there's a weighting and scoring sheet for the RFP - people will often share i freely, and that will tell you what you need to know about where to spend your time in the proposal.

So I'm left with a warm fuzzy feeling about Leeds. People had travelled in - several from Manchester and one of two from London, and although actual attendance didnt quite match registration numbers, it was a respectable crowd.

I'm back for more tommorow...

doh.robot

New automated UI testing goodies just landed in dojo, and I’m moved to blog about them. Getting test coverage of the messy stuff - user interactions, mouse-movement, clicks, drags - has always been an achiles heel of testing web UIs. Any kind of automated testing is better than none (provided you are testing the right things and keeping a good testing/developing balance), but for UI testing so much can go wrong when your page/app loads up in a real browser and has a real user start poking at it you’re left with a giant hole to fill with tedious, manual testing. doh.robot (and its dojo, dijit descendants) offer the ability to write tests that include real keyboard and mouse events, that can mimic actual use of interactive widgets.

Let’s not kid ourselves - manual testing isnt going away anytime soon - and nor should it - but having a suite of tests that can catch regressions, can run though some basic load, click, move, enter input, clear input kind of interactions across key components of your app is a huge plus. It allows you some confidence to make otherwise punishing changes - that would normally require real humans to step though a test script in all your target browsers to confirm nothing got broken.

Some people may love the precarious feeling of developing without unit tests, but personally it gives me the willies. It can be paralyzing as the codebase grows and each addition and change multiplies the potential for error. When you do stop and test how much will you have to tear back when an error pops up? You dont see construction workers free-climbing as a building goes up. You build a stable scaffolding, and anchor that against each successive floor that you add. So with testing. Unit tests let you look forwards at what remains to be done, rather than worrying constantly about what you’ve already built. And with accurate, non-synthetic automated UI interaction testing that doh.robot offers, that can only be a good thing for the growth of the web as an application platform.

RoadRunner DNS / OpenDNS

Like a few other people, I couldnt help but notice that RoadRunner monkeyed with their service recently with the result that my day to day internet activity has slowed to a crawl. You know something’s wrong when you go to search on google and get a rr.com page saying host google.com not found (and offering all sorts of sponsored links and searches).

Today I reached my bullshit threshold and went looking for a solution. OpenDNS was exactly as simple and successful as promised. I just plugged in the new DNS IPs into my router config and like magic the internet was fast again. They have walkthroughs for configuring lots of OS and router variations and it was utterly painless.

I tried to contact RR support, but they have a voice-driven menu system now which pushed me over the edge and spattered the remnants of any patience I had left as spittle on my screen.

dijit.byNode and firebug fun

Here’s a little tip if you’re working with dojo widgets. In firebug you can select an element in the HTML view. Back in the firebug console, your selected node is available as

1
$1
So,
1
$1.tagName
shows you the element name, etc.

If you’ve got dojo on your page you can use anything dojo has provided in the console, and if you’re using dijit, you also have that stuff too. So, in the HTML view click on the element that represents your widget. It’ll have a

1
widgetId
attribute. Now, in the console, try:

dijit.byNode($1)

this is a pattern I repeat so often I actually printed and read the firebug manual to get around there with keyboard shortcuts. I recommend you do the same. Now you can quickly and intuitively explore the state of your widget:

dijit.byNode($1)._started
console.dir(dijit.byNode($1).getChildren())
dojo.getObject(dijit.byNode($1).declaredClass).prototype

And/or, you can go back and forth between console/HTML:

dojo.query("[region]", $1).filter(function(n) { return dijit.byNode(n).declaredClass.indexOf("ContentPane") > -1; });

.. gets you call the ContentPane domNodes that are descendants of your selected BorderContainer node. Click on one, and:

dijit.byNode($1).setContent("boo!"); 

its your page, have fun!

Restoring SVN repositories from disk - a story

I recently had to move off a company laptop I'd been using for a while, and (thanks to the flu) didnt have much time to do it. So, I backed up those directories I knew had any personal projects and data in and crossed-fingers I'd be able to get what I needed out of there when the time came.

One of the directories I got housed my subversion respositories (I'd been using the flat-file db option). When I started setting back up on a new laptop (and new-to-me platform in OSX) I was faced with a little problem: How to let the new install of subversion know about the old data.

A little reading around in the SVN book soon told me that what you are /supposed/ to do is run a svnadmin dump command, then create the new repos and

svnadmin load /path/to/reponame < /path/to/my/repo1.dump

Nice to know - for next time. After some searching and asking around, I finally got a pointer (from the evolt list)

svnserve --daemon --root "C:\Path\to\Subversion Repository"

That wouldnt work as-is, but it pointed me in the right direction. Subversion of course has a notion of a root directory where it expects to find everything. I was running subversion via apache though. I’d gone through the basic set up to configure it, and it was busily serving up an entirely fresh and empty repo. To cut a long story short, I finally ended up with this:

LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so
<Location /svn>
DAV svn
SVNParentPath /my/laptop/backup/SVN
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /etc/apache2/svn-auth-file
Require valid-user
</Location>

SVNParentPath was the magical incantation I needed. After that I was left only permissions to fix. That's apparently where most people stumble. And its not my strong point. I can chmod 755 myscript.cgi like the rest of them, but dont ask me to explain what it (and all its possible variations) does exactly. I dug briefly into a nice tutorial on chmod, to grok the details once and for all, but found this walkthrough, and this one which instead supplied all the information I needed.

On OSX/Leopard I needed to use the www user, otherwise that was basically it.

1
sudo acpachectl restart
picks up the new apache config.
1
http://localhost/svn/my-repo
shows a directory listing of the repo, and:

svn co --username me http://localhost/svn/clients-repo \
/path/to/clients

...finally got me pay dirt - the full directory tree, with version history

A Parable

A man was asked to do some renovation on a house. He worked steadily at it for several weeks and finally called his client to come take a look around.

He said, "I was able to keep a lot of the original flooring. I got a good match for the wood and finish where I had to patch and extend the floor. I'm nearly done. I just need to pick up my offcuts and sweep up."

"Oh good" said the client. "So I'll arrange to start moving my family back in tomorrow. Sound OK?"

"Sure".

The main picked up some of the debris, and noticed an ugly dark spot under a piece of paper. As he scraped at it, it revealed itself to be the end of a protruding steel rod. By scraping away around it, the man was able to get pliers on it and wiggle it. As he did, something clicked below the floor and now several of the boards creaked as he walked on them. Creaking was one of the things he'd been called in to fix, so he pried up those board to take a look. There he saw that the steel rod was actually a pin that had been rigged to hold together some structural beams. It had been driven down to sit flush with the floor, but was now rusted away and very fragile. As he stared in disbelief, the beams began to drift apart, the house sagged and collapsed in a pile of rubble.

Moral: A job is done or not done, never nearly done.

dijit.Declaration and its mixins

I love the dijit.Declaration widget introduced into the dojo toolkit around version 0.9+. It lets you declare a new widget class inline in your html - which can be very useful, especially when you want the widget templateString to be dynamic output from the server.

Just a little tip - I had been getting a

1
m._findMixin is not a function
error when instantiating widgets from my Declaration. If you’ve ever tried to step through widget instantiation you have an idea how sigh-worthy this particular error was. After a little debugging and poking through Declaration.js I noticed that the mixins property was typed as an array. When using dojo.declare directly, the parent class is the 2nd argument. And if you need mixins (like dijit._Templated) you make that 2nd argument an array and list them out in order as its content. So, it can be either a string or an array and dojo.declare will do the right thing. It turns out that with dijit.Declaration, the mixins property must be an array, even if you only have one value to put in there:

<div
dojoType="dijit.Declaration"
widgetClass="myns.widget.WidgetClassName"
mixins="[dijit._Widget]"
...
>...</div<

Which put me back in action, and I hope steers you around this particular hole in the road.

Regexp to match only html filenames and directory names

I’ve been working on a script to create filtered directory tree listings. It can be configured with both include conditions, and exclude conditions. If something passes the include filters, it then checks to see if its explicitly excluded. For example, I want to exclude cgi-bin, but include all other directories and files.

So its useful to have a good catch-all pattern for including only the good stuff. I needed only html files this time. So after some head scratching I came up with:

1
/(^.*\.htm(l?)$)|(^[^\.]+$)/

I dont like using .*, so to improve it maybe I could use a character range instead, or a negated range like [^.]+, but this works beautifully.