2
* jQuery history plugin
4
* sample page: http://www.mikage.to/jquery/jquery_history.html
6
* Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
7
* Licensed under the MIT License:
8
* http://www.opensource.org/licenses/mit-license.php
10
* Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization
11
* for msie when no initial hash supplied.
16
historyCurrentHash: undefined,
17
historyCallback: undefined,
18
historyIframeSrc: undefined,
20
historyInit: function(callback, src){
21
jQuery.historyCallback = callback;
22
if (src) jQuery.historyIframeSrc = src;
23
var current_hash = location.hash.replace(/\?.*$/, '');
25
jQuery.historyCurrentHash = current_hash;
26
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
27
if (jQuery.browser.msie) {
28
// To stop the callback firing twice during initilization if no hash present
29
if (jQuery.historyCurrentHash == '') {
30
jQuery.historyCurrentHash = '#';
33
// add hidden iframe for IE
34
jQuery("body").prepend('<iframe id="jQuery_history" style="display: none;"'+
35
(jQuery.historyIframeSrc ? ' src="'+jQuery.historyIframeSrc+'"' : '')
38
var ihistory = jQuery("#jQuery_history")[0];
39
var iframe = ihistory.contentWindow.document;
42
iframe.location.hash = current_hash;
44
else if (jQuery.browser.safari) {
45
// etablish back/forward stacks
46
jQuery.historyBackStack = [];
47
jQuery.historyBackStack.length = history.length;
48
jQuery.historyForwardStack = [];
49
jQuery.lastHistoryLength = history.length;
51
jQuery.isFirst = true;
54
jQuery.historyCallback(current_hash.replace(/^#/, ''));
55
setInterval(jQuery.historyCheck, 100);
58
historyAddHistory: function(hash) {
59
// This makes the looping function do something
60
jQuery.historyBackStack.push(hash);
62
jQuery.historyForwardStack.length = 0; // clear forwardStack (true click occured)
66
historyCheck: function(){
67
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
68
if (jQuery.browser.msie) {
69
// On IE, check for location.hash of iframe
70
var ihistory = jQuery("#jQuery_history")[0];
71
var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
72
var current_hash = iframe.location.hash.replace(/\?.*$/, '');
73
if(current_hash != jQuery.historyCurrentHash) {
75
location.hash = current_hash;
76
jQuery.historyCurrentHash = current_hash;
77
jQuery.historyCallback(current_hash.replace(/^#/, ''));
80
} else if (jQuery.browser.safari) {
81
if(jQuery.lastHistoryLength == history.length && jQuery.historyBackStack.length > jQuery.lastHistoryLength) {
82
jQuery.historyBackStack.shift();
84
if (!jQuery.dontCheck) {
85
var historyDelta = history.length - jQuery.historyBackStack.length;
86
jQuery.lastHistoryLength = history.length;
88
if (historyDelta) { // back or forward button has been pushed
89
jQuery.isFirst = false;
90
if (historyDelta < 0) { // back button has been pushed
91
// move items to forward stack
92
for (var i = 0; i < Math.abs(historyDelta); i++) jQuery.historyForwardStack.unshift(jQuery.historyBackStack.pop());
93
} else { // forward button has been pushed
94
// move items to back stack
95
for (var i = 0; i < historyDelta; i++) jQuery.historyBackStack.push(jQuery.historyForwardStack.shift());
97
var cachedHash = jQuery.historyBackStack[jQuery.historyBackStack.length - 1];
98
if (cachedHash != undefined) {
99
jQuery.historyCurrentHash = location.hash.replace(/\?.*$/, '');
100
jQuery.historyCallback(cachedHash);
102
} else if (jQuery.historyBackStack[jQuery.historyBackStack.length - 1] == undefined && !jQuery.isFirst) {
103
// back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
104
// document.URL doesn't change in Safari
106
var current_hash = location.hash;
107
jQuery.historyCallback(location.hash.replace(/^#/, ''));
109
var current_hash = '';
110
jQuery.historyCallback('');
112
jQuery.isFirst = true;
116
// otherwise, check for location.hash
117
var current_hash = location.hash.replace(/\?.*$/, '');
118
if(current_hash != jQuery.historyCurrentHash) {
119
jQuery.historyCurrentHash = current_hash;
120
jQuery.historyCallback(current_hash.replace(/^#/, ''));
124
historyLoad: function(hash){
126
hash = decodeURIComponent(hash.replace(/\?.*$/, ''));
128
if (jQuery.browser.safari) {
132
newhash = '#' + hash;
133
location.hash = newhash;
135
jQuery.historyCurrentHash = newhash;
137
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
138
if (jQuery.browser.msie) {
139
var ihistory = jQuery("#jQuery_history")[0];
140
var iframe = ihistory.contentWindow.document;
143
iframe.location.hash = newhash;
144
jQuery.lastHistoryLength = history.length;
145
jQuery.historyCallback(hash);
147
else if (jQuery.browser.safari) {
148
jQuery.dontCheck = true;
149
// Manually keep track of the history values for Safari
150
this.historyAddHistory(hash);
152
// Wait a while before allowing checking so that Safari has time to update the "history" object
153
// correctly (otherwise the check loop would detect a false change in hash).
154
var fn = function() {jQuery.dontCheck = false;};
155
window.setTimeout(fn, 200);
156
jQuery.historyCallback(hash);
157
// N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards.
158
// By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the
159
// URL in the browser and the "history" object are both updated correctly.
160
location.hash = newhash;
163
jQuery.historyCallback(hash);