Using JSON Objects as RSH Location

In the past year, many sites have upgraded to use AJAX, loading dynamic content to their sites with JavaScript and some server side data format. This is a huge boon, to the UI as it is no longer the click and wait paradigm of Web 1.0. However, the downside of JavaScript loaded, dynamic content is that is not bookmarkable and breaks the history flow the client browser.

At the end of last year, we saw many companies competing to produce the best JavaScript history manager, including big names like Google and YAHOO. In the coming year, I believe most AJAX sites will start including a history mechanism. I am putting my support behind Really Simple History (RSH). As, I have mentioned before, RSH is simple, clean, and easy to use. It is also getting continued support by Brian Dillard of Agile Ajax.

Really Simple History

RSH is easy to use, and I believe Brian does a good job at explaining how it works. For the rest of this article, I will assume, you have everything included properly and understand basically how RSH works. You might have written code that looks something like the following for managing history on a page:

Example 1: RSH Module Example

var pageController = function() {
	
	// pageController Module Constant Variables
	
	var DEFAULT_LOC = {"param1":"value1", "param2": "value2", "param3": "value3"},
		LOC_PREFIX = location:; // default JSON object for location
	
	// pageController Module Local Variables
	
	var F = function() {},
		that = null;
	
	
	// pageController Module Event Namespace
	
	var evt = {
	
	
		/**
		 * Example event that adds a history value
		 *
		 * @method ajaxEventExample
		 * @param e {event} the triggered event
		 * @private
		 */
		ajaxEventExample: function(e) {
			// some logic on the event
			// assume logic creates value1, value2, and value3
			var loc = PREFIX + {"param1":" + value1 + ", "param2": " + value2 + ", "param3": " + value3 + "};
			dhtmlHistory.add(loc, null);
		},

		/**
		 * A function that is called whenever the user presses the back or forward buttons. This function will be passed the newLocation,
         *     as well as any history data we associated with the location.
		 *
		 * @method onChangeHistory
         * @param newLocation {string} the location
         * @param historyDate {object} the history
		 * @private
         */
		onChangeHistory(newLocation, historyData) {
			var loc = unescape(newLocation) || LOC_PREFIX + DEFAULT_LOC;
			
			if (loc && window.location.hash !== loc && -1 < window.location.indexOf(LOC_PREFIX)) {
				var json = unescape(loc.replace(LOC_PREFIX, )).parseJSON() || DEFAULT_LOC.parseJSON();
				that.updateWidgetFunction(json.param1, json.param2, json.param3);
			}
		}
	};
	
	
	// Public Functions and Variables
	
	F.prototype = {
	
	
		/**
		 * An example update method
		 *
		 * @method updateWidgetFunction
		 * @param param1 {string} value1 from location JSON
		 * @param param2 {string} value2 from location JSON
		 * @param param3 {string} value3 from location JSON
		 * @public
		 */
		updateWidgetFunction: function(param1, param2, param3) {
			// update logic
		}
	};
	
	// scope that variable to this
	that = new F();
	
	/** START - RSH SETUP LOGIC **/

	// add history listener function
	dhtmlHistory.addListener(evt.onChangeHistory);

	// fetch the current location, if any
	var initialLocation = dhtmlHistory.getCurrentLocation();

	// if no location specified, use the default
	if (initialLocation) {
		evt.onChangeHistory(initialLocation, null);
	}
	
	/** STOP - RSH SETUP LOGIC **/
	
	// return public methods
	return that;
}();

This example shows a complete template for using RSH included in a page controller. Modify this to your liking and include it as the last file on your page (if not the end, then at least after rsh.js is included) to get RSH to work. Now lets discuss how to use JSON with RSH:

First, prefix all locations with a unique string; in this example we use location: as the prefix. The prefix is important for filtering "window.hash" changes so they do not break your code, as your history code path wont execute if the location prefix is not present. It also, helps for readability of the location portion of the URL.

Second, when we use the history (add and update) we convert our parameters to a JSON object in String format. "json.js" will be included in the project anyway (or an equivalent package) for use with RSH, so you can leverage it to convert JSON objects to and from strings, otherwise, you can do it manually as I have in the add function. It is important to unescape the retrieved location in the history callback function as the history code will have escaped it before adding it to "window.hash".

Using these techniques you can now store your RSH location history as a JSON object, which is helpful if you typically use JSON objects to store JavaScript data or you were simply confused how this worked. If you prefer JSON objects, then you will have to do one less conversion in your code, and JSON objects are a robust and well-known format.

Hopefully, you also now have the understanding of RSH to modify this code to support storing the history as a query string or some other mechanism. Feel free to comment if you have any questions.

xJson Object Continued (Part II)

Today we are concluding our discussion of the xJSON object package. You should have read the following two articles and know what Model.js does, and understand the "extend" function with super class inheritance: Improving Extend With SuperXJSON ObjectsDownload the most up-to-date xJSON package. There are 4 JSON models in this package: JsonArray, JsonObject, XJsonArray, and XJsonObject. As a recap, the xJSON Objects are used to improve the performance of large, ...

xJson Objects

Alright everyone, I have finished the xJSON object suite, or at least a decent first pass. This was a bigger project than I expected and I apologize for dragging it out over the past couple weeks. It seemed like every time I was about to finish, I would uncover a corner case that would break an entire second of the project. Anyway, I was away over the passed weekend and had to do a lot ...

Issues with JsonArray

My goal today was to finish most of the models that I have been working on and share this with you. However, it is turning out to be a much more complicated problem than I originally thought. I want the JsonArray object to dynamically create JsonObjects (as necessary) when retrieving elements out of the array. However, the JsonObject declaration requires that you know what Object is being passed, and more importantly, what keys to expect. ...

JsonObject Model Prototype

I have been doing a lot of server-side work in PHP and JAVA this past month. One of the design practices used by server-side webapp languages is the MVC (model-view-controller) framework. An MVC makes writing extensible and scalable code, much easier. In JavaScript I have seen a couple of attempts at a similar MVC framework, but most of the time it is overkill or poorly implemented. Shutterfly.com on the other-hand, has a lot ...