Remove the blockages that keep IE6 around

With all the MS bashing and kill-IE6 sentiments I was wondering what are the actual impediments to upgrading? For the most part it is legacy applications in organizations that have no upgrade path. Stuff like timesheet apps, expense reporting and so on that was written eons ago that is critical to company operations, but has little or negative ROI to replace or fix.

Sure, there are cases where IE6 is in use simply because it was the browser that shipped with XP. Lets put aside the cost and difficulty of operating system upgrades, and focus on the part of the problem we can conceivably do something about. What prevents deployment of IE8 to these desktops? What compatibility problem with which applications are complicating this problem? Is there anything we can do to smooth the path to browser upgrades?

What’s needed is an audit. A big ugly audit of all the gnarly sticking points that IT organizations are faced with which cause the issue to be punted everytime it comes up. Odds are good that there are reasonable solutions to at least some of these problems if we only knew what they were. Perhaps its an upgrade or alternative with a tried and true migration path. Or just a simple code shim that can provide backwards-compatibility. I’m not discounting the ripple effect even a one-line code change can have, the risk and cost of regression, but we can offset that by connecting people in the same boat, by sharing gotchas and tried and tested solutions.

Imagine a clearing house kind of site that lists the offending applications & implementations and details the IE6 dependencies. The audit is crowd-sourced, built by the motivated individuals in every organization that deal with the problem every day but are powerless to fix it. Each problem once itemized, prioritized by the number of IE6 installs depending on it and paired with suggestions, known alternatives, actual patches and even bids or volunteers to fix it. It would be a pragmatic approach to unsticking the development of the web, as well as “naming-and-shaming” the sticking points. In the web development community we all share the burden of the continued existence of this browser, yet we are powerless to fix it. With information comes power.

Community pressure on browser vendors to support standards in their future browsers has started to yield results. But for the legacy browsers - to-date we’ve had a strategy of sitting and waiting. IE6 usage is dropping slowly but surely and for some the end is in sight - it is approaching the threshold where they can officially drop support. For many though this is still years away. What can we do to help?

AIR command line arguments

I’ve been working on the next release of the Dojo Toolbox - which is an Adobe AIR app, using the Dojo Toolkit. I’m taking a TDD kind of approach to get on a better footing for evolving this thing, and needed a quick way to run a particular set of unit tests.

I wanted to be able to do something like this:

$ adl runTests.xml testModule=toolbox.tests.SomeThing

Getting command line arguments in AIR is via the invoke event, it looks something like this:

air.NativeApplication.nativeApplication.addEventListener(
air.InvokeEvent.INVOKE, function(evt){
window.scriptArgs = getScriptArgs(evt);
}
)

…But when I tried it, I just got a console error:

initial content not found

It turns out that command line arguments to an AIR application are expected to be filenames - like if you dropped a file onto the app’s icon. To pass through parameters and switches you first need

1
--
, like so:

$ adl runTests.xml -- testModule=toolbox.tests.all

The event your handler is passed has an arguments array property, and from there its straightforward to process what you’ve got to do the right thing. I’ll get more into how I’m doing the unit tests in another post, but as this took a little digging I thought I’d share.

A rhino prompt

I’m tinkering with another ill-conceived friday night project that may or may not see the light of day. But in the meantime, I just put together this little snippet that illustrates a lot of what’s to like about rhino:

var getInput = function() {
var br = new java.io.BufferedReader(
new java.io.InputStreamReader(java.lang.System["in"])
);
return br.readLine();
};

var greetUser = function() {
// use out.print for the prompt
// instead of rhino's print - which is really println
java.lang.System.out.print("Your name? ");
var name = getInput();
print("Hello " + name);
};

greetUser();
quit();

Arguably (and laughably if that’s your attitude) there’s exactly nothing special here - a whole lot of lines of code to do what in a browser (not to mention any other self-respecting scripting language) is done with one:

alert("Hello: " + prompt("Your name? ", ""))

But the point is that Rhino doesn’t provide a prompt function, and it doesnt matter because you can easily make one. I’ll take flexibility and potential like this over cute predefined functions every time.

Setting up Rhino

I’ve been using the Rhino engine more and more to run command-line scripts, fiddle and try things out. But my setup has taken shape slowly, and it wasn’t much fun to be honest when I first got started.


I’m on a mac (Leopard), and here’s how I’ve got it now:

  1. Download the Rhino .jar file, you’ll find it inside the latest (binary) release.

  2. Drop it in your {user}/Library/java/Extensions folder (create it if it doesnt already exist). That way its automatically added to your classpath whenever you run java, so no need for -jar cmdline params to pull it in (and the classpath insanity that brings).
  3. I made a shell script to invoke rhino and aliased that, but actually you could simply alias the one-liner it contains:

    1
    java jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main "$@"



    To make an alias, in my ~/.profile I’ve got the following:


    1
    alias rhino='~/utils/runjs.sh'

  4. Now, in your terminal, you just type ‘
    1
    rhino
    ‘ and it puts you into an interactive shell where you can load files, write js statements and see the results instantly.


  5. But, Rhino’s shell is frankly, a crappy user experience. Its got no history, no cursor movement at all. You can just type and hit enter. If you screw something up you have to type it all over again. And the whole beauty of writing javascript like this is that you can load a .js library repeatedly as you work on it and try calling its functions. But its a PITA out of the box.



    Look again at that java cmd-line I’m using to run rhino and you’ll see its using jline. This enlightening post on Taming the Rhino finally brought happiness to my rhino shell by introducing me to jline



    You download jline and again, drop the .jar file into your Library/java/Extensions folder. Now the interactive shell is much more shell-like. You have a history on the up arrow, you can back up and move around the current line to edit, and do more scripting and less typing in general.



    To run a particular .js file and exit, you do ‘

    1
    rhino yourfile.js
    ‘. Further cmd-line parameters populate the
    1
    arguments
    object in your script, so
    1
    rhino script.js filename1 filename2 myoption=true
    would populate
    1
    arguments
    like this:


    [
    filename1,
    filename2,
    myoption=true
    ]


    FWIW I use a pattern like this to wrap my script body:


    (function(scriptArgs) {
    function main() {
    // process scriptArgs,
    // e.g. split on = to get name/value pairs
    // and populate an options object
    }
    main();
    })(Array.prototype.slice.apply(arguments));


    Back in the shell, you can load, try, load again, try again:


    $ jeltz:trunk sfoster$ rhino
    Rhino 1.7 release 1 2008 03 06
    js> load(“lib/docblock.js”);
    js: “lib/docblock.js”, line 7: uncaught JavaScript runtime exception: ReferenceError:\

    “lang” is not defined.
    at lib/docblock.js:7
    at lib/docblock.js:5
    at <stdin>:2

    js> load(“lib/langUtils.js”);
    js: “<stdin>”, line 3: Couldn’t open file “lib/langUtils.js”.
    js> load(“lib/langUtil.js”);
    js> load(“lib/docblock.js”);
    js> var p = docblock.getParser();
    js> p.parse(“/* @author sfoster /“);
    TAG:author:sfoster
    js> quit();
    jeltz:trunk sfoster$


    Try it, I think you’ll like it.

    Barcamp Liverpool

    I took in the first day of BarCamp Liverpool. It was Liverpool’s first, and my second, and went off well I thought. I learnt some things, saw some new and familiar stuff and felt it was time extremely well spent. It was great to see people coming out of the woodwork and talking about what they are doing.

    There was much talk of iPhone apps, and the economic opportunities (or not) that presents for the developer, lots of startup hobnobbing and general feel-good about being in the industry. Something was missing though, and I’ve been trying to put my finger on it. In the evening there was a partly-for-fun “pitching” event in which people presented startup ideas to a panel. I think it was significant that the idea that got everyone most excited about was a hardware project - to monitor power consumption of a device at the socket and chart and aggregate data to build consumer awareness of energy usage and perhaps drive usage and purchase decisions. The Web2.0 narcissism is wearing thin I think - the web is maturing as a platform for real work and useful stuff to take place, but it needs more of this grounding in the practical, tangible and meaningful. I hope future barcamps and other events are able to draw more from the “fringes” of the web community, where it less about web technology and culture as a topic in itself, and more about the internet as a component in projects that touch peoples lives in tangible and practical ways.

    My talk (in direct contradiction to all that) was on maturing client-side development techniques and practices, to introduce more rigour to the discipline. It was a response to the need for repeatable, reliable client-side output that is highlighted by ever more complex demands in web-based UIs. The front-end is a part of a product development process that needs just as much attention as server-side development, and as Steve Souders has being pointing out, in lot of cases, when you actual break down the experience from the user’s point of view - warrants more.

    I introduced a few techniques and tools for testing and profiling client-side tech, but the topic was too big to fit in the 45 minute slot and probably left more questions than answers. I need to either break it out into complementary pieces or take a different approach to a high-level overview. My slides are posted to geekup though, and if you were there or have thoughts, please comment.

    String repetition in javascript

    This is about a little snippet I came up with the other month, while a colleague and I were talking about string building and its performance in javascript. I was looking for a neat way to front-pad or indent a string, and missing the

    1
    x
    operator in perl.

    It turns out there is a succinct, one-line idiom:

    var indent = new Array(10).join(" ")

    That gets you a 9-spaces-long string. Using the formal Array constructor (rather than the array literal

    1
    [ ]
    ) you can specify what the initial size or length of the array should be, and we leverage that when joining our otherwise empty array. The string we provide to
    1
    join
    with ends up being repeated n-1 times. Cute huh. It also turns out to be pretty fast. Not quite as fast as the equivalent loop using += to build the string, but much faster in many cases than pushing each character into an array and joining to produce the string.

    Of course if you already know something about what string you are looking to create here, its definately fastest to declare a long string like

    var spacePadding = “          “;
    and then
    1
    var indent = spacePadding.substring(indentLevel)
    , and cross your fingers that spacePadding will always be long enough. That’s going to be a pain, though, when you need to output something like
    »»»»level 1
    »»»»»»level 2

    Or, worse (or better) if you need to repeat something like

    1
    &lt;span class="indent"&gt;
    . Its trivial with our
    1
    join
    trick:

    var indent = new Array(indentLevel+1).join('<span class="indent">');

    You can see the test file I used to time various options. new Array(n).join performs worst when n is a small number - like 20 - and its a short or single character string you are repeating. Frankly, for the use case I’ve outlined - front-padding something - that’s also a likely range. As you scale up, and start repeating 100s or 1000s of times, and also increase the length of the string you are repeating, then this margin disappears.

    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…