More on site-specific browsers: Webkit-based Fluid

After my recent post on Prism, the Mozilla-based site-specific browsing tool, a commenter pointed me toward Fluid, Prism's Webkit-based cousin. After giving it a test drive, I'm impressed. Although it lacks the cross-platform appeal of Prism, Fluid already offers a nicer user experience than the project that inspired it.

Fluid_new_instance

Fluid's advantages:

  • Better preferences: Fluid offers a far more polished UI, including preferences that help Fluid integrate with Apple's Spaces multi-desktop environment.
  • Tabbed browsing: You can set Fluid up to launch secondary windows in a new tab instead of a new window. This greatly enhances the user experience of webapps with lots of popup windows. It also allows users to more easily open multiple screens of an application at the same time.
  • Browse any URL: Prism spawns any URL that's not part of the associated webapp in your default browser. So does Fluid, at least by default. But by changing your preferences for any individual Fluid instance, you can enable browsing to other URLs within that Fluid instance. Want to click on an outside link in a Gmail message? Now it won't take you out of context and into another application.
  • Less wonky Dock behavior: In the current version of Prism, when you create a new site-specific instance, Prism restarts the Dock and launches the application. Even then, the icon for the newly created instance remains the default Prism icon until you quit and restart that instance. Only then does the icon you picked - the site's favicon or any arbitrary image - show up in the Dock. With Fluid, upon creation of a new instance, you get a dialog that lets you choose whether to launch your webapp immediately. If you do, it's got the correct icon from the get-go.

Fluid_preferences

Continue reading "More on site-specific browsers: Webkit-based Fluid" »

Developer's Notebook: Find computed styles in IE, Firefox, Opera or Safari

At my recent Web 2.0 Expo talk, I exhorted developers to get comfortable outside the Firebug/Firefox safety zone. By rotating between Opera, Safari and even IE as our primary development environments, we can really get to know those browsers - and perhaps learn to utilize their non-standard features. Switching things up, however, can inhibit productivity until you learn your way around each browser's tools.

To that end, I offer these step-by-step instructions for finding computed styles in all four A-grade browsers. I chose the display of computed styles as my "debuggers are cool" use case because it's an obscure but useful feature for CSS debugging. Most of the time I can debug styles by looking at my debugger's snapshot of the current cascade for a given element. But sometimes that's not enough. If I've assigned a value of "inherit" to the font-family of an element, then the cascade snapshot won't tell me what font is actually applied to that element. (Not being a designer, I often can't tell the difference between various sans-serif faces, especially at small sizes.) Luckily, computed styles can give me the information I need.

As these examples demonstrate, debugging tools have come a long way in the last couple of years. Let's make the most of them for all of our UI-layer needs.

Internet Explorer 8 and DebugBar

IE's JavaScript debugging tools have finally matured, but its CSS ones lag behind. Even IE8, with its built-in debuggers (under Tools > Developer Tools), won't show you computed styles. Luckily, Jean-Fabrice Rabaute has crafted DebugBar, an plugin for Internet Explorer 5+ that adds all sorts of useful tools. Install DebugBar, fire up your version of IE and choose View > Toolbars > DebugBar to make the plugin visible. Then click the "DebugBar" icon in the resulting toolbar to open the DebugBar sidebar. You'll see two tabbed panes, one below the other. Choose the "DOM" tab on top and the "Comp. Style" tab on the bottom. In the upper pane, you should see a target icon with the caption "Drag target on document to find element." Drag the icon anywhere on an open web page and you'll see computed styles for the corresponding element in the bottom pane of the sidebar.

IE8 DebugBar

Continue reading "Developer's Notebook: Find computed styles in IE, Firefox, Opera or Safari" »

Alternate approaches to IE6 and transparent PNGs

Who knew IE6 and transparent PNGs could inspire so much discussion?

When you're churning out tips and tricks on a regular basis, you quickly learn to state things like this:

"I had Problem X, and my solution was Y given constraints Z."

... instead of this:

"The only way to solve Problem X is Y."

Ajaxian_logo I was reminded of this lesson last week, after I posted a series of beginner-level tutorials about overcoming some of IE6's shortcomings with jQuery. My two-part piece on transparent PNG support got picked up by the kind folks at Ajaxian, and boy did the comments come. Between the two sites, we've heard from 20 people so far. A few were from the usual cranky haters. (Thanks to whoever felt the need to write, "Is this year 2001? IE6 png transparency? News on Ajaxian? Good heavens..." instead of just moving on to the next post.) But the rest provided lively debate and some valuable alternative approaches to the problem.

For review, here are the posts (with comments):

And here are some of the various approaches suggested:

Continue reading "Alternate approaches to IE6 and transparent PNGs" »

"Do Try This at Home: Ajax Bookmarking, Cross-Site Scripting and Other Web 2.0 Browser Hacks" - my talk at Web Expo 2.0 in April

O'Reilly has booked me to speak at Web 2.0 Expo, which runs April 22-25, 2008 at San Francisco's Moscone West convention center. I'm in the process of changing the session title, so ignore what it says on the website. The new title will be something along the lines of Do Try This at Home: Ajax Bookmarking, Cross-Site Scripting and Other Web 2.0 Browser Hacks.

Webtwopointohexpo

Regardless of the slug, my talk will focus on how to push the latest and greatest browsers to their limits by peering under the hood and finding the quirks, bugs, hidden APIs and partially implemented draft specs you can use and abuse in your Ajax apps. My thesis is that instead of waiting for the Dojo or Prototype or Moo folks to exploit all the hidden goodies in today's browsers, you can go on a hunting expedition yourself if you have the right tools. With Firefox 3 and IE8 on the horizon, now's the time to start hacking.

Ajax history management will, of course, inform much of my talk, thanks to my stewardship of Really Simple History. But I'll also delve into cross-site-scripting hacks, offline storage and other on-the-bubble technologies.

My talk is scheduled for the final time slot on the final day of the conference: 04/25/2008 at 3:50 p.m. (conference schedule here). Any Agile Ajax readers who are attending the conference and plan to stick around till the bitter end should come and check me out.

IE8 Beta 1

Unless you've been stuck under a rock for the last week, you've probably heard about the IE8 Beta 1 release. My colleague Brian will have a post or two next week to dig under the surface and tell you what IE8 means to Ajax developers.






Technorati Tags: ,

Keeping up with Firefox 3: Six more bookmark-manager gotchas

I found four more bugs and two more feature requests to add to yesterday's massive, minutiae-laden post about the Firefox 3 bookmarks manager:

Firefox_3_bookmark_manager_menu_pro

Feature request: It would be awesome if you could sort your bookmarks by specific criteria, then make that sort order permanent. This would work exactly like the iTunes "Copy to playlist order" command. As in Firefox 2, you can approximate this by sorting your bookmarks alphabetically, moving them to a new folder, and moving them back. Then, even when you revert back to the "unsorted" view, the bookmarks stay in alphabetical order. Of course, this is way less necessary in Firefox 3, which can remember different sort orders for different bookmark folders, thus obviating the need to wrangle some folders into natural sort and others into alphabetical sort by brute force. Still, it's a nice-to-have.

Feature request: The Views menu in the top toolbar should be broken out into separate Show and Sort menus. This is commonly accessed functionality, and it's really annoying to have a two-item menu where each item contains around 10 sub-items which can only be accessed by clicking the menu, moving down, moving right, then moving down again to locate the desired item.

Bug: If you accidentally try to move an item to the same folder it's already in, it will simply disappear. Thank god for command-Z, otherwise I would have accidentally deleted a folder with hundreds of bookmarks.

Continue reading "Keeping up with Firefox 3: Six more bookmark-manager gotchas" »

Web standards won't get you into heaven

Picture_1

The endless hand-wringing over browser version targeting in IE8 illustrates what's wrong with the web standards community. For every sane, rational discussion about the practicalities of future-proofing the web, we get a couple knee-jerk anti-Microsoft screeds and at least one accusation that A List Apart - the standard-bearer of web standards - has somehow sold out by signing on to Redmond's plan.

First, a little background: Howls of protest echoed across the 'net a few weeks ago when Microsoft announced that Internet Explorer 8 would implement a new type of meta tag to enable both forward and backward compatibility in web pages. Once IE8 is out, users will be able to target rendering of their pages to a specific version of IE so that changes to the rendering engine of IE9 (or IE10 ...) won't subsequently "break" those pages. Basically, from IE8, onward, Explorer will include multiple rendering engines and display individual pages based on the browser version targeted by this new meta tag. The markup will look something like this:

<meta http-equiv="X-UA-Compatible" content="IE=8" />

I have no interest in debating whether or not it's "semantic" and "standards compliant" to include the name and version number of a specific user-agent in my markup. That's already been debated to death (on the 200,000+ pages Google currently reports for the keywords "IE8 meta tag"). What I want to know is this: Will Microsoft's move make my job as a web developer easier or harder? At this point, the jury's still out, but I think the answer is probably "easier."

Continue reading "Web standards won't get you into heaven" »

Ajax, Browsers, Running Out of Time

History repeats itself, first as tragedy, second as farce. -- Karl Marx

I can remember the day, back in 1994, when I abandoned the Mac for Windows. It was a gloomy, overcast day when I made that bittersweet decision -- I was a Mac and Unix nerd all through college -- but after my twelfth or thirteenth crash of the day, I had had enough. Photoshop, Netscape, Secure Shell and Word were just not meant to run more than one at a time on Mac OS 7. Had I stayed with Apple through that rough patch I'm sure I would have been slimmer, sexier and happier, but NT 3.51 only crashed twice a day, so my hand was forced. I  ran out and bought a PC that very day.

Now I fear history may be repeating itself. Yesterday, I had Firefox 2 for linux crash 5 times, and IE7 for XP crash 7 times. The cause? Too many fat Ajax applications. Zimbra, the whole Google bestiary of applications, Yahoo Mail, etc.. These are all long running applications that I keep open for most of the day. Then all of a sudden the Browser is gone and I have to relaunch and login all over again.

I'm not alone in this. Colleagues and friends report similar problems with Safari/Mac, IE7/Vista, Firefox/Mac. I've even checked with a friend that runs the helpdesk for a large firm: reported problems with browsers are up. The only one who seems blissfully unaffected is the lone Opera nerd in my office. He just keeps chugging along with what seem like 200 open tabs.

The cause should be evident to everyone. We've taken what was first called LiveScript -- a crufty embedding just good enough to validate a form or two -- and we've abused it into being the foundation for a whole new kind of application platform. The browsers have just not kept up and the situation will only get worse with the accelerated proliferation of Web 2.0 apps.

Help is on the way, in the form of bytecode interpreters and vm's for Safari and Mozilla, though the future of IE is still cloudy (still, there is a plan to bring Tamarin to IE). But if the new Browser version don't arrive quickly enough, or if they don't fully solve the problem of browsers crashing once an hour, then a mass migration to Opera may be the best we can hope for. At worst, content and application producers will opt for more stable non-Ajax alternatives such as Flash or Silverlight.

Ajax and the browsers it depends on are running out of time. If the notion spreads that it isn't reliable, it will be as dead as the Java Applet, never to be heard from again.

DOMContentLoaded and the quick rise of de facto standards

There's never been a better time to be a JavaScript developer. JS hit the big time with the advent of Ajax, and overnight client-side programmers went from being the redheaded step-children of the web-development world to front-and-center participants in the RIA revolution. Even if you're working on a team of one, there's a thriving global community of JavaScript gurus constanly pushing the language forward, working out browser kinks, demonstrating how to import concepts from other languages and computing paradigms, and otherwise inspire you. It's a big change from 10 years ago, when you had Webmonkey and the David Flanagan book and a few cookbook-style compendiums of tips and tricks. This is seriously the golden age.

Working for the last couple of months on Really Simple History, though, I've become interested in the way specific techniques become the flavor of the month and quickly redefine how we conceptualize "good" JavaScript coding practices. Take, for instance, DOMContentLoaded. After the first version came onto the scene, within a matter of months we had many competing implementations of the basic concept that your scripts shouldn't have to wait for window.onload to fire before getting down to business. Now, DOMContentLoaded is the de facto start point for many, many JavaScript applications. Heck, it's even the basis of the entire jQuery event model. There's nothing wrong with that, but widespread use of Ajax toolkits can conceal the fact that DOMContentLoaded is just a collection of hacks. It works, as long as our toolkits keep iterating one step ahead of the browser vendors. But do we really need it?

At Orbitz Worldwide, my previous employer, we implemented a first-rate unobtrusive-JavaScript architecture. (See it in action at Ebookers UK.) Everything was progressively enhanced from dumb markup. That meant our application worked just about everywhere. But it also meant lots of DOM parsing and initialization that couldn't begin until window.onload. As our application grew, this caused enough of a UI flicker - form controls turning into widgets, links morphing into Ajax calls - that we needed to jump the gun on window.onload if we wanted a good experience for the majority of users ... the ones with modern, JS-capable browsers. DOMContentLoaded made sense, and architect Nik Krimm pounced on it.

But for a large subset of websites, there really isn't THAT much difference between window.onload and DOMContentLoaded. If you're merely adding an unobtrusive behavior layer to a traditional, content-driven website, chances are that good old window.onload will perform just fine. There's usually little reason NOT to use DOMContentLoaded. But unless you are developing a desktop-style webapp or implementing progressive enhancement on a foundational level, it's not really necessary. And in certain cases, it just flat-out won't work.

An enthusiastic beta-tester discovered such a case when trying to initialize RSH's dhtmlHistory object from DOMContentLoaded. It broke, and I immediately knew why: RSH relies on the ability of modern browsers to auto-save form data for the life of a session. RSH uses a hidden textarea to cache serialized Ajax application state and render the back button useful again. Internet Explorer doesn't repopulate the cached value of that textarea until an instant after window.onload. If you try to access that cache during DOMContentLoaded, it simply isn't there. This is true of both IE6 and IE7. Therefore, you need to wait for window.onload.

I'm not really sure there's any big conclusion to draw from this example. As I said, it's just interesting to me that in the space of a year or two, DOMContentLoaded has become a de facto standard. As we pile browser hacks on top of one another to push the web forward, sometimes they're going to conflict. Luckily, we can always peek past the curtains and figure out what's  going on behind the scenes.

Really Simple History 0.6 RC1 now live at Google Code

After much tinkering, I am happy to announce the release of Really Simple History 0.6 Release Candidate 1. This version offers a number of improvements and bug-fixes over the 0.6 beta released on Oct. 23. I encourage the 600+ people who have downloaded the beta to upgrade immediately to this release candidate. As for the 3,200+ people who have downloaded the stable 0.4 version in the last two months, it's your turn, too. Beta-testers helped me put RSH 0.6 through its paces in a wide range of browsers and platforms, alongside a wide range of Ajax frameworks, and the result is solid. I fully expect this version of the code to become the new, stable 0.6 release on December 1, barring any show-stopping bug reports.

What will change between now and the final release

We'll provide a minified version of the stable release for download. We'll also provide links to sample apps. That's it.

How to upgrade

Change log

  • Rock-solid support of Opera up to 9.5 beta for Mac and PC.
  • Rock-solid support of Safari/Mac from 2.03 through 3.03.
  • Tons of internal refactoring.
  • Two-line initialization of dhtmlHistory and historyStorage (as opposed to the previous two init calls in the library and two more in your code).
  • Support for an optional options bundle in the initialization call to trigger debug mode or override default JSON methods.
  • Compatibility with Prototype thanks to the aforementioned JSON override capability.
  • Additional choice in JSON parsers; we now ship with a default 2007 JSON parser that alters core object prototypes and an older 2005 version that doesn't.
  • Better user-agent sniffing that's more resistant to UA spoofing.
  • Removal of a bug introduced in 0.6 beta that threw an error when you hit a virgin (hashless) page state.
  • Graceful swallowing of errors in non-debug mode.
  • Replacement of equality operators with JSLint-friendly identity operators where appropriate.
  • Cleanup of a little cruft from the 0.4 and 0.6 beta versions.

Browser compatibility

Supported

  • IE6 (Windows)
  • IE7 (Windows)
  • Firefox 2.x (Mac, Windows, Linux)
  • Opera 9.22-9.5 (Mac and Windows)
  • Safari 2.03, 2.04 and 3.03 (Mac)

Unsupported

  • Safari 3.x (Windows): Falls prey to fundamental bugs in Apple's current beta release.
  • Non-Mozilla-based Linux browsers.
  • Any browser not listed above; test before you deploy.

Want to showcase your RSH-enabled application?

If you use Really Simple History 0.6 in your production code, I'd love to take a look and possibly highlight your app in a future post. Please email me, comment here, or send a note to our Google Group.

Technorati Tags

Unofficial Firefox 3 Beta 1 release for Mac and Linux

Occasionally, in-between the latest iPod rumors and stupid top-10 lists from Cracked, Digg coughs up the good stuff. Case in point: today's post about Firefox 3 Beta 1. So far it's only available for Mac and Linux, and the download directory includes the following "IMPORTANT NOTE":

These files are not release versions, they are just potential release versions. Use them at your own risk, without any of the warnings that we will be putting in the release notes.

To be honest, if you're here from Digg or something similar, we'd really rather you waited until 3.0b1 was officially announced, so the servers don't get overloaded and we don't have a bunch of extra work to do.

Because I'm a bad citizen - and because I didn't see the note till afterward - I downloaded the beta and installed it on my Macbook Pro. All my extensions, of course, got disabled immediately. Still, I'm already impressed with the interface improvements. The Places concept looks promising. The bookmarks manager is VASTLY more useful and intuitive. And the download manager, though a little iffy on usability, has some cool new bells and whistles, especially the ability to interact with your downloaded files from within the manager itself.

Also, strangely, dropdowns and other form elements now have the native Mac OS look-and-feel: rounded corners and all that jazz. Is this is new feature, or just something that was always there but hidden by my extensions?

Picture_3_2

Technorati Tags

More on Safari and the new Gmail upgrade

Over the weekend my Gmail finally got upgraded to the new version. (I know, I know, a week is hardly a long time to wait for a slow-rollout Google feature. But I'm impatient.) I have to say, the history and back-button support is AWESOME. It's funny that Gmail warns you in a huge red banner to disable Firebug. I, of course, kept it enabled and immediately began digging through the DOM of the new UI. As usual, most of the JavaScript is so obfusticated that it's hard to tell what's going on. Still, it's interesting to dig through layers and layers of iframes and nested divs and see how much DOM hackery is involved. Looking behind the scenes at any commercial-grade webapp is like taking a tour of a sausage factory.

Luckily, I have a strong stomach. I'm going to make it a weekend project to really dig in and learn how they're handling their history support. In a previous post, I wondered why the new Gmail is only available for Firefox 2 and Internet Explorer 7. Given my own experiences with Safari's history object, I shouldn't be surprised. With bookmarkable URLs and history management so central to the new Gmail UI, no wonder Safari has been left in the cold; it's simply too buggy in this regard to receive A-grade support. Safari users have been complaining to Google that it should fix Gmail for Safari even with the old UI. I think those complaints should be lodged at Apple, not Google.

Picture_1_3

P.S. Sure enough, leave Firebug open in Gmail for any length of time and your Firefox will slow to a crawl. My FF has been crashing a bunch this week, but I'm not sure whether it's Gmail or Firefox's own latest updates. Commenters, am I the only one seeing this?

DOM methods, document.write and the art of library design

So I ended up doing some last-minute fiddling with the Really Simple History 0.6 beta before posting it for testing over at Google Code. Matt Snider pointed me to a potential SSL problem with using DOM methods rather than document.write to insert IE's hidden iframe. I've got four places where I need to insert stuff into the DOM, and I had already hemmed and hawed quite a bit about whether I should use DOM methods, document.write or a mixture. For now, based on Matt's comments and the verbosity of DOM methods, I've reverted back to using dirty-but-concise document.write. I'm going to continue testing this in as many browsers as possible before settling on a permanent solution.

While fiddling, I discovered something interesting that contradicted yesterday's (now-corrected) post. I originally wrote that if you've got script-generated DOM elements that need to be treated as native to the document (so, for instance, you can persist form values across an entire session regardless of whether you navigate off-site), you must use document.write to insert them into the DOM. Not true, as it turns out. It doesn't matter whether you call document.write or standard DOM methods from the head of your document. Either way, both methods seem to result in "native" HTML form fields that can properly persist values. Looking at Firebug or Opera's developer console, you can see that these elements end up being children of the body element even though they were, in fact, inserted into the head element. Modern browsers are so smart!

This whole issue of when to generate DOM nodes brings up an interesting facet of library development: Deciding how much stuff the end user (i.e the developer who is leveraging your library) has to do in the actual document. For most libraries, it's not an issue, because their objects and methods aren't going to do anything until called by application code. But it's different for something like Really Simple History, which relies on a variety of browser-specific hacks, many of which need to be set up before the DOM finishes loading. Sure, you could include inline script blocks in the body of your document to write the hidden, browser-specific DOM elements that enable your library to function. But developers really hate it when the use of a library forces them to fiddle with their page templates. Library authors have to get creative - for instance, by calling their initialization methods in the library file itself, even though that will result in DOM elements getting written to the document head.

As I said in yesterday's post, Ajax history management works only thanks to a variety of browser quirks and hacks. If you want clean code that doesn't break any standards, then you should cross history management off your list of requirements.

Things get even more interesting when your browser-specific DOM hacks work best when they're included as actual markup. My beta is out there, but I'm still scrambling to figure out the best strategy for Opera which, thanks to a bug introduced in 9.x, relies on a hack involving an image tag a crazy URL:

<img src="javascript:location.href='javascript:dhtmlHistory.checkLocation();';" style="visibility:hidden" />

This image throws errors in IE, so I couldn't tell developers to include it in their actual markup even if I wanted to release a library with such brittle implementation rules. If I want it to go in the actual HTML, I'd have to ask developers to do server-side browser sniffing and include it only for Opera users. YUCK. Yet all of the methods of writing it to the DOM via script have drawbacks. The way I'm doing it now, it works in Opera, but it throws an exception in the JavaScript console. Sure, only developers will see that exception, but still.... I guess I still have my work cut out for me.

Technorati Tags

Coming soon: Really Simple History 0.6 beta

Late tonight over at Google Code, I'll be posting a beta of Really Simple History 0.6 for testing. The goal is to elicit help from RSH users in chasing down any bugs I've failed to catch, then push out a stable release around Halloween.

I've tried to be as ambitious as possible with this release: full support of IE7/Win, Safari/Win, Safari/Mac, Opera/Win, Opera/Mac. I've didn't quite get there, but I got close.

Features in the new version include:

  • Full support for IE7/Windows (though my only Windows machines use IE7 Standalone, so I need help testing on "real" IE7 installs).
  • Full support for Safari 2/Mac (though I'm still trying to eliminate the "infinite loading" bug before I push out the beta).
  • Partial support for Safari 3/Windows (hampered by bugs in the current beta version of the browser).
  • Full support for cross-platform Opera 9.22 (though you may need to hard-code an image into your markup).
  • A totally revamped test page that allows you to play with the library in your browser of choice and see how it works behind the scenes.

As always, RSH works beautifully in Firefox 2 for Windows and the Mac. I hope to give it a good shakedown on Linux browsers in the next release.

So what is Really Simple History, and why am I updating it?

An Ajax bookmarking and history-management framework originally developed by Brad Neuberg, RSH became my responsibility a little over a month ago. I tinkered with it for a few weeks, then finally camped out with it for most of the past week to get a release out.

This is the first time I've ever contributed in this manner to an open-source project. It's been a lot of fun, but it's also been maddening, as anybody who's ever dug into the bowels of cross-browser history management can tell you. Here's a sampling of what I've learned from RSH:

Safari is crazy

Plenty of people who've worked on Ajax bookmarking projects have commented about this, but it only becomes clear once you've actually seen it in action. Getting this thing to work in Safari 2 for the Mac took a wildly disproportionate amount of time considering its market share. I wouldn't have been able to do it without Bertrand Le Roy over at Microsoft, whose blog entry on the development of the .Net history manager pointed the way for both Safari and Opera.

As Le Roy and others have noted, the Safari 3 Windows beta is so buggy that history management is hopeless. You can enable the back button for Ajax apps, but once you use it, the forward button becomes disabled. I noticed yet another wrinkle in this behavior (skip ahead if you're easily bored):

Navigate to a non-RSH site - Google, for instance. Then travel to an RSH site, create some history entries via RSH, and use your back button. The forward button stops working: a known bug. Now keep hitting back until you get back to Google again. Suddenly, your forward button works again. Hit forward and land back in your RSH app. Magically, the forward button continues to work.

If I hadn't spent so much of the last week lost in Safari-land, this interesting behavior might be worth further investigation. For now, I'm just hoping the Safari 3 team fixes this before the final Windows release.

Don't try to retire document.write just yet

A couple of different RSH users suggested getting rid of Brad's original calls to document.write in favor of standard DOM methods for adding elements to your page. That approach worked for some elements, but not for others.

In IE, RSH writes a hidden iframe into the document and uses the location and history of that iframe to help it track application state. Writing the iframe with document.createElement works just great.

But for all browsers, RSH uses a hidden textarea to store the entire history stack behind the scenes. This powers one of RSH's coolest features: its ability to retain history even if you navigate away to another site and then come back to your RSH application. This works because modern browsers retain form-field values throughout an entire browser session. But they do so only for form fields that exist in the DOM natively - that is, exist in the actual HTML markup or get inserted via document.write get inserted into the DOM before it's finished loading. 

If you create a form element after your DOM is already loaded, the browser has no way to persist values in that element after you leave the page. Each time the page loads, even from the cache, you essentially create a virgin new form field. I'm therefore using document.write for the hidden textarea - and for the hidden form field I've added to RSH for Safari support.

UPDATE: As it turns out, it's immaterial whether you use DOM methods or document.write. The important thing is to use either method before onload fires. I ended up using document.write in the 0.6 beta because of SSH concerns and the fact that it's so much more concise. For more on this topic, see this subsequent post. 

Because of the way RSH is structured, these elements actually get written to the head rather than the body of your document. Still, it works, and it should only offend the most anal-retentive of standards geeks. After all, if you're hacking the browser 10 different ways from Sunday just to enable Ajax bookmarking, then inserting a bit of non-validating markup via JavaScript is hardly the worst of your sins.

RSH won't be hitching its wagon to [insert name of your favorite framework here]

A few users suggested rewriting RSH in Prototype so it would be more compact. I appreciate the impulse, but I think that defeats one of RSH's chief virtues: the fact that it's written in Plain Old JavaScript and doesn't lock you into any specific Ajax framework. It plays well with any library you want it to: Prototype, jQuery, YUI, whatever. (If it doesn't, please file a bug so I can find out why.)

A little JSON never hurt anyone

The one library that RSH does require is a JSON parser; it ships with the latest open-source version. RSH 0.4 included an earlier version of the parser in the same file as its native code; I've broken it into a separate file under the logic that many users will already be serving a similar library. RSH's methods don't actually call toJSONString or parseJSON directly; instead, I've provided bridges so that you can hack in your own JSON methods without having to modify the guts of RSH itself.

Future roadmap

I've got quite a punch list for the next release:

  • Provide minified versions of RSH and JSON for download
  • Make use of Crockford's module pattern for better encapsulation
  • Add official support for Linux browsers, Safari 3/Mac and Safari 3/Win

That's the future. For now, I have to get 0.6 packaged up and ready for testing. Check Google Code late this evening or first thing tomorrow.

Technorati Tags

Developer's Notebook: Forward-thinking CSS float-clearing

The art of float-clearing - getting containers to honor the height of floated elements inside of them - has slowly evolved over the past several years as Safari has taken over many Mac desktops, IE5/Mac has atrophied, IE7 has slowly caught on, and our use of CSS filters has improved. I'd like to share a slight variation on the state of the art that I believe makes for much cleaner markup. But first, a little background.

How we got here

Several years ago, Tony Aslett of csscreator.com convinced us to stop using clearing our floats using this sort of junk markup:

<div id="container">
   <div id="rail" style="float: left;"></div>
   <div id="content" style="float: left;"></div>
   <br style="clear: both; height: 0; visibility: hidden;">
</div>

His solution, popularized on Position is Everything, convinced us to use pure CSS to solve the problem:

.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}

.clearfix {display: inline-block;}

/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */

<div id="container" class="clearfix">
    <div id="rail" style="float: left;"></div>
    <div id="content" style="float: left;"></div>
</div>

The advantage, of course, was that you didn't have to litter your markup with extra <br /> tags that would eventually become totally useless once the state of the art changed.

Where we are now

For sites that have dropped support of IE5/Mac and adopted support of IE7, the recent concensus on float-clearing has been something like this (using the same markup as above):

/* float clearing for IE6 */
* html .clearfix{
  height: 1%;
  overflow: visible;
}

/* float clearing for IE7 */
*+html .clearfix{
  min-height: 1%;
}

/* float clearing for everyone else */
.clearfix:after{
  clear: both;
  content: ".";
  display: block;
  height: 0;
  visibility: hidden;
}

And now, a slight refinement

Which leads me to a technique used at Orbitz, my previous employer, to apply the same methodology with even less impact on the markup itself. Instead of declaring a single clearfix class and then applying it to countless containers inside their XHTML, the Orbitz UI team uses a grocery list of CSS selectors, like this:

/* float clearing for IE6 */
* html #container,
* html .classThatNeedsToBeCleared,
* html div.anotherClassThatNeedsToBeCleared,
* html #someDiv .someClass .yetAnotherClassThatNeedsToBeCleared{
  height: 1%;
  overflow: visible;
}

/* float clearing for IE7 */
*+html #container,
*+html .classThatNeedsToBeCleared,
*+html div.anotherClassThatNeedsToBeCleared,
*+html #someDiv .someClass .yetAnotherClassThatNeedsToBeCleared{
  min-height: 1%;
}

/* float clearing for everyone else */
#container:after,
.classThatNeedsToBeCleared:after,
div.anotherClassThatNeedsToBeCleared:after,
#someDiv .someClass .yetAnotherClassThatNeedsToBeCleared:after{
  clear: both;
  content: ".";
  display: block;
  height: 0;
  visibility: hidden;
}

<div id="container">
    <div id="rail" style="float: left;"></div>
    <div id="content" style="float: left;"></div>
</div>

The idea here, of course, is that each time you have another container that needs to be cleared, you add browser-specific selectors for it to each of the three blocks above. Suddenly, there's no need to apply a utility class to a zillion different nodes in your HTML. Instead, you apply the same CSS rules to a bunch of atomic CSS selectors. Voila: float-clearing with absolutely no impact on markup. Presto: a solution completely centralized in a single block of CSS code, so that it can be changed in one place as the browser landscape evolves.

(Props to Gena Wilson, Orbitz's CSS headmistress extraordinaire, for constantly synthesizing elegant solutions like this one.)

Final side note: As long as folks are going to keep griping about missing items from their CSS wish list, could we please just eliminate the need to clear floats altogether? I know that the need to clear floats isn't actually a bug, according to the WC3, but it should be. I can't think of a single time I've ever _not_ needed to clear my floats. Can you? Tell me in the comments.

Really Simple History: Onwards and upwards

I'm excited to announce that I've heard the call and volunteered to tackle maintenance and stewardship of Really Simple History, Brad Neuberg's intuitive, lightweight Ajax history library. Brad developed RSH a couple of years ago, drawing inspiration from the Dojo Toolkit folks to deliver a standalone library that provides back-button and bookmarking support for Ajax apps in IE6 and various Gecko-based browsers. Since, then, many additional Ajax frameworks have implemented back-button and bookmark support, some of them drawing on Brad's work.

Meanwhile, Brad's been too busy with other projects to upgrade RSH for a variety of new and existing browsers: IE7, Opera, Safari/Mac and Safari/Windows. I asked Brad to let me take care of his baby for several reasons. For one thing, I've been an enthusiastic user of the library. For another, I've been wanting to get involved on a more formal basis with open-source JavaScript projects. But most of all, I believe RSH remains a great tool for folks who want a solution to the Ajax history issue without the overhead of a larger Ajax framework.

I'm currently working with Brad to migrate RSH to Google Code, get acquainted with the bug base, and start tackling the thorny issues surrounding Ajax history support in the 2007 browser landscape. I look forward to shamelessly pilfering the many fine solutions uncovered by a large community of developers since Brad's initial work. (Brad was kind enough to point me to this blog post from Bertrand Le Roy, which lays out many of the aforementioned fine solutions and thorny issues.)

In the meantime, I'd love to hear from RSH users about their hopes for the future of the framework. Comments, please, or ping me directly at bdillard (at) pathf.com. Thanks!

IBM's CoScripter: Greasemonkey for non-geeks

Think of all those annoying step-by-step processes you must learn and memorize to go about your daily online business: logging onto your bank site to check the balance on your savings account; filling out a tedious form; ordering prints of your digital photos. The elements of the UI are easy to understand, but the process itself differs wildly from site to site.

Now imagine a Greasemonkey-esque add-on that not only automates those processes, but shares the automations with everyone else. All you have to do is write the instructions in plain English, let your browser record the steps in real time, or search the existing archive for somebody else's previously recorded automation. Sold yet? Good, then meet CoScripter, a new Firefox add-on from IBM.

Alex Faaborg over at Mozilla Labs sums up CoScripter thusly:

What do you get when you mix one part automation, one part natural language interpretation, two parts programming by demonstration, and three parts online collaboration? If you stir all of these research areas together and toss in some XUL, you get one of the most innovative extensions for Firefox: CoScripter.

Jon Udell has kicked off a pretty interesting discussion of CoScripter as a mash-up of social networking and domain-specific languages. But I'm most excited about the technology for its grassroots potential. Like microformats, CoScripter has the potential to evolve into an "accidental standard" that proves the enduring power of the Open Web. I can foresee a future in which site owners coach newbies about their interfaces by releasing CoScripts instead of publishing big chunks of step-by-step instructional text. Of course, the technology's future ecosystem depends on how IBM licenses it. One less-than-promising sign: the onerous registration process and EULA I had to endure before downloading the add-on.

Nevertheless, as of this writing, 190 CoScripts have been submitted. Lots of them seem fairly limited in scope, but I'm sure that will change as the community grows and the technology matures. The add-on's handy Sidebar interface displays the "editor's picks" for most useful scripts. I'm particularly fond of Add your phone number to the national do not call list.

I wrote two of those 190 scripts myself, and my experiences highlight the strengths and weaknesses of CoScripter as it's currently implemented.

First off, I tried to automate the process of logging into popular blogging engine Vox and starting a post. The tutorials helped me figure out how to parameterize private data such as email addresses and passwords into a locally stored "personal database." That way, I can write scripts that work for me, then share them with anybody who sets up similar key/value pairs in their datastore.

The plugin did a pretty good job of recording my steps as I interacted with the browser. (Users of the open-source Selenium QA framework will feel right at home.) But the recording engine totally ignored my interactions with Vox's password field. Even after I manually scripted this step - in CoScripter's eminently simple natural-language syntax - I couldn't get the sequence to work. Still, I've saved it (Login to Vox and Compose Post) in the shared repository. Perhaps a smarter Vox user than me could get it running? Here's the source code:

              
  • go to "http://www.vox.com/"
  • enter your "vox login" into the "Member sign in"'s "Email:" textbox
  • enter your "vox password" into the "Member sign in"'s "Password:" field
  • click the "Sign In" link
  • click the "Compose Post" link
          

Next, I tackled something much simpler: Read La Dolce Musto. I love this Village Voice column, but I always have to hunt for it on the busy homepage of NYC's alternative weekly. There's no landing page for columnist Michael Musto, and the site's layout changes weekly. My simple, two-step script hits the homepage and activates the first instance of the writer's name as a link. It worked for this week's issue, but I'll have to wait till next Wednesday to make sure it doesn't bomb out once the homepage rolls over.

Again, the source code:

                         

Given how difficult I found it to get a moderately complex script working, and how trivial my actual working example is, I can't say that CoScripter is going to set the world on fire immediately. Password fields seem to be a problem, and there's no ability to use conditional structures. I'd love, for instance, to be able to write a script that goes to Vox, logs me in only if I'm not already authenticated, then begins a post. It would also be great if I could build in timers, such as "wait x seconds," so that Ajax interactions or other slow-moving changes in state could be accommodated. I mentioned Selenium before, and its powerful syntax for writing test scripts seems like a model for future development. If CoScripter's engineers can expand the power of their DSL without losing its simplicity and ease of use, this add-on seems likely to earn a wide and enthusiastic user base.

[Thanks to the awesome Lamda the Ultimate for the original tip.]

IE6: The zombie browser

Paul Graham's much-dissected essay Microsoft is Dead offers some witty and perceptive analysis, but it sidesteps the fact that Microsoft's rotten corpse will take decades to decompose. In the meantime, we still live in a world where most people trawl the Internet with a Microsoft browser. I've already linked to Kevin Hale's perceptive essay On the Tenacity of Internet Explorer 6, and I've already covered Eric Meyer's useful techniques for taking advantage of IE7's power while continuing to support IE6. But I've got a few more links to add to Dietrich's and my back-and-forth about the state of JavaScript tooling. I regularly stop by the IEBlog the same way I keep tabs on the neighbors I don't really like but have to live near. They recently added a more in-depth post about Ajax View, a pretty cool profiler that they'd previously covered along with other IE development tools earlier this summer. In a previous post, I surmised that most front-end developers code for Firefox first, then put off their Safari/Explorer testing till the end. Maybe if IE tooling continues to mature, we'll see less of that.

Cognitive Load, Portability and the Superiority of Client-Side Frameworks

The recent introduction of TrimPath Junction got me to thinking about Dietrich's widely read post on Cognitive Load and the Superiority of Server-Side Ajax GUI Frameworks. GWT's big advantage is that it mobilizes armies of Java programmers to write browser-based applications without having to learn JavaScript. This is clearly of enormous benefit to organizations with lots of Java programmers, few client-side resources, and a burning desire to build powerful webapps. Yet for the similarly huge army of client-side programmers out there, GWT is pretty useless. Why learn a foreign language just to have it translated back into your native tongue?

I haven't yet had a chance to play with TrimPath Junction, but it sounds pretty cool. Using the open-source Helma framework, it offers Rails-style MVC scaffolding in a JavaScript syntax that executes the same code on the client and server. Basically, it's RoR meets Adobe AIR for JavaScript programmers. I hope to give it a test drive soon.

Server-side JavaScript has been around for ages, but it's never really become a common development model. I remember writing ASP Classic apps in server-side JScript back at the turn of the millennium and having people wig out on me. "Why not write in VBScript like everyone else," they'd ask. My answer: "Because I can save time by running the same validation libraries on the client and the server ... and because I can write the entire app in one language." I obviously have no argument with Dietrich's thesis on cognitive load. It's just that my brain features a JavaScript compiler, not a Java one.

GWT is a great piece of engineering that keeps getting better; just check out the new non-beta 1.4 release. But I think there are a lot of advantages to frameworks that mobilize the JavaScript masses to write front-to-back webapps. The same cognitive efficiencies can be achieved, plus client-side programmers already know all the pieces of the UI puzzle. Ask a room of Java developers how to build accessibility and usability into standards-compliant XHTML and CSS. Nine out of 10 wouldn't have a clue.

The other big advantage to developing UI code in its native language is that you can port it to any server platform. With GWT and similar frameworks, you've got to rebuild much of your UI from scratch if you want to change course in mid-stream. With purely client-side frameworks such as Prototype, jQuery, YUI or MooTools, switching libraries may entail rewiring some of your code to a new API. But switching server platforms, from J2EE to .Net to PHP to RoR, can be done without much work at the UI layer. "The right tool for the right job" is a truism for a reason. Pure client-side development of UI code allows for the development of reusable components whose only dependency is on the standards bodies and browser vendors who control JS, CSS and HTML. GWT and its peers are useful for some teams and some projects, but they're not the only answer to webapp development.

An Event Apart Chicago: Day 2

Tuesday saw the conclusion of An Event Apart Chicago 2007, the two-day web-development conference from the folks at A List Apart. Here's my sequel to yesterday's day-one overview. I'll be back Friday with analysis and afterthoughts.

Jeremy Keith, author of "Bulletproof Ajax" and "DOM Scripting," led the day. His topic? "Be Pure. Be Vigilant. Behave," wherein he outlined the concepts behind "Hijax," the application of progressive enhancement to Ajax functionality. A staunch proponent of unobtrusive JavaScript, Keith warned against throwing web standards out the door when developing Ajax functionality. His examples demonstrated how to separate behavior from content and presentation by abandoning such outmoded techniques as the javascript: URL pseudo-protocol. His most extensive example showed how to code a graphical widget for the assignment of star ratings so that it would degrade gracefully into a standard HTML select box in less capable browsers. After discussing the difficulty of making XHR functionality play nicely with bookmarks and the back button, Keith acknowledged that his parting message - when in doubt, leave XHR out - was a bit of a copout for the author of an Ajax manual.

Next up was Luke Wroblewski, a Yahoo product designer whose resume includes work on the original Mosaic web browser. Wroblewski covered "Best Practices for Form Design" using exhaustive research from his forthcoming book on the subject. In case study after case study, he demonstrated how simple choices in the design and deployment of HTML forms - from the widths and alignment of inputs and labels to the placement and visual differentiation of cancel and submit buttons - can cut the time it takes to complete them in half. Wroblewski's most persuasive argument, however, was conceptual rather than technical. He made a powerful case that because forms are barriers between users and the things they want to do - buy your product, join your site or begin creating content - you should make them as easy to get through as possible. This central thesis added considerable weight to his many practical how-tos.

Accessibility advocate Derek Featherstone closed off the morning with "Accessibility: Lost in Translation." Featherstone looked at how markup choices can make a site transparent to assistive devices - or render it totally opaque. Using real-world examples from Amazon and other sites, he demonstrated how screen-reading software actually parses markup. His live examples proved that the lack of semantic markup and the absence of ostensibly optional HTML attributes can render a site worthless for disabled users. Featherstone then went beyond the basics, explaining how source order - the sequence in which nodes appear in your markup - can be used to enhance accessibility. By placing your central content first, then positioning chrome above it with CSS and providing jump navigation to skip past inessential modules, you can achieve the presentation you want for typical users without shortchanging disabled ones. In another example, Featherstone examined the ways in which meaning can be encoded in the color and position of elements on the page - and how to replicate that meta-data in a way that disabled users can understand. As with many of the other speakers, Featherstone's examples argued persuasively for the continuing relevance of web standards.

After lunch, CSS expert Eric Meyer again took the stage, this time to explore "The State of CSS in an IE7 World." Using the recent release of Microsoft Internet Explorer 7 as a springboard, Meyer illustrated the concepts that have governed the changing of the browser guard for more than a decade. His overall premise was that developers need to use their own server logs to gauge when support for an older browser can safely be dropped for their site. For most of us, IE6 isn't going away anytime soon, so we need to get creative if we want to harness advanced functionality. To that end, Meyer delved deeply into the details of IE7 techniques, filters and hacks. He praised the browser for the strides it makes over IE6's CSS engine in such areas as child selectors, adjacent sibling selectors and attribute selectors. His real-world examples demonstrated how such functionality adds power and elegance to our code. To cope with IE6's continuing market share, Meyer advocated the use of Dean Edwards's IE7 compatibility script, a JavaScript library that adds IE7 capabilities to older versions of the browser. The take-home message was that older browsers may take a long time to die out, but creative programming techniques can harness the future of CSS now.

The final two sessions for AEA Chicago 2007 were a little offbeat, which was a relief after 10 technical sessions in the previous 32 hours. In the highly anecdotal "Selling Design," ALA publisher Jeffrey Zeldman used stories from his own long career to illustrate best practices for handling difficult clients. His thesis was that collaborative work requires us to deal with a wide range of other people, so we should hone our ability to influence our collaborators - and pick good clients to begin with. Agency owner Jim Coudal closed things off wittily with "Dealing With the Both of You," a slide-free presentation about the crossover between personal projects and professional work-for-hire. Coudal assembled a number of satirical short films to drive home his point: Because most web developers are curious and easily bored, we should strive to marry passion with professionalism whether our clients are external or ourselves.

An Event Apart Chicago: Day 1

The folks from A List Apart rolled into town yesterday for An Event Apart Chicago 2007, a two-day web-development conference. Around 500 programmers, designers and information architects flocked to the seventh floor of the downtown Mariott for a varied slate of talks by some of the biggest names in the industry. Today and tomorrow I'll give high-level overviews of each day's sessions. On Friday, I'll provide some color commentary.

Stylesheet guru Eric Meyer's "Secrets of the CSS Jedi" kicked things off with an in-depth case study in which pure CSS 1 and 2 transformed tabular data into an Excel-style bar graph. Meyer's presentation was interesting not only for what his techniques could accomplish, but also for what they couldn't. It was inspiring to see that plain-vanilla data could be given a powerful visual makeover, yet still remain completely semantic and accessible to handicapped users. But it was disheartening to see that the simple addition of tick marks within the graph demanded the addition of hard-coded percentage values to a number of CSS classes. The lack of simple computational ability within CSS declarations has long been a drawback of the "not a programming language" language. CSS remains a powerful and flexible technology, but, as I discussed at length a few days ago, it's got a lot of room for growth. For those who were already conversant with Meyer's techniques, perhaps the most interesting digression in his talk was the chance to tear through Firefox's built-in browser stylesheets and see how even the most fundamental rules of HTML presentation - such as the invisibility of meta tags and the entire <head> block - are controlled by CSS behind the scenes. Meyer also went over the basic building blocks of the kind "reset" stylesheet most jedis use.

Up next was Jeffrey Zeldman, publisher of A List Apart and therefore another another rock star to this crowd. A lot of recent ALA content has focused on the overlooked art of writing for the web, so it was no surprise that Zeldman tackled the topic "Writing the User Interface," which packed in plenty of practical advice for writers and non-writers alike. His central thesis was that copy was the cheapest and easiest thing to improve on most sites. Using lots of witty real-world examples, he provided a useful paradigm for breaking textual content into discrete components - guide copy (a.k.a. instructional text), brand copy (taglines and other branding assets), copy copy (a.k.a. real content), labels and URLs - and applying different editing criteria to each. As befits the author of "Designing With Web Standards," Zeldman was careful to demonstrate that the rules of good web writing and the rules of semantic markup are often one and the same. As with most of Zeldman's advice over the years, he started with a compelling philosophy, then showed how to break it down into small, actionable steps.

Happy Cog designer Jason Santa Maria finished off the morning block with "Design Your Way Out of a Paper Bag," a look at the process of rebranding and redesigning an existing site. An illustrated tour of Santa Maria's own iterative design process, the presentation was, like the earlier sessions, a case study in how a series of small steps can have a big impact on the usefulness of a site. Using an amusing Flickr tour of real-life signage and the abuse and misuse of the poor apostrophe therein, the designer drove home his biggest advice: "Sweat the small stuff." Along the way, he touched on typography, branding, logo development, grid-based layout, whitespace and other design concerns. As befits a designer, Santa Maria's session was probably the most visual and the least easily captured in the PDF slides distributed to attendees. He did, however, suggest some excellent further reading, most notably "The Elements of Typographic Style," "Thinking With Type," "Grid Systems" and "Making and Breaking the Grid."

After lunch, Lou Rosenfeld led with "Search Analytics For Fun and Profit." In a series of painstaking real-world case studies - most notably of my alma mater Michigan State University - Rosenfeld explained how server logs and especially search engine logs offer the keys to a successful site redesign. It's a simple idea that may seem elementary to many developers, but given how infrequently web-development teams actually use this feedback loop effectively, Rosenfeld's techniques struck me as really powerful. You would expect a session like this to show you how users' most popular search terms could serve as the springboard to an overhaul of your navigational systems. But Rosenfeld also delved several levels deeper, showing how much powerful business intelligence can be obtained from inexpensive tools with little or no custom code to support them. Site indices, metadata, search algorithms and the search interface itself - all can be tweaked based the subtle metrics that emerge from careful, detailed session analysis.

Perhaps the most inspiring session was Liz Danzico's "The Seven Lies of Information Architecture," in which the Happy Cog information architect recast the high commandments of IA as guidelines rather than rules. Danzico used copious examples to demonstrate how the most successful sites often bend or break the supposedly unwavering rules of IA. The idea of the magic number - most users can only remember 7 +/- 2 items in their short-term memory at any given time - was the first concept to show cracks under Danzico's microscope. She went on to debunk the holy status of such maxims as "consistency is good," "navigation is necessary," "the shortest path is the best path," "experience must be seamless" and "users should always know where they are." Sometimes, the idiosyncratic nature of her examples suggested that certain guidelines work for most sites and are best broken only for a specific purpose. Other times, especially in her examination of Amazon's and Apple's navigational systems, her case studies suggested that even mainstream sites do and should break the rules. It was Danzico's last rule - the idea that only IAs should do IA work - that she most thoroughly debunked by the end of her session. She argued passionately that site owners, designers, programmers and end users can and should understand the guidelines of information architecture - but, like IAs themselves, they should apply those guidelines judiciously rather than rigidly.

Last up was designer Dan Cederholm, founder of SimpleBits and Cork'd. He constructed an elaborate site prototype, ToupeePal, to demonstrate "Interface Design Juggling," his thesis that great design involves keeping lots of balls in the air at the same time. Delving deeply into typography, microformats and the development of favicons, Cederholm demonstrated that beautiful and useful interfaces can be constructed using the supposedly unsophisticated visual and informational tools already at our disposal. Cederholm cried foul on the idea that web typography sucks because too few cross-platform fonts are available. He argued that the single-font typography of the Itallian Renaissance is some of the most beautiful ever created, then he demonstrated practical techniques for getting similar mileage out of limited existing web fonts. Word-spacing, letter-spacing, line-spacing, color, weight, italicization and other simple tools can all elevate even the most familiar typefaces into the design stratosphere. Likewise, even a tiny 16x16-pixel favicon can provide a powerful branding tool when designed correctly. Cederholm closed with an in-depth look at the "accidental API" of microformats, demonstrating that a even a grassroots open-source movement can add power and value to the web without the support of standards bodies and browser vendors.

Check back tomorrow for coverage of today's sessions, from Eric Meyer's look at the post-IE7 world to Derek Featherstone's talk on accessibility.

CSS considered harmful by Ajaxian commentators?

There's a super-entertaining comment thread/flamewar going down at Ajaxian in response to Dion Almaer's recent editorial on The Future of CSS and the end of 3.0. Almaer has lots of interesting and perceptive things to say about the maddeningly erratic way in which new standards make their way into general use. But the vast majority of commentators jumped at the chance to sound off on some of his minor points:

CSS is great for simple web style. CSS is awful for layout. Rich Ajax apps need layout. You spend the majority of your time trying to get CSS working correctly!

Of those four assertations, there's not a single one I can fully endorse. IMHO, current implementations of CSS are _pretty good_ for simple web style, but they're not great. (See the comments for many examples: rounded corners, varied fonts, etc.) They're not great for layout, either, but if you take the time to learn the tricks - and account for spotty browser implementations - then you can develop attractive, robust and usable UIs using CSS. As for whether rich Ajax apps need layout, well, yes. But what kind of layout is open to considerable interpretation. Just because the first few generations of web designers kept trying to apply the same old print paradigms to the browser doesn't mean it was right. The same goes for the current wave Ajax frameworks and the desktop-app layout paradigms some of them attempt to implement.

The assertation that bothers me the most, though, is the one about the time it takes to get CSS working properly. As with any code executed in the browser, CSS is subject to the quirks and peccidillos of browser vendors, operating systems and ever-mutating standards. Still, once you account for the major differences in execution environment, it's not that hard to come up with a single global stylesheet that can zero out built-in styles and browser quirks to offers a more or less blank canvas for cross-browser CSS development. CSS authors may not release their design frameworks under open-source licences the way JavaScript authors do. But that doesn't mean they don't exist. Just peek under the hood at a big, forward-thinking consumer webapp or pick up a Jeffrey Zeldman book.

Regardless of what _I_ think, the thread at Ajaxian provides an interesting vox populi. As can be expected, comments range from wholehearted endorsements of Almaer's position to finger-wagging about the importance of web standards to chest-puffing from people who've mastered the tricky art of CSS layout and don't have much sympathy for those who haven't. I'm fascinated by the way participants in these conversations let their personal investment in a certain skill set lead them to make sweeping generalizations about entire swaths of the software-engineering world. Just because you know how to make a site look a certain way using tables, or floats, or XSLT, doesn't mean that that's the only way, or that the Internet won't eventually cough up a much better way than any of the above.

The fact is, any programming language or development framework can be improved, and there's lots to both love and hate about the CSS specs and the various imperfect implementations of them. It's _so_ far from the all-or-nothing proposition that many of the commentators would have you believe.

Dealing with client-side technology is frustrating for anybody who's used to having complete control over their execution environment, or a stable platform at all. The reason the pace of change is so glacial on the client side is that standards take time to develop; vendors take time to implement them; and a variety of market forces contribute to how well and how quickly they're implemented. Nobody said the Open Web was easy, but it's vastly preferable a host of closed-off, proprietary formats controlled by individual vendors and immune to grassroots innovation.

Any developer who's lived through successive generations of client-side technology knows that things have only gotten better with time. It's hard to imagine that standards won't continue to improve, no matter how painfully slow the process.

The awesome state of JavaScript development tools

Dietrich's post on the depressing state of IE develpment tools got me to thinking about the generally wonderful state of JavaScript tooling. Compared to just a few short years ago, we've got a wealth of productivity-enhancing browser add-ons, TDD frameworks and static-analysis tools at our disposal - most of them open-source. For those who want to get their hands dirty writing POJ, this is a golden era.

Like most developers, my code circa 1998 was filled with commented-out alert() statements. I spent way too many hours cursing IE4's inability to report accurate line numbers in its error dialogs. I relied heavily on Netscape's built-in debugger. Within a couple of years I had graduated to a primitive logging utility that spawned a separate browser window and output messages into it using simple DHTML. At the time, it seemed like a huge advance.

Then came the Firefox era, with its host of disparate add-ons. You could edit your CSS in the sidebar, selectively disable JavaScript and CSS, inspect the DOM .... Once again, the possibilities seemed endless. Now, thanks to Firebug, most of my grab-bag of browser add-ons are gone. Firebug is so powerful and wide-ranging that the only other add-on I use regularly is the venerable Web Developer Toolbar. Yahoo's new Firebug extension YSlow adds some really useful optimization benchmarks to the suite. When a plug-in begins to spawn its own plug-ins, you know you've got a winner.

I'd be interested to know, though, what kind of process UI developers use to debug their JavaScript. Most of us are using similar tools, but how are we using them? (That's an invitation to jump in on the comments, folks.) Every UI person I know develops prototypes in Firefox and Firebug, crossing his or her fingers that there won't be too many implementation-specific issues to tackle in the other browsers. Many rely on a logging utility - heir to that long-ago popup window - to grind away at any such browser bugs.

But beyond that kind of hunt-and-peck debugging, have we arrived at an industry-standard practice for client-side code maintenance? Who's doing true TDD with one of the flavors of JsUnit? Who's using Selenium to test their entire webapp in the browser? Who's picking apart the details of their syntax with Douglas Crockford's JsLint? Who's busting out Fangs or another accessibility test tool on a regular basis? The tools are out there. It would be interesting to know who's using them, and how.

When you're banging your head against a wall trying to figure out why a certain DOM element won't return the same node type from one browser to the next, it's easy to see why there are a hundred competing Ajax frameworks promising to solve all your cross-browser issues for you. Let's just remember how far we've come - and how important it is for real-deal UI developers to maintain the skills that they've honed for over a decade. The more trust we put in frameworks, the more helpless we'll feel when our code fails and we've lost the ability to figure out why.

2007 Predictions Coming True? - The Coming Browser Revolution

At the beginning of the year, I made a few predictions about Ajax in 2007. In particular, I predicted that

Microsoft and Mozilla will add new features to their browsers to extend Ajax support. These features will address things like cross site scripting (making it easier and more secure), security, widgets standards support, extensions of Javascript, etc. The browser will evolve into more of an application platform than it is now.

That doesn't really seem to be happening, from what I can tell, since Firefox 4 won't be available until 2008, and Firefox 3 is making only modest changes on the Ajax front. It's too soon to say anything about IE8.

InfoWorld has a breathless article about the revolutionary changes coming in Firefox 3. A careful reading of the article, however, shows that most of the really interesting changes are planned for Firefox 4, such as support for Javascript 2.

You can read the detailed feature list for Firefox 3 here, in the form of a Google Spreadsheet. It doesn't look like either of the two features -- web services as Mime-type handlers and SQL Lite for offline storage -- are in Alpha 2, but hopefully they'll show up in the next release.

What these two new features might look like isn't exactly clear from the planning documents, but they should take their direction from section 5 of the WhatWG specification on Web Applications 1.0.

The registerProtocolHandler() method allows Web sites to register themselves as possible handlers for particular protocols. For example, an online fax service could register itself as a handler of the fax: protocol ([RFC2806]), so that if the user clicks on such a link, he is given the opportunity to use that Web site. Analogously, the registerContentHandler() method allows Web sites to register themselves as possible handlers for content in a particular MIME type. For example, the same online fax service could register itself as a handler for image/g3fax files ([RFC1494]), so that if the user has no native application capable of handling G3 Facsimile byte streams, his Web browser can instead suggest he use that site to view the image.

At the simplest level, when a particular Mime type is encountered, a web application will be launched, instead of the usual desktop application. The feature list, however, states that Firefox 3 will Support web services as MIME type handlers. That sounds a little bit different from what the WhatWG spec provides.

All Ajax-enabled web developers should take an interest in browser standards and developments. The future of their profession depends upon it.

Technorati : , , , ,

Whither Canvas?

This world is but canvas to our imaginations. -- Henry David Thoreau

First support for the WhatWG canvas element was announced by Apple in Safari, then it was included in Opera and Firefox. A little while back, Emil did a cool hack with VML to produce a subset of functionality as canvas for IE. There was a rumor that google would release this or some other code as its Canvas for IE solution, and it sort of has, landing with a thud over at sourceforge with a Google Code imprimature.

There have been no apparent developments since then. It doesn't seem to have been widely tested, is much slower than canvas in Firefox, and has enough differences and functional gaps to make integrating it with Javascript libraries that build on the canvas tag somewhat difficult.

There don't appear to be any plans to support canvas in IE7, but things can change quickly over there, apparently. So, do you support canvas in IE with an impressive piece of late night hackery like Emil's work, or is support for canvas just not there yet -- a really nice feature not supported effectively for 90% of the web browsing public?

I'm leaning toward the latter. What do you think?


Technorati : , ,