- We design and build extraordinary applications for companies looking to make the next great idea a reality.
- learn more
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'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.
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
500
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.

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."
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:
“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.
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.
Topics: Agile Development, Browsers, Javascript
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.
Topics: Announcement, Browsers, IE8
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:
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.
Web standards won’t get you into heaven
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."
Topics: Browsers, IE, Web Standards
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.
Topics: Ajax Applications, Browsers, Editorial, Firefox, IE, IE6, IE7, Javascript
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.
Topics: Ajax Bookmarking, Ajax Frameworks, Browsers, IE, IE6, IE7, Javascript, Javascript Libraries, jQuery, Really Simple History
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
- Visit the downloads tab at our Google Code repository.
- Join our Google Group for ongoing updates.
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?
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.
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?
Topics: Browsers, Firefox, Firefox Extensions, Google, Safari
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
Topics: Ajax Frameworks, Browsers, Javascript, Really Simple History
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
Topics: Ajax Frameworks, Browsers, Firefox, IE6, IE7, Really Simple History, Safari
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.
Topics: Browsers, CSS, Developer's Notebook
About Pathfinder
Recent
- A Look Back At Past Posts
- Flash Player on iPhone gossip
- Microsoft to Jump on Board EC2
- TAE Boston 2008: The Unsexy Presentations
- The Ajax Experience 2008: Hope to see you in Beantown
- TankEngine: New plugin for Rails iPhone Development
- Simphony of Ruby on Rails and Flex through RubyAMF
- “Build half a product, not a half-assed product” - tips on clarity and focus from Jason Fried of 37Signals
- Rails Performance, Code Metrics, and Locking Down your Application: Tips & Tricks from Windy City Rails 2008
- Betting Your Business on the iPhone
Archives
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006








