/src/main/webapp/public/js/lib/jquery.history.js

http://thoughtsite.googlecode.com/ · JavaScript · 165 lines · 120 code · 17 blank · 28 comment · 41 complexity · d035c1f13f1795e6d739cd045d6dfb9b MD5 · raw file

  1. /*
  2. * jQuery history plugin
  3. *
  4. * sample page: http://www.mikage.to/jquery/jquery_history.html
  5. *
  6. * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari)
  7. * Licensed under the MIT License:
  8. * http://www.opensource.org/licenses/mit-license.php
  9. *
  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.
  12. */
  13. jQuery.extend({
  14. historyCurrentHash: undefined,
  15. historyCallback: undefined,
  16. historyIframeSrc: undefined,
  17. historyNeedIframe: jQuery.browser.msie && (jQuery.browser.version < 8 || document.documentMode < 8),
  18. historyInit: function(callback, src){
  19. jQuery.historyCallback = callback;
  20. if (src) jQuery.historyIframeSrc = src;
  21. var current_hash = location.hash.replace(/\?.*$/, '');
  22. jQuery.historyCurrentHash = current_hash;
  23. if (jQuery.historyNeedIframe) {
  24. // To stop the callback firing twice during initilization if no hash present
  25. if (jQuery.historyCurrentHash == '') {
  26. jQuery.historyCurrentHash = '#';
  27. }
  28. // add hidden iframe for IE
  29. jQuery("body").prepend('<iframe id="jQuery_history" style="display: none;"'+
  30. ' src="javascript:false;"></iframe>'
  31. );
  32. var ihistory = jQuery("#jQuery_history")[0];
  33. var iframe = ihistory.contentWindow.document;
  34. iframe.open();
  35. iframe.close();
  36. iframe.location.hash = current_hash;
  37. }
  38. else if (jQuery.browser.safari) {
  39. // etablish back/forward stacks
  40. jQuery.historyBackStack = [];
  41. jQuery.historyBackStack.length = history.length;
  42. jQuery.historyForwardStack = [];
  43. jQuery.lastHistoryLength = history.length;
  44. jQuery.isFirst = true;
  45. }
  46. if(current_hash)
  47. jQuery.historyCallback(current_hash.replace(/^#/, ''));
  48. setInterval(jQuery.historyCheck, 100);
  49. },
  50. historyAddHistory: function(hash) {
  51. // This makes the looping function do something
  52. jQuery.historyBackStack.push(hash);
  53. jQuery.historyForwardStack.length = 0; // clear forwardStack (true click occured)
  54. this.isFirst = true;
  55. },
  56. historyCheck: function(){
  57. if (jQuery.historyNeedIframe) {
  58. // On IE, check for location.hash of iframe
  59. var ihistory = jQuery("#jQuery_history")[0];
  60. var iframe = ihistory.contentDocument || ihistory.contentWindow.document;
  61. var current_hash = iframe.location.hash.replace(/\?.*$/, '');
  62. if(current_hash != jQuery.historyCurrentHash) {
  63. location.hash = current_hash;
  64. jQuery.historyCurrentHash = current_hash;
  65. jQuery.historyCallback(current_hash.replace(/^#/, ''));
  66. }
  67. } else if (jQuery.browser.safari) {
  68. if(jQuery.lastHistoryLength == history.length && jQuery.historyBackStack.length > jQuery.lastHistoryLength) {
  69. jQuery.historyBackStack.shift();
  70. }
  71. if (!jQuery.dontCheck) {
  72. var historyDelta = history.length - jQuery.historyBackStack.length;
  73. jQuery.lastHistoryLength = history.length;
  74. if (historyDelta) { // back or forward button has been pushed
  75. jQuery.isFirst = false;
  76. if (historyDelta < 0) { // back button has been pushed
  77. // move items to forward stack
  78. for (var i = 0; i < Math.abs(historyDelta); i++) jQuery.historyForwardStack.unshift(jQuery.historyBackStack.pop());
  79. } else { // forward button has been pushed
  80. // move items to back stack
  81. for (var i = 0; i < historyDelta; i++) jQuery.historyBackStack.push(jQuery.historyForwardStack.shift());
  82. }
  83. var cachedHash = jQuery.historyBackStack[jQuery.historyBackStack.length - 1];
  84. if (cachedHash != undefined) {
  85. jQuery.historyCurrentHash = location.hash.replace(/\?.*$/, '');
  86. jQuery.historyCallback(cachedHash);
  87. }
  88. } else if (jQuery.historyBackStack[jQuery.historyBackStack.length - 1] == undefined && !jQuery.isFirst) {
  89. // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
  90. // document.URL doesn't change in Safari
  91. if (location.hash) {
  92. var current_hash = location.hash;
  93. jQuery.historyCallback(location.hash.replace(/^#/, ''));
  94. } else {
  95. var current_hash = '';
  96. jQuery.historyCallback('');
  97. }
  98. jQuery.isFirst = true;
  99. }
  100. }
  101. } else {
  102. // otherwise, check for location.hash
  103. var current_hash = location.hash.replace(/\?.*$/, '');
  104. if(current_hash != jQuery.historyCurrentHash) {
  105. jQuery.historyCurrentHash = current_hash;
  106. jQuery.historyCallback(current_hash.replace(/^#/, ''));
  107. }
  108. }
  109. },
  110. historyLoad: function(hash){
  111. var newhash;
  112. hash = decodeURIComponent(hash.replace(/\?.*$/, ''));
  113. if (jQuery.browser.safari) {
  114. newhash = hash;
  115. }
  116. else {
  117. newhash = '#' + hash;
  118. location.hash = newhash;
  119. }
  120. jQuery.historyCurrentHash = newhash;
  121. if (jQuery.historyNeedIframe) {
  122. var ihistory = jQuery("#jQuery_history")[0];
  123. var iframe = ihistory.contentWindow.document;
  124. iframe.open();
  125. iframe.close();
  126. iframe.location.hash = newhash;
  127. jQuery.lastHistoryLength = history.length;
  128. jQuery.historyCallback(hash);
  129. }
  130. else if (jQuery.browser.safari) {
  131. jQuery.dontCheck = true;
  132. // Manually keep track of the history values for Safari
  133. this.historyAddHistory(hash);
  134. // Wait a while before allowing checking so that Safari has time to update the "history" object
  135. // correctly (otherwise the check loop would detect a false change in hash).
  136. var fn = function() {jQuery.dontCheck = false;};
  137. window.setTimeout(fn, 200);
  138. jQuery.historyCallback(hash);
  139. // N.B. "location.hash=" must be the last line of code for Safari as execution stops afterwards.
  140. // By explicitly using the "location.hash" command (instead of using a variable set to "location.hash") the
  141. // URL in the browser and the "history" object are both updated correctly.
  142. location.hash = newhash;
  143. }
  144. else {
  145. jQuery.historyCallback(hash);
  146. }
  147. }
  148. });