Agile Ajax

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

Comments: 2 so far

  1. ooh I really like that you are breaking JSON out into it’s own file, I have been including 2 different versions of JSON in my project because of this! I will try and look at it soon and give some feedback.

    Thanks for all your hard work.

    Comment by Treu, Tuesday, October 23, 2007 @ 2:47 pm

  2. Brian,

    I saw your comment on my blog about my RSH redo and realized that you wrote for Agile Ajax. I thought it appropriate to answer your question here:

    “Did you find a way around this problem (the issue with replacing document.write with standard DOM methods), or were you only testing your solution while staying within your own app?”

    No, I did not find a solution. It had slipped my mind to try to leave the site and come back and, yes, it is broken with my method. I have also, been debugging forward button issues in IE, which are probably related to this. Let me know if you ever find a way around it.

    Also, a warning. If you modeled your IFRAME creation after me, it will error in IE 6 on SSL servers:

    iframe = getBodyElement().appendChild(document.createElement(’iframe’));
    iframe.id = ‘DhtmlHistoryFrame’;
    iframe.name = ‘DhtmlHistoryFrame’;
    iframe.src = ‘blank.html?’ + initialHash;
    iframe.style.border = ‘0px’;
    iframe.style.bottom = ‘0px’;
    iframe.style.height = ‘1px’;
    iframe.style.position = ‘absolute’;
    iframe.style.right = ‘0px’;
    iframe.style.visibility = ‘visible’;
    iframe.style.width = ‘1px’;

    The problem is that the IFRAME is appended to the document with an empty SRC attribute, which IE treats as coming from a non-secure source. To fix this move the append to the end; I changed:

    iframe = document.appendChild(document.createElement(’iframe’));

    to:

    iframe = document.createElement(’iframe’);

    and added to the end of the code block:

    getBodyElement().appendChild(iframe);

    the “getBodyElement” function is just an X-Browser method I use to find the body tag.

    Comment by matt snider, Tuesday, October 23, 2007 @ 5:00 pm

Leave a comment

Powered by WP Hashcash

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics

WordPress

Comments about this site: info@pathf.com