2007-11-13

Embrace your constraints

As a web developer, it is your job to love and leverage the straight-jacket that is your confinement. This may sound wrong to you, at first. Working with the grain, and not against it, likely sounds better, but it does not as closely capture the essence of it, as being a successful web developer really is about understanding and loving your imprisonment. This imprisonment should not be fought, it should be understood, and your innovation space should not extend beyond the solution space it offers, or you will produce crap. The very finest, expensive, useless crap.

To excel is to understand and embrace the solution space offered by the properties and features offered by your platform, never, ever, fighting to replace them with crutches in your own image. Crafting new and improved basic UI widgets from scratch, for instance, is a job for Apple, Microsoft, Opera Software, GNOME or other providers of low level widget architectures operating on a C, C++ or ObjectiveC level -- people that create the build-once, use-everywhere interface components which users learn-once, use-daily. Don't knock this, even if your scroll bar would be off white, looking oh, so stylish!

It would be fundamentally broken in myriads of subtle ways, affecting your entire user base, to varying degrees, starting at "something unfamiliar and new to have to learn" for your novice users, to "not implementing 75% of the feature set I use", for your expert users.

The expert browser user is steadily gaining in numbers with today's generation of kids who have been around the UI elements of the giants since birth. It will annoy them that they can't use the scroll wheel. Or click the scrolled pane, arrow around, page up and down, home, end, via the keyboard. Or that their browser's Find feature might not scroll the found content into view. Or that it does not obey how they have configured their environment to behave, with respect to smooth scrolling, scroll wheel yield, modifiers held down at the same time to change yield, that their keyboard and locale's settings for which keys to press at the same time to mean "Page Up" should not trigger some other surprising effect that your American layout would not.

"Hey; that's unfair!", you might say; "How should I be able to know and circumvent that?"

Correct -- you shouldn't. It is not your problem, and thus you should not touch it either. All of these are things you can not and should not try to mimic in a browser environment. Keyboard handling, for one thing, is still fundamentally flawed and unstandardized in the browser UI model, as reinventing user interface workings has not been the primary focus of the web, so the provisions for doing so are sketchy and not unlikely prone to be leaky abstractions. Your user base are using a myriad different environments, rarely if ever sharing a common computer, operating system, browser, locale or keyboard layout, if what you think of as a keyboard even happens to be their input device of choice.

The solution space you operate in is on a level above all that. You can't, and should not, care about such details. You should blend in with how their web works, not set out to change it, on this level. You may have to tell your superiors (or users!) that what they want, if they ask for this, should not be addressed by your software, which lives in the wrong end of the spectrum. That you could theoretically do something at best almost as good as what they already have, after draining endless amounts of resources on a wild goose chase.

You address higher level problems, and there is a mark on the abstraction chain below which you should never tread. These are the laws of innovating the evolving browser straight-jacket, from within. Breaking them is negative productivity, degrading your user experience. Work within, and your application is timeless, growing with you and the platform. Do not put up with tying your application down into today's constraints unless that is a goal in and of itself.

2007-11-01

Javascript Base64 singleton

Similar to the javascript MD5 singleton micro-lib I wrapped up some time ago (source code), here is an even tinier Base64.encode / Base64.decode singleton (source code) I reworked from Tyler Akins' public domain original. Absolutely no error handling or recovery in this variant, so don't pass anything but eight-bit data to Base64.encode, nor correct base64 data to Base64.decode.
// Based on public domain code by Tyler Akins <http://rumkin.com/>
// Original code at http://rumkin.com/tools/compression/base64.php

var Base64 = (function() {
function encode_base64(data) {
var out = "", c1, c2, c3, e1, e2, e3, e4;
for (var i = 0; i < data.length; ) {
c1 = data.charCodeAt(i++);
c2 = data.charCodeAt(i++);
c3 = data.charCodeAt(i++);
e1 = c1 >> 2;
e2 = ((c1 & 3) << 4) + (c2 >> 4);
e3 = ((c2 & 15) << 2) + (c3 >> 6);
e4 = c3 & 63;
if (isNaN(c2))
e3 = e4 = 64;
else if (isNaN(c3))
e4 = 64;
out += tab.charAt(e1) + tab.charAt(e2) + tab.charAt(e3) + tab.charAt(e4);
}
return out;
}

function decode_base64(data) {
var out = "", c1, c2, c3, e1, e2, e3, e4;
for (var i = 0; i < data.length; ) {
e1 = tab.indexOf(data.charAt(i++));
e2 = tab.indexOf(data.charAt(i++));
e3 = tab.indexOf(data.charAt(i++));
e4 = tab.indexOf(data.charAt(i++));
c1 = (e1 << 2) + (e2 >> 4);
c2 = ((e2 & 15) << 4) + (e3 >> 2);
c3 = ((e3 & 3) << 6) + e4;
out += String.fromCharCode(c1);
if (e3 != 64)
out += String.fromCharCode(c2);
if (e4 != 64)
out += String.fromCharCode(c3);
}
return out;
}

var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return { encode:encode_base64, decode:decode_base64 };
})();