-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.history.js
166 lines (146 loc) · 5.4 KB
/
jquery.history.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* jQuery history plugin
*
* Copyright (c) 2006 Taku Sano (Mikage Sawatari)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* Modified by Lincoln Cooper to add Safari support and only call the callback once during initialization
* for msie when no initial hash supplied.
* API rewrite by Lauris Buk�is-Haberkorns
*/
(function($) {
function History()
{
this._curHash = '';
this._callback = function(hash){};
this._callbackParams = {};
};
$.extend(History.prototype, {
init: function(callback, state, callbackParams) {
this._callback = callback;
this._callbackParams = callbackParams;
this._curHash = location.hash;
if($.browser.msie) {
// To stop the callback firing twice during initilization if no hash present
if (this._curHash == '') {
this._curHash = '#';
}
// add hidden iframe for IE
$("body").prepend('<iframe id="jQuery_history" style="display: none;"></iframe>');
var iframe = $("#jQuery_history")[0].contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = this._curHash;
}
else if ($.browser.safari) {
// etablish back/forward stacks
this._historyBackStack = [];
this._historyBackStack.length = history.length;
this._historyForwardStack = [];
this._isFirst = true;
this._dontCheck = false;
}
this._callback(this._curHash.replace(/^#/, ''), state, callbackParams, 'init');
var that = this;
setInterval(function(){
that._check(state, callbackParams);
}, 100);
},
add: function(hash) {
// This makes the looping function do something
this._historyBackStack.push(hash);
this._historyForwardStack.length = 0; // clear forwardStack (true click occured)
this._isFirst = true;
},
_check: function(callbackParams) {
var thisFunction = arguments.callee;
if (!thisFunction.count) thisFunction.count = 0;
++thisFunction.count;
if($.browser.msie) {
// On IE, check for location.hash of iframe
var ihistory = $("#jQuery_history")[0];
var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
var current_hash = iframe.location.hash;
if(current_hash != $.history._curHash) {
location.hash = current_hash;
$.history._curHash = current_hash;
$.history._callback(current_hash.replace(/^#/, ''), 'check', '', callbackParams);
}
} else if ($.browser.safari) {
if (!$.history._dontCheck) {
var historyDelta = history.length - $.history._historyBackStack.length;
if (historyDelta) { // back or forward button has been pushed
$.history._isFirst = false;
if (historyDelta < 0) { // back button has been pushed
// move items to forward stack
for (var i = 0; i < Math.abs(historyDelta); i++) $.history._historyForwardStack.unshift($.history._historyBackStack.pop());
} else { // forward button has been pushed
// move items to back stack
for (var i = 0; i < historyDelta; i++) $.history._historyBackStack.push($.history._historyForwardStack.shift());
}
var cachedHash = $.history._historyBackStack[$.history._historyBackStack.length - 1];
if (cachedHash != undefined) {
$.history._curHash = location.hash;
$.history._callback(cachedHash, 'check', '', callbackParams);
}
} else if ($.history._historyBackStack[$.history._historyBackStack.length - 1] == undefined && !$.history._isFirst) {
// back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
// document.URL doesn't change in Safari
if (document.URL.indexOf('#') >= 0) {
$.history._callback(document.URL.split('#')[1], 'check', '', callbackParams);
} else {
$.history._callback('', 'check', '');
}
$.history._isFirst = true;
}
}
} else {
// otherwise, check for location.hash
var current_hash = location.hash;
if(current_hash != $.history._curHash) {
$.history._curHash = current_hash;
$.history._callback(current_hash.replace(/^#/, ''), 'check', '', callbackParams);
}
}
},
load: function(hash) {
var newhash;
if ($.browser.safari) {
newhash = hash;
} else {
newhash = '#' + hash;
location.hash = newhash;
}
this._curHash = newhash;
if ($.browser.msie) {
var ihistory = $("#jQuery_history")[0]; // TODO: need contentDocument?
var iframe = ihistory.contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = newhash;
this._callback(hash, 'load', this._callbackParams);
}
else if ($.browser.safari) {
this._dontCheck = true;
// Manually keep track of the history values for Safari
this.add(hash);
// Wait a while before allowing checking so that Safari has time to update the "history" object
// correctly (otherwise the check loop would detect a false change in hash).
var fn = function() {$.history._dontCheck = false;};
window.setTimeout(fn, 200);
this._callback(hash, 'load', this._callbackParams);
// N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards.
// By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the
// URL in the browser and the "history" object are both updated correctly.
location.hash = newhash;
}
else {
this._callback(hash, 'load', this._callbackParams, 'loooooooloooool'+arguments[0]);
}
}
});
$(document).ready(function() {
$.history = new History(); // singleton instance
});
})(jQuery);