This repository has been archived by the owner on Nov 25, 2020. It is now read-only.
/
proto.history.js
158 lines (145 loc) · 5.47 KB
/
proto.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
/*
* jQuery history plugin ported for Prototype
*
* 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.
*
* Modified by Charles du Jeu to port code to Prototype library instead of jQuery
*/
Proto.History = Class.create({
historyCurrentHash: undefined,
historyCallback: undefined,
initialize:function(callback){
this.historyCallback = callback;
var current_hash = location.hash;
this.historyCurrentHash = current_hash;
if(Prototype.Browser.IE){
// To stop the callback firing twice during initilization if no hash present
if(this.historyCurrentHash == ''){
this.historyCurrentHash = '#';
}
bod = document.getElementsByTagName('body')[0];
var iframe = new Element('iframe');
iframe.writeAttribute('id', 'prototype_history').writeAttribute("style", "display:none;");
bod.appendChild(iframe);
iframe = $("prototype_history").contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = current_hash;
}
else if (Prototype.Browser.WebKit)
{
// etablish back/forward stacks
this.historyBackStack = [];
this.historyBackStack.length = history.length;
this.historyForwardStack = [];
this.isFirst = true;
}
//this.historyCallback(current_hash.replace(/^#/, ''));
new PeriodicalExecuter(function(){
this.historyCheck();
}.bind(this), 0.2);
},
historyAddHistory: 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;
},
historyCheck: function(){
if(Prototype.Browser.IE){
// On IE, check for location.hash of iframe
var iframe = $('prototype_history').contentDocument || $('prototype_history').contentWindow.document;
var current_hash = iframe.location.hash;
if(current_hash != this.historyCurrentHash) {
location.hash = current_hash;
this.refreshFavicon();
this.historyCurrentHash = current_hash;
this.historyCallback(current_hash.replace(/^#/, ''));
}
}else if (Prototype.Browser.WebKit) {
if (!this.dontCheck) {
var historyDelta = history.length - this.historyBackStack.length;
if (historyDelta) { // back or forward button has been pushed
this.isFirst = false;
if (historyDelta < 0) { // back button has been pushed
// move items to forward stack
for (var i = 0; i < Math.abs(historyDelta); i++) this.historyForwardStack.unshift(this.historyBackStack.pop());
} else { // forward button has been pushed
// move items to back stack
for (var i = 0; i < historyDelta; i++) this.historyBackStack.push(this.historyForwardStack.shift());
}
var cachedHash = this.historyBackStack[this.historyBackStack.length - 1];
if (cachedHash != undefined) {
this.historyCurrentHash = location.hash;
this.historyCallback(cachedHash);
}
} else if (this.historyBackStack[this.historyBackStack.length - 1] == undefined && !this.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) {
this.historyCallback(document.URL.split('#')[1]);
} else {
var current_hash = location.hash;
this.historyCallback('');
}
this.isFirst = true;
}
}
} else {
// otherwise, check for location.hash
var current_hash = location.hash;
if(current_hash != this.historyCurrentHash) {
this.historyCurrentHash = current_hash;
this.historyCallback(current_hash.replace(/^#/, ''));
}
}
},
historyLoad: function(hash){
var newhash;
if (Prototype.Browser.WebKit) {
newhash = hash;
}
else {
newhash = '#' + hash;
location.hash = newhash;
this.refreshFavicon();
}
this.historyCurrentHash = newhash;
if(Prototype.Browser.IE) {
var iframe = $("prototype_history").contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = newhash;
//this.historyCallback(hash);
}
else if (Prototype.Browser.WebKit) {
this.dontCheck = true;
// Manually keep track of the history values for Safari
this.historyAddHistory(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() {this.dontCheck = false;}.bind(this);
window.setTimeout(fn, 200);
//this.historyCallback(hash);
// 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;
this.refreshFavicon();
}
else {
//this.historyCallback(hash);
}
},
refreshFavicon : function(){
if(!Prototype.Browser.Gecko) return;
var link = $$('link[type="image/x-png"]')[0].remove();
$$('head')[0].insert('<link href="' + link.href + '" type="image/x-png" rel="icon">');
delete link;
}
});