compass-jquery-plugin 0.3.2.3 → 0.3.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. data/README.md +54 -37
  2. data/VERSION.yml +1 -1
  3. data/lib/handle_attributes.rb +4 -4
  4. data/lib/handle_js_files.rb +5 -5
  5. data/lib/jqtouch_theme.rb +2 -2
  6. data/lib/jquery/dynatree.rb +2 -2
  7. data/lib/jquery/emulators.rb +1 -1
  8. data/lib/jquery/flash_messages.rb +6 -6
  9. data/lib/jquery/graphics.rb +5 -0
  10. data/lib/jquery/gridify/assertions.rb +1 -1
  11. data/lib/jquery/gridify/grid.rb +76 -59
  12. data/lib/jquery/gridify/grid_column.rb +73 -67
  13. data/lib/jquery/gridify/grid_finder.rb +79 -79
  14. data/lib/jquery/gridify/grid_options.rb +154 -149
  15. data/lib/jquery/gridify/grid_view.rb +143 -143
  16. data/lib/jquery/gridify.rb +25 -25
  17. data/lib/jquery/ical/calendar.rb +2 -2
  18. data/lib/jquery/ical/event.rb +48 -44
  19. data/lib/jquery/ical/helpers/ui_event_helper.rb +3 -3
  20. data/lib/jquery/jqgrid/jqgrid.rb +58 -58
  21. data/lib/jquery/jqgrid.rb +1 -1
  22. data/lib/jquery/jqtouch.rb +1 -1
  23. data/lib/jquery/jquery.rb +117 -117
  24. data/lib/jquery/jquery_auto_complete.rb +9 -9
  25. data/lib/jquery/jquery_json_response.rb +12 -12
  26. data/lib/jquery/jquery_selector_assertions.rb +55 -53
  27. data/lib/jquery/jstree.rb +2 -2
  28. data/lib/jquery/mobile.rb +1 -1
  29. data/lib/jquery/ribbon.rb +2 -2
  30. data/lib/jquery/secret_sauce/controller/ui_dialog_controls.rb +5 -5
  31. data/lib/jquery/secret_sauce/controller/ui_grid_controls.rb +5 -5
  32. data/lib/jquery/secret_sauce/helpers/ui_dialog_helper.rb +1 -1
  33. data/lib/jquery/secret_sauce/helpers/ui_form_helper.rb +39 -39
  34. data/lib/jquery/secret_sauce/helpers/ui_grid_helper.rb +74 -74
  35. data/lib/jquery/secret_sauce/model/find_for_grid.rb +21 -21
  36. data/lib/jquery/secret_sauce.rb +1 -1
  37. data/lib/jquery/tools.rb +1 -1
  38. data/lib/jquery_mobile_theme.rb +2 -2
  39. data/lib/jquery_ui_theme.rb +12 -12
  40. data/templates/dynatree/config/initializers/dynatree.rb +3 -3
  41. data/templates/dynatree/jquery/dynatree/aero.scss +16 -16
  42. data/templates/dynatree/jquery/dynatree/aqua.scss +16 -16
  43. data/templates/dynatree/jquery/dynatree/crystal.scss +16 -16
  44. data/templates/dynatree/jquery/dynatree/xp.scss +17 -17
  45. data/templates/dynatree/jquery.dynatree.js +2926 -2912
  46. data/templates/emulators/config/initializers/emulators.rb +6 -6
  47. data/templates/graphics/config/initializers/graphics.rb +5 -0
  48. data/templates/graphics/jquery/ganttView.scss +89 -0
  49. data/templates/graphics/jquery.ganttView.js +1669 -0
  50. data/templates/graphics/jquery.ganttView.min.js +70 -0
  51. data/templates/{jquery → graphics}/jquery.sparkline.js +466 -438
  52. data/templates/{jquery → graphics}/jquery.sparkline.min.js +0 -0
  53. data/templates/graphics/manifest.rb +9 -0
  54. data/templates/jqgrid/config/initializers/jqgrid.rb +1 -1
  55. data/templates/jqgrid/i18n/jqgrid/locale-ar.js +131 -125
  56. data/templates/jqgrid/i18n/jqgrid/locale-bg.js +135 -131
  57. data/templates/jqgrid/i18n/jqgrid/locale-bg1251.js +135 -131
  58. data/templates/jqgrid/i18n/jqgrid/locale-cat.js +132 -126
  59. data/templates/jqgrid/i18n/jqgrid/locale-cn.js +137 -131
  60. data/templates/jqgrid/i18n/jqgrid/locale-cs.js +133 -127
  61. data/templates/jqgrid/i18n/jqgrid/locale-da.js +132 -126
  62. data/templates/jqgrid/i18n/jqgrid/locale-de.js +138 -132
  63. data/templates/jqgrid/i18n/jqgrid/locale-el.js +131 -125
  64. data/templates/jqgrid/i18n/jqgrid/locale-en.js +133 -127
  65. data/templates/jqgrid/i18n/jqgrid/locale-es.js +133 -127
  66. data/templates/jqgrid/i18n/jqgrid/locale-fa.js +19 -16
  67. data/templates/jqgrid/i18n/jqgrid/locale-fi.js +132 -126
  68. data/templates/jqgrid/i18n/jqgrid/locale-fr.js +131 -125
  69. data/templates/jqgrid/i18n/jqgrid/locale-gl.js +131 -125
  70. data/templates/jqgrid/i18n/jqgrid/locale-he.js +132 -126
  71. data/templates/jqgrid/i18n/jqgrid/locale-hu.js +133 -127
  72. data/templates/jqgrid/i18n/jqgrid/locale-is.js +131 -125
  73. data/templates/jqgrid/i18n/jqgrid/locale-it.js +8 -1
  74. data/templates/jqgrid/i18n/jqgrid/locale-ja.js +139 -136
  75. data/templates/jqgrid/i18n/jqgrid/locale-nl.js +4 -1
  76. data/templates/jqgrid/i18n/jqgrid/locale-no.js +14 -1
  77. data/templates/jqgrid/i18n/jqgrid/locale-pl.js +132 -126
  78. data/templates/jqgrid/i18n/jqgrid/locale-pt-br.js +132 -126
  79. data/templates/jqgrid/i18n/jqgrid/locale-pt.js +130 -124
  80. data/templates/jqgrid/i18n/jqgrid/locale-ro.js +144 -138
  81. data/templates/jqgrid/i18n/jqgrid/locale-ru.js +132 -126
  82. data/templates/jqgrid/i18n/jqgrid/locale-sk.js +132 -126
  83. data/templates/jqgrid/i18n/jqgrid/locale-sr.js +133 -127
  84. data/templates/jqgrid/i18n/jqgrid/locale-sv.js +132 -126
  85. data/templates/jqgrid/i18n/jqgrid/locale-tr.js +131 -125
  86. data/templates/jqgrid/i18n/jqgrid/locale-ua.js +132 -126
  87. data/templates/jqgrid/jquery.jqGrid.js +12735 -10444
  88. data/templates/jqgrid/jquery.jqGrid.min.js +477 -469
  89. data/templates/jqgrid/public/stylesheets/ellipsis-xbl.xml +12 -10
  90. data/templates/jqtouch/config/initializers/jqtouch.rb +3 -3
  91. data/templates/jqtouch/jquery/touch/jqtouch.scss +1 -1
  92. data/templates/jqtouch/jquery.jqtouch.js +10025 -10043
  93. data/templates/jquery/config/initializers/jquery.rb +2 -4
  94. data/templates/jquery/history.adapter.jquery.js +71 -0
  95. data/templates/jquery/history.adapter.jquery.min.js +4 -0
  96. data/templates/jquery/history.html4.js +690 -0
  97. data/templates/jquery/history.html4.min.js +21 -0
  98. data/templates/jquery/history.js +1297 -0
  99. data/templates/jquery/history.min.js +29 -0
  100. data/templates/jquery/i18n/jquery.ui/datepicker-af.js +20 -20
  101. data/templates/jquery/i18n/jquery.ui/datepicker-ar-DZ.js +19 -19
  102. data/templates/jquery/i18n/jquery.ui/datepicker-ar.js +19 -19
  103. data/templates/jquery/i18n/jquery.ui/datepicker-az.js +19 -19
  104. data/templates/jquery/i18n/jquery.ui/datepicker-bg.js +8 -8
  105. data/templates/jquery/i18n/jquery.ui/datepicker-bs.js +20 -20
  106. data/templates/jquery/i18n/jquery.ui/datepicker-ca.js +20 -20
  107. data/templates/jquery/i18n/jquery.ui/datepicker-cs.js +20 -20
  108. data/templates/jquery/i18n/jquery.ui/datepicker-da.js +14 -14
  109. data/templates/jquery/i18n/jquery.ui/datepicker-de.js +20 -20
  110. data/templates/jquery/i18n/jquery.ui/datepicker-el.js +20 -20
  111. data/templates/jquery/i18n/jquery.ui/datepicker-en-AU.js +20 -20
  112. data/templates/jquery/i18n/jquery.ui/datepicker-en-GB.js +20 -20
  113. data/templates/jquery/i18n/jquery.ui/datepicker-en-NZ.js +20 -20
  114. data/templates/jquery/i18n/jquery.ui/datepicker-eo.js +20 -20
  115. data/templates/jquery/i18n/jquery.ui/datepicker-es.js +20 -20
  116. data/templates/jquery/i18n/jquery.ui/datepicker-et.js +20 -20
  117. data/templates/jquery/i18n/jquery.ui/datepicker-eu.js +20 -20
  118. data/templates/jquery/i18n/jquery.ui/datepicker-fa.js +18 -18
  119. data/templates/jquery/i18n/jquery.ui/datepicker-fi.js +15 -15
  120. data/templates/jquery/i18n/jquery.ui/datepicker-fo.js +20 -20
  121. data/templates/jquery/i18n/jquery.ui/datepicker-fr-CH.js +20 -20
  122. data/templates/jquery/i18n/jquery.ui/datepicker-fr.js +22 -22
  123. data/templates/jquery/i18n/jquery.ui/datepicker-gl.js +20 -20
  124. data/templates/jquery/i18n/jquery.ui/datepicker-he.js +20 -20
  125. data/templates/jquery/i18n/jquery.ui/datepicker-hr.js +20 -20
  126. data/templates/jquery/i18n/jquery.ui/datepicker-hu.js +20 -20
  127. data/templates/jquery/i18n/jquery.ui/datepicker-hu.min.js +1 -1
  128. data/templates/jquery/i18n/jquery.ui/datepicker-hy.js +20 -20
  129. data/templates/jquery/i18n/jquery.ui/datepicker-id.js +20 -20
  130. data/templates/jquery/i18n/jquery.ui/datepicker-is.js +20 -20
  131. data/templates/jquery/i18n/jquery.ui/datepicker-it.js +20 -20
  132. data/templates/jquery/i18n/jquery.ui/datepicker-ja.js +20 -20
  133. data/templates/jquery/i18n/jquery.ui/datepicker-ko.js +20 -20
  134. data/templates/jquery/i18n/jquery.ui/datepicker-kz.js +20 -20
  135. data/templates/jquery/i18n/jquery.ui/datepicker-lt.js +20 -20
  136. data/templates/jquery/i18n/jquery.ui/datepicker-lv.js +20 -20
  137. data/templates/jquery/i18n/jquery.ui/datepicker-ml.js +20 -20
  138. data/templates/jquery/i18n/jquery.ui/datepicker-ms.js +20 -20
  139. data/templates/jquery/i18n/jquery.ui/datepicker-nl.js +20 -20
  140. data/templates/jquery/i18n/jquery.ui/datepicker-no.js +16 -16
  141. data/templates/jquery/i18n/jquery.ui/datepicker-no.min.js +2 -2
  142. data/templates/jquery/i18n/jquery.ui/datepicker-pl.js +20 -20
  143. data/templates/jquery/i18n/jquery.ui/datepicker-pt-BR.js +20 -20
  144. data/templates/jquery/i18n/jquery.ui/datepicker-pt.js +20 -20
  145. data/templates/jquery/i18n/jquery.ui/datepicker-rm.js +18 -18
  146. data/templates/jquery/i18n/jquery.ui/datepicker-ro.js +20 -20
  147. data/templates/jquery/i18n/jquery.ui/datepicker-ru.js +20 -20
  148. data/templates/jquery/i18n/jquery.ui/datepicker-sk.js +20 -20
  149. data/templates/jquery/i18n/jquery.ui/datepicker-sl.js +20 -20
  150. data/templates/jquery/i18n/jquery.ui/datepicker-sq.js +20 -20
  151. data/templates/jquery/i18n/jquery.ui/datepicker-sr-SR.js +20 -20
  152. data/templates/jquery/i18n/jquery.ui/datepicker-sr.js +20 -20
  153. data/templates/jquery/i18n/jquery.ui/datepicker-sv.js +14 -14
  154. data/templates/jquery/i18n/jquery.ui/datepicker-ta.js +20 -20
  155. data/templates/jquery/i18n/jquery.ui/datepicker-th.js +20 -20
  156. data/templates/jquery/i18n/jquery.ui/datepicker-tr.js +20 -20
  157. data/templates/jquery/i18n/jquery.ui/datepicker-uk.js +20 -20
  158. data/templates/jquery/i18n/jquery.ui/datepicker-vi.js +20 -20
  159. data/templates/jquery/i18n/jquery.ui/datepicker-zh-CN.js +20 -20
  160. data/templates/jquery/i18n/jquery.ui/datepicker-zh-HK.js +20 -20
  161. data/templates/jquery/i18n/jquery.ui/datepicker-zh-TW.js +20 -20
  162. data/templates/jquery/{partials → jquery/ui}/_flash_messages.scss +0 -0
  163. data/templates/jquery/jquery/ui/_theme.scss +14 -13
  164. data/templates/jquery/jquery/ui/contextMenu/configure.png +0 -0
  165. data/templates/jquery/jquery/ui/contextMenu/copy.png +0 -0
  166. data/templates/jquery/jquery/ui/contextMenu/cut.png +0 -0
  167. data/templates/jquery/jquery/ui/contextMenu/delete.png +0 -0
  168. data/templates/jquery/jquery/ui/contextMenu/edit.png +0 -0
  169. data/templates/jquery/jquery/ui/contextMenu/exit.png +0 -0
  170. data/templates/jquery/jquery/ui/contextMenu/new.png +0 -0
  171. data/templates/jquery/jquery/ui/contextMenu/paste.png +0 -0
  172. data/templates/jquery/jquery/ui/contextMenu/rename.png +0 -0
  173. data/templates/jquery/jquery/ui/contextMenu/show.png +0 -0
  174. data/templates/jquery/jquery/ui/contextMenu/trash.png +0 -0
  175. data/templates/jquery/jquery/ui/contextMenu.scss +16 -10
  176. data/templates/jquery/jquery-ui.js +11839 -23066
  177. data/templates/jquery/jquery-ui.min.js +401 -795
  178. data/templates/jquery/jquery.bgiframe.js +27 -25
  179. data/templates/jquery/jquery.contextMenu.js +209 -196
  180. data/templates/jquery/jquery.cookie.js +3 -1
  181. data/templates/jquery/jquery.dotimeout.js +236 -228
  182. data/templates/jquery/jquery.dst.js +154 -151
  183. data/templates/jquery/jquery.farbtastic.js +293 -293
  184. data/templates/jquery/jquery.flashMessages.js +26 -0
  185. data/templates/jquery/jquery.flashMessages.min.js +1 -0
  186. data/templates/jquery/jquery.form.js +803 -786
  187. data/templates/jquery/jquery.haml.js +248 -247
  188. data/templates/jquery/jquery.hotkeys.js +89 -89
  189. data/templates/jquery/jquery.js +8141 -8106
  190. data/templates/jquery/jquery.layout.js +2451 -2415
  191. data/templates/jquery/jquery.min.js +167 -166
  192. data/templates/jquery/jquery.mousewheel.js +62 -54
  193. data/templates/jquery/jquery.offline.js +171 -171
  194. data/templates/jquery/jquery.pngFix.js +76 -76
  195. data/templates/jquery/jquery.replacetext.js +83 -83
  196. data/templates/jquery/jquery.themeswitchertool.js +202 -177
  197. data/templates/jquery/jquery.tmpl.js +478 -473
  198. data/templates/jquery/jquery.tmplPlus.js +82 -81
  199. data/templates/jquery/jrails.js +178 -175
  200. data/templates/jquery/json.js +77 -7
  201. data/templates/jquery/json2.js +480 -0
  202. data/templates/jquery/json2.min.js +7 -0
  203. data/templates/jquery/lib/tasks/haml.rake +2 -2
  204. data/templates/jquery/manifest.rb +21 -17
  205. data/templates/jstree/jquery.jstree.js +5967 -4536
  206. data/templates/mobile/config/initializers/mobile.rb +1 -1
  207. data/templates/mobile/jquery/mobile/_base.scss +944 -927
  208. data/templates/mobile/jquery/mobile/default.scss +61 -48
  209. data/templates/mobile/jquery/mobile/valencia.scss +56 -42
  210. data/templates/mobile/jquery.mobile.js +4461 -4347
  211. data/templates/mobile/jquery.mobile.min.js +11 -2
  212. data/templates/mobile/lib/tasks/jquery.mobile.rake +12 -12
  213. data/templates/ribbon/config/initializers/ribbon.rb +2 -2
  214. data/templates/ribbon/jquery.ribbon.js +50 -29
  215. data/templates/secret_sauce/secret_sauce.js +8 -8
  216. data/templates/tools/flowplayer.js +945 -1
  217. data/templates/tools/jquery.tools.js +4645 -4335
  218. data/templates/tools/jquery.tools.min.js +37 -37
  219. data/templates/tools/lib/tasks/jquery.tools.rake +4 -4
  220. data/templates/tools/swfobject.js +813 -773
  221. metadata +33 -21
  222. data/templates/jquery/haml.js +0 -506
  223. data/templates/jquery/haml.min.js +0 -5
  224. data/templates/jquery/jquery/ui/contextMenu/door.png +0 -0
  225. data/templates/jquery/jquery/ui/contextMenu/page_white_copy.png +0 -0
  226. data/templates/jquery/jquery/ui/contextMenu/page_white_delete.png +0 -0
  227. data/templates/jquery/jquery/ui/contextMenu/page_white_edit.png +0 -0
  228. data/templates/jquery/jquery/ui/contextMenu/page_white_new.png +0 -0
  229. data/templates/jquery/jquery/ui/contextMenu/page_white_paste.png +0 -0
  230. data/templates/jquery/jquery.compat-1.3.js +0 -291
  231. data/templates/jquery/jquery.compat-1.3.min.js +0 -6
  232. data/templates/jquery/jquery.flash_messages.js +0 -5
  233. data/templates/jquery/jquery.flash_messages.min.js +0 -1
  234. data/templates/jquery/jquery.history.js +0 -194
  235. data/templates/jquery/jquery.history.min.js +0 -5
@@ -0,0 +1,21 @@
1
+ /*
2
+ New BSD License <http://creativecommons.org/licenses/BSD/>
3
+ Public Domain
4
+ @author Benjamin Arthur Lupton <contact@balupton.com>
5
+ @author James Padolsey <https://gist.github.com/527683>
6
+ Public Domain
7
+ @author Benjamin Arthur Lupton <contact@balupton.com>
8
+ */
9
+ (function(h){h.History=h.History||{};h._History=h._History||{};var i=h.document,b=h._History,a=h.History;if(typeof a.initHtml4!=="undefined")throw Error("History.js HTML4 Support has already been loaded...");a.initHtml4=function(){if(typeof a.initHtml5==="undefined"||typeof a.Adapter==="undefined")return false;b.getInternetExplorerMajorVersion=function(){return b.getInternetExplorerMajorVersion.cached=typeof b.getInternetExplorerMajorVersion.cached!=="undefined"?b.getInternetExplorerMajorVersion.cached:
10
+ function(){for(var c=3,d=i.createElement("div"),f=d.getElementsByTagName("i");d.innerHTML="<!--[if gt IE "+ ++c+"]><i></i><![endif]--\>",f[0];);return c>4?c:void 0}()};b.isInternetExplorer=function(){return b.isInternetExplorer.cached=typeof b.isInternetExplorer.cached!=="undefined"?b.isInternetExplorer.cached:b.getInternetExplorerMajorVersion()!==0};a.emulated.hashChange=Boolean(!("onhashchange"in h||"onhashchange"in i)||b.isInternetExplorer()&&b.getInternetExplorerMajorVersion()<8);b.savedHashes=
11
+ [];b.isLastHash=function(c){var d=b.getHashByIndex();return c===d};b.saveHash=function(c){if(b.isLastHash(c))return false;b.savedHashes.push(c);return true};b.getHashByIndex=function(c){var d=null;return d=typeof c==="undefined"?b.savedHashes[b.savedHashes.length-1]:c<0?b.savedHashes[b.savedHashes.length+c]:b.savedHashes[c]};b.stateHashExists=function(c){return typeof b.statesByHash[c]!=="undefined"};b.discardedHashes={};b.discardedStates={};b.discardState=function(c,d,f){a.debug("History.discardState",
12
+ this,arguments);var j=a.contractState(c);b.discardedStates[j]={discardedState:c,backState:f,forwardState:d};return true};b.discardHash=function(c,d,f){a.debug("History.discardState",this,arguments);b.discardedHashes[c]={discardedHash:c,backState:f,forwardState:d};return true};b.discardedState=function(c){c=a.contractState(c);return b.discardedStates[c]||false};b.discardedHash=function(c){return b.discardedHashes[c]||false};b.recycleState=function(c){a.debug("History.recycleState",this,arguments);
13
+ var d=a.contractState(c);b.discardedState(c)&&delete b.discardedStates[d];return true};a.emulated.hashChange&&a.Adapter.onDomLoad(function(){b.checkerFunction=null;if(b.isInternetExplorer()){var c=i.createElement("iframe");c.setAttribute("id","historyjs-iframe");c.style.display="none";i.body.appendChild(c);c.contentWindow.document.open();c.contentWindow.document.close();var d=null,f=null,j=false;b.checkerFunction=function(){if(j){a.debug("hashchange.checker: checker is running");return false}j=true;
14
+ var e=a.getHash(),g=b.unescapeHash(c.contentWindow.document.location.hash);if(e!==d){d=e;if(g!==e){a.debug("hashchange.checker: iframe hash change","documentHash (new):",e,"iframeHash (old):",g);f=e;c.contentWindow.document.open();c.contentWindow.document.close();c.contentWindow.document.location.hash=b.escapeHash(e)}a.Adapter.trigger(h,"hashchange")}else if(g!==f){a.debug("hashchange.checker: iframe hash out of sync","iframeHash (new):",g,"documentHash (old):",e);f=g;a.setHash(g,false)}j=false;return true}}else{d=
15
+ null;b.checkerFunction=function(){var e=a.getHash();if(e!==d){d=e;a.Adapter.trigger(h,"hashchange")}return true}}setInterval(b.checkerFunction,a.options.hashChangeCheckerDelay);return true});if(a.emulated.pushState){b.onHashChange=function(c){a.debug("_History.onHashChange",this,arguments);currentHash=unescape(a.extractHashFromUrl(c&&c.newURL||i.location.href));currentStateHashExits=currentStateHash=currentState=null;if(b.isLastHash(currentHash)){a.debug("_History.onHashChange: no change");a.busy(false);
16
+ return false}b.saveHash(currentHash);currentState=a.expandHash(currentHash);if(!currentState){a.debug("_History.onHashChange: traditional anchor");a.Adapter.trigger(h,"anchorchange");a.busy(false);return false}if(b.isLastState(currentState)){a.debug("_History.onHashChange: no change");a.busy(false);return false}currentStateHash=a.contractState(currentState);a.debug("_History.onHashChange: ","currentStateHash",currentStateHash,"Hash -1",b.getHashByIndex(-1),"Hash -2",b.getHashByIndex(-2),"Hash -3",
17
+ b.getHashByIndex(-3),"Hash -4",b.getHashByIndex(-4),"Hash -5",b.getHashByIndex(-5),"Hash -6",b.getHashByIndex(-6),"Hash -7",b.getHashByIndex(-7));var d=b.discardedState(currentState);if(d){a.debug("forwardState:",a.contractState(d.forwardState),"backState:",a.contractState(d.backState));if(b.getHashByIndex(-2)===a.contractState(d.forwardState)){a.debug("_History.onHashChange: go backwards");a.back(false)}else{a.debug("_History.onHashChange: go forwards");a.forward(false)}a.busy(false);return false}a.debug("_History.onHashChange: success hashchange");
18
+ a.pushState(currentState.data,currentState.title,currentState.url,false);return true};a.Adapter.bind(h,"hashchange",b.onHashChange);a.pushState=function(c,d,f,j){a.debug("History.pushState",this,arguments);if(a.extractHashFromUrl(f))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(j!==false&&a.busy()){a.debug("History.pushState: we must wait",arguments);a.pushQueue({scope:a,callback:a.pushState,args:arguments,queue:j});return false}a.busy(true);var e=
19
+ a.createStateObject(c,d,f),g=a.contractState(e);a.getState();var k=a.getStateHash(),l=unescape(a.getHash());b.storeState(e);b.recycleState(e);if(i.title!==e.title){i.title=e.title;try{i.getElementsByTagName("title")[0].innerHTML=e.title}catch(m){}}a.debug("History.pushState: details","newStateHash:",g,"oldStateHash:",k,"html4Hash:",l);if(g===k){a.debug("History.pushState: no change",g);return false}if(g!==l){a.debug("History.pushState: update hash",g);a.setHash(g,false);return false}b.saveState(e);
20
+ a.debug("History.pushState: trigger popstate");a.Adapter.trigger(h,"statechange");a.busy(false);return true};a.replaceState=function(c,d,f,j){a.debug("History.replaceState",this,arguments);if(a.extractHashFromUrl(f))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(j!==false&&a.busy()){a.debug("History.replaceState: we must wait",arguments);a.pushQueue({scope:a,callback:a.replaceState,args:arguments,queue:j});return false}a.busy(true);var e=a.createStateObject(c,
21
+ d,f),g=a.getState(),k=b.getStateByIndex(-2);b.discardState(g,e,k);a.pushState(e.data,e.title,e.url,false);return true};if(!i.location.hash||i.location.hash==="#")a.Adapter.onDomLoad(function(){a.debug("Internet Explorer Initial State Change Fix");var c=a.createStateObject({},"",i.location.href);a.pushState(c.data,c.title,c.url)});else if(!a.emulated.hashChange){a.debug("Firefox Initial State Change Fix");a.Adapter.onDomLoad(function(){b.onHashChange()})}}};a.initHtml4()})(window);
@@ -0,0 +1,1297 @@
1
+ /**
2
+ * History.js HTML5 Support
3
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
4
+ * @copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com>
5
+ * @license New BSD License <http://creativecommons.org/licenses/BSD/>
6
+ */
7
+
8
+ (function(window,undefined){
9
+
10
+ // --------------------------------------------------------------------------
11
+ // Initialise
12
+
13
+ // History Object
14
+ window.History = window.History||{};
15
+ window._History = window._History||{};
16
+
17
+ // Localise Globals
18
+ var
19
+ console = window.console||undefined, // Prevent a JSLint complain
20
+ document = window.document, // Make sure we are using the correct document
21
+ _History = window._History, // Private History Object
22
+ History = window.History, // Public History Object
23
+ history = window.history; // Old History Object
24
+
25
+ // Check Existence of History.js
26
+ if ( typeof History.initHtml5 !== 'undefined' ) {
27
+ throw new Error('History.js HTML5 Support has already been loaded...');
28
+ }
29
+
30
+ // Initialise
31
+ History.initHtml5 = function(){
32
+
33
+ // ----------------------------------------------------------------------
34
+ // Check Status
35
+
36
+ if ( typeof History.Adapter === 'undefined' ) {
37
+ return false;
38
+ }
39
+
40
+ // ----------------------------------------------------------------------
41
+ // Debug Helpers
42
+
43
+ /**
44
+ * History.options
45
+ * Configurable options
46
+ */
47
+ History.options = {
48
+ /**
49
+ * History.options.hashChangeCheckerDelay
50
+ * How long should the interval be before hashchange checks
51
+ */
52
+ hashChangeCheckerDelay: 100,
53
+ /**
54
+ * History.options.busyDelay
55
+ * How long should we wait between busy events
56
+ */
57
+ busyDelay: 250
58
+ };
59
+
60
+ // ----------------------------------------------------------------------
61
+ // Debug Helpers
62
+
63
+ /**
64
+ * History.debug(message,...)
65
+ * Logs the passed arguments if debug enabled
66
+ */
67
+ History.debug = function(){
68
+ if ( (History.debug.enable||false) ) {
69
+ History.log.apply(History,arguments);
70
+ }
71
+ };
72
+ History.debug.enable = false;
73
+
74
+ /**
75
+ * History.log(message,...)
76
+ * Logs the passed arguments
77
+ */
78
+ History.log = function(){
79
+ // Prepare
80
+ var
81
+ consoleExists = (typeof console !== 'undefined'),
82
+ textarea = document.getElementById('log'),
83
+ message = ("\n"+arguments[0]+"\n"),
84
+ i
85
+ ;
86
+
87
+ // Write to Console
88
+ if ( consoleExists ) {
89
+ var
90
+ args = Array.prototype.slice.call(arguments),
91
+ message = args.shift();
92
+ if ( typeof console.debug !== 'undefined' ) {
93
+ console.debug.apply(console,[message,args]);
94
+ }
95
+ else {
96
+ console.log.apply(console,[message,args]);
97
+ }
98
+ }
99
+
100
+ // Write to log
101
+ for ( i=1,n=arguments.length; i<n; ++i ) {
102
+ var arg = arguments[i];
103
+ if ( typeof arg === 'object' && typeof JSON !== 'undefined' ) {
104
+ try {
105
+ arg = JSON.stringify(arg);
106
+ }
107
+ catch ( Exception ) {
108
+ // Recursive Object
109
+ }
110
+ }
111
+ message += "\n"+arg+"\n";
112
+ }
113
+
114
+ // Textarea
115
+ if ( textarea ) {
116
+ textarea.value += message+"\n-----\n";
117
+ textarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;
118
+ }
119
+ // No Textarea, No Console
120
+ else if ( !consoleExists ) {
121
+ alert(message);
122
+ }
123
+
124
+ // Return true
125
+ return true;
126
+ };
127
+
128
+ // ----------------------------------------------------------------------
129
+ // Emulated Status
130
+
131
+ /**
132
+ * _History.getInternetExplorerMajorVersion()
133
+ * Get's the major version of Internet Explorer
134
+ * @return {integer}
135
+ * @license Public Domain
136
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
137
+ * @author James Padolsey <https://gist.github.com/527683>
138
+ */
139
+ _History.getInternetExplorerMajorVersion = function(){
140
+ var result = _History.getInternetExplorerMajorVersion.cached =
141
+ (typeof _History.getInternetExplorerMajorVersion.cached !== 'undefined')
142
+ ? _History.getInternetExplorerMajorVersion.cached
143
+ : (function(){
144
+ var undef,
145
+ v = 3,
146
+ div = document.createElement('div'),
147
+ all = div.getElementsByTagName('i');
148
+ while (
149
+ div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
150
+ all[0]
151
+ );
152
+ return v > 4 ? v : undef;
153
+ })()
154
+ ;
155
+ return result;
156
+ };
157
+
158
+ /**
159
+ * _History.isInternetExplorer()
160
+ * Are we using Internet Explorer?
161
+ * @return {boolean}
162
+ * @license Public Domain
163
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
164
+ */
165
+ _History.isInternetExplorer = function(){
166
+ var result = _History.isInternetExplorer.cached =
167
+ (typeof _History.isInternetExplorer.cached !== 'undefined')
168
+ ? _History.isInternetExplorer.cached
169
+ : (_History.getInternetExplorerMajorVersion() !== 0)
170
+ ;
171
+ return result;
172
+ };
173
+
174
+ /**
175
+ * History.emulated
176
+ * Which features require emulating?
177
+ */
178
+ History.emulated = {
179
+ pushState: !Boolean(window.history && window.history.pushState && window.history.replaceState)
180
+ };
181
+
182
+ /**
183
+ * _History.isEmptyObject(obj)
184
+ * Checks to see if the Object is Empty
185
+ * @param {Object} obj
186
+ * @return {boolean}
187
+ */
188
+ _History.isEmptyObject = function(obj) {
189
+ for ( var key in obj ) {
190
+ if ( !this.hasOwnProperty(key) ) {
191
+ continue;
192
+ }
193
+ return false;
194
+ }
195
+ return true;
196
+ };
197
+
198
+ /**
199
+ * _History.cloneObject(obj)
200
+ * Clones a object
201
+ * @param {Object} obj
202
+ * @return {Object}
203
+ */
204
+ _History.cloneObject = function(obj) {
205
+ var hash,newObj;
206
+ if ( obj ) {
207
+ hash = JSON.stringify(obj);
208
+ newObj = JSON.parse(hash);
209
+ }
210
+ else {
211
+ newObj = {};
212
+ }
213
+ return newObj;
214
+ };
215
+
216
+ // ----------------------------------------------------------------------
217
+ // State Object Helpers
218
+
219
+ /**
220
+ * History.contractUrl(url)
221
+ * Ensures that we have a relative URL and not a absolute URL
222
+ * @param {string} url
223
+ * @return {string} url
224
+ */
225
+ History.contractUrl = function(url){
226
+ // Prepare
227
+ url = History.expandUrl(url);
228
+
229
+ // Prepare for Base Domain
230
+ var baseDomain = document.location.protocol+'//'+(document.location.hostname||document.location.host);
231
+ if ( document.location.port||false ) {
232
+ baseDomain += ':'+document.location.port;
233
+ }
234
+ baseDomain += '/';
235
+
236
+ // Adjust for Base Domain
237
+ url = url.replace(baseDomain,'/');
238
+
239
+ // Return url
240
+ return url;
241
+ };
242
+
243
+ /**
244
+ * History.expandUrl(url)
245
+ * Ensures that we have an absolute URL and not a relative URL
246
+ * @param {string} url
247
+ * @return {string} url
248
+ */
249
+ History.expandUrl = function(url){
250
+ // Prepare
251
+ url = url||'';
252
+
253
+ // Test for Full URL
254
+ if ( /[a-z]+\:\/\//.test(url) ) {
255
+ // We have a Full URL
256
+ }
257
+
258
+ // Relative URL
259
+ else {
260
+ // Test for Base Page
261
+ if ( url.length === 0 || url.substring(0,1) === '?' ) {
262
+ // Fetch Base Page
263
+ var basePage = document.location.href.replace(/[#\?].*/,'');
264
+
265
+ // Adjust Page
266
+ url = basePage+url;
267
+ }
268
+
269
+ // No Base Page
270
+ else {
271
+
272
+ // Prepare for Base Element
273
+ var
274
+ baseElements = document.getElementsByTagName('base'),
275
+ baseElement = null,
276
+ baseHref = '';
277
+
278
+ // Test for Base Element
279
+ if ( baseElements.length === 1 ) {
280
+ // Prepare for Base Element
281
+ baseElement = baseElements[0];
282
+ baseHref = baseElement.href;
283
+ if ( baseHref[baseHref.length-1] !== '/' ) baseHref += '/';
284
+
285
+ // Adjust for Base Element
286
+ url = baseHref+url.replace(/^\//,'');
287
+ }
288
+
289
+ // No Base Element
290
+ else {
291
+ // Test for Base URL
292
+ if ( url.substring(0,1) === '.' ) {
293
+ // Prepare for Base URL
294
+ var baseUrl = document.location.href.replace(/[#\?].*/,'').replace(/[^\/]+$/,'');
295
+ if ( baseUrl[baseUrl.length-1] !== '/' ) baseUrl += '/';
296
+
297
+ // Adjust for Base URL
298
+ url = baseUrl + url;
299
+ }
300
+
301
+ // No Base URL
302
+ else {
303
+ // Prepare for Base Domain
304
+ var baseDomain = document.location.protocol+'//'+(document.location.hostname||document.location.host);
305
+ if ( document.location.port||false ) {
306
+ baseDomain += ':'+document.location.port;
307
+ }
308
+ baseDomain += '/';
309
+
310
+ // Adjust for Base Domain
311
+ url = baseDomain+url.replace(/^\//,'');
312
+ }
313
+ }
314
+ }
315
+ }
316
+
317
+ // Return url
318
+ return url;
319
+ };
320
+
321
+ /**
322
+ * History.expandState(State)
323
+ * Expands a State Object
324
+ * @param {object} State
325
+ * @return {object}
326
+ */
327
+ History.expandState = function(oldState){
328
+ oldState = oldState||{};
329
+ var newState = {
330
+ 'data': oldState.data||{},
331
+ 'url': History.expandUrl(oldState.url||''),
332
+ 'title': oldState.title||''
333
+ };
334
+ newState.data.title = newState.data.title||newState.title;
335
+ newState.data.url = newState.data.url||newState.url;
336
+ return newState;
337
+ };
338
+
339
+ /**
340
+ * History.createStateObject(data,title,url)
341
+ * Creates a object based on the data, title and url state params
342
+ * @param {object} data
343
+ * @param {string} title
344
+ * @param {string} url
345
+ * @return {object}
346
+ */
347
+ History.createStateObject = function(data,title,url){
348
+ // Hashify
349
+ var State = {
350
+ 'data': data,
351
+ 'title': title,
352
+ 'url': url
353
+ };
354
+
355
+ // Expand the State
356
+ State = History.expandState(State);
357
+
358
+ // Return object
359
+ return State;
360
+ };
361
+
362
+ /**
363
+ * History.expandHash(hash)
364
+ * Expands a Hash into a StateHash if applicable
365
+ * @param {string} hash
366
+ * @return {Object|null} State
367
+ */
368
+ History.expandHash = function(hash){
369
+ // Prepare
370
+ var State = null;
371
+
372
+ // JSON
373
+ try {
374
+ State = JSON.parse(hash);
375
+ }
376
+ catch ( Exception ) {
377
+ var
378
+ parts = /(.*)\/uid=([0-9]+)$/.exec(hash),
379
+ url = parts ? (parts[1]||hash) : hash,
380
+ uid = parts ? String(parts[2]||'') : '';
381
+
382
+ if ( uid ) {
383
+ State = _History.getStateByUid(uid)||null;
384
+ }
385
+
386
+ if ( !State && /\//.test(hash) ) {
387
+ // Is a URL
388
+ var expandedUrl = History.expandUrl(hash);
389
+ State = History.createStateObject(null,null,expandedUrl);
390
+ }
391
+ else {
392
+ // Non State Hash
393
+ // do nothing
394
+ }
395
+ }
396
+
397
+ // Expand
398
+ State = State ? History.expandState(State) : null;
399
+
400
+ // Return State
401
+ return State;
402
+ };
403
+
404
+ /**
405
+ * History.contractState(State)
406
+ * Creates a Hash for the State Object
407
+ * @param {object} passedState
408
+ * @return {string} hash
409
+ */
410
+ History.contractState = function(passedState){
411
+ // Check
412
+ if ( !passedState ) {
413
+ return null;
414
+ }
415
+
416
+ // Prepare
417
+ var
418
+ hash = null,
419
+ State = _History.cloneObject(passedState);
420
+
421
+ // Ensure State
422
+ if ( State ) {
423
+ // Clean
424
+ State.data = State.data||{};
425
+ delete State.data.title;
426
+ delete State.data.url;
427
+
428
+ // Handle
429
+ if ( _History.isEmptyObject(State) && !State.title ) {
430
+ hash = History.contractUrl(State.url);
431
+ }
432
+ else {
433
+ // Serialised Hash
434
+ hash = JSON.stringify(State);
435
+
436
+ // Has it been associated with a UID?
437
+ var uid;
438
+ if ( typeof _History.hashesToUids[hash] !== 'undefined' ) {
439
+ uid = _History.hashesToUids[hash];
440
+ }
441
+ else {
442
+ while ( true ) {
443
+ uid = String(Math.floor(Math.random()*1000));
444
+ if ( typeof _History.uidsToStates[uid] === 'undefined' ) {
445
+ break;
446
+ }
447
+ }
448
+ }
449
+
450
+ // Associate UID with Hash
451
+ _History.hashesToUids[hash] = uid;
452
+ _History.uidsToStates[uid] = State;
453
+
454
+ // Simplified Hash
455
+ hash = History.contractUrl(State.url)+'/uid='+uid;
456
+ }
457
+ }
458
+
459
+ // Return hash
460
+ return hash;
461
+ };
462
+
463
+ /**
464
+ * _History.uidsToStates
465
+ * UIDs to States
466
+ */
467
+ _History.uidsToStates = {};
468
+
469
+ /**
470
+ * _History.hashesToUids
471
+ * Serialised States to UIDs
472
+ */
473
+ _History.hashesToUids = {};
474
+
475
+ /**
476
+ * _History.getStateByUid(uid)
477
+ * Get a state by it's UID
478
+ * @param {string} uid
479
+ */
480
+ _History.getStateByUid = function(uid){
481
+ uid = String(uid);
482
+ var State = _History.uidsToStates[uid]||undefined;
483
+ return State;
484
+ };
485
+
486
+
487
+ // ----------------------------------------------------------------------
488
+ // State Storage
489
+
490
+ /**
491
+ * _History.statesByUrl
492
+ * Store the states indexed by their URLs
493
+ */
494
+ _History.statesByUrl = {};
495
+
496
+ /**
497
+ * _History.duplicateStateUrls
498
+ * Which urls have duplicate states (indexed by url)
499
+ */
500
+ _History.duplicateStateUrls = {};
501
+
502
+ /**
503
+ * _History.statesByHash
504
+ * Store the states indexed by their Hashes
505
+ */
506
+ _History.statesByHash = {};
507
+
508
+ /**
509
+ * _History.savedStates
510
+ * Store the states in an array
511
+ */
512
+ _History.savedStates = [];
513
+
514
+ /**
515
+ * History.getState()
516
+ * Get an object containing the data, title and url of the current state
517
+ * @return {Object} State
518
+ */
519
+ History.getState = function(){
520
+ return _History.getStateByIndex();
521
+ };
522
+
523
+ /**
524
+ * History.getStateHash()
525
+ * Get the hash of the current state
526
+ * @return {string} hash
527
+ */
528
+ History.getStateHash = function(){
529
+ return History.contractState(History.getState());
530
+ };
531
+
532
+ /**
533
+ * _History.getStateByUrl
534
+ * Get a state by it's url
535
+ * @param {string} stateUrl
536
+ */
537
+ _History.getStateByUrl = function(stateUrl){
538
+ var State = _History.statesByUrl[stateUrl]||undefined;
539
+ return State;
540
+ };
541
+
542
+ /**
543
+ * _History.getStateByHash
544
+ * Get a state by it's hash
545
+ * @param {string} stateHash
546
+ */
547
+ _History.getStateByHash = function(stateHash){
548
+ var State = _History.statesByHash[stateHash]||undefined;
549
+ return State;
550
+ };
551
+
552
+ /**
553
+ * _History.storeState
554
+ * Store a State
555
+ * @param {object} State
556
+ * @return {boolean} true
557
+ */
558
+ _History.storeState = function(newState){
559
+ // Prepare
560
+ var
561
+ newStateHash = History.contractState(newState),
562
+ oldState = _History.getStateByUrl(newState.url);
563
+
564
+ // Check for Conflict
565
+ if ( typeof oldState !== 'undefined' ) {
566
+ // Compare Hashes
567
+ var oldStateHash = History.contractState(oldState);
568
+ if ( oldStateHash !== newStateHash ) {
569
+ // We have a conflict
570
+ _History.duplicateStateUrls[newState.url] = true;
571
+ }
572
+ }
573
+
574
+ // Store the State
575
+ _History.statesByUrl[newState.url] = _History.statesByHash[newStateHash] = newState;
576
+
577
+ // Return true
578
+ return true;
579
+ };
580
+
581
+ /**
582
+ * _History.isLastState(newState)
583
+ * Tests to see if the state is the last state
584
+ * @param {Object} newState
585
+ * @return {boolean} isLast
586
+ */
587
+ _History.isLastState = function(newState){
588
+ // Prepare
589
+ var
590
+ newStateHash = History.contractState(newState),
591
+ oldStateHash = History.getStateHash();
592
+
593
+ // Check
594
+ var isLast = _History.savedStates.length && newStateHash === oldStateHash;
595
+
596
+ // Return isLast
597
+ return isLast;
598
+ };
599
+
600
+ /**
601
+ * _History.saveState
602
+ * Push a State
603
+ * @param {Object} newState
604
+ * @return {boolean} changed
605
+ */
606
+ _History.saveState = function(newState){
607
+ // Check Hash
608
+ if ( _History.isLastState(newState) ) {
609
+ return false;
610
+ }
611
+
612
+ // Push the State
613
+ _History.savedStates.push(newState);
614
+
615
+ // Return true
616
+ return true;
617
+ };
618
+
619
+ /**
620
+ * _History.getStateByIndex()
621
+ * Gets a state by the index
622
+ * @param {integer} index
623
+ * @return {Object}
624
+ */
625
+ _History.getStateByIndex = function(index){
626
+ // Prepare
627
+ var State = null;
628
+
629
+ // Handle
630
+ if ( typeof index === 'undefined' ) {
631
+ // Get the last inserted
632
+ State = _History.savedStates[_History.savedStates.length-1];
633
+ }
634
+ else if ( index < 0 ) {
635
+ // Get from the end
636
+ State = _History.savedStates[_History.savedStates.length+index];
637
+ }
638
+ else {
639
+ // Get from the beginning
640
+ State = _History.savedStates[index];
641
+ }
642
+
643
+ // Return State
644
+ return State;
645
+ };
646
+
647
+ /**
648
+ * _History.stateUrlExists
649
+ * Checks if the State Url Exists
650
+ * @param {string} stateUrl
651
+ * @return {boolean} exists
652
+ */
653
+ _History.stateUrlExists = function(stateUrl){
654
+ // Prepare
655
+ var exists = typeof _History.statesByUrl[stateUrl] !== 'undefined';
656
+
657
+ // Return exists
658
+ return exists;
659
+ };
660
+
661
+ /**
662
+ * _History.urlDuplicateExists
663
+ * Check if the url has multiple states associated to it
664
+ * @param {string} stateUrl
665
+ * @return {boolean} exists
666
+ */
667
+ _History.urlDuplicateExists = function(stateUrl){
668
+ var exists = typeof _History.duplicateStateUrls[stateUrl] !== 'undefined';
669
+ return exists;
670
+ };
671
+
672
+
673
+ // ----------------------------------------------------------------------
674
+ // Hash Helpers
675
+
676
+ /**
677
+ * History.getHash()
678
+ * Gets the current document hash
679
+ * @return {string}
680
+ */
681
+ History.getHash = function(){
682
+ var hash = _History.unescapeHash(document.location.hash);
683
+ return hash;
684
+ };
685
+
686
+ /**
687
+ * _History.unescapeHash()
688
+ * Normalise and Unescape a Hash
689
+ * @return {string}
690
+ */
691
+ _History.unescapeHash = function(hash){
692
+ var result = _History.normalizeHash(hash);
693
+
694
+ // Unescape hash
695
+ if ( /[\%]/.test(result) ) {
696
+ result = unescape(result);
697
+ }
698
+
699
+ // Return result
700
+ return result;
701
+ };
702
+
703
+ /**
704
+ * _History.normalizeHash()
705
+ * Normalise a hash across browsers
706
+ * @return {string}
707
+ */
708
+ _History.normalizeHash = function(hash){
709
+ var result = hash.replace(/[^#]*#/,'').replace(/#.*/, '');
710
+
711
+ // Return result
712
+ return result;
713
+ };
714
+
715
+ /**
716
+ * History.setHash(hash)
717
+ * Sets the document hash
718
+ * @param {string} hash
719
+ * @return {string}
720
+ */
721
+ History.setHash = function(hash,queue){
722
+ // Handle Queueing
723
+ if ( queue !== false && History.busy() ) {
724
+ // Wait + Push to Queue
725
+ History.debug('History.setHash: we must wait', arguments);
726
+ History.pushQueue({
727
+ scope: History,
728
+ callback: History.setHash,
729
+ args: arguments,
730
+ queue: queue
731
+ });
732
+ return false;
733
+ }
734
+
735
+ // Prepare
736
+ var adjustedHash = _History.escapeHash(hash);
737
+
738
+ // Log hash
739
+ History.debug('History.setHash',this,arguments,'hash:',hash,'adjustedHash:',adjustedHash,'oldHash:',document.location.hash);
740
+
741
+ // Make Busy + Continue
742
+ History.busy(true);
743
+
744
+ // Apply hash
745
+ document.location.hash = adjustedHash;
746
+
747
+ // Return hash
748
+ return hash;
749
+ };
750
+
751
+ /**
752
+ * _History.escape()
753
+ * Normalise and Escape a Hash
754
+ * @return {string}
755
+ */
756
+ _History.escapeHash = function(hash){
757
+ var result = _History.normalizeHash(hash);
758
+
759
+ // Escape hash
760
+ if ( /[^a-zA-Z0-9\/\-\_\%\.]/.test(result) ) {
761
+ result = escape(result);
762
+ }
763
+
764
+ // Return result
765
+ return result;
766
+ };
767
+
768
+ /**
769
+ * History.extractHashFromUrl(url)
770
+ * Extracts the Hash from a URL
771
+ * @param {string} url
772
+ * @return {string} url
773
+ */
774
+ History.extractHashFromUrl = function(url){
775
+ // Extract the hash
776
+ var hash = String(url)
777
+ .replace(/([^#]*)#?([^#]*)#?(.*)/, '$2')
778
+ ;
779
+
780
+ // Unescape hash
781
+ hash = _History.unescapeHash(hash);
782
+
783
+ // Return hash
784
+ return hash;
785
+ };
786
+
787
+ /**
788
+ * History.isTraditionalAnchor(url)
789
+ * Checks to see if the url is a traditional anchor
790
+ * @param {string} url
791
+ * @return {boolean}
792
+ */
793
+ History.isTraditionalAnchor = function(url){
794
+ var
795
+ hash = History.extractHashFromUrl(url),
796
+ el = document.getElementById(hash),
797
+ isTraditionalAnchor = typeof el !== 'undefined';
798
+
799
+ // Return isTraditionalAnchor
800
+ return isTraditionalAnchor;
801
+ };
802
+
803
+ // ----------------------------------------------------------------------
804
+ // Queueing
805
+
806
+ /**
807
+ * History.queues
808
+ * The list of queues to use
809
+ * First In, First Out
810
+ */
811
+ History.queues = [];
812
+
813
+ /**
814
+ * History.busy(value)
815
+ * @param {boolean} value [optional]
816
+ * @return {boolean} busy
817
+ */
818
+ History.busy = function(value){
819
+ History.debug('History.busy: called: changing ['+(History.busy.flag||false)+'] to ['+(value||false)+']', History.queues);
820
+
821
+ // Apply
822
+ if ( typeof value !== 'undefined' ) {
823
+ History.busy.flag = value;
824
+ }
825
+ // Default
826
+ else if ( typeof History.busy.flag === 'undefined' ) {
827
+ History.busy.flag = false;
828
+ }
829
+
830
+ // Queue
831
+ if ( !History.busy.flag ) {
832
+ // Execute the next item in the queue
833
+ clearTimeout(History.busy.timeout);
834
+ var fireNext = function(){
835
+ if ( History.busy.flag ) return;
836
+ for ( var i=History.queues.length-1; i >= 0; --i ) {
837
+ var queue = History.queues[i];
838
+ if ( queue.length === 0 ) continue;
839
+ var item = queue.shift();
840
+ History.debug('History.busy: firing', item);
841
+ History.fireQueueItem(item);
842
+ History.busy.timeout = setTimeout(fireNext,History.options.busyDelay);
843
+ }
844
+ };
845
+ History.busy.timeout = setTimeout(fireNext,History.options.busyDelay);
846
+ }
847
+
848
+ // Return
849
+ return History.busy.flag;
850
+ };
851
+
852
+ /**
853
+ * History.fireQueueItem(item)
854
+ * Fire a Queue Item
855
+ * @param {Object} item
856
+ * @return {Mixed} result
857
+ */
858
+ History.fireQueueItem = function(item){
859
+ return item.callback.apply(item.scope||History,item.args||[]);
860
+ };
861
+
862
+ /**
863
+ * History.pushQueue(callback,args)
864
+ * Add an item to the queue
865
+ * @param {Object} item [scope,callback,args,queue]
866
+ */
867
+ History.pushQueue = function(item){
868
+ History.debug('History.pushQueue: called', arguments);
869
+
870
+ // Prepare the queue
871
+ History.queues[item.queue||0] = History.queues[item.queue||0]||[];
872
+
873
+ // Add to the queue
874
+ History.queues[item.queue||0].push(item);
875
+
876
+ // End pushQueue closure
877
+ return true;
878
+ };
879
+
880
+ /**
881
+ * History.queue (item,queue), (func,queue), (func), (item)
882
+ * Either firs the item now if not busy, or adds it to the queue
883
+ */
884
+ History.queue = function(item,queue){
885
+ // Prepare
886
+ if ( typeof item === 'function' ) {
887
+ item = {
888
+ callback: item
889
+ };
890
+ }
891
+ if ( typeof queue !== 'undefined' ) {
892
+ item.queue = queue;
893
+ }
894
+
895
+ // Handle
896
+ if ( History.busy() ) {
897
+ History.pushQueue(item);
898
+ } else {
899
+ History.fireQueueItem(item);
900
+ }
901
+
902
+ // End queue closure
903
+ return true;
904
+ };
905
+
906
+
907
+ // ----------------------------------------------------------------------
908
+ // State Aliases
909
+
910
+ /**
911
+ * History.back(queue)
912
+ * Send the browser history back one item
913
+ * @param {Integer} queue [optional]
914
+ */
915
+ History.back = function(queue){
916
+ History.debug('History.back: called', arguments);
917
+
918
+ // Handle Queueing
919
+ if ( queue !== false && History.busy() ) {
920
+ // Wait + Push to Queue
921
+ History.debug('History.back: we must wait', arguments);
922
+ History.pushQueue({
923
+ scope: History,
924
+ callback: History.back,
925
+ args: arguments,
926
+ queue: queue
927
+ });
928
+ return false;
929
+ }
930
+
931
+ // Make Busy + Continue
932
+ History.busy(true);
933
+
934
+ // Fix a bug in IE6,IE7
935
+ if ( History.emulated.hashChange && _History.isInternetExplorer() ) {
936
+ // Prepare
937
+ var currentHash = History.getHash();
938
+
939
+ // Apply Check
940
+ setTimeout(function(){
941
+ var newHash = History.getHash();
942
+ if ( newHash === currentHash ) {
943
+ // No change occurred, try again
944
+ History.debug('History.back: trying again');
945
+ return History.back(false);
946
+ }
947
+ return true;
948
+ },History.options.hashChangeCheckerDelay*5);
949
+ }
950
+
951
+ // Go back
952
+ history.go(-1);
953
+
954
+ // End back closure
955
+ return true;
956
+ };
957
+
958
+ /**
959
+ * History.forward(queue)
960
+ * Send the browser history forward one item
961
+ * @param {Integer} queue [optional]
962
+ */
963
+ History.forward = function(queue){
964
+ History.debug('History.forward: called', arguments);
965
+
966
+ // Handle Queueing
967
+ if ( queue !== false && History.busy() ) {
968
+ // Wait + Push to Queue
969
+ History.debug('History.forward: we must wait', arguments);
970
+ History.pushQueue({
971
+ scope: History,
972
+ callback: History.forward,
973
+ args: arguments,
974
+ queue: queue
975
+ });
976
+ return false;
977
+ }
978
+
979
+ // Make Busy + Continue
980
+ History.busy(true);
981
+
982
+ // Fix a bug in IE6,IE7
983
+ if ( History.emulated.hashChange && _History.isInternetExplorer() ) {
984
+ // Prepare
985
+ var currentHash = History.getHash();
986
+
987
+ // Apply Check
988
+ setTimeout(function(){
989
+ var newHash = History.getHash();
990
+ if ( newHash === currentHash ) {
991
+ // No change occurred, try again
992
+ History.debug('History.forward: trying again');
993
+ return History.forward(false);
994
+ }
995
+ return true;
996
+ },History.options.hashChangeCheckerDelay*5);
997
+ }
998
+
999
+ // Go forward
1000
+ history.go(1);
1001
+
1002
+ // End forward closure
1003
+ return true;
1004
+ };
1005
+
1006
+ /**
1007
+ * History.go(index,queue)
1008
+ * Send the browser history back or forward index times
1009
+ * @param {Integer} queue [optional]
1010
+ */
1011
+ History.go = function(index,queue){
1012
+ History.debug('History.go: called', arguments);
1013
+
1014
+ // Handle
1015
+ if ( index > 0 ) {
1016
+ // Forward
1017
+ for ( var i=1; i<=index; ++i ) {
1018
+ History.forward(queue);
1019
+ }
1020
+ }
1021
+ else if ( index < 0 ) {
1022
+ // Backward
1023
+ for ( var i=-1; i>=index; --i ) {
1024
+ History.back(queue);
1025
+ }
1026
+ }
1027
+ else {
1028
+ throw new Error('History.go: History.go requires a positive or negative integer passed.');
1029
+ }
1030
+
1031
+ // End go closure
1032
+ return true;
1033
+ };
1034
+
1035
+
1036
+ // ----------------------------------------------------------------------
1037
+ // HTML5 State Support
1038
+
1039
+ if ( !History.emulated.pushState ) {
1040
+ /*
1041
+ * Use native HTML5 History API Implementation
1042
+ */
1043
+
1044
+ /**
1045
+ * _History.onPopState(event,extra)
1046
+ * Refresh the Current State
1047
+ */
1048
+ _History.onPopState = function(event){
1049
+ History.debug('_History.onPopState',this,arguments);
1050
+
1051
+ // Check for a Hash, and handle apporiatly
1052
+ var currentHash = unescape(History.getHash());
1053
+ if ( currentHash ) {
1054
+ // Expand Hash
1055
+ var currentState = History.expandHash(currentHash);
1056
+ if ( currentState ) {
1057
+ // We were able to parse it, it must be a State!
1058
+ // Let's forward to replaceState
1059
+ History.debug('_History.onPopState: state anchor', currentHash, currentState);
1060
+ History.replaceState(currentState.data, currentState.tite, currentState.url, false);
1061
+ }
1062
+ else {
1063
+ // Traditional Anchor
1064
+ History.debug('_History.onPopState: traditional anchor', currentHash);
1065
+ History.Adapter.trigger(window,'anchorchange');
1066
+ History.busy(false);
1067
+ }
1068
+
1069
+ // We don't care for hashes
1070
+ return false;
1071
+ }
1072
+
1073
+ // Prepare
1074
+ var
1075
+ currentStateHashExits = null,
1076
+ stateData = {},
1077
+ stateTitle = null,
1078
+ stateUrl = null,
1079
+ newState = null;
1080
+
1081
+ // Prepare
1082
+ event = event||{};
1083
+ if ( typeof event.state === 'undefined' ) {
1084
+ // jQuery
1085
+ if ( typeof event.originalEvent !== 'undefined' && typeof event.originalEvent.state !== 'undefined' ) {
1086
+ event.state = event.originalEvent.state;
1087
+ }
1088
+ // MooTools
1089
+ else if ( typeof event.event !== 'undefined' && typeof event.event.state !== 'undefined' ) {
1090
+ event.state = event.event.state;
1091
+ }
1092
+ }
1093
+
1094
+ // Fetch Data
1095
+ if ( event.state === null ) {
1096
+ // Vanilla: State has no data (new state, not pushed)
1097
+ stateData = event.state;
1098
+ }
1099
+ else if ( typeof event.state !== 'undefined' ) {
1100
+ // Vanilla: Back/forward button was used
1101
+
1102
+ // Using Chrome Fix
1103
+ var
1104
+ newStateUrl = History.expandUrl(document.location.href),
1105
+ oldState = _History.getStateByUrl(newStateUrl),
1106
+ duplicateExists = _History.urlDuplicateExists(newStateUrl);
1107
+
1108
+ // Does oldState Exist?
1109
+ if ( typeof oldState !== 'undefined' && !duplicateExists ) {
1110
+ stateData = oldState.data;
1111
+ }
1112
+ else {
1113
+ stateData = event.state;
1114
+ }
1115
+
1116
+ // Use the way that should work
1117
+ // stateData = event.state;
1118
+ }
1119
+ else {
1120
+ // Vanilla: A new state was pushed, and popstate was called manually
1121
+
1122
+ // Get State object from the last state
1123
+ var
1124
+ newStateUrl = History.expandUrl(document.location.href),
1125
+ oldState = _History.getStateByUrl(newStateUrl);
1126
+
1127
+ // Check if the URLs match
1128
+ if ( oldState && newStateUrl == oldState.url ) {
1129
+ stateData = oldState.data;
1130
+ }
1131
+ else {
1132
+ throw new Error('Unknown state');
1133
+ }
1134
+ }
1135
+
1136
+ // Resolve newState
1137
+ stateData = (typeof stateData !== 'object' || stateData === null) ? {} : stateData;
1138
+ stateTitle = stateData.title||'',
1139
+ stateUrl = stateData.url||document.location.href,
1140
+ newState = History.createStateObject(stateData,stateTitle,stateUrl);
1141
+
1142
+ // Check if we are the same state
1143
+ if ( _History.isLastState(newState) ) {
1144
+ // There has been no change (just the page's hash has finally propagated)
1145
+ History.debug('_History.onPopState: no change', newState, _History.savedStates);
1146
+ History.busy(false);
1147
+ return false;
1148
+ }
1149
+
1150
+ // Log
1151
+ History.debug(
1152
+ '_History.onPopState',
1153
+ 'newState:', newState,
1154
+ 'oldState:', _History.getStateByUrl(History.expandUrl(document.location.href)),
1155
+ 'duplicateExists:', _History.urlDuplicateExists(History.expandUrl(document.location.href))
1156
+ );
1157
+
1158
+ // Store the State
1159
+ _History.storeState(newState);
1160
+ _History.saveState(newState);
1161
+
1162
+ // Force update of the title
1163
+ if ( newState.title ) {
1164
+ document.title = newState.title
1165
+ }
1166
+
1167
+ // Fire Our Event
1168
+ History.Adapter.trigger(window,'statechange');
1169
+ History.busy(false);
1170
+
1171
+ // Return true
1172
+ return true;
1173
+ };
1174
+ History.Adapter.bind(window,'popstate',_History.onPopState);
1175
+
1176
+ /**
1177
+ * History.pushState(data,title,url)
1178
+ * Add a new State to the history object, become it, and trigger onpopstate
1179
+ * We have to trigger for HTML4 compatibility
1180
+ * @param {object} data
1181
+ * @param {string} title
1182
+ * @param {string} url
1183
+ * @return {true}
1184
+ */
1185
+ History.pushState = function(data,title,url,queue){
1186
+ // Check the State
1187
+ if ( History.extractHashFromUrl(url) ) {
1188
+ throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1189
+ }
1190
+
1191
+ // Handle Queueing
1192
+ if ( queue !== false && History.busy() ) {
1193
+ // Wait + Push to Queue
1194
+ History.debug('History.pushState: we must wait', arguments);
1195
+ History.pushQueue({
1196
+ scope: History,
1197
+ callback: History.pushState,
1198
+ args: arguments,
1199
+ queue: queue
1200
+ });
1201
+ return false;
1202
+ }
1203
+
1204
+ // Make Busy + Continue
1205
+ History.busy(true);
1206
+
1207
+ // Create the newState
1208
+ var newState = History.createStateObject(data,title,url);
1209
+
1210
+ // Store the newState
1211
+ _History.storeState(newState);
1212
+
1213
+ // Push the newState
1214
+ history.pushState(newState.data,newState.title,newState.url);
1215
+
1216
+ // Fire HTML5 Event
1217
+ History.Adapter.trigger(window,'popstate');
1218
+
1219
+ // End pushState closure
1220
+ return true;
1221
+ }
1222
+
1223
+ /**
1224
+ * History.replaceState(data,title,url)
1225
+ * Replace the State and trigger onpopstate
1226
+ * We have to trigger for HTML4 compatibility
1227
+ * @param {object} data
1228
+ * @param {string} title
1229
+ * @param {string} url
1230
+ * @return {true}
1231
+ */
1232
+ History.replaceState = function(data,title,url,queue){
1233
+ // Check the State
1234
+ if ( History.extractHashFromUrl(url) ) {
1235
+ throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1236
+ }
1237
+
1238
+ // Handle Queueing
1239
+ if ( queue !== false && History.busy() ) {
1240
+ // Wait + Push to Queue
1241
+ History.debug('History.replaceState: we must wait', arguments);
1242
+ History.pushQueue({
1243
+ scope: History,
1244
+ callback: History.replaceState,
1245
+ args: arguments,
1246
+ queue: queue
1247
+ });
1248
+ return false;
1249
+ }
1250
+
1251
+ // Make Busy + Continue
1252
+ History.busy(true);
1253
+
1254
+ // Create the newState
1255
+ var newState = History.createStateObject(data,title,url);
1256
+
1257
+ // Store the newState
1258
+ _History.storeState(newState);
1259
+
1260
+ // Push the newState
1261
+ history.replaceState(newState.data,newState.title,newState.url);
1262
+
1263
+ // Fire HTML5 Event
1264
+ History.Adapter.trigger(window,'popstate');
1265
+
1266
+ // End replaceState closure
1267
+ return true;
1268
+ }
1269
+
1270
+
1271
+ /**
1272
+ * Ensure Cross Browser Compatibility
1273
+ */
1274
+ if ( navigator.vendor === 'Apple Computer, Inc.' ) {
1275
+ /**
1276
+ * Fix Safari Initial State Issue
1277
+ */
1278
+ History.Adapter.onDomLoad(function(){
1279
+ History.debug('Safari Initial State Change Fix');
1280
+ var currentState = History.createStateObject({},'',document.location.href);
1281
+ History.pushState(currentState.data,currentState.title,currentState.url);
1282
+ });
1283
+
1284
+ /**
1285
+ * Fix Safari HashChange Issue
1286
+ */
1287
+ History.Adapter.bind(window,'hashchange',function(){
1288
+ History.Adapter.trigger(window,'popstate');
1289
+ });
1290
+ }
1291
+ }
1292
+ }; // init
1293
+
1294
+ // Try Load HTML5 Support
1295
+ History.initHtml5();
1296
+
1297
+ })(window);