-
Get a monthly update on best practices for delivering successful software.
Progress on Really Simple History is progressing nicely, though I'm taking a break this week to finish up my presentation for next week's O'Reilly Web 2.0 Expo in San Francisco (more on that tomorrow).
In taking RSH one step closer to a 1.0 release, I am basically re-writing everything from the ground up. My objectives include the following:
Topics: Ajax Bookmarking, Really Simple History
Speaking of Really Simple History....
While perusing John Resig's widely discussed analysis of IE8, I was surprised by his lack of fanfare when discussing its support of HTML 5's Ajax navigation module. This is a major development in the arena of Ajax history and bookmark management.
John's comments:
HTML 5: window.location.hash
Already supported fairly well by most browsers. Modifying window.location.hash changes the page URL and adds the page to the history (allowing for back-button simulation in Ajax applications). IE went a step further and broadcasts the hashchanged event (the first browser to do so, as far as I know).
Topics: Ajax Bookmarking, IE8, Javascript, Really Simple History
Besides providing a useful tool to other developers, my chief interest in taking over Brad Neuberg's Really Simple History was to test the limits of my own JavaScript and browser-hacking skills. Version 0.6 was basically a maintenance release designed to acquaint the library with the browsers that had come of age since its initial 2005 release. The forthcoming 0.8 will be more of a redesign, adding new functionality while taking advantage of more modern JavaScript programming idioms. Lazy function definitions will improve performance, while closures and internal functions will lock down several methods that are currently public but need to be private.
Andrew Mattie is also hard at work modernizing his own Ajax history library: dsHistory, which just came out with a new release. I've been playing around with dsHistory, and I have to say I'm impressed. The differentiating feature of Really Simple History is its ability to maintain history states even after the user navigates away to other sites and back again. The unique thing about dsHistory, however, is its ability to bind the back button to arbitrary JavaScript functions without touching the URL fragment identifier. It's always interesting to see how other developers solve the same problems, often by slightly reframing them. Their differing outlooks make the two libraries suitable for different audiences, but there's also a lot of common ground.
Topics: Ajax Bookmarking, Really Simple History
Things have been quiet on the Really Simple History front for the last month or so. But progress is continuing behind the scenes, albeit slowly. The forthcoming 0.8 release, which I had hoped to complete by the end of December, now looks more likely for February. What can I say? A little thing called the holidays got in the way. The good news? I'm one marathon weekend session away from completing the required feature work, refactoring and cross-browser testing.
Speaking of marathon weekend sessions, I should point out that all of my development on Really Simple History has been funded by my employer, Pathfinder Development. I've sunk at least 160 person-hours into the library so far - and that's a pretty conservative estimate. I have spent many long weekdays and weekends working on RSH instead of doing Pathfinder R&D or working on paid client projects. I'm therefore happy to announce that RSH now has a page on the Pathfinder website. More importantly, Pathfinder is now offering my services as an RSH/Ajax history consultant. Paid consulting on RSH will help us fund continued development of the library. (Read the announcement here.)
Topics: Ajax Bookmarking, Really Simple History
A week after wondering whether title updates were worth the trouble in Really Simple History, I'm reconsidering my opinion. It turns out a couple of users had already tackled this problem and come up with some solutions to the worst issues. (That will teach me to post about RSH without keeping up to date on my own Google Group and issue tracker.) At this point I have Firefox, IE and Safari working. Opera is proving to be a bigger challenge.
My original problem was that when a user clicks the back button to
land on a previous history point, RSH can't update the document title
until the history change is already complete. That means the browser's
history entry for the new hash gets set to the document title that
matches the previous hash. The trick - as pointed out in the comments here
- is to simply reload the current hash after the title change is
complete each time a history callback gets triggered. That causes the
browser history stack to replace the incorrect title with the correct
one. This seems to do the trick in Safari and Firefox. The code looks
like this:
Topics: Ajax Bookmarking, Really Simple History
One of the features I want to implement for Really Simple History 0.8 - based on requests from the RSH Google Group - is automatic updates of the document title. When the hash changes, so will the title, guaranteeing that bookmarks, the history menu and the dropdowns on the back and forward buttons all give relevant information about each discrete page state. Instead of bookmarking a page with a generic title such as "My Email Program," you'll get something useful, like "My Email Program: Inbox" or "My Email Program: Drafts."
Initial implementation was easy. When you add a history point in RSH, you pass in an optional JSON hash of supplementary data that can be recovered for the duration of that session. This historyData object was the most sensible place to pass in a new document title, so I added a method to inspect the historyData of any given history point, look for a member called newTitle, and dynamically update the title. I also got a little fancy and gave the user the option to set a base title with a replacement parameter so that they didn't have to keep passing in the name of their website with each history point. The new method looked like this:
changeTitle: function(historyData) {
/*change the document title if called to do so*/
if (historyData && historyData.newTitle) {
/*Plug new title into the base title or use it raw if none is found*/
var winTitle = this.baseTitle
? this.baseTitle.replace('@@@', historyData.newTitle)
: historyData.newTitle
;/*IE history is keyed off the iframe, so we need to update its title, too*/
if (this.isIE) {
this.iframe.contentWindow.document.title = winTitle;
}
document.title = winTitle;
}
},
Then, I just needed to add code to delegate to the new changeTitle method each time a history point was added or a history event fired. The changes to my add method looked like this:
add: function(newLocation, historyData) {
if (this.isSafari) {//EXISTING CODE HERE
this.changeTitle(historyData);
} else {
var that = this;
var addImpl = function() {
//EXISTING CODE HERE
that.changeTitle(historyData);
};/*Now queue up this add request*/
window.setTimeout(addImpl, this.currentWaitTime);/*Indicate that the next request will have to wait for awhile*/
this.currentWaitTime = this.currentWaitTime + this.waitTime;
}
},
The changes to my fireHistoryEvent method looked like this:
fireHistoryEvent: function(newHash) {
var decodedHash = decodeURIComponent(newHash)
/*extract the value from our history storage for this hash*/
var historyData = historyStorage.get(decodedHash);this.changeTitle(historyData);
/*call our listener*/
this.listener.call(null, decodedHash, historyData);
},
Playing around with various test pages and RSH applications, I was happy with my work. Each time I added a history point or clicked the back button, my page title updated to exactly what I wanted it to. Then things got tricky. To put my new method through its paces, I started navigating back and forward through the history stack and inspecting the back and forward dropdowns each time. Things quickly got weird. Page titles that had previously appeared correct in these dropdowns were getting updated with the wrong values. You'd go to a history point with a title such as "Inbox" and instead you'd see the "Drafts" page. It took some playing around, but I finally realized why.
Each time the back or forward button gets clicked, the document title for the page that is coming off of the history stack to become the current document gets reset to the current document title. (This only happens when the history changes involve new hash values on the same base URL.) The document title doesn't get set when a document moves out of the current document position, but rather when it moves into the current document position.
That's a real problem for RSH and other history managers. Because RSH is essentially reactive - waiting for history changes to occur via back or forward and then working its magic - there's no way to change the document title before the history change occurs. So as a page that's already in the history stack becomes the current page, it gets assigned the the wrong title. This behavior manifests itself a little differently in various browsers - especially IE, whose history-stack page titles get set by a hidden iframe - but it's an issue in all of them. Setting a title when a history point gets added: no problem. Setting a title after a history change has occurred: too late.
The new feature does get a couple of things right: The title in the browser title bar always reflects the current state of the application, and bookmarks always reflect the correct title. (By the time a user is able to bookmark a page state, the title has already been updated to reflect that state.) Two out of three ain't bad - right?
I'm a little torn as to where to go from here. Is this really a feature rather than a bug if it improves some aspects of the browsing experience while degrading others? At least when the history stack shows the same document title 10 times in a row, the only sin is a lack of information. With this new feature enabled, the history stack reports wrong information. The user who tries to find a specific page state in the history stack will end up with the wrong place and quickly grow annoyed.
I've given some thought about how this state of affairs could be improved, but any potential solutions would vastly complicate the fireHistoryEvent method. You'd have to intercept each history change, change the document title to the correct value, change the hash back to the previous hash so that the correct title would get set in the history stack, then change the hash again. I'll probably implement this functionality just to see whether it's possible and how weird the flicker looks in the address bar. But it seems like a lot of extra code - and extra testing - for something that's not essential to history management.
If any RSH users want to play around with the code and offer solutions, I'm all ears. The provisional changes are part of the latest code in the Google Code SVN repo.
Topics: Ajax Bookmarking, Really Simple History
Really Simple History 0.6 rolled over this morning from release candidate into final production code. All previous versions are now considered deprecated. The production version of 0.6 is exactly the same as RC1, but it includes more complete release notes and a minified version of rsh.js. (Much respect to Dojo ShrinkSafe!)
I'd like to extend thanks to the many tireless beta-testers who have put RSH through its paces over the last couple of months. Thanks also to the many developers whose work on other Ajax history frameworks has informed my own. Most of all, thanks to Brad Neuberg for initiating the project and allowing me to get my grubby little paw prints all over it.
As always, you can download RSH from its home at Google Code and participate in the RSH community at its Google Group.
The roadmap from 0.6 to 1.0 is taking shape:
0.8 will become available for beta testing by the end of the year. It will include the following enhancements and changes:
1.0 is scheduled for 2008 Q1. It will include full jsUnit and Selenium test coverage.
Topics: Ajax Bookmarking, Really Simple History
I committed several weeks ago to roll Really Simple History 0.6 RC1 over into a final release on Dec. 1. That's still the plan, but I'm having trouble resisting the urge to tinker. I'm starting to see how a project like this could remain in indefinite limbo if I don't just draw a line in the sand and release a final "hard" version that people can rely on for production code. The current SVN trunk includes a number of backwards-compatible enhancements. I'm working hard to test them all as comprehensively as possible, but I'm going to avoid adding risk to 0.6. Instead, I'll save them for 0.7, which will come out in beta before Christmas.
The enhancements targeted for 0.7, some of them already complete, include the following:
The roadmap for 1.0 includes the following:
In the meantime, downloads for 0.6 RC1 have crept to just under 350 almost 700. Look for me to "flip the switch" on Saturday, promote 0.6 to the stable production version, and deprecate 0.4 once and for all.
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
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.
We'll provide a minified version of the stable release for download. We'll also provide links to sample apps. That's it.
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.
Point your browsers to Google Code for the new home of Really Simple History, the Ajax bookmarking and back-button library I recently agreed to take over from creator Brad Neuberg.
I just got back from vacation and spent today diving into the code, which hasn't been versioned in a couple of years. I've already gotten some great feedback and suggestions from users who have hacked the library since its last update. I expect to get a new version out in the next few weeks, so keep the requests and comments coming.
Topics: Ajax Bookmarking, Really Simple History
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!
Topics: Ajax Bookmarking, Ajax Frameworks, Back Button, Browsers, Firefox, Frameworks, IE, IE6, IE7, Javascript Libraries, Opera, Really Simple History, Safari, Webkit