HistoryManager - The Ajax Back-Button (v1.0)

HistoryManager is an unobtrusive MooTools plugin to allow history handling for multiple modules. It solves the typical “Back-Button” and “Ajax Bookmarks” problems for accessible browsing and a better usability in Rich Internet applications.

Showcases:

Showcase “Multiple Widgets”

Complex example with multiple widgets and implementations.

The Action Happens Here

Example is a Pagination class which just updates the number.

Pagination Examples

Please browser our non-existing product list.
Jump to Page 10
Or imagine some creative images here:

Accordion with History

Abstract
Nulla ligula. Pharetra elementum sed in arcu, orci vestibulum consequat nibh dictumst vivamus nunc, erat id eget viverra ipsum, posuere diam quam sit occaecat. Mollis quisque aliquam. Ante magna pulvinar, justo mauris congue nibh in cursus ut, sociis aliquam ac donec lorem tempor arcu, potenti nulla fames in sit euismod sagittis. Fringilla ipsum donec rhoncus. In parturient eu at pretium dignissim nunc, orci arcu lorem nulla.
How to use it
Gravida sit, ullamcorper at eros quisque sed. Et sodales tempor morbi, et ut quisque vel diam, vestibulum et volutpat velit sodales quam bibendum, amet massa lacus ac volutpat condimentum. Turpis arcu neque eros wisi dapibus, aliquam orci egestas et tellus in, urna et risus, quis habitant justo commodo pede ut, dictum vitae diam semper mauris suspendisse fusce. Id aliquam imperdiet sed, sed in non tellus rutrum consequat, pellentesque sapien adipiscing ullamcorper amet, tortor phasellus sociis orci, molestie quam ut donec enim. Dui magna nascetur morbi non faucibus, vulputate integer aliquet malesuada arcu in, eget dignissimos, morbi eget a, fusce nunc a.
Documentation
Please read first "How to use it"!
Rutrum ullamcorper ornare blandit sollicitudin hac leo, sed mus turpis vitae phasellus lobortis, donec a, quibusdam facilisis odio. Sed ornare eget mattis, pede integer etiam quis curabitur metus ac. In cras erat hendrerit eget id eros, enim vivamus ac, ultricies eu ipsum nunc magna tincidunt. Urna commodo habitant nonummy ac felis, velit condimentum ultricies sit ac cum. Ac suscipit suspendisse elit dui, rem enim donec justo, amet luctus in mi placerat, feugiat est sapien nec. Aliquam lorem vitae ultrices ultrices a.

Implented with ajaxified Links

Content 1 | Content 2 | Content 3 | Content 4

The Gimmicks

Bookmark this link, its the current state ...

JavaScript & MooTools

 
/**
 * Class PaginationClass
 *
 * Simulates navigation through multiple pages, saving them
 * in a history state.
 */
var PaginationClass = new Class({
 
	initialize: function(el, max) {
		this.element = $(el);
		this.max = max;
 
		this.historyKey = this.element.id + '-page';
		this.history = HistoryManager.register(
			this.historyKey,
			[1],
			function(values) {
				this.to(parseInt(values[0]));
			}.bind(this),
			function(values) {
				return [this.historyKey, '(', values[0], ')'].join('');
			}.bind(this),
			this.historyKey + '\\((\\d+)\\)');
	},
 
	by: function(dir) {
		this.to(this.page + dir);
	},
 
	to: function(page) {
		page = Math.max(Math.min(this.max, page), 1);
		this.page = page;
		this.element.setHTML('Page ', this.page);
		this.history.setValue(0, this.page);
	}
 
});
 
/**
 * Extends Accordion with history state
 */
Accordion = Accordion.extend({
 
	options: {
		id: null,
		useHistory: false
	},
 
	initialize: function(togglers, elements, options) {
		this.setOptions(options);
		this.id = $pick(this.options.id, 'accordion-' + (Accordion.count++));
		if (this.options.useHistory) {
			this.history = HistoryManager.register(
				this.id,
				[this.options.display],
				function(args) { this.display(args[0]); }.bind(this),
				false,
				false);
		}
		return this.parent(togglers, elements, options);
	},
 
	display: function(index) {
		if (this.history) this.history.setValue(0, index);
		this.parent(index);
	}
 
});
 
Accordion.count = 0;
 
window.addEvent('domready', function(){
 
	/**
	 * If you want to set options, set them here, otherwise initialize is
	 * called automatically when the first module is registered
	 */
	HistoryManager.initialize();
 
	/**
	 * First Pagination class
	 */
	var pagi = new PaginationClass('products', 10);
 
	$('b1-1').addEvent('click', function(e) {
		e.stop();
		pagi.by(-1);
	}.bindWithEvent());
 
	$('b1-2').addEvent('click', function(e) {
		e.stop();
		pagi.by(1);
	}.bindWithEvent());
 
	/**
	 * Second Pagination class
	 */
	var pagi2 = new PaginationClass('images', 10);
 
	$('b2-1').addEvent('click', function(e) {
		new Event(e).stop();
		pagi2.by(-1);
	});
 
	$('b2-2').addEvent('click', function(e) {
		new Event(e).stop();
		pagi2.by(1);
	});
 
	/**
	 * The holy Accordion
	 */
	var accordion1 = new Accordion(
		$$('#demo-accordion h5'),
		$$('#demo-accordion div'),
		{id: 'abstract', useHistory: true}
	);
 
 
	/**
	 * Simple example how to save Ajax
	 *
	 * This adds Ajax content loading to all ajaxified links.
	 * All allowed links are saved in hrefs, so we can validate
	 * the data from HistoryManager
	 */
	var ajaxs = $$('a.ajaxified');
 
	// all possible hrefs are here, we use the index
	var hrefs = ajaxs.getProperty('href');
	// no index now
	var currentIndex = -1;
 
	var req = new Ajax('', {
		method: 'get',
		update: $('ajaxified-target'),
		autoCancel: true
	});
 
	var reqHistory = HistoryManager.register(
		'page-index',
		[0], // default, page 0
		function(values) {
			ajaxUpdate(values[0]);
		},
		function(values) {
			return 'page-index(' + values[0] + ')';
		},
		/page-index\((\d+)\)/ // the regexp to match "page-index(0)"
	);
 
	/**
	 * Loads the url (by index) if the index is valid and not the current page
	 */
	function ajaxUpdate(index) {
		var url = hrefs[index] || null;
		if (!url || (currentIndex == index)) return;
 
		// fancy state change with classes
		if (currentIndex != -1) ajaxs[currentIndex].removeClass('ajaxified-selected');
		ajaxs[index].addClass('ajaxified-selected');
 
		currentIndex = index;
 
		// updating the history
		reqHistory.setValue(0, index);
 
		// request
		req.url = url;
		req.request();
	};
 
	ajaxs.each(function(el, i) {
		el.addEvent('click', function(e) {
			if (e) new Event(e).stop();
			ajaxUpdate(i);
		});
	});
	// load first panel
	ajaxs[0].fireEvent('click');
 
	/**
	 * This is an example how to generate a bookmarkable/sendable link on every change
	 */
	var bmLink = $E('a#bookmark');
	HistoryManager.addEvent('onStateChange', function(state) {
		bmLink.setProperty('href', '#' + state).getFirst().setHTML('#' + state);
	});
 
	/**
	 * on start it start checking the hash
	 */
	HistoryManager.start();
 
	/**
	 * Example how to generate a link (with the current states) for one specific target state/module
	 */
	$E('a[href$="#abstract-1"]').setProperty('href', accordion1.history.generate([1]));
 
});

XHTML Markup

<p>Example is a Pagination class which just updates the number.</p>
 
<h4>Pagination Examples</h4>
 
<h5>Please browser our non-existing product list.</h5>
 
<input type="button" value="Previous" id="b1-1" />
<span id="products"></span>
<input type="button" value="Next" id="b1-2" />
 
<a href="#products-page(10)" title="This link ignores the current other states, it sets only one state and resets all others">Jump to Page 10</a>
 
<hr />
 
<h5>Or imagine some creative images here:</h5>
 
<input type="button" value="Previous" id="b2-1" />
<span id="images"></span>
<input type="button" value="Next" id="b2-2" />
 
<h4>Accordion with History</h4>
 
<div id="demo-accordion">
	<h5>Abstract</h5>
	<div>
		Nulla ligula. Pharetra elementum sed in arcu, orci vestibulum consequat nibh dictumst vivamus nunc, erat id eget viverra ipsum, posuere diam quam sit occaecat. Mollis quisque aliquam. Ante magna pulvinar, justo mauris congue nibh in cursus ut, sociis aliquam ac donec lorem tempor arcu, potenti nulla fames in sit euismod sagittis. Fringilla ipsum donec rhoncus. In parturient eu at pretium dignissim nunc, orci arcu lorem nulla.
	</div>
	<h5>How to use it</h5>
	<div>
		Gravida sit, ullamcorper at eros quisque sed. Et sodales tempor morbi, et ut quisque vel diam, vestibulum et volutpat velit sodales quam bibendum, amet massa lacus ac volutpat condimentum. Turpis arcu neque eros wisi dapibus, aliquam orci egestas et tellus in, urna et risus, quis habitant justo commodo pede ut, dictum vitae diam semper mauris suspendisse fusce. Id aliquam imperdiet sed, sed in non tellus rutrum consequat, pellentesque sapien adipiscing ullamcorper amet, tortor phasellus sociis orci, molestie quam ut donec enim. Dui magna nascetur morbi non faucibus, vulputate integer aliquet malesuada arcu in, eget dignissimos, morbi eget a, fusce nunc a.
	</div>
	<h5>Documentation</h5>
	<div>
		Please read first <a href="#abstract-1" title="This Link refers also to the bookmarked state when you entered this site!">"How to use it"</a>!<br />
		Rutrum ullamcorper ornare blandit sollicitudin hac leo, sed mus turpis vitae phasellus lobortis, donec a, quibusdam facilisis odio. Sed ornare eget mattis, pede integer etiam quis curabitur metus ac. In cras erat hendrerit eget id eros, enim vivamus ac, ultricies eu ipsum nunc magna tincidunt. Urna commodo habitant nonummy ac felis, velit condimentum ultricies sit ac cum. Ac suscipit suspendisse elit dui, rem enim donec justo, amet luctus in mi placerat, feugiat est sapien nec. Aliquam lorem vitae ultrices ultrices a.
	</div>
</div>
 
<h4>Implented with ajaxified Links</h4>
 
<a class="ajaxified" href="content1.html">Content 1</a> |
<a class="ajaxified" href="content2.html">Content 2</a> |
<a class="ajaxified" href="content3.html">Content 3</a> |
<a class="ajaxified" href="content4.html">Content 4</a>
<div id="ajaxified-target"></div>
 
<h4>The Gimmicks</h4>
 
<a id="bookmark">Bookmark this link, its the current state ... <span></span></a>

CSS Stylesheet

#demo-accordion h5
{
	cursor:				pointer;
	background-color:	#eee;
	padding:			5px;
	margin:				0;
}
#demo-accordion h5:hover
{
	background-color:	#333;
	color:				#fff;
}
#demo-accordion div
{
	background-color:	#fff;
}
 
.ajaxified-selected
{
	font-weight:		bold;
}
 
#ajaxified-target
{
	padding:			1em;
	height:				250px;
	overflow:			auto;
	border:				1px solid #f5f5f5;
}

This example and the accompanying sources/assets are © 2008-2009 by Harald Kirschner and available under The MIT License. For debugging and profiling the scripts and their markup download Firefox and use addons like Firebug and Web Developer Toolbar.

Share it: Stumble it!Digg This!del.icio.us (No Posts)

discussion by DISQUS No Comments

Please use the support forums for discussing the project, asking questions or posting bug-fixes!

Sort:
No Comments
  • First
  • ‹ Prev
  • Next ›
  • Last
No Comments
  • First
  • ‹ Prev
  • Next ›
  • Last

Post your comment

Please use the support forums for discussing the project, asking questions or posting bug-fixes!


Internet Consultant & Contractor

I'm available to combine forces with you and your team to find the most simple, elegant and convenient web solutions . I await your call.

If you just like my work and want to say Thank You, donate via PayPal or Amazon Wish List.

Developer Resources & Tools