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 167 168
|
/*
* jQuery history plugin
*
* sample page: http://www.mikage.to/jquery/jquery_history.html
*
* Copyright (c) 2006-2009 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.
*/
jQuery.extend({
historyCurrentHash: undefined,
historyCallback: undefined,
historyIframeSrc: undefined,
historyInit: function(callback, src){
jQuery.historyCallback = callback;
if (src) jQuery.historyIframeSrc = src;
var current_hash = location.hash.replace(/\?.*$/, '');
jQuery.historyCurrentHash = current_hash;
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
if (jQuery.browser.msie) {
// To stop the callback firing twice during initilization if no hash present
if (jQuery.historyCurrentHash == '') {
jQuery.historyCurrentHash = '#';
}
// add hidden iframe for IE
jQuery("body").prepend('<iframe id="jQuery_history" style="display: none;"'+
(jQuery.historyIframeSrc ? ' src="'+jQuery.historyIframeSrc+'"' : '')
+'></iframe>'
);
var ihistory = jQuery("#jQuery_history")[0];
var iframe = ihistory.contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = current_hash;
}
else if (jQuery.browser.safari) {
// etablish back/forward stacks
jQuery.historyBackStack = [];
jQuery.historyBackStack.length = history.length;
jQuery.historyForwardStack = [];
jQuery.lastHistoryLength = history.length;
jQuery.isFirst = true;
}
if(current_hash)
jQuery.historyCallback(current_hash.replace(/^#/, ''));
setInterval(jQuery.historyCheck, 100);
},
historyAddHistory: function(hash) {
// This makes the looping function do something
jQuery.historyBackStack.push(hash);
jQuery.historyForwardStack.length = 0; // clear forwardStack (true click occured)
this.isFirst = true;
},
historyCheck: function(){
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
if (jQuery.browser.msie) {
// On IE, check for location.hash of iframe
var ihistory = jQuery("#jQuery_history")[0];
var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
var current_hash = iframe.location.hash.replace(/\?.*$/, '');
if(current_hash != jQuery.historyCurrentHash) {
location.hash = current_hash;
jQuery.historyCurrentHash = current_hash;
jQuery.historyCallback(current_hash.replace(/^#/, ''));
}
} else if (jQuery.browser.safari) {
if(jQuery.lastHistoryLength == history.length && jQuery.historyBackStack.length > jQuery.lastHistoryLength) {
jQuery.historyBackStack.shift();
}
if (!jQuery.dontCheck) {
var historyDelta = history.length - jQuery.historyBackStack.length;
jQuery.lastHistoryLength = history.length;
if (historyDelta) { // back or forward button has been pushed
jQuery.isFirst = false;
if (historyDelta < 0) { // back button has been pushed
// move items to forward stack
for (var i = 0; i < Math.abs(historyDelta); i++) jQuery.historyForwardStack.unshift(jQuery.historyBackStack.pop());
} else { // forward button has been pushed
// move items to back stack
for (var i = 0; i < historyDelta; i++) jQuery.historyBackStack.push(jQuery.historyForwardStack.shift());
}
var cachedHash = jQuery.historyBackStack[jQuery.historyBackStack.length - 1];
if (cachedHash != undefined) {
jQuery.historyCurrentHash = location.hash.replace(/\?.*$/, '');
jQuery.historyCallback(cachedHash);
}
} else if (jQuery.historyBackStack[jQuery.historyBackStack.length - 1] == undefined && !jQuery.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 (location.hash) {
var current_hash = location.hash;
jQuery.historyCallback(location.hash.replace(/^#/, ''));
} else {
var current_hash = '';
jQuery.historyCallback('');
}
jQuery.isFirst = true;
}
}
} else {
// otherwise, check for location.hash
var current_hash = location.hash.replace(/\?.*$/, '');
if(current_hash != jQuery.historyCurrentHash) {
jQuery.historyCurrentHash = current_hash;
jQuery.historyCallback(current_hash.replace(/^#/, ''));
}
}
},
historyLoad: function(hash){
var newhash;
hash = decodeURIComponent(hash.replace(/\?.*$/, ''));
if (jQuery.browser.safari) {
newhash = hash;
}
else {
newhash = '#' + hash;
location.hash = newhash;
}
jQuery.historyCurrentHash = newhash;
// if ((jQuery.browser.msie) && (jQuery.browser.version < 8)) {
if (jQuery.browser.msie) {
var ihistory = jQuery("#jQuery_history")[0];
var iframe = ihistory.contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = newhash;
jQuery.lastHistoryLength = history.length;
jQuery.historyCallback(hash);
}
else if (jQuery.browser.safari) {
jQuery.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() {jQuery.dontCheck = false;};
window.setTimeout(fn, 200);
jQuery.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;
}
else {
jQuery.historyCallback(hash);
}
}
});
|