hash.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * hash.js
  3. *
  4. * Copyright (C) 2012 Emmanuel Garcia
  5. * MIT Licensed
  6. *
  7. * ****************************************
  8. *
  9. * Hash.pushState(true);
  10. *
  11. * Hash.on('/page/([0-9]+)$',
  12. * {yep: function(path, parts) { }, nop: function() { }},
  13. * 'Page $1');
  14. *
  15. * Hash.go('/page/1');
  16. **/
  17. (function() {
  18. 'use strict';
  19. var hashes = {},
  20. regexp = {},
  21. history = [],
  22. freq = 100,
  23. num = 0,
  24. pushState = false,
  25. timer = null,
  26. currentUrl = null,
  27. freeze = function(obj) {
  28. if (Object.freeze) return Object.freeze(obj);
  29. return obj;
  30. },
  31. getHashParts = function() {
  32. return window.location.href.split('#');
  33. },
  34. startTimer = function() {
  35. if (!timer)
  36. timer = setInterval(function() {
  37. if (num>0 && currentUrl!=window.location.href) {
  38. currentUrl = window.location.href;
  39. window.Hash.check();
  40. }
  41. }, freq);
  42. },
  43. stopTimer = function() {
  44. if (timer) {
  45. clearInterval(timer);
  46. timer = null;
  47. }
  48. };
  49. window.Hash = freeze({
  50. pushState: function(yes) {
  51. if (window.history && window.history.pushState)
  52. pushState = yes;
  53. return this;
  54. },
  55. fragment: function() {
  56. var hash = getHashParts();
  57. return (pushState) ?
  58. window.location.pathname + ((hash[1]) ? '#' + hash[1] : '')
  59. : hash[1] || '';
  60. },
  61. get: function(path, params) {
  62. var p, fragment = '', parameters = [];
  63. for(p in params) {
  64. if (!Object.prototype.hasOwnProperty(p))
  65. continue;
  66. parameters.push(encodeURIComponent(p) + '=' + encodeURIComponent(params[p]));
  67. }
  68. if (parameters.length>0)
  69. parameters = '?' + parameters.join('&');
  70. return (pushState) ? path + parameters :
  71. getHashParts()[0] + '#' + path + parameters;
  72. },
  73. go: function(hash, params) {
  74. if (this.fragment()!=hash) {
  75. var to = this.get(hash, params);
  76. if (pushState)
  77. window.history.pushState(null, document.title, to);
  78. else
  79. window.location.href = to;
  80. }
  81. return this;
  82. },
  83. update: function () {
  84. currentUrl = window.location.href;
  85. return this;
  86. },
  87. on: function(hash, callback, title) {
  88. if (!hashes[hash])
  89. hashes[hash] = {title: title, listeners: []};
  90. hashes[hash].listeners.push(callback);
  91. num++;
  92. startTimer();
  93. return this;
  94. },
  95. check: function() {
  96. var i,
  97. hash,
  98. parts,
  99. fragment = this.fragment();
  100. for (hash in hashes) {
  101. if (!Object.prototype.hasOwnProperty.call(hashes, hash))
  102. continue;
  103. hashes[hash].regexp = hashes[hash].regexp || new RegExp(hash);
  104. if ((parts = hashes[hash].regexp.exec(fragment))) {
  105. if (hashes[hash].title)
  106. document.title = hashes[hash].title;
  107. for (i = 0; i<hashes[hash].listeners.length; i++)
  108. if (hashes[hash].listeners[i].yep)
  109. hashes[hash].listeners[i].yep(fragment, parts);
  110. } else {
  111. for (i = 0; i<hashes[hash].listeners.length; i++)
  112. if (hashes[hash].listeners[i].nop)
  113. hashes[hash].listeners[i].nop(fragment);
  114. }
  115. }
  116. return this;
  117. }
  118. });
  119. })();