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 (59 Posts: )

discussion by DISQUS 41 Comments

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

Sort:
Comments 1 – 20 of 41:
  • reply
    Avatar
    thanh luan
    said 2 years ago (1 Point)
    hi,

    my code is

    <script src="jscripts/mootools.js"></script> (version 1.2)

    function changePage(page,id,parent,type) {
    var jsonRequest = new Request.JSON({url: "getData.php?id="+id+"&parentid="+parent+"&type="+type, onComplete: function(json,resText){

    $('pleft').set('html','<img src="'+ json.imagelarge + '">');
    $('prtcont').set('html',json.description);
    $('prbottom').set('html','<img src="'+ json.image + '">');
    var strCen= '  <img src="images/node.jpg"> ' + json.name + '
    ';
    for(var i=0;i<json.numchild;i++) <br="" {=""> strCen+= '    <img src="images/node.jpg"> ' + json[i].pc_name + '
    ';

    }
    if (json.idback!=-100) {
    strCen+= '
    <div align="right" style="margin-right:5px;"><img src="images/back.png"></div>
    ';
    }
    $('pcenter').set('html',strCen);
    }}).send();


    }



    index
    product
    news


    how can i use back button with your historymanager? </json.numchild;i++)>
  • reply
    Avatar
    said 2 years ago (1 Point)
    if only it worked with v1.2
  • reply
    Avatar
    mt85
    said 2 years ago (1 Point)
    Hy

    My Accordion will not work with the version 1.2.
    I tried it also with the modified versions of historymanager.
    Could anyone help me?

    Thanks
  • reply
    Avatar
    said 2 years ago (1 Point)
    I updated to mootools 1.2.2 http://gist.github.com/129829
  • reply
    Avatar
    brian bobek
    replied 2 years ago (1 Point)
    Not sure if this works in Safari 3 (mac), but in Safari 4 in fails in a big way. Note to all: I removed the webkit conditionals in getState and setState and that took care of it.

    See -- http://www.springfieldnuclear....
  • reply
    Avatar
    brian bobek
    replied 2 years ago (1 Point)
    Also (or more importantly) I made it compatible with IE8.
  • reply
    Avatar
    peterpunk 1 Point
    replied 2 years ago (1 Point)
    I got your changes, I will continue with safari support. thanks
  • reply
    Avatar
    peterpunk 1 Point
    replied 2 years ago (1 Point)
    I tested with safari 3.21 and 4 and works fine without the safari code, may be no working with safari 2.0 I will check it out soon.
  • reply
    Avatar
    perrohunter 2 Points
    said 3 years ago (1 Point)
    Let me see if I get this right, I can only use a hash that I can match with a regexp ?

    Can I use a different hash with every request ?
    #example
    #another-site
    #learning-history-manager
    ?
  • reply
    Avatar
    said 3 years ago (1 Point)
    I made a version compatible with 1.2[.1]:
    http://lotosdesign.ru/HistoryM...

    Works just as the previous one.
    Notice: DomReady is needed
  • reply
    Avatar
    Pat
    replied 2 years ago (1 Point)
    Nice work Ruslan, been waiting for a while for a 1.2 release.

    IE didnt work for me until I changed "window.ie" to "Browser.Engine.trident" on lines 205 and 274, not sure if that effects you as well.

    Thankyou Ruslan and Harald!
  • reply
    Avatar
    luckyB
    replied 2 years ago (1 Point)
    Hi, thanks to Harald and to Ruslan for the compatible version with mootools 1.2.

    it works very fine but i have got a little problem with ie8 RC1(the same problem can be seen with the version 1.1 of mootool) : in fact, the states curl.
    for exemple if i do:
    state 1 -> state 2 -> state 3
    first back send me to state 2 (perfect :-) )
    but second back send me to state 3 again
    a third back send me to step 2 agin...

    if someone could help: i really don't understand why it is doing tha way...

    in fact, i tried gmail and it is not working fine with ie8 too...
    perhaps the trick does'nt work with this new version of ie :-(
  • reply
    Avatar
    luckyB
    replied 2 years ago (1 Point)
    For the moment, i have in the head of my pages:
    <meta content="IE=7" http-equiv="X-UA-Compatible">
    and it works fine like that.

    perhaps someone could find something better...
  • reply
    Avatar
    perrohunter 2 Points
    replied 3 years ago (1 Point)
    yep ! and example would be wonderful :)
  • reply
    Avatar
    replied 3 years ago (1 Point)
    It Is possible a little example??
  • reply
    Avatar
    Matty
    said 3 years ago (1 Point)
    Hallo Harald,

    deine Scripts sind echt die aller besten. Allerdings hab ich ein Problem mit dem HistoryManager. Das vor und zurück navigieren anhand der Browser-Buttons funktioniert prächtig (also die URL ändert sich in der Adresszeile auch dementsprechend) ... Refreshe ich die Seite jedoch (per Button oder F5) wird zwar der richtige Content zur eigentlichen URL dargestellt.. jedoch ist in der Adresszeile nur ein "#" und nicht "#show(meineSeite)" zusehen ... hast du eine Idee warum er hier die "Parameter" verschluckt?

    Danke ... achja nutze den Firefox 2.1 irgendwas.
  • reply
    Avatar
    Schlum
    said 3 years ago (1 Point)
    any progress on update to v1.2?
    thanks!!!
  • reply
    Avatar
    michalc 1 Point
    said 3 years ago (1 Point)
    This is great: I've tried it out and it seems to work great! This is exactly what I've been looking for.
  • reply
    Avatar
    michalc 1 Point
    replied 3 years ago (1 Point)
    Oh... this was meant to be in reply to Clem's Unofficial update thread. (But of course the original HistoryManager is great) I think the logging in thingy doesn't work well if you reply to a post, but then need to login. It seems to post it as a new thread.
  • reply
    Avatar
    said 3 years ago (1 Point)
    Great work ! A History Manager for version 1.2 would be greater !
Comments 1 – 20 of 41:

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