compass-jquery-plugin 0.3.2.7 → 0.3.2.8

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 (317) hide show
  1. data/README.md +17 -11
  2. data/VERSION.yml +2 -2
  3. data/lib/handle_js_files.rb +1 -1
  4. data/lib/jquery/emulators.rb +13 -0
  5. data/templates/dynatree/jquery.dynatree.min.js +79 -81
  6. data/templates/emulators/config/initializers/emulators.rb +0 -9
  7. data/templates/emulators/emulators/{blackberry.landscape.scss → blackberry.torch.landscape.scss} +6 -2
  8. data/templates/emulators/emulators/{blackberry.portrait.scss → blackberry.torch.portrait.scss} +6 -1
  9. data/templates/emulators/emulators/galaxy.s.landscape.png +0 -0
  10. data/templates/emulators/emulators/galaxy.s.landscape.scss +20 -0
  11. data/templates/emulators/emulators/galaxy.s.portrait.png +0 -0
  12. data/templates/emulators/emulators/galaxy.s.portrait.scss +20 -0
  13. data/templates/emulators/emulators/galaxy.s2.landscape.png +0 -0
  14. data/templates/emulators/emulators/galaxy.s2.landscape.scss +20 -0
  15. data/templates/emulators/emulators/galaxy.s2.portrait.png +0 -0
  16. data/templates/emulators/emulators/galaxy.s2.portrait.scss +20 -0
  17. data/templates/emulators/emulators/galaxy.tab.10.1.landscape.png +0 -0
  18. data/templates/emulators/emulators/galaxy.tab.10.1.landscape.scss +20 -0
  19. data/templates/emulators/emulators/galaxy.tab.10.1.portrait.png +0 -0
  20. data/templates/emulators/emulators/galaxy.tab.10.1.portrait.scss +20 -0
  21. data/templates/emulators/emulators/galaxy.tab.7.landscape.png +0 -0
  22. data/templates/emulators/emulators/galaxy.tab.7.landscape.scss +20 -0
  23. data/templates/emulators/emulators/galaxy.tab.7.portrait.png +0 -0
  24. data/templates/emulators/emulators/galaxy.tab.7.portrait.scss +20 -0
  25. data/templates/emulators/emulators/galaxy.tab.8.9.landscape.png +0 -0
  26. data/templates/emulators/emulators/galaxy.tab.8.9.landscape.scss +20 -0
  27. data/templates/emulators/emulators/galaxy.tab.8.9.portrait.png +0 -0
  28. data/templates/emulators/emulators/galaxy.tab.8.9.portrait.scss +20 -0
  29. data/templates/emulators/emulators/ipad.landscape.png +0 -0
  30. data/templates/emulators/emulators/ipad.landscape.scss +9 -4
  31. data/templates/emulators/emulators/ipad.portrait.png +0 -0
  32. data/templates/emulators/emulators/ipad.portrait.scss +9 -4
  33. data/templates/emulators/emulators/{iphone.landscape.png → iphone.3.landscape.png} +0 -0
  34. data/templates/emulators/emulators/{iphone.landscape.scss → iphone.3.landscape.scss} +7 -3
  35. data/templates/emulators/emulators/{iphone.portrait.png → iphone.3.portrait.png} +0 -0
  36. data/templates/emulators/emulators/{iphone.portrait.scss → iphone.3.portrait.scss} +7 -3
  37. data/templates/emulators/emulators/iphone.4.landscape .scss +20 -0
  38. data/templates/emulators/emulators/iphone.4.landscape.png +0 -0
  39. data/templates/emulators/emulators/iphone.4.portrait.png +0 -0
  40. data/templates/emulators/emulators/iphone.4.portrait.scss +20 -0
  41. data/templates/emulators/emulators/{palm.pre.landscape.png → palm.pre.2.landscape.png} +0 -0
  42. data/templates/emulators/emulators/{palm.landscape.scss → palm.pre.2.landscape.scss} +7 -3
  43. data/templates/emulators/emulators/{palm.pre.portrait.png → palm.pre.2.portrait.png} +0 -0
  44. data/templates/emulators/emulators/{palm.portrait.scss → palm.pre.2.portrait.scss} +7 -3
  45. data/templates/emulators/manifest.rb +34 -10
  46. data/templates/graphics/config/initializers/graphics.rb +8 -0
  47. data/templates/graphics/highcharts/dark-blue.js +170 -0
  48. data/templates/graphics/highcharts/dark-blue.min.js +4 -0
  49. data/templates/graphics/highcharts/dark-green.js +170 -0
  50. data/templates/graphics/highcharts/dark-green.min.js +4 -0
  51. data/templates/graphics/highcharts/gray.js +164 -0
  52. data/templates/graphics/highcharts/gray.min.js +4 -0
  53. data/templates/graphics/highcharts/grid.js +97 -0
  54. data/templates/graphics/highcharts/grid.min.js +3 -0
  55. data/templates/graphics/highcharts/highslide-config.js +12 -0
  56. data/templates/graphics/highcharts/highslide-config.min.js +1 -0
  57. data/templates/graphics/highcharts/highslide-full.js +3391 -0
  58. data/templates/graphics/highcharts/highslide-full.min.js +132 -0
  59. data/templates/graphics/highcharts/skies.js +89 -0
  60. data/templates/graphics/highcharts/skies.min.js +3 -0
  61. data/templates/graphics/jquery.ganttView.js +1 -1
  62. data/templates/graphics/jquery.ganttView.min.js +61 -61
  63. data/templates/graphics/jquery.highcharts.js +11342 -0
  64. data/templates/graphics/jquery.highcharts.min.js +176 -0
  65. data/templates/graphics/jquery.sparkline.min.js +35 -36
  66. data/templates/graphics/jquery/highcharts/graphics/close.png +0 -0
  67. data/templates/graphics/jquery/highcharts/graphics/closeX.png +0 -0
  68. data/templates/graphics/jquery/highcharts/graphics/controlbar-black-border.gif +0 -0
  69. data/templates/graphics/jquery/highcharts/graphics/controlbar-text-buttons.png +0 -0
  70. data/templates/graphics/jquery/highcharts/graphics/controlbar-white-small.gif +0 -0
  71. data/templates/graphics/jquery/highcharts/graphics/controlbar-white.gif +0 -0
  72. data/templates/graphics/jquery/highcharts/graphics/controlbar2.gif +0 -0
  73. data/templates/graphics/jquery/highcharts/graphics/controlbar3.gif +0 -0
  74. data/templates/graphics/jquery/highcharts/graphics/controlbar4-hover.gif +0 -0
  75. data/templates/graphics/jquery/highcharts/graphics/controlbar4.gif +0 -0
  76. data/templates/graphics/jquery/highcharts/graphics/fullexpand.gif +0 -0
  77. data/templates/graphics/jquery/highcharts/graphics/geckodimmer.png +0 -0
  78. data/templates/graphics/jquery/highcharts/graphics/icon.gif +0 -0
  79. data/templates/graphics/jquery/highcharts/graphics/loader.gif +0 -0
  80. data/templates/graphics/jquery/highcharts/graphics/loader.white.gif +0 -0
  81. data/templates/graphics/jquery/highcharts/graphics/outlines/beveled.png +0 -0
  82. data/templates/graphics/jquery/highcharts/graphics/outlines/drop-shadow.png +0 -0
  83. data/templates/graphics/jquery/highcharts/graphics/outlines/glossy-dark.png +0 -0
  84. data/templates/graphics/jquery/highcharts/graphics/outlines/outer-glow.png +0 -0
  85. data/templates/graphics/jquery/highcharts/graphics/outlines/rounded-black.png +0 -0
  86. data/templates/graphics/jquery/highcharts/graphics/outlines/rounded-white.png +0 -0
  87. data/templates/graphics/jquery/highcharts/graphics/resize.gif +0 -0
  88. data/templates/graphics/jquery/highcharts/graphics/scrollarrows.png +0 -0
  89. data/templates/graphics/jquery/highcharts/graphics/zoomin.cur +0 -0
  90. data/templates/graphics/jquery/highcharts/graphics/zoomout.cur +0 -0
  91. data/templates/graphics/jquery/highcharts/skies.jpg +0 -0
  92. data/templates/graphics/jquery/highslide.scss +763 -0
  93. data/templates/graphics/manifest.rb +43 -0
  94. data/templates/ical/config/initializers/ical.rb +1 -0
  95. data/templates/ical/jquery.ical.js +8401 -8209
  96. data/templates/ical/jquery.ical.min.js +206 -208
  97. data/templates/ical/jquery/ical.print.scss +48 -0
  98. data/templates/ical/jquery/ical.scss +372 -343
  99. data/templates/ical/manifest.rb +1 -0
  100. data/templates/jqgrid/i18n/jqgrid/locale-ar.min.js +2 -2
  101. data/templates/jqgrid/i18n/jqgrid/locale-bg.min.js +1 -1
  102. data/templates/jqgrid/i18n/jqgrid/locale-bg1251.min.js +1 -1
  103. data/templates/jqgrid/i18n/jqgrid/locale-cat.min.js +1 -1
  104. data/templates/jqgrid/i18n/jqgrid/locale-cn.min.js +1 -1
  105. data/templates/jqgrid/i18n/jqgrid/locale-cs.min.js +1 -1
  106. data/templates/jqgrid/i18n/jqgrid/locale-da.min.js +1 -1
  107. data/templates/jqgrid/i18n/jqgrid/locale-de.min.js +1 -1
  108. data/templates/jqgrid/i18n/jqgrid/locale-el.min.js +2 -2
  109. data/templates/jqgrid/i18n/jqgrid/locale-en.min.js +1 -1
  110. data/templates/jqgrid/i18n/jqgrid/locale-es.min.js +2 -2
  111. data/templates/jqgrid/i18n/jqgrid/locale-fa.min.js +1 -1
  112. data/templates/jqgrid/i18n/jqgrid/locale-fi.min.js +1 -1
  113. data/templates/jqgrid/i18n/jqgrid/locale-fr.min.js +2 -2
  114. data/templates/jqgrid/i18n/jqgrid/locale-gl.min.js +2 -2
  115. data/templates/jqgrid/i18n/jqgrid/locale-he.min.js +1 -1
  116. data/templates/jqgrid/i18n/jqgrid/locale-hu.min.js +1 -1
  117. data/templates/jqgrid/i18n/jqgrid/locale-is.min.js +1 -1
  118. data/templates/jqgrid/i18n/jqgrid/locale-it.min.js +2 -2
  119. data/templates/jqgrid/i18n/jqgrid/locale-ja.min.js +1 -1
  120. data/templates/jqgrid/i18n/jqgrid/locale-lt.min.js +2 -2
  121. data/templates/jqgrid/i18n/jqgrid/locale-nl.min.js +1 -1
  122. data/templates/jqgrid/i18n/jqgrid/locale-no.min.js +1 -1
  123. data/templates/jqgrid/i18n/jqgrid/locale-pl.min.js +1 -1
  124. data/templates/jqgrid/i18n/jqgrid/locale-pt-br.min.js +1 -1
  125. data/templates/jqgrid/i18n/jqgrid/locale-pt.min.js +1 -1
  126. data/templates/jqgrid/i18n/jqgrid/locale-ro.min.js +1 -1
  127. data/templates/jqgrid/i18n/jqgrid/locale-ru.min.js +2 -2
  128. data/templates/jqgrid/i18n/jqgrid/locale-sk.min.js +1 -1
  129. data/templates/jqgrid/i18n/jqgrid/locale-sr.min.js +1 -1
  130. data/templates/jqgrid/i18n/jqgrid/locale-sv.min.js +1 -1
  131. data/templates/jqgrid/i18n/jqgrid/locale-tr.min.js +1 -1
  132. data/templates/jqgrid/i18n/jqgrid/locale-ua.min.js +2 -2
  133. data/templates/jqgrid/jquery.jqGrid.js +162 -850
  134. data/templates/jqgrid/jquery.jqGrid.min.js +476 -497
  135. data/templates/jqgrid/jquery/jqGrid.scss +0 -19
  136. data/templates/jquery/amplify.store.js +248 -0
  137. data/templates/jquery/amplify.store.min.js +6 -0
  138. data/templates/jquery/config/initializers/jquery.rb +5 -1
  139. data/templates/jquery/history.adapter.jquery.js +37 -43
  140. data/templates/jquery/history.adapter.jquery.min.js +1 -1
  141. data/templates/jquery/history.html4.js +596 -587
  142. data/templates/jquery/history.html4.min.js +8 -8
  143. data/templates/jquery/history.js +1839 -1669
  144. data/templates/jquery/history.min.js +27 -25
  145. data/templates/jquery/i18n/jquery.ui/datepicker-af.min.js +1 -1
  146. data/templates/jquery/i18n/jquery.ui/datepicker-ar-DZ.min.js +1 -1
  147. data/templates/jquery/i18n/jquery.ui/datepicker-ar.min.js +1 -1
  148. data/templates/jquery/i18n/jquery.ui/datepicker-az.min.js +1 -1
  149. data/templates/jquery/i18n/jquery.ui/datepicker-bg.min.js +1 -1
  150. data/templates/jquery/i18n/jquery.ui/datepicker-bs.min.js +1 -1
  151. data/templates/jquery/i18n/jquery.ui/datepicker-ca.min.js +1 -1
  152. data/templates/jquery/i18n/jquery.ui/datepicker-cs.min.js +1 -1
  153. data/templates/jquery/i18n/jquery.ui/datepicker-da.min.js +1 -1
  154. data/templates/jquery/i18n/jquery.ui/datepicker-de.min.js +1 -1
  155. data/templates/jquery/i18n/jquery.ui/datepicker-el.min.js +1 -1
  156. data/templates/jquery/i18n/jquery.ui/datepicker-en-AU.min.js +1 -1
  157. data/templates/jquery/i18n/jquery.ui/datepicker-en-GB.min.js +1 -1
  158. data/templates/jquery/i18n/jquery.ui/datepicker-en-NZ.min.js +1 -1
  159. data/templates/jquery/i18n/jquery.ui/datepicker-eo.min.js +1 -1
  160. data/templates/jquery/i18n/jquery.ui/datepicker-es.min.js +1 -1
  161. data/templates/jquery/i18n/jquery.ui/datepicker-et.min.js +1 -1
  162. data/templates/jquery/i18n/jquery.ui/datepicker-eu.min.js +1 -1
  163. data/templates/jquery/i18n/jquery.ui/datepicker-fa.min.js +2 -2
  164. data/templates/jquery/i18n/jquery.ui/datepicker-fi.min.js +1 -1
  165. data/templates/jquery/i18n/jquery.ui/datepicker-fo.min.js +1 -1
  166. data/templates/jquery/i18n/jquery.ui/datepicker-fr-CH.min.js +1 -1
  167. data/templates/jquery/i18n/jquery.ui/datepicker-fr.min.js +1 -1
  168. data/templates/jquery/i18n/jquery.ui/datepicker-gl.min.js +1 -1
  169. data/templates/jquery/i18n/jquery.ui/datepicker-he.min.js +1 -1
  170. data/templates/jquery/i18n/jquery.ui/datepicker-hr.min.js +1 -1
  171. data/templates/jquery/i18n/jquery.ui/datepicker-hu.min.js +1 -1
  172. data/templates/jquery/i18n/jquery.ui/datepicker-hy.min.js +1 -1
  173. data/templates/jquery/i18n/jquery.ui/datepicker-id.min.js +1 -1
  174. data/templates/jquery/i18n/jquery.ui/datepicker-is.min.js +1 -1
  175. data/templates/jquery/i18n/jquery.ui/datepicker-it.min.js +1 -1
  176. data/templates/jquery/i18n/jquery.ui/datepicker-ja.min.js +1 -1
  177. data/templates/jquery/i18n/jquery.ui/datepicker-ko.min.js +1 -1
  178. data/templates/jquery/i18n/jquery.ui/datepicker-kz.min.js +1 -1
  179. data/templates/jquery/i18n/jquery.ui/datepicker-lt.min.js +1 -1
  180. data/templates/jquery/i18n/jquery.ui/datepicker-lv.min.js +1 -1
  181. data/templates/jquery/i18n/jquery.ui/datepicker-ml.min.js +2 -2
  182. data/templates/jquery/i18n/jquery.ui/datepicker-ms.min.js +1 -1
  183. data/templates/jquery/i18n/jquery.ui/datepicker-nl.min.js +1 -1
  184. data/templates/jquery/i18n/jquery.ui/datepicker-no.min.js +1 -1
  185. data/templates/jquery/i18n/jquery.ui/datepicker-pl.min.js +1 -1
  186. data/templates/jquery/i18n/jquery.ui/datepicker-pt-BR.min.js +1 -1
  187. data/templates/jquery/i18n/jquery.ui/datepicker-pt.min.js +1 -1
  188. data/templates/jquery/i18n/jquery.ui/datepicker-rm.min.js +1 -1
  189. data/templates/jquery/i18n/jquery.ui/datepicker-ro.min.js +1 -1
  190. data/templates/jquery/i18n/jquery.ui/datepicker-ru.min.js +1 -1
  191. data/templates/jquery/i18n/jquery.ui/datepicker-sk.min.js +1 -1
  192. data/templates/jquery/i18n/jquery.ui/datepicker-sl.min.js +1 -1
  193. data/templates/jquery/i18n/jquery.ui/datepicker-sq.min.js +1 -1
  194. data/templates/jquery/i18n/jquery.ui/datepicker-sr-SR.min.js +1 -1
  195. data/templates/jquery/i18n/jquery.ui/datepicker-sr.min.js +1 -1
  196. data/templates/jquery/i18n/jquery.ui/datepicker-sv.min.js +1 -1
  197. data/templates/jquery/i18n/jquery.ui/datepicker-ta.min.js +1 -1
  198. data/templates/jquery/i18n/jquery.ui/datepicker-th.min.js +1 -1
  199. data/templates/jquery/i18n/jquery.ui/datepicker-tj.min.js +1 -1
  200. data/templates/jquery/i18n/jquery.ui/datepicker-tr.min.js +1 -1
  201. data/templates/jquery/i18n/jquery.ui/datepicker-uk.min.js +1 -1
  202. data/templates/jquery/i18n/jquery.ui/datepicker-vi.min.js +1 -1
  203. data/templates/jquery/i18n/jquery.ui/datepicker-zh-CN.min.js +1 -1
  204. data/templates/jquery/i18n/jquery.ui/datepicker-zh-HK.min.js +1 -1
  205. data/templates/jquery/i18n/jquery.ui/datepicker-zh-TW.min.js +1 -1
  206. data/templates/jquery/jquery-ui.js +217 -104
  207. data/templates/jquery/jquery-ui.min.js +437 -436
  208. data/templates/jquery/jquery.bgiframe.min.js +1 -1
  209. data/templates/jquery/jquery.contextMenu.min.js +7 -7
  210. data/templates/jquery/jquery.cookie.js +60 -58
  211. data/templates/jquery/jquery.cookie.min.js +1 -1
  212. data/templates/jquery/jquery.dotimeout.min.js +2 -2
  213. data/templates/jquery/jquery.dst.min.js +4 -4
  214. data/templates/jquery/jquery.farbtastic.min.js +10 -10
  215. data/templates/jquery/jquery.form.js +15 -5
  216. data/templates/jquery/jquery.form.min.js +20 -20
  217. data/templates/jquery/jquery.haml.min.js +5 -5
  218. data/templates/jquery/jquery.hotkeys.min.js +3 -3
  219. data/templates/jquery/jquery.js +8205 -8170
  220. data/templates/jquery/jquery.layout.min.js +48 -50
  221. data/templates/jquery/jquery.min.js +166 -167
  222. data/templates/jquery/jquery.mousewheel.min.js +2 -2
  223. data/templates/jquery/jquery.offline.min.js +4 -4
  224. data/templates/jquery/jquery.pngFix.js +28 -30
  225. data/templates/jquery/jquery.pngFix.min.js +5 -5
  226. data/templates/jquery/jquery.rails.js +166 -0
  227. data/templates/jquery/jquery.rails.min.js +6 -0
  228. data/templates/jquery/jquery.replacetext.min.js +1 -1
  229. data/templates/jquery/jquery.themeswitchertool.min.js +4 -4
  230. data/templates/jquery/jquery.tmpl.js +14 -12
  231. data/templates/jquery/jquery.tmpl.min.js +12 -12
  232. data/templates/jquery/jquery.tmplPlus.js +2 -2
  233. data/templates/jquery/jquery.tmplPlus.min.js +3 -3
  234. data/templates/jquery/jquery.tokeninput.js +729 -0
  235. data/templates/jquery/jquery.tokeninput.min.js +14 -0
  236. data/templates/jquery/jquery/ui/_theme.scss +23 -16
  237. data/templates/jquery/jquery/ui/black-tie/ui-icons_4ca300_256x240.png +0 -0
  238. data/templates/jquery/jquery/ui/black-tie/ui-icons_bbbbbb_256x240.png +0 -0
  239. data/templates/jquery/jquery/ui/black-tie/ui-icons_ededed_256x240.png +0 -0
  240. data/templates/jquery/jquery/ui/black-tie/ui-icons_ffcf29_256x240.png +0 -0
  241. data/templates/jquery/jquery/ui/tokeninput.facebook.scss +95 -0
  242. data/templates/jquery/jquery/ui/tokeninput.mac.scss +164 -0
  243. data/templates/jquery/jquery/ui/tokeninput.scss +85 -0
  244. data/templates/jquery/jquery/ui/vader/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  245. data/templates/jquery/jquery/ui/vader/ui-icons_bbbbbb_256x240.png +0 -0
  246. data/templates/jquery/jquery/ui/vader/ui-icons_c98000_256x240.png +0 -0
  247. data/templates/jquery/jquery/ui/vader/ui-icons_f29a00_256x240.png +0 -0
  248. data/templates/jquery/json.min.js +6 -6
  249. data/templates/jquery/json2.js +214 -214
  250. data/templates/jquery/json2.min.js +5 -6
  251. data/templates/jquery/manifest.rb +9 -2
  252. data/templates/jstree/jquery.jstree.min.js +222 -224
  253. data/templates/mobile/config/initializers/mobile.rb +1 -1
  254. data/templates/mobile/jquery.mobile.js +887 -404
  255. data/templates/mobile/jquery.mobile.min.js +4 -4
  256. data/templates/mobile/jquery/mobile/_base.scss +50 -26
  257. data/templates/mobile/jquery/mobile/default.scss +59 -63
  258. data/templates/mobile/jquery/mobile/valencia.scss +44 -42
  259. data/templates/ribbon/jquery.ribbon.min.js +14 -14
  260. data/templates/tiny_mce/manifest.rb +4 -0
  261. data/templates/tiny_mce/tiny_mce/langs/de.js +1 -1
  262. data/templates/tiny_mce/tiny_mce/langs/en.js +1 -1
  263. data/templates/tiny_mce/tiny_mce/plugins/advimage/js/image.js +1 -1
  264. data/templates/tiny_mce/tiny_mce/plugins/advimage/langs/de_dlg.js +1 -1
  265. data/templates/tiny_mce/tiny_mce/plugins/advlink/js/advlink.js +1 -1
  266. data/templates/tiny_mce/tiny_mce/plugins/advlink/langs/en_dlg.js +1 -1
  267. data/templates/tiny_mce/tiny_mce/plugins/advlink/link.htm +1 -1
  268. data/templates/tiny_mce/tiny_mce/plugins/advlist/editor_plugin.js +1 -1
  269. data/templates/tiny_mce/tiny_mce/plugins/advlist/editor_plugin_src.js +1 -1
  270. data/templates/tiny_mce/tiny_mce/plugins/autolink/editor_plugin.js +1 -0
  271. data/templates/tiny_mce/tiny_mce/plugins/autolink/editor_plugin_src.js +1 -0
  272. data/templates/tiny_mce/tiny_mce/plugins/autoresize/editor_plugin.js +1 -1
  273. data/templates/tiny_mce/tiny_mce/plugins/autoresize/editor_plugin_src.js +1 -1
  274. data/templates/tiny_mce/tiny_mce/plugins/contextmenu/editor_plugin.js +1 -1
  275. data/templates/tiny_mce/tiny_mce/plugins/contextmenu/editor_plugin_src.js +1 -1
  276. data/templates/tiny_mce/tiny_mce/plugins/fullpage/css/fullpage.css +1 -1
  277. data/templates/tiny_mce/tiny_mce/plugins/fullpage/editor_plugin.js +1 -1
  278. data/templates/tiny_mce/tiny_mce/plugins/fullpage/editor_plugin_src.js +1 -1
  279. data/templates/tiny_mce/tiny_mce/plugins/fullpage/fullpage.htm +1 -1
  280. data/templates/tiny_mce/tiny_mce/plugins/fullpage/js/fullpage.js +1 -1
  281. data/templates/tiny_mce/tiny_mce/plugins/legacyoutput/editor_plugin.js +1 -1
  282. data/templates/tiny_mce/tiny_mce/plugins/legacyoutput/editor_plugin_src.js +1 -1
  283. data/templates/tiny_mce/tiny_mce/plugins/lists/editor_plugin.js +1 -0
  284. data/templates/tiny_mce/tiny_mce/plugins/lists/editor_plugin_src.js +1 -0
  285. data/templates/tiny_mce/tiny_mce/plugins/media/js/media.js +1 -1
  286. data/templates/tiny_mce/tiny_mce/plugins/media/media.htm +1 -1
  287. data/templates/tiny_mce/tiny_mce/plugins/noneditable/editor_plugin.js +1 -1
  288. data/templates/tiny_mce/tiny_mce/plugins/noneditable/editor_plugin_src.js +1 -1
  289. data/templates/tiny_mce/tiny_mce/plugins/paste/editor_plugin.js +1 -1
  290. data/templates/tiny_mce/tiny_mce/plugins/paste/editor_plugin_src.js +1 -1
  291. data/templates/tiny_mce/tiny_mce/plugins/searchreplace/js/searchreplace.js +1 -1
  292. data/templates/tiny_mce/tiny_mce/plugins/spellchecker/editor_plugin.js +1 -1
  293. data/templates/tiny_mce/tiny_mce/plugins/spellchecker/editor_plugin_src.js +1 -1
  294. data/templates/tiny_mce/tiny_mce/plugins/table/editor_plugin.js +1 -1
  295. data/templates/tiny_mce/tiny_mce/plugins/table/editor_plugin_src.js +1 -1
  296. data/templates/tiny_mce/tiny_mce/plugins/xhtmlxtras/editor_plugin.js +1 -1
  297. data/templates/tiny_mce/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js +1 -1
  298. data/templates/tiny_mce/tiny_mce/plugins/xhtmlxtras/js/attributes.js +1 -1
  299. data/templates/tiny_mce/tiny_mce/themes/advanced/editor_template.js +1 -1
  300. data/templates/tiny_mce/tiny_mce/themes/advanced/editor_template_src.js +1 -1
  301. data/templates/tiny_mce/tiny_mce/themes/advanced/js/charmap.js +1 -1
  302. data/templates/tiny_mce/tiny_mce/themes/advanced/langs/de_dlg.js +1 -1
  303. data/templates/tiny_mce/tiny_mce/themes/advanced/langs/en_dlg.js +1 -1
  304. data/templates/tiny_mce/tiny_mce/themes/advanced/skins/default/ui.css +1 -1
  305. data/templates/tiny_mce/tiny_mce/themes/advanced/skins/o2k7/dialog.css +1 -1
  306. data/templates/tiny_mce/tiny_mce/themes/advanced/skins/o2k7/ui.css +1 -1
  307. data/templates/tiny_mce/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +1 -1
  308. data/templates/tiny_mce/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +1 -1
  309. data/templates/tiny_mce/tiny_mce/tiny_mce.js +1 -1
  310. data/templates/tiny_mce/tiny_mce/utils/form_utils.js +1 -1
  311. data/templates/tiny_mce/tiny_mce/utils/validate.js +1 -1
  312. data/templates/tools/flowplayer.min.js +29 -30
  313. data/templates/tools/jquery.tools.min.js +96 -96
  314. data/templates/tools/swfobject.min.js +18 -19
  315. metadata +95 -16
  316. data/templates/jquery/jrails.js +0 -200
  317. data/templates/jquery/jrails.min.js +0 -8
@@ -1,11 +1,11 @@
1
1
  /*
2
2
  New BSD License <http://creativecommons.org/licenses/BSD/>
3
3
  */
4
- (function(h){var i=h.document,a=h.History=h.History||{};if(typeof a.initHtml4!=="undefined")throw Error("History.js HTML4 Support has already been loaded...");a.initHtml4=function(){if(typeof a.initHtml4.initialized!=="undefined")return false;else a.initHtml4.initialized=true;a.savedHashes=[];a.isLastHash=function(b){var c=a.getHashByIndex();return b===c};a.saveHash=function(b){if(a.isLastHash(b))return false;a.savedHashes.push(b);return true};a.getHashByIndex=function(b){var c=null;return c=typeof b===
5
- "undefined"?a.savedHashes[a.savedHashes.length-1]:b<0?a.savedHashes[a.savedHashes.length+b]:a.savedHashes[b]};a.discardedHashes={};a.discardedStates={};a.discardState=function(b,c,e){var f=a.getHashByState(b);a.discardedStates[f]={discardedState:b,backState:e,forwardState:c};return true};a.discardHash=function(b,c,e){a.discardedHashes[b]={discardedHash:b,backState:e,forwardState:c};return true};a.discardedState=function(b){b=a.getHashByState(b);return a.discardedStates[b]||false};a.discardedHash=
6
- function(b){return a.discardedHashes[b]||false};a.recycleState=function(b){var c=a.getHashByState(b);a.discardedState(b)&&delete a.discardedStates[c];return true};if(a.emulated.hashChange){a.hashChangeInit=function(){a.checkerFunction=null;var b="";if(a.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 e="",f=false;a.checkerFunction=function(){if(f)return false;
7
- f=true;var d=a.getHash()||"",g=a.unescapeHash(c.contentWindow.document.location.hash)||"";if(d!==b){b=d;if(g!==d){e=d;c.contentWindow.document.open();c.contentWindow.document.close();c.contentWindow.document.location.hash=a.escapeHash(d)}a.Adapter.trigger(h,"hashchange")}else if(g!==e){e=g;a.setHash(g,false)}f=false;return true}}else a.checkerFunction=function(){var d=a.getHash();if(d!==b){b=d;a.Adapter.trigger(h,"hashchange")}return true};setInterval(a.checkerFunction,a.options.hashChangeInterval);
8
- return true};a.Adapter.onDomLoad(a.hashChangeInit)}if(a.emulated.pushState){a.onHashChange=function(b){var c=a.getHashByUrl(b&&b.newURL||i.location.href);b=null;if(a.isLastHash(c)){a.busy(false);return false}a.doubleCheckComplete();a.saveHash(c);b=a.extractState(c||i.location.href);if(!b){a.Adapter.trigger(h,"anchorchange");a.busy(false);return false}if(a.isLastSavedState(b)){a.busy(false);return false}a.getHashByState(b);if(c=a.discardedState(b)){a.getHashByIndex(-2)===a.getHashByState(c.forwardState)?
9
- a.back(false):a.forward(false);a.busy(false);return false}a.pushState(b.data,b.title,b.url,false);return true};a.Adapter.bind(h,"hashchange",a.onHashChange);a.pushState=function(b,c,e,f){if(a.getHashByUrl(e))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(f!==false&&a.busy()){a.pushQueue({scope:a,callback:a.pushState,args:arguments,queue:f});return false}a.busy(true);var d=a.createStateObject(b,c,e),g=a.getHashByState(d),j=a.getState(false);j=a.getHashByState(j);
10
- var k=a.getHash();a.storeState(d);a.expectedStateId=d.id;a.recycleState(d);a.setTitle(d);if(g===j){a.busy(false);return false}if(g!==k&&g!==a.getShortUrl(i.location.href)){a.setHash(g,false);return false}a.saveState(d);a.Adapter.trigger(h,"statechange");a.busy(false);return true};a.replaceState=function(b,c,e,f){if(a.getHashByUrl(e))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(f!==false&&a.busy()){a.pushQueue({scope:a,callback:a.replaceState,args:arguments,
11
- queue:f});return false}a.busy(true);var d=a.createStateObject(b,c,e),g=a.getState(false),j=a.getStateByIndex(-2);a.discardState(g,d,j);a.pushState(d.data,d.title,d.url,false);return true};a.saveState(a.storeState(a.createStateObject({},"",i.location.href)));a.getHash()&&!a.emulated.hashChange&&a.Adapter.onDomLoad(function(){a.Adapter.trigger(h,"hashchange")})}};a.init()})(window);
4
+ (function(f){var i=f.document,j=f.setInterval||j,a=f.History=f.History||{};if(typeof a.initHtml4!=="undefined")throw Error("History.js HTML4 Support has already been loaded...");a.initHtml4=function(){if(typeof a.initHtml4.initialized!=="undefined")return!1;else a.initHtml4.initialized=!0;a.enabled=!0;a.savedHashes=[];a.isLastHash=function(b){var c=a.getHashByIndex();return b===c};a.saveHash=function(b){if(a.isLastHash(b))return!1;a.savedHashes.push(b);return!0};a.getHashByIndex=function(b){var c=
5
+ null;return c=typeof b==="undefined"?a.savedHashes[a.savedHashes.length-1]:b<0?a.savedHashes[a.savedHashes.length+b]:a.savedHashes[b]};a.discardedHashes={};a.discardedStates={};a.discardState=function(b,c,e){var g=a.getHashByState(b);a.discardedStates[g]={discardedState:b,backState:e,forwardState:c};return!0};a.discardHash=function(b,c,e){a.discardedHashes[b]={discardedHash:b,backState:e,forwardState:c};return!0};a.discardedState=function(b){b=a.getHashByState(b);return a.discardedStates[b]||!1};
6
+ a.discardedHash=function(b){return a.discardedHashes[b]||!1};a.recycleState=function(b){var c=a.getHashByState(b);a.discardedState(b)&&delete a.discardedStates[c];return!0};if(a.emulated.hashChange)a.hashChangeInit=function(){a.checkerFunction=null;var b="";if(a.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 e="",g=!1;a.checkerFunction=function(){if(g)return!1;
7
+ g=!0;var d=a.getHash()||"",h=a.unescapeHash(c.contentWindow.document.location.hash)||"";if(d!==b){b=d;if(h!==d)e=d,c.contentWindow.document.open(),c.contentWindow.document.close(),c.contentWindow.document.location.hash=a.escapeHash(d);a.Adapter.trigger(f,"hashchange")}else h!==e&&(e=h,a.setHash(h,!1));g=!1;return!0}}else a.checkerFunction=function(){var c=a.getHash();c!==b&&(b=c,a.Adapter.trigger(f,"hashchange"));return!0};j(a.checkerFunction,a.options.hashChangeInterval);return!0},a.Adapter.onDomLoad(a.hashChangeInit);
8
+ if(a.emulated.pushState&&(a.onHashChange=function(b){var c=a.getHashByUrl(b&&b.newURL||i.location.href),b=null;if(a.isLastHash(c))return a.busy(!1),!1;a.doubleCheckComplete();a.saveHash(c);if(c&&a.isTraditionalAnchor(c))return a.Adapter.trigger(f,"anchorchange"),a.busy(!1),!1;b=a.extractState(a.getFullUrl(c||i.location.href,!1),!0);if(a.isLastSavedState(b))return a.busy(!1),!1;a.getHashByState(b);if(c=a.discardedState(b))return a.getHashByIndex(-2)===a.getHashByState(c.forwardState)?a.back(!1):a.forward(!1),
9
+ !1;a.pushState(b.data,b.title,b.url,!1);return!0},a.Adapter.bind(f,"hashchange",a.onHashChange),a.pushState=function(b,c,e,g){if(a.getHashByUrl(e))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(g!==!1&&a.busy())return a.pushQueue({scope:a,callback:a.pushState,args:arguments,queue:g}),!1;a.busy(!0);var d=a.createStateObject(b,c,e),h=a.getHashByState(d),k=a.getState(!1),k=a.getHashByState(k),j=a.getHash();a.storeState(d);a.expectedStateId=d.id;a.recycleState(d);
10
+ a.setTitle(d);if(h===k)return a.busy(!1),!1;if(h!==j&&h!==a.getShortUrl(i.location.href))return a.setHash(h,!1),!1;a.saveState(d);a.Adapter.trigger(f,"statechange");a.busy(!1);return!0},a.replaceState=function(b,c,e,g){if(a.getHashByUrl(e))throw Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(g!==!1&&a.busy())return a.pushQueue({scope:a,callback:a.replaceState,args:arguments,queue:g}),!1;a.busy(!0);var d=a.createStateObject(b,c,e),h=a.getState(!1),f=a.getStateByIndex(-2);
11
+ a.discardState(h,d,f);a.pushState(d.data,d.title,d.url,!1);return!0},a.getHash()&&!a.emulated.hashChange))a.Adapter.onDomLoad(function(){a.Adapter.trigger(f,"hashchange")})};a.init()})(window);
@@ -5,1674 +5,1844 @@
5
5
  * @license New BSD License <http://creativecommons.org/licenses/BSD/>
6
6
  */
7
7
 
8
- (function(window,undefined){
9
- "use strict";
10
-
11
- // --------------------------------------------------------------------------
12
- // Initialise
13
-
14
- // Localise Globals
15
- var
16
- console = window.console||undefined, // Prevent a JSLint complain
17
- document = window.document, // Make sure we are using the correct document
18
- navigator = window.navigator, // Make sure we are using the correct navigator
19
- History = window.History = window.History||{}, // Public History Object
20
- history = window.history; // Old History Object
21
-
22
- // Check Existence
23
- if ( typeof History.init !== 'undefined' ) {
24
- throw new Error('History.js Core has already been loaded...');
25
- }
26
-
27
- // Initialise History
28
- History.init = function(){
29
- // Check Load Status of Adapter
30
- if ( typeof History.Adapter === 'undefined' ) {
31
- return false;
32
- }
33
-
34
- // Check Load Status of Core
35
- if ( typeof History.initCore !== 'undefined' ) {
36
- History.initCore();
37
- }
38
-
39
- // Check Load Status of HTML4 Support
40
- if ( typeof History.initHtml4 !== 'undefined' ) {
41
- History.initHtml4();
42
- }
43
-
44
- // Return true
45
- return true;
46
- };
47
-
48
- // --------------------------------------------------------------------------
49
- // Initialise Core
50
-
51
- // Initialise Core
52
- History.initCore = function(){
53
- // Initialise
54
- if ( typeof History.initCore.initialized !== 'undefined' ) {
55
- // Already Loaded
56
- return false;
57
- }
58
- else {
59
- History.initCore.initialized = true;
60
- }
61
-
62
- // ----------------------------------------------------------------------
63
- // Options
64
-
65
- /**
66
- * History.options
67
- * Configurable options
68
- */
69
- History.options = History.options||{};
70
-
71
- /**
72
- * History.options.hashChangeInterval
73
- * How long should the interval be before hashchange checks
74
- */
75
- History.options.hashChangeInterval = History.options.hashChangeInterval || 100;
76
-
77
- /**
78
- * History.options.safariPollInterval
79
- * How long should the interval be before safari poll checks
80
- */
81
- History.options.safariPollInterval = History.options.safariPollInterval || 500;
82
-
83
- /**
84
- * History.options.doubleCheckInterval
85
- * How long should the interval be before we perform a double check
86
- */
87
- History.options.doubleCheckInterval = History.options.doubleCheckInterval || 500;
88
-
89
- /**
90
- * History.options.busyDelay
91
- * How long should we wait between busy events
92
- */
93
- History.options.busyDelay = History.options.busyDelay || 250;
94
-
95
- /**
96
- * History.options.debug
97
- * If true will enable debug messages to be logged
98
- */
99
- History.options.debug = History.options.debug || false;
100
-
101
- /**
102
- * History.options.initialTitle
103
- * What is the title of the initial state
104
- */
105
- History.options.initialTitle = History.options.initialTitle || document.title;
106
-
107
-
108
- // ----------------------------------------------------------------------
109
- // Debug
110
-
111
- /**
112
- * History.debug(message,...)
113
- * Logs the passed arguments if debug enabled
114
- */
115
- History.debug = function(){
116
- if ( (History.options.debug||false) ) {
117
- History.log.apply(History,arguments);
118
- }
119
- };
120
-
121
- /**
122
- * History.log(message,...)
123
- * Logs the passed arguments
124
- */
125
- History.log = function(){
126
- // Prepare
127
- var
128
- consoleExists = (typeof console !== 'undefined' && typeof console.log !== 'undefined' && typeof console.log.apply !== 'undefined'),
129
- textarea = document.getElementById('log'),
130
- message,
131
- i,n
132
- ;
133
-
134
- // Write to Console
135
- if ( consoleExists ) {
136
- var args = Array.prototype.slice.call(arguments);
137
- message = args.shift();
138
- if ( typeof console.debug !== 'undefined' ) {
139
- console.debug.apply(console,[message,args]);
140
- }
141
- else {
142
- console.log.apply(console,[message,args]);
143
- }
144
- }
145
- else {
146
- message = ("\n"+arguments[0]+"\n");
147
- }
148
-
149
- // Write to log
150
- for ( i=1,n=arguments.length; i<n; ++i ) {
151
- var arg = arguments[i];
152
- if ( typeof arg === 'object' && typeof JSON !== 'undefined' ) {
153
- try {
154
- arg = JSON.stringify(arg);
155
- }
156
- catch ( Exception ) {
157
- // Recursive Object
158
- }
159
- }
160
- message += "\n"+arg+"\n";
161
- }
162
-
163
- // Textarea
164
- if ( textarea ) {
165
- textarea.value += message+"\n-----\n";
166
- textarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;
167
- }
168
- // No Textarea, No Console
169
- else if ( !consoleExists ) {
170
- alert(message);
171
- }
172
-
173
- // Return true
174
- return true;
175
- };
176
-
177
- // ----------------------------------------------------------------------
178
- // Emulated Status
179
-
180
- /**
181
- * History.getInternetExplorerMajorVersion()
182
- * Get's the major version of Internet Explorer
183
- * @return {integer}
184
- * @license Public Domain
185
- * @author Benjamin Arthur Lupton <contact@balupton.com>
186
- * @author James Padolsey <https://gist.github.com/527683>
187
- */
188
- History.getInternetExplorerMajorVersion = function(){
189
- var result = History.getInternetExplorerMajorVersion.cached =
190
- (typeof History.getInternetExplorerMajorVersion.cached !== 'undefined')
191
- ? History.getInternetExplorerMajorVersion.cached
192
- : (function(){
193
- var v = 3,
194
- div = document.createElement('div'),
195
- all = div.getElementsByTagName('i');
196
- while ( (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->') && all[0] ) {}
197
- return (v > 4) ? v : false;
198
- })()
199
- ;
200
- return result;
201
- };
202
-
203
- /**
204
- * History.isInternetExplorer()
205
- * Are we using Internet Explorer?
206
- * @return {boolean}
207
- * @license Public Domain
208
- * @author Benjamin Arthur Lupton <contact@balupton.com>
209
- */
210
- History.isInternetExplorer = function(){
211
- var result =
212
- History.isInternetExplorer.cached =
213
- (typeof History.isInternetExplorer.cached !== 'undefined')
214
- ? History.isInternetExplorer.cached
215
- : Boolean(History.getInternetExplorerMajorVersion())
216
- ;
217
- return result;
218
- };
219
-
220
- /**
221
- * History.emulated
222
- * Which features require emulating?
223
- */
224
- History.emulated = {
225
- pushState: !Boolean(
226
- window.history && window.history.pushState && window.history.replaceState
227
- && !(/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent) /* disable for versions of iOS before version 4.3 (8F190) */
228
- ),
229
- hashChange: Boolean(
230
- !(('onhashchange' in window) || ('onhashchange' in document))
231
- ||
232
- (History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8)
233
- )
234
- };
235
-
236
- /**
237
- * History.bugs
238
- * Which bugs are present
239
- */
240
- History.bugs = {
241
- /**
242
- * Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call
243
- * https://bugs.webkit.org/show_bug.cgi?id=56249
244
- */
245
- setHash: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2][0-9]|3[0-3])/.test(navigator.userAgent)),
246
-
247
- /**
248
- * Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions
249
- * https://bugs.webkit.org/show_bug.cgi?id=42940
250
- */
251
- safariPoll: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2][0-9]|3[0-3])/.test(navigator.userAgent)),
252
-
253
- /**
254
- * MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)
255
- */
256
- ieDoubleCheck: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8),
257
-
258
- /**
259
- * MSIE 6 requires the entire hash to be encoded for the hashes to trigger the onHashChange event
260
- */
261
- hashEscape: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 7)
262
- };
263
-
264
- /**
265
- * History.isEmptyObject(obj)
266
- * Checks to see if the Object is Empty
267
- * @param {Object} obj
268
- * @return {boolean}
269
- */
270
- History.isEmptyObject = function(obj) {
271
- for ( var name in obj ) {
272
- return false;
273
- }
274
- return true;
275
- };
276
-
277
- /**
278
- * History.cloneObject(obj)
279
- * Clones a object
280
- * @param {Object} obj
281
- * @return {Object}
282
- */
283
- History.cloneObject = function(obj) {
284
- var hash,newObj;
285
- if ( obj ) {
286
- hash = JSON.stringify(obj);
287
- newObj = JSON.parse(hash);
288
- }
289
- else {
290
- newObj = {};
291
- }
292
- return newObj;
293
- };
294
-
295
- // ----------------------------------------------------------------------
296
- // URL Helpers
297
-
298
- /**
299
- * History.getRootUrl()
300
- * Turns "http://mysite.com/dir/page.html?asd" into "http://mysite.com"
301
- * @return {String} rootUrl
302
- */
303
- History.getRootUrl = function(){
304
- // Create
305
- var rootUrl = document.location.protocol+'//'+(document.location.hostname||document.location.host);
306
- if ( document.location.port||false ) {
307
- rootUrl += ':'+document.location.port;
308
- }
309
- rootUrl += '/';
310
-
311
- // Return
312
- return rootUrl;
313
- };
314
-
315
- /**
316
- * History.getBaseHref()
317
- * Fetches the `href` attribute of the `<base href="...">` element if it exists
318
- * @return {String} baseHref
319
- */
320
- History.getBaseHref = function(){
321
- // Create
322
- var
323
- baseElements = document.getElementsByTagName('base'),
324
- baseElement = null,
325
- baseHref = '';
326
-
327
- // Test for Base Element
328
- if ( baseElements.length === 1 ) {
329
- // Prepare for Base Element
330
- baseElement = baseElements[0];
331
- baseHref = baseElement.href.replace(/[^\/]+$/,'');
332
- }
333
-
334
- // Adjust trailing slash
335
- baseHref = baseHref.replace(/\/+$/,'');
336
- if ( baseHref ) baseHref += '/';
337
-
338
- // Return
339
- return baseHref;
340
- };
341
-
342
- /**
343
- * History.getBaseUrl()
344
- * Fetches the baseHref or basePageUrl or rootUrl (whichever one exists first)
345
- * @return {String} baseUrl
346
- */
347
- History.getBaseUrl = function(){
348
- // Create
349
- var baseUrl = History.getBaseHref()||History.getBasePageUrl()||History.getRootUrl();
350
-
351
- // Return
352
- return baseUrl;
353
- };
354
-
355
- /**
356
- * History.getPageUrl()
357
- * Fetches the URL of the current page
358
- * @return {String} pageUrl
359
- */
360
- History.getPageUrl = function(){
361
- // Fetch
362
- var
363
- State = History.getState(),
364
- stateUrl = State.url||document.location.href;
365
-
366
- // Create
367
- var pageUrl = stateUrl.replace(/\/+$/,'').replace(/[^\/]+$/,function(part,index,string){
368
- return (/\./).test(part) ? part : part+'/';
369
- });
370
-
371
- // Return
372
- return pageUrl;
373
- };
374
-
375
- /**
376
- * History.getBasePageUrl()
377
- * Fetches the Url of the directory of the current page
378
- * @return {String} basePageUrl
379
- */
380
- History.getBasePageUrl = function(){
381
- // Create
382
- var basePageUrl = document.location.href.replace(/[#\?].*/,'').replace(/[^\/]+$/,function(part,index,string){
383
- return (/\./).test(part) ? '' : part;
384
- }).replace(/\/+$/,'')+'/';
385
-
386
- // Return
387
- return basePageUrl;
388
- };
389
-
390
- /**
391
- * History.getFullUrl(url)
392
- * Ensures that we have an absolute URL and not a relative URL
393
- * @param {string} url
394
- * @return {string} fullUrl
395
- */
396
- History.getFullUrl = function(url){
397
- // Prepare
398
- var fullUrl = url, firstChar = url.substring(0,1);
399
-
400
- // Check
401
- if ( /[a-z]+\:\/\//.test(url) ) {
402
- // Full URL
403
- }
404
- else if ( firstChar === '/' ) {
405
- // Root URL
406
- fullUrl = History.getRootUrl()+url.replace(/^\/+/,'');
407
- }
408
- else if ( firstChar === '#' ) {
409
- // Anchor URL
410
- fullUrl = History.getPageUrl().replace(/#.*/,'')+url;
411
- }
412
- else if ( firstChar === '?' ) {
413
- // Query URL
414
- fullUrl = History.getPageUrl().replace(/[\?#].*/,'')+url;
415
- }
416
- else {
417
- // Relative URL
418
- fullUrl = History.getBaseUrl()+url;
419
- }
420
-
421
- // Return
422
- return fullUrl.replace(/\#$/,'');
423
- };
424
-
425
- /**
426
- * History.getShortUrl(url)
427
- * Ensures that we have a relative URL and not a absolute URL
428
- * @param {string} url
429
- * @return {string} url
430
- */
431
- History.getShortUrl = function(url){
432
- // Prepare
433
- var shortUrl, rootUrl = History.getRootUrl(); // History.getBaseHref()||History.getBasePageUrl()
434
-
435
- // Adjust
436
- shortUrl = url.replace(rootUrl,'/');
437
-
438
- // Return
439
- return shortUrl.replace(/\#$/,'');
440
- };
441
-
442
- // ----------------------------------------------------------------------
443
- // State Storage
444
-
445
- /**
446
- * History.idToState
447
- * 1-1: State ID to State Object
448
- */
449
- History.idToState = {};
450
-
451
- /**
452
- * History.stateToId
453
- * 1-1: State String to State ID
454
- */
455
- History.stateToId = {};
456
-
457
- /**
458
- * History.urlToId
459
- * 1-1: State URL to State ID
460
- */
461
- History.urlToId = {};
462
-
463
- /**
464
- * History.storedStates
465
- * Store the states in an array
466
- */
467
- History.storedStates = [];
468
-
469
- /**
470
- * History.savedStates
471
- * Saved the states in an array
472
- */
473
- History.savedStates = [];
474
-
475
- /**
476
- * History.getState()
477
- * Get an object containing the data, title and url of the current state
478
- * @return {Object} State
479
- */
480
- History.getState = function(friendly){
481
- // Prepare
482
- if ( typeof friendly === 'undefined' ) { friendly = true; }
483
-
484
- // Fetch
485
- var State = History.getLastSavedState()||History.createStateObject();
486
-
487
- // Adjust
488
- if ( friendly ) {
489
- State = History.cloneObject(State);
490
- State.url = State.cleanUrl||State.url;
491
- }
492
-
493
- // Return
494
- return State;
495
- };
496
-
497
- /**
498
- * History.getIdByState(State)
499
- * Gets a ID for a State
500
- * @param {State} newState
501
- * @return {String} id
502
- */
503
- History.getIdByState = function(newState){
504
-
505
- // Fetch ID
506
- var id = History.extractId(newState.url);
507
- if ( !id ) {
508
- // Find ID via State String
509
- var str = History.getStateString(newState);
510
- if ( typeof History.stateToId[str] !== 'undefined' ) {
511
- id = History.stateToId[str];
512
- }
513
- else {
514
- // Generate a new ID
515
- while ( true ) {
516
- id = String(Math.floor(Math.random()*1000));
517
- if ( typeof History.idToState[id] === 'undefined' ) {
518
- break;
519
- }
520
- }
521
-
522
- // Apply the new State to the ID
523
- History.stateToId[str] = id;
524
- History.idToState[id] = newState;
525
- }
526
- }
527
-
528
- // Return ID
529
- return id;
530
- };
531
-
532
- /**
533
- * History.normalizeState(State)
534
- * Expands a State Object
535
- * @param {object} State
536
- * @return {object}
537
- */
538
- History.normalizeState = function(oldState){
539
- // Prepare
540
- if ( !oldState || (typeof oldState !== 'object') ) {
541
- oldState = {};
542
- }
543
-
544
- // Check
545
- if ( typeof oldState.normalized !== 'undefined' ) {
546
- return oldState;
547
- }
548
-
549
- // Adjust
550
- if ( !oldState.data || (typeof oldState.data !== 'object') ) {
551
- oldState.data = {};
552
- }
553
-
554
- // ----------------------------------------------------------------------
555
-
556
- // Create
557
- var newState = {};
558
- newState.normalized = true;
559
- newState.title = oldState.title||'';
560
- newState.url = History.getFullUrl(oldState.url||document.location.href);
561
- newState.hash = History.getShortUrl(newState.url);
562
- newState.data = History.cloneObject(oldState.data);
563
-
564
- // Fetch ID
565
- newState.id = History.getIdByState(newState);
566
-
567
- // ----------------------------------------------------------------------
568
-
569
- // Check to see if we have more than just a url
570
- var dataNotEmpty = !History.isEmptyObject(newState.data);
571
-
572
- // Apply
573
- if ( newState.title || dataNotEmpty ) {
574
- // Add ID to Hash
575
- newState.hash = History.getShortUrl(newState.url).replace(/\&_suid.*/,'');
576
- if ( !/\?/.test(newState.hash) ) {
577
- newState.hash += '?';
578
- }
579
- newState.hash += '&_suid='+newState.id;
580
- }
581
-
582
- // Create the Hashed URL
583
- newState.hashedUrl = History.getFullUrl(newState.hash);
584
- newState.cleanUrl = newState.url.replace(/\&_suid.*/,'');
585
-
586
- // ----------------------------------------------------------------------
587
-
588
- // Update the URL if we have a duplicate
589
- if ( History.hasUrlDuplicate(newState) ) {
590
- newState.url = newState.hashedUrl;
591
- }
592
-
593
- // ----------------------------------------------------------------------
594
-
595
- // Return
596
- return newState;
597
- };
598
-
599
- /**
600
- * History.createStateObject(data,title,url)
601
- * Creates a object based on the data, title and url state params
602
- * @param {object} data
603
- * @param {string} title
604
- * @param {string} url
605
- * @return {object}
606
- */
607
- History.createStateObject = function(data,title,url){
608
- // Hashify
609
- var State = {
610
- 'data': data,
611
- 'title': title,
612
- 'url': url
613
- };
614
-
615
- // Expand the State
616
- State = History.normalizeState(State);
617
-
618
- // Return object
619
- return State;
620
- };
621
-
622
- /**
623
- * History.getStateById(id)
624
- * Get a state by it's UID
625
- * @param {String} id
626
- */
627
- History.getStateById = function(id){
628
- id = String(id);
629
- var State = History.idToState[id]||undefined;
630
- return State;
631
- };
632
-
633
- /**
634
- * Get a State's String
635
- * @param {State} passedState
636
- */
637
- History.getStateString = function(passedState){
638
- // Prepare
639
- var State = History.normalizeState(passedState);
640
-
641
- // Clean
642
- var cleanedState = {
643
- data: State.data,
644
- title: passedState.title,
645
- url: passedState.url
646
- };
647
-
648
- // Fetch
649
- var str = JSON.stringify(cleanedState);
650
-
651
- // Return
652
- return str;
653
- };
654
-
655
- /**
656
- * Get a State's ID
657
- * @param {State} passedState
658
- * @return {String} id
659
- */
660
- History.getStateId = function(passedState){
661
- // Prepare
662
- var State = History.normalizeState(passedState);
663
-
664
- // Fetch
665
- var id = State.id;
666
-
667
- // Return
668
- return id;
669
- };
670
-
671
- /**
672
- * History.getHashByState(State)
673
- * Creates a Hash for the State Object
674
- * @param {State} passedState
675
- * @return {String} hash
676
- */
677
- History.getHashByState = function(passedState){
678
- // Prepare
679
- var hash, State = History.normalizeState(passedState);
680
-
681
- // Fetch
682
- hash = State.hash;
683
-
684
- // Return
685
- return hash;
686
- };
687
-
688
- /**
689
- * History.extractId(url_or_hash)
690
- * Get a State ID by it's URL or Hash
691
- * @param {string} url_or_hash
692
- * @return {string} id
693
- */
694
- History.extractId = function ( url_or_hash ) {
695
- // Prepare
696
- var id;
697
-
698
- // Extract
699
- var parts,url;
700
- parts = /(.*)\&_suid=([0-9]+)$/.exec(url_or_hash);
701
- url = parts ? (parts[1]||url_or_hash) : url_or_hash;
702
- id = parts ? String(parts[2]||'') : '';
703
-
704
- // Return
705
- return id||false;
706
- };
707
-
708
- /**
709
- * History.extractState
710
- * Get a State by it's URL or Hash
711
- */
712
- History.extractState = function(url_or_hash,create){
713
- // Prepare
714
- var State = null;
715
- create = create||false;
716
-
717
- // Fetch SUID
718
- var id = History.extractId(url_or_hash);
719
- if ( id ) {
720
- State = History.getStateById(id);
721
- }
722
-
723
- // Fetch SUID returned no State
724
- if ( !State ) {
725
- // Fetch URL
726
- var url = History.getFullUrl(url_or_hash);
727
-
728
- // Check URL
729
- id = History.getIdByUrl(url)||false;
730
- if ( id ) {
731
- State = History.getStateById(id);
732
- }
733
- // Create State
734
- else if ( create && /\//.test(url_or_hash) ) {
735
- State = History.createStateObject(null,null,url.replace(/\&_suid.*/,''));
736
- }
737
- }
738
-
739
- // Return
740
- return State;
741
- };
742
-
743
- /**
744
- * History.getIdByUrl()
745
- * Get a State ID by a State URL
746
- */
747
- History.getIdByUrl = function(url){
748
- var id = History.urlToId[url]||false;
749
- return id;
750
- };
751
-
752
- /**
753
- * History.getLastSavedState()
754
- * Get an object containing the data, title and url of the current state
755
- * @return {Object} State
756
- */
757
- History.getLastSavedState = function(){
758
- return History.savedStates[History.savedStates.length-1]||undefined;
759
- };
760
-
761
- /**
762
- * History.getLastStoredState()
763
- * Get an object containing the data, title and url of the current state
764
- * @return {Object} State
765
- */
766
- History.getLastStoredState = function(){
767
- return History.storedStates[History.storedStates.length-1]||undefined;
768
- };
769
-
770
- /**
771
- * History.hasUrlDuplicate
772
- * Checks if a Url will have a url conflict
773
- * @param {Object} newState
774
- * @return {Boolean} hasDuplicate
775
- */
776
- History.hasUrlDuplicate = function(newState) {
777
- // Prepare
778
- var hasDuplicate = false;
779
-
780
- // Fetch
781
- var oldState = History.extractState(newState.url);
782
-
783
- // Check
784
- hasDuplicate = oldState && oldState.id !== newState.id;
785
-
786
- // Return
787
- return hasDuplicate;
788
- };
789
-
790
- /**
791
- * History.storeState
792
- * Store a State
793
- * @param {Object} newState
794
- * @return {Object} newState
795
- */
796
- History.storeState = function(newState){
797
- // Store the State
798
- History.urlToId[newState.url] = newState.id;
799
-
800
- // Push the State
801
- History.storedStates.push(History.cloneObject(newState));
802
-
803
- // Return newState
804
- return newState;
805
- };
806
-
807
- /**
808
- * History.isLastSavedState(newState)
809
- * Tests to see if the state is the last state
810
- * @param {Object} newState
811
- * @return {boolean} isLast
812
- */
813
- History.isLastSavedState = function(newState){
814
- // Prepare
815
- var isLast = false;
816
-
817
- // Check
818
- if ( History.savedStates.length ) {
819
- var
820
- newId = newState.id,
821
- oldState = History.getLastSavedState(),
822
- oldId = oldState.id;
823
-
824
- // Check
825
- isLast = (newId === oldId);
826
- }
827
-
828
- // Return
829
- return isLast;
830
- };
831
-
832
- /**
833
- * History.saveState
834
- * Push a State
835
- * @param {Object} newState
836
- * @return {boolean} changed
837
- */
838
- History.saveState = function(newState){
839
- // Check Hash
840
- if ( History.isLastSavedState(newState) ) {
841
- return false;
842
- }
843
-
844
- // Push the State
845
- History.savedStates.push(History.cloneObject(newState));
846
-
847
- // Return true
848
- return true;
849
- };
850
-
851
- /**
852
- * History.getStateByIndex()
853
- * Gets a state by the index
854
- * @param {integer} index
855
- * @return {Object}
856
- */
857
- History.getStateByIndex = function(index){
858
- // Prepare
859
- var State = null;
860
-
861
- // Handle
862
- if ( typeof index === 'undefined' ) {
863
- // Get the last inserted
864
- State = History.savedStates[History.savedStates.length-1];
865
- }
866
- else if ( index < 0 ) {
867
- // Get from the end
868
- State = History.savedStates[History.savedStates.length+index];
869
- }
870
- else {
871
- // Get from the beginning
872
- State = History.savedStates[index];
873
- }
874
-
875
- // Return State
876
- return State;
877
- };
878
-
879
- // ----------------------------------------------------------------------
880
- // Hash Helpers
881
-
882
- /**
883
- * History.getHash()
884
- * Gets the current document hash
885
- * @return {string}
886
- */
887
- History.getHash = function(){
888
- var hash = History.unescapeHash(document.location.hash);
889
- return hash;
890
- };
891
-
892
- /**
893
- * History.unescapeHash()
894
- * normalize and Unescape a Hash
895
- * @return {string}
896
- */
897
- History.unescapeHash = function(hash){
898
- var result = History.normalizeHash(hash);
899
-
900
- // Unescape hash
901
- if ( /\%[^2][^5]/.test(result) ) {
902
- result = window.unescape(result);
903
- }
904
-
905
- // Return result
906
- return result;
907
- };
908
-
909
- /**
910
- * History.normalizeHash()
911
- * normalize a hash across browsers
912
- * @return {string}
913
- */
914
- History.normalizeHash = function(hash){
915
- var result = hash.replace(/[^#]*#/,'').replace(/#.*/, '');
916
-
917
- // Return result
918
- return result;
919
- };
920
-
921
- /**
922
- * History.setHash(hash)
923
- * Sets the document hash
924
- * @param {string} hash
925
- * @return {History}
926
- */
927
- History.setHash = function(hash,queue){
928
- // Handle Queueing
929
- if ( queue !== false && History.busy() ) {
930
- // Wait + Push to Queue
931
- //History.debug('History.setHash: we must wait', arguments);
932
- History.pushQueue({
933
- scope: History,
934
- callback: History.setHash,
935
- args: arguments,
936
- queue: queue
937
- });
938
- return false;
939
- }
940
-
941
- // Log
942
- //History.debug('History.setHash: called',hash);
943
-
944
- // Prepare
945
- var adjustedHash = History.escapeHash(hash);
946
-
947
- // Make Busy + Continue
948
- History.busy(true);
949
-
950
- // Check if hash is a state
951
- var State = History.extractState(hash,true);
952
- if ( State && !History.emulated.pushState ) {
953
- // Hash is a state so skip the setHash
954
- //History.debug('History.setHash: Hash is a state so skipping the hash set with a direct pushState call',arguments);
955
-
956
- // PushState
957
- History.pushState(State.data,State.title,State.url,false);
958
- }
959
- else if ( document.location.hash !== adjustedHash ) {
960
- // Hash is a proper hash, so apply it
961
-
962
- // Handle browser bugs
963
- if ( History.bugs.setHash ) {
964
- // Fix Safari Bug https://bugs.webkit.org/show_bug.cgi?id=56249
965
-
966
- // Fetch the base page
967
- var pageUrl = History.getPageUrl();
968
-
969
- // Safari hash apply
970
- History.pushState(null,null,pageUrl+'#'+adjustedHash,false);
971
- }
972
- else {
973
- // Normal hash apply
974
- document.location.hash = adjustedHash;
975
- }
976
- }
977
-
978
- // Chain
979
- return History;
980
- };
981
-
982
- /**
983
- * History.escape()
984
- * normalize and Escape a Hash
985
- * @return {string}
986
- */
987
- History.escapeHash = function(hash){
988
- var result = History.normalizeHash(hash);
989
-
990
- // Escape hash
991
- result = window.escape(result);
992
-
993
- // IE6 Escape Bug
994
- if ( !History.bugs.hashEscape ) {
995
- // Restore common parts
996
- result = result
997
- .replace('%21','!')
998
- .replace('%26','&')
999
- .replace('%3D','=')
1000
- .replace('%3F','?');
1001
- }
1002
-
1003
- // Return result
1004
- return result;
1005
- };
1006
-
1007
- /**
1008
- * History.getHashByUrl(url)
1009
- * Extracts the Hash from a URL
1010
- * @param {string} url
1011
- * @return {string} url
1012
- */
1013
- History.getHashByUrl = function(url){
1014
- // Extract the hash
1015
- var hash = String(url)
1016
- .replace(/([^#]*)#?([^#]*)#?(.*)/, '$2')
1017
- ;
1018
-
1019
- // Unescape hash
1020
- hash = History.unescapeHash(hash);
1021
-
1022
- // Return hash
1023
- return hash;
1024
- };
1025
-
1026
- /**
1027
- * History.isTraditionalAnchor(url)
1028
- * Checks to see if the url is a traditional anchor
1029
- * @param {string} url
1030
- * @return {boolean}
1031
- */
1032
- History.isTraditionalAnchor = function(url){
1033
- var
1034
- hash = History.getHashByUrl(url),
1035
- el = document.getElementById(hash),
1036
- isTraditionalAnchor = typeof el !== 'undefined';
1037
-
1038
- // Return isTraditionalAnchor
1039
- return isTraditionalAnchor;
1040
- };
1041
-
1042
- /**
1043
- * History.setTitle(title)
1044
- * Applies the title to the document
1045
- * @param {State} newState
1046
- * @return {Boolean}
1047
- */
1048
- History.setTitle = function(newState){
1049
- // Prepare
1050
- var title = newState.title;
1051
-
1052
- // Initial
1053
- if ( !title ) {
1054
- var firstState = History.getStateByIndex(0);
1055
- if ( firstState && firstState.url === newState.url ) {
1056
- title = firstState.title||History.options.initialTitle;
1057
- }
1058
- }
1059
-
1060
- // Apply
1061
- try {
1062
- document.getElementsByTagName('title')[0].innerHTML = title.replace('<','&lt;').replace('>','&gt;').replace(' & ',' &amp; ');
1063
- }
1064
- catch ( Exception ) { }
1065
- document.title = title;
1066
-
1067
- // Chain
1068
- return History;
1069
- };
1070
-
1071
- // ----------------------------------------------------------------------
1072
- // Queueing
1073
-
1074
- /**
1075
- * History.queues
1076
- * The list of queues to use
1077
- * First In, First Out
1078
- */
1079
- History.queues = [];
1080
-
1081
- /**
1082
- * History.busy(value)
1083
- * @param {boolean} value [optional]
1084
- * @return {boolean} busy
1085
- */
1086
- History.busy = function(value){
1087
- // Apply
1088
- if ( typeof value !== 'undefined' ) {
1089
- //History.debug('History.busy: changing ['+(History.busy.flag||false)+'] to ['+(value||false)+']', History.queues.length);
1090
- History.busy.flag = value;
1091
- }
1092
- // Default
1093
- else if ( typeof History.busy.flag === 'undefined' ) {
1094
- History.busy.flag = false;
1095
- }
1096
-
1097
- // Queue
1098
- if ( !History.busy.flag ) {
1099
- // Execute the next item in the queue
1100
- clearTimeout(History.busy.timeout);
1101
- var fireNext = function(){
1102
- if ( History.busy.flag ) return;
1103
- for ( var i=History.queues.length-1; i >= 0; --i ) {
1104
- var queue = History.queues[i];
1105
- if ( queue.length === 0 ) continue;
1106
- var item = queue.shift();
1107
- History.fireQueueItem(item);
1108
- History.busy.timeout = setTimeout(fireNext,History.options.busyDelay);
1109
- }
1110
- };
1111
- History.busy.timeout = setTimeout(fireNext,History.options.busyDelay);
1112
- }
1113
-
1114
- // Return
1115
- return History.busy.flag;
1116
- };
1117
-
1118
- /**
1119
- * History.fireQueueItem(item)
1120
- * Fire a Queue Item
1121
- * @param {Object} item
1122
- * @return {Mixed} result
1123
- */
1124
- History.fireQueueItem = function(item){
1125
- return item.callback.apply(item.scope||History,item.args||[]);
1126
- };
1127
-
1128
- /**
1129
- * History.pushQueue(callback,args)
1130
- * Add an item to the queue
1131
- * @param {Object} item [scope,callback,args,queue]
1132
- */
1133
- History.pushQueue = function(item){
1134
- // Prepare the queue
1135
- History.queues[item.queue||0] = History.queues[item.queue||0]||[];
1136
-
1137
- // Add to the queue
1138
- History.queues[item.queue||0].push(item);
1139
-
1140
- // Chain
1141
- return History;
1142
- };
1143
-
1144
- /**
1145
- * History.queue (item,queue), (func,queue), (func), (item)
1146
- * Either firs the item now if not busy, or adds it to the queue
1147
- */
1148
- History.queue = function(item,queue){
1149
- // Prepare
1150
- if ( typeof item === 'function' ) {
1151
- item = {
1152
- callback: item
1153
- };
1154
- }
1155
- if ( typeof queue !== 'undefined' ) {
1156
- item.queue = queue;
1157
- }
1158
-
1159
- // Handle
1160
- if ( History.busy() ) {
1161
- History.pushQueue(item);
1162
- } else {
1163
- History.fireQueueItem(item);
1164
- }
1165
-
1166
- // Chain
1167
- return History;
1168
- };
1169
-
1170
- /**
1171
- * History.clearQueue()
1172
- * Clears the Queue
1173
- */
1174
- History.clearQueue = function(){
1175
- History.busy.flag = false;
1176
- History.queues = [];
1177
- return History;
1178
- };
1179
-
1180
-
1181
- // ----------------------------------------------------------------------
1182
- // IE Bug Fix
1183
-
1184
- /**
1185
- * History.stateChanged
1186
- * States whether or not the state has changed since the last double check was initialised
1187
- */
1188
- History.stateChanged = false;
1189
-
1190
- /**
1191
- * History.doubleChecker
1192
- * Contains the timeout used for the double checks
1193
- */
1194
- History.doubleChecker = false;
1195
-
1196
- /**
1197
- * History.doubleCheckComplete()
1198
- * Complete a double check
1199
- * @return {History}
1200
- */
1201
- History.doubleCheckComplete = function(){
1202
- // Update
1203
- History.stateChanged = true;
1204
-
1205
- // Clear
1206
- History.doubleCheckClear();
1207
-
1208
- // Chain
1209
- return History;
1210
- };
1211
-
1212
- /**
1213
- * History.doubleCheckClear()
1214
- * Clear a double check
1215
- * @return {History}
1216
- */
1217
- History.doubleCheckClear = function(){
1218
- // Clear
1219
- if ( History.doubleChecker ) {
1220
- clearTimeout(History.doubleChecker);
1221
- History.doubleChecker = false;
1222
- }
1223
-
1224
- // Chain
1225
- return History;
1226
- };
1227
-
1228
- /**
1229
- * History.doubleCheck()
1230
- * Create a double check
1231
- * @return {History}
1232
- */
1233
- History.doubleCheck = function(tryAgain){
1234
- // Reset
1235
- History.stateChanged = false;
1236
- History.doubleCheckClear();
1237
-
1238
- // Fix IE6,IE7 bug where calling history.back or history.forward does not actually change the hash (whereas doing it manually does)
1239
- // Fix Safari 5 bug where sometimes the state does not change: https://bugs.webkit.org/show_bug.cgi?id=42940
1240
- if ( History.bugs.ieDoubleCheck ) {
1241
- // Apply Check
1242
- History.doubleChecker = setTimeout(
1243
- function(){
1244
- History.doubleCheckClear();
1245
- if ( !History.stateChanged ) {
1246
- //History.debug('History.doubleCheck: State has not yet changed, trying again', arguments);
1247
- // Re-Attempt
1248
- tryAgain();
1249
- }
1250
- return true;
1251
- },
1252
- History.options.doubleCheckInterval
1253
- );
1254
- }
1255
-
1256
- // Chain
1257
- return History;
1258
- };
1259
-
1260
- // ----------------------------------------------------------------------
1261
- // Safari Bug Fix
1262
-
1263
- /**
1264
- * History.safariStatePoll()
1265
- * Poll the current state
1266
- * @return {History}
1267
- */
1268
- History.safariStatePoll = function(){
1269
- // Poll the URL
1270
-
1271
- // Get the Last State which has the new URL
1272
- var
1273
- urlState = History.extractState(document.location.href),
1274
- newState;
1275
-
1276
- // Check for a difference
1277
- if ( !History.isLastSavedState(urlState) ) {
1278
- newState = urlState;
1279
- }
1280
- else {
1281
- return;
1282
- }
1283
-
1284
- // Check if we have a state with that url
1285
- // If not create it
1286
- if ( !newState ) {
1287
- //History.debug('History.safariStatePoll: new');
1288
- newState = History.createStateObject();
1289
- }
1290
-
1291
- // Apply the New State
1292
- //History.debug('History.safariStatePoll: trigger');
1293
- History.Adapter.trigger(window,'popstate');
1294
-
1295
- // Chain
1296
- return History;
1297
- };
1298
-
1299
- // ----------------------------------------------------------------------
1300
- // State Aliases
1301
-
1302
- /**
1303
- * History.back(queue)
1304
- * Send the browser history back one item
1305
- * @param {Integer} queue [optional]
1306
- */
1307
- History.back = function(queue){
1308
- //History.debug('History.back: called', arguments);
1309
-
1310
- // Handle Queueing
1311
- if ( queue !== false && History.busy() ) {
1312
- // Wait + Push to Queue
1313
- //History.debug('History.back: we must wait', arguments);
1314
- History.pushQueue({
1315
- scope: History,
1316
- callback: History.back,
1317
- args: arguments,
1318
- queue: queue
1319
- });
1320
- return false;
1321
- }
1322
-
1323
- // Make Busy + Continue
1324
- History.busy(true);
1325
-
1326
- // Fix certain browser bugs that prevent the state from changing
1327
- History.doubleCheck(function(){
1328
- History.back(false);
1329
- });
1330
-
1331
- // Go back
1332
- history.go(-1);
1333
-
1334
- // End back closure
1335
- return true;
1336
- };
1337
-
1338
- /**
1339
- * History.forward(queue)
1340
- * Send the browser history forward one item
1341
- * @param {Integer} queue [optional]
1342
- */
1343
- History.forward = function(queue){
1344
- //History.debug('History.forward: called', arguments);
1345
-
1346
- // Handle Queueing
1347
- if ( queue !== false && History.busy() ) {
1348
- // Wait + Push to Queue
1349
- //History.debug('History.forward: we must wait', arguments);
1350
- History.pushQueue({
1351
- scope: History,
1352
- callback: History.forward,
1353
- args: arguments,
1354
- queue: queue
1355
- });
1356
- return false;
1357
- }
1358
-
1359
- // Make Busy + Continue
1360
- History.busy(true);
1361
-
1362
- // Fix certain browser bugs that prevent the state from changing
1363
- History.doubleCheck(function(){
1364
- History.forward(false);
1365
- });
1366
-
1367
- // Go forward
1368
- history.go(1);
1369
-
1370
- // End forward closure
1371
- return true;
1372
- };
1373
-
1374
- /**
1375
- * History.go(index,queue)
1376
- * Send the browser history back or forward index times
1377
- * @param {Integer} queue [optional]
1378
- */
1379
- History.go = function(index,queue){
1380
- //History.debug('History.go: called', arguments);
1381
-
1382
- // Prepare
1383
- var i;
1384
-
1385
- // Handle
1386
- if ( index > 0 ) {
1387
- // Forward
1388
- for ( i=1; i<=index; ++i ) {
1389
- History.forward(queue);
1390
- }
1391
- }
1392
- else if ( index < 0 ) {
1393
- // Backward
1394
- for ( i=-1; i>=index; --i ) {
1395
- History.back(queue);
1396
- }
1397
- }
1398
- else {
1399
- throw new Error('History.go: History.go requires a positive or negative integer passed.');
1400
- }
1401
-
1402
- // Chain
1403
- return History;
1404
- };
1405
-
1406
-
1407
- // ----------------------------------------------------------------------
1408
- // HTML5 State Support
1409
-
1410
- if ( History.emulated.pushState ) {
1411
- /*
1412
- * Provide Skeleton for HTML4 Browsers
1413
- */
1414
-
1415
- // Prepare
1416
- var emptyFunction = function(){};
1417
- History.pushState = History.pushState||emptyFunction;
1418
- History.replaceState = History.replaceState||emptyFunction;
1419
- }
1420
- else {
1421
- /*
1422
- * Use native HTML5 History API Implementation
1423
- */
1424
-
1425
- /**
1426
- * History.onPopState(event,extra)
1427
- * Refresh the Current State
1428
- */
1429
- History.onPopState = function(event){
1430
- // Reset the double check
1431
- History.doubleCheckComplete();
1432
-
1433
- // Check for a Hash, and handle apporiatly
1434
- var currentHash = History.getHash();
1435
- if ( currentHash ) {
1436
- // Expand Hash
1437
- var currentState = History.extractState(currentHash||document.location.href,true);
1438
- if ( currentState ) {
1439
- // We were able to parse it, it must be a State!
1440
- // Let's forward to replaceState
1441
- //History.debug('History.onPopState: state anchor', currentHash, currentState);
1442
- History.replaceState(currentState.data, currentState.title, currentState.url, false);
1443
- }
1444
- else {
1445
- // Traditional Anchor
1446
- //History.debug('History.onPopState: traditional anchor', currentHash);
1447
- History.Adapter.trigger(window,'anchorchange');
1448
- History.busy(false);
1449
- }
1450
-
1451
- // We don't care for hashes
1452
- History.expectedStateId = false;
1453
- return false;
1454
- }
1455
-
1456
- // Prepare
1457
- var newState = null;
1458
-
1459
- // Prepare
1460
- event = event||{};
1461
- if ( typeof event.state === 'undefined' ) {
1462
- // jQuery
1463
- if ( typeof event.originalEvent !== 'undefined' && typeof event.originalEvent.state !== 'undefined' ) {
1464
- event.state = event.originalEvent.state||false;
1465
- }
1466
- // MooTools
1467
- else if ( typeof event.event !== 'undefined' && typeof event.event.state !== 'undefined' ) {
1468
- event.state = event.event.state||false;
1469
- }
1470
- }
1471
-
1472
- // Ensure
1473
- event.state = (event.state||false);
1474
-
1475
- // Fetch State
1476
- if ( event.state ) {
1477
- // Vanilla: Back/forward button was used
1478
- newState = History.getStateById(event.state);
1479
- }
1480
- else if ( History.expectedStateId ) {
1481
- // Vanilla: A new state was pushed, and popstate was called manually
1482
- newState = History.getStateById(History.expectedStateId);
1483
- }
1484
- else {
1485
- // Initial State
1486
- newState = History.extractState(document.location.href);
1487
- }
1488
-
1489
- // Clean
1490
- History.expectedStateId = false;
1491
-
1492
- // Check if we are the same state
1493
- if ( History.isLastSavedState(newState) ) {
1494
- // There has been no change (just the page's hash has finally propagated)
1495
- //History.debug('History.onPopState: no change', newState, History.savedStates);
1496
- History.busy(false);
1497
- return false;
1498
- }
1499
-
1500
- // Store the State
1501
- History.storeState(newState);
1502
- History.saveState(newState);
1503
-
1504
- // Force update of the title
1505
- History.setTitle(newState);
1506
-
1507
- // Fire Our Event
1508
- History.Adapter.trigger(window,'statechange');
1509
- History.busy(false);
1510
-
1511
- // Return true
1512
- return true;
1513
- };
1514
- History.Adapter.bind(window,'popstate',History.onPopState);
1515
-
1516
- /**
1517
- * History.pushState(data,title,url)
1518
- * Add a new State to the history object, become it, and trigger onpopstate
1519
- * We have to trigger for HTML4 compatibility
1520
- * @param {object} data
1521
- * @param {string} title
1522
- * @param {string} url
1523
- * @return {true}
1524
- */
1525
- History.pushState = function(data,title,url,queue){
1526
- //History.debug('History.pushState: called', arguments);
1527
-
1528
- // Check the State
1529
- if ( History.getHashByUrl(url) && History.emulated.pushState ) {
1530
- throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1531
- }
1532
-
1533
- // Handle Queueing
1534
- if ( queue !== false && History.busy() ) {
1535
- // Wait + Push to Queue
1536
- //History.debug('History.pushState: we must wait', arguments);
1537
- History.pushQueue({
1538
- scope: History,
1539
- callback: History.pushState,
1540
- args: arguments,
1541
- queue: queue
1542
- });
1543
- return false;
1544
- }
1545
-
1546
- // Make Busy + Continue
1547
- History.busy(true);
1548
-
1549
- // Create the newState
1550
- var newState = History.createStateObject(data,title,url);
1551
-
1552
- // Check it
1553
- if ( History.isLastSavedState(newState) ) {
1554
- // Won't be a change
1555
- History.busy(false);
1556
- }
1557
- else {
1558
- // Store the newState
1559
- History.storeState(newState);
1560
- History.expectedStateId = newState.id;
1561
-
1562
- // Push the newState
1563
- var pushUrl =
1564
- (History.bugs.safariPoll && History.hasUrlDuplicate(newState))
1565
- ? newState.hashedUrl
1566
- : newState.url;
1567
- history.pushState(newState.id,newState.title,pushUrl);
1568
-
1569
- // Fire HTML5 Event
1570
- History.Adapter.trigger(window,'popstate');
1571
- }
1572
-
1573
- // End pushState closure
1574
- return true;
1575
- };
1576
-
1577
- /**
1578
- * History.replaceState(data,title,url)
1579
- * Replace the State and trigger onpopstate
1580
- * We have to trigger for HTML4 compatibility
1581
- * @param {object} data
1582
- * @param {string} title
1583
- * @param {string} url
1584
- * @return {true}
1585
- */
1586
- History.replaceState = function(data,title,url,queue){
1587
- //History.debug('History.replaceState: called', arguments);
1588
-
1589
- // Check the State
1590
- if ( History.getHashByUrl(url) && History.emulated.pushState ) {
1591
- throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1592
- }
1593
-
1594
- // Handle Queueing
1595
- if ( queue !== false && History.busy() ) {
1596
- // Wait + Push to Queue
1597
- //History.debug('History.replaceState: we must wait', arguments);
1598
- History.pushQueue({
1599
- scope: History,
1600
- callback: History.replaceState,
1601
- args: arguments,
1602
- queue: queue
1603
- });
1604
- return false;
1605
- }
1606
-
1607
- // Make Busy + Continue
1608
- History.busy(true);
1609
-
1610
- // Create the newState
1611
- var newState = History.createStateObject(data,title,url);
1612
-
1613
- // Check it
1614
- if ( History.isLastSavedState(newState) ) {
1615
- // Won't be a change
1616
- History.busy(false);
1617
- }
1618
- else {
1619
- // Store the newState
1620
- History.storeState(newState);
1621
- History.expectedStateId = newState.id;
1622
-
1623
- // Push the newState
1624
- var pushUrl =
1625
- (History.bugs.safariPoll && History.hasUrlDuplicate(newState))
1626
- ? newState.hashedUrl
1627
- : newState.url;
1628
- history.replaceState(newState.id,newState.title,pushUrl);
1629
-
1630
- // Fire HTML5 Event
1631
- History.Adapter.trigger(window,'popstate');
1632
- }
1633
-
1634
- // End replaceState closure
1635
- return true;
1636
- };
1637
-
1638
- /**
1639
- * Create the initial State
1640
- */
1641
- History.saveState(History.storeState(History.createStateObject({},'',document.location.href)));
1642
-
1643
- /**
1644
- * Setup Safari Fix
1645
- */
1646
- if ( History.bugs.safariPoll ) {
1647
- setInterval(History.safariStatePoll, History.options.safariPollInterval);
1648
- }
1649
-
1650
- /**
1651
- * Ensure Cross Browser Compatibility
1652
- */
1653
- if ( navigator.vendor === 'Apple Computer, Inc.' || (navigator.appCodeName||'') === 'Mozilla' ) {
1654
- /**
1655
- * Fix Safari HashChange Issue
1656
- */
1657
-
1658
- // Setup Alias
1659
- History.Adapter.bind(window,'hashchange',function(){
1660
- History.Adapter.trigger(window,'popstate');
1661
- });
1662
-
1663
- // Initialise Alias
1664
- if ( History.getHash() ) {
1665
- History.Adapter.onDomLoad(function(){
1666
- History.Adapter.trigger(window,'hashchange');
1667
- });
1668
- }
1669
- }
1670
-
1671
- } // !History.emulated.pushState
1672
-
1673
- }; // History.initCore
1674
-
1675
- // Try and Initialise History
1676
- History.init();
8
+ (function(window, undefined) {
9
+ "use strict";
10
+
11
+ // --------------------------------------------------------------------------
12
+ // Initialise
13
+
14
+ // Localise Globals
15
+ var
16
+ console = window.console || undefined, // Prevent a JSLint complain
17
+ document = window.document, // Make sure we are using the correct document
18
+ navigator = window.navigator, // Make sure we are using the correct navigator
19
+ amplify = window.amplify || false, // Amplify.js
20
+ setTimeout = window.setTimeout,
21
+ clearTimeout = window.clearTimeout,
22
+ setInterval = window.setInterval,
23
+ JSON = window.JSON,
24
+ History = window.History = window.History || {}, // Public History Object
25
+ history = window.history; // Old History Object
26
+
27
+ // MooTools Compatibility
28
+ JSON.stringify = JSON.stringify || JSON.encode;
29
+ JSON.parse = JSON.parse || JSON.decode;
30
+
31
+ // Check Existence
32
+ if (typeof History.init !== 'undefined') {
33
+ throw new Error('History.js Core has already been loaded...');
34
+ }
35
+
36
+ // Initialise History
37
+ History.init = function() {
38
+ // Check Load Status of Adapter
39
+ if (typeof History.Adapter === 'undefined') {
40
+ return false;
41
+ }
42
+
43
+ // Check Load Status of Core
44
+ if (typeof History.initCore !== 'undefined') {
45
+ History.initCore();
46
+ }
47
+
48
+ // Check Load Status of HTML4 Support
49
+ if (typeof History.initHtml4 !== 'undefined') {
50
+ History.initHtml4();
51
+ }
52
+
53
+ // Return true
54
+ return true;
55
+ };
56
+
57
+ // --------------------------------------------------------------------------
58
+ // Initialise Core
59
+
60
+ // Initialise Core
61
+ History.initCore = function() {
62
+ // Initialise
63
+ if (typeof History.initCore.initialized !== 'undefined') {
64
+ // Already Loaded
65
+ return false;
66
+ }
67
+ else {
68
+ History.initCore.initialized = true;
69
+ }
70
+
71
+ // ----------------------------------------------------------------------
72
+ // Options
73
+
74
+ /**
75
+ * History.options
76
+ * Configurable options
77
+ */
78
+ History.options = History.options || {};
79
+
80
+ /**
81
+ * History.options.hashChangeInterval
82
+ * How long should the interval be before hashchange checks
83
+ */
84
+ History.options.hashChangeInterval = History.options.hashChangeInterval || 100;
85
+
86
+ /**
87
+ * History.options.safariPollInterval
88
+ * How long should the interval be before safari poll checks
89
+ */
90
+ History.options.safariPollInterval = History.options.safariPollInterval || 500;
91
+
92
+ /**
93
+ * History.options.doubleCheckInterval
94
+ * How long should the interval be before we perform a double check
95
+ */
96
+ History.options.doubleCheckInterval = History.options.doubleCheckInterval || 500;
97
+
98
+ /**
99
+ * History.options.storeInterval
100
+ * How long should we wait between store calls
101
+ */
102
+ History.options.storeInterval = History.options.storeInterval || 1000;
103
+
104
+ /**
105
+ * History.options.busyDelay
106
+ * How long should we wait between busy events
107
+ */
108
+ History.options.busyDelay = History.options.busyDelay || 250;
109
+
110
+ /**
111
+ * History.options.debug
112
+ * If true will enable debug messages to be logged
113
+ */
114
+ History.options.debug = History.options.debug || false;
115
+
116
+ /**
117
+ * History.options.initialTitle
118
+ * What is the title of the initial state
119
+ */
120
+ History.options.initialTitle = History.options.initialTitle || document.title;
121
+
122
+
123
+ // ----------------------------------------------------------------------
124
+ // Debug
125
+
126
+ /**
127
+ * History.debug(message,...)
128
+ * Logs the passed arguments if debug enabled
129
+ */
130
+ History.debug = function() {
131
+ if ((History.options.debug || false)) {
132
+ History.log.apply(History, arguments);
133
+ }
134
+ };
135
+
136
+ /**
137
+ * History.log(message,...)
138
+ * Logs the passed arguments
139
+ */
140
+ History.log = function() {
141
+ // Prepare
142
+ var
143
+ consoleExists = !(typeof console === 'undefined' || typeof console.log === 'undefined' || typeof console.log.apply === 'undefined'),
144
+ textarea = document.getElementById('log'),
145
+ message,
146
+ i,n
147
+ ;
148
+
149
+ // Write to Console
150
+ if (consoleExists) {
151
+ var args = Array.prototype.slice.call(arguments);
152
+ message = args.shift();
153
+ if (typeof console.debug !== 'undefined') {
154
+ console.debug.apply(console, [message,args]);
155
+ }
156
+ else {
157
+ console.log.apply(console, [message,args]);
158
+ }
159
+ }
160
+ else {
161
+ message = ("\n" + arguments[0] + "\n");
162
+ }
163
+
164
+ // Write to log
165
+ for (i = 1,n = arguments.length; i < n; ++i) {
166
+ var arg = arguments[i];
167
+ if (typeof arg === 'object' && typeof JSON !== 'undefined') {
168
+ try {
169
+ arg = JSON.stringify(arg);
170
+ }
171
+ catch (Exception) {
172
+ // Recursive Object
173
+ }
174
+ }
175
+ message += "\n" + arg + "\n";
176
+ }
177
+
178
+ // Textarea
179
+ if (textarea) {
180
+ textarea.value += message + "\n-----\n";
181
+ textarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;
182
+ }
183
+ // No Textarea, No Console
184
+ else if (!consoleExists) {
185
+ alert(message);
186
+ }
187
+
188
+ // Return true
189
+ return true;
190
+ };
191
+
192
+ // ----------------------------------------------------------------------
193
+ // Emulated Status
194
+
195
+ /**
196
+ * History.getInternetExplorerMajorVersion()
197
+ * Get's the major version of Internet Explorer
198
+ * @return {integer}
199
+ * @license Public Domain
200
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
201
+ * @author James Padolsey <https://gist.github.com/527683>
202
+ */
203
+ History.getInternetExplorerMajorVersion = function() {
204
+ var result = History.getInternetExplorerMajorVersion.cached =
205
+ (typeof History.getInternetExplorerMajorVersion.cached !== 'undefined')
206
+ ? History.getInternetExplorerMajorVersion.cached
207
+ : (function() {
208
+ var v = 3,
209
+ div = document.createElement('div'),
210
+ all = div.getElementsByTagName('i');
211
+ while ((div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->') && all[0]) {
212
+ }
213
+ return (v > 4) ? v : false;
214
+ })()
215
+ ;
216
+ return result;
217
+ };
218
+
219
+ /**
220
+ * History.isInternetExplorer()
221
+ * Are we using Internet Explorer?
222
+ * @return {boolean}
223
+ * @license Public Domain
224
+ * @author Benjamin Arthur Lupton <contact@balupton.com>
225
+ */
226
+ History.isInternetExplorer = function() {
227
+ var result =
228
+ History.isInternetExplorer.cached =
229
+ (typeof History.isInternetExplorer.cached !== 'undefined')
230
+ ? History.isInternetExplorer.cached
231
+ : Boolean(History.getInternetExplorerMajorVersion())
232
+ ;
233
+ return result;
234
+ };
235
+
236
+ /**
237
+ * History.emulated
238
+ * Which features require emulating?
239
+ */
240
+ History.emulated = {
241
+ pushState: !Boolean(
242
+ window.history && window.history.pushState && window.history.replaceState
243
+ && !(
244
+ (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent) /* disable for versions of iOS before version 4.3 (8F190) */
245
+ || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent) /* disable for the mercury iOS browser, or at least older versions of the webkit engine */
246
+ )
247
+ ),
248
+ hashChange: Boolean(
249
+ !(('onhashchange' in window) || ('onhashchange' in document))
250
+ ||
251
+ (History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8)
252
+ )
253
+ };
254
+
255
+ /**
256
+ * History.enabled
257
+ * Is History enabled?
258
+ */
259
+ History.enabled = !History.emulated.pushState;
260
+
261
+ /**
262
+ * History.bugs
263
+ * Which bugs are present
264
+ */
265
+ History.bugs = {
266
+ /**
267
+ * Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call
268
+ * https://bugs.webkit.org/show_bug.cgi?id=56249
269
+ */
270
+ setHash: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2]|3[0-3])/.test(navigator.userAgent)),
271
+
272
+ /**
273
+ * Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions
274
+ * https://bugs.webkit.org/show_bug.cgi?id=42940
275
+ */
276
+ safariPoll: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2]|3[0-3])/.test(navigator.userAgent)),
277
+
278
+ /**
279
+ * MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function)
280
+ */
281
+ ieDoubleCheck: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8),
282
+
283
+ /**
284
+ * MSIE 6 requires the entire hash to be encoded for the hashes to trigger the onHashChange event
285
+ */
286
+ hashEscape: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 7)
287
+ };
288
+
289
+ /**
290
+ * History.isEmptyObject(obj)
291
+ * Checks to see if the Object is Empty
292
+ * @param {Object} obj
293
+ * @return {boolean}
294
+ */
295
+ History.isEmptyObject = function(obj) {
296
+ for (var name in obj) {
297
+ return false;
298
+ }
299
+ return true;
300
+ };
301
+
302
+ /**
303
+ * History.cloneObject(obj)
304
+ * Clones a object
305
+ * @param {Object} obj
306
+ * @return {Object}
307
+ */
308
+ History.cloneObject = function(obj) {
309
+ var hash,newObj;
310
+ if (obj) {
311
+ hash = JSON.stringify(obj);
312
+ newObj = JSON.parse(hash);
313
+ }
314
+ else {
315
+ newObj = {};
316
+ }
317
+ return newObj;
318
+ };
319
+
320
+ // ----------------------------------------------------------------------
321
+ // URL Helpers
322
+
323
+ /**
324
+ * History.getRootUrl()
325
+ * Turns "http://mysite.com/dir/page.html?asd" into "http://mysite.com"
326
+ * @return {String} rootUrl
327
+ */
328
+ History.getRootUrl = function() {
329
+ // Create
330
+ var rootUrl = document.location.protocol + '//' + (document.location.hostname || document.location.host);
331
+ if (document.location.port || false) {
332
+ rootUrl += ':' + document.location.port;
333
+ }
334
+ rootUrl += '/';
335
+
336
+ // Return
337
+ return rootUrl;
338
+ };
339
+
340
+ /**
341
+ * History.getBaseHref()
342
+ * Fetches the `href` attribute of the `<base href="...">` element if it exists
343
+ * @return {String} baseHref
344
+ */
345
+ History.getBaseHref = function() {
346
+ // Create
347
+ var
348
+ baseElements = document.getElementsByTagName('base'),
349
+ baseElement = null,
350
+ baseHref = '';
351
+
352
+ // Test for Base Element
353
+ if (baseElements.length === 1) {
354
+ // Prepare for Base Element
355
+ baseElement = baseElements[0];
356
+ baseHref = baseElement.href.replace(/[^\/]+$/, '');
357
+ }
358
+
359
+ // Adjust trailing slash
360
+ baseHref = baseHref.replace(/\/+$/, '');
361
+ if (baseHref) baseHref += '/';
362
+
363
+ // Return
364
+ return baseHref;
365
+ };
366
+
367
+ /**
368
+ * History.getBaseUrl()
369
+ * Fetches the baseHref or basePageUrl or rootUrl (whichever one exists first)
370
+ * @return {String} baseUrl
371
+ */
372
+ History.getBaseUrl = function() {
373
+ // Create
374
+ var baseUrl = History.getBaseHref() || History.getBasePageUrl() || History.getRootUrl();
375
+
376
+ // Return
377
+ return baseUrl;
378
+ };
379
+
380
+ /**
381
+ * History.getPageUrl()
382
+ * Fetches the URL of the current page
383
+ * @return {String} pageUrl
384
+ */
385
+ History.getPageUrl = function() {
386
+ // Fetch
387
+ var
388
+ State = History.getState(false, false),
389
+ stateUrl = (State || {}).url || document.location.href;
390
+
391
+ // Create
392
+ var pageUrl = stateUrl.replace(/\/+$/, '').replace(/[^\/]+$/, function(part, index, string) {
393
+ return (/\./).test(part) ? part : part + '/';
394
+ });
395
+
396
+ // Return
397
+ return pageUrl;
398
+ };
399
+
400
+ /**
401
+ * History.getBasePageUrl()
402
+ * Fetches the Url of the directory of the current page
403
+ * @return {String} basePageUrl
404
+ */
405
+ History.getBasePageUrl = function() {
406
+ // Create
407
+ var basePageUrl = document.location.href.replace(/[#\?].*/, '').replace(/[^\/]+$/,
408
+ function(part, index, string) {
409
+ return (/[^\/]$/).test(part) ? '' : part;
410
+ }).replace(/\/+$/, '') + '/';
411
+
412
+ // Return
413
+ return basePageUrl;
414
+ };
415
+
416
+ /**
417
+ * History.getFullUrl(url)
418
+ * Ensures that we have an absolute URL and not a relative URL
419
+ * @param {string} url
420
+ * @param {Boolean} allowBaseHref
421
+ * @return {string} fullUrl
422
+ */
423
+ History.getFullUrl = function(url, allowBaseHref) {
424
+ // Prepare
425
+ var fullUrl = url, firstChar = url.substring(0, 1);
426
+ allowBaseHref = (typeof allowBaseHref === 'undefined') ? true : allowBaseHref;
427
+
428
+ // Check
429
+ if (/[a-z]+\:\/\//.test(url)) {
430
+ // Full URL
431
+ }
432
+ else if (firstChar === '/') {
433
+ // Root URL
434
+ fullUrl = History.getRootUrl() + url.replace(/^\/+/, '');
435
+ }
436
+ else if (firstChar === '#') {
437
+ // Anchor URL
438
+ fullUrl = History.getPageUrl().replace(/#.*/, '') + url;
439
+ }
440
+ else if (firstChar === '?') {
441
+ // Query URL
442
+ fullUrl = History.getPageUrl().replace(/[\?#].*/, '') + url;
443
+ }
444
+ else {
445
+ // Relative URL
446
+ if (allowBaseHref) {
447
+ fullUrl = History.getBaseUrl() + url.replace(/^(\.\/)+/, '');
448
+ } else {
449
+ fullUrl = History.getBasePageUrl() + url.replace(/^(\.\/)+/, '');
450
+ }
451
+ // We have an if condition above as we do not want hashes
452
+ // which are relative to the baseHref in our URLs
453
+ // as if the baseHref changes, then all our bookmarks
454
+ // would now point to different locations
455
+ // whereas the basePageUrl will always stay the same
456
+ }
457
+
458
+ // Return
459
+ return fullUrl.replace(/\#$/, '');
460
+ };
461
+
462
+ /**
463
+ * History.getShortUrl(url)
464
+ * Ensures that we have a relative URL and not a absolute URL
465
+ * @param {string} url
466
+ * @return {string} url
467
+ */
468
+ History.getShortUrl = function(url) {
469
+ // Prepare
470
+ var shortUrl = url, baseUrl = History.getBaseUrl(), rootUrl = History.getRootUrl();
471
+
472
+ // Trim baseUrl
473
+ if (History.emulated.pushState) {
474
+ // We are in a if statement as when pushState is not emulated
475
+ // The actual url these short urls are relative to can change
476
+ // So within the same session, we the url may end up somewhere different
477
+ shortUrl = shortUrl.replace(baseUrl, '');
478
+ }
479
+
480
+ // Trim rootUrl
481
+ shortUrl = shortUrl.replace(rootUrl, '/');
482
+
483
+ // Ensure we can still detect it as a state
484
+ if (History.isTraditionalAnchor(shortUrl)) {
485
+ shortUrl = './' + shortUrl;
486
+ }
487
+
488
+ // Clean It
489
+ shortUrl = shortUrl.replace(/^(\.\/)+/g, './').replace(/\#$/, '');
490
+
491
+ // Return
492
+ return shortUrl;
493
+ };
494
+
495
+ // ----------------------------------------------------------------------
496
+ // State Storage
497
+
498
+ /**
499
+ * History.store
500
+ * The store for all session specific data
501
+ */
502
+ History.store = amplify ? (amplify.store('History.store') || {}) : {};
503
+ History.store.idToState = History.store.idToState || {};
504
+ History.store.urlToId = History.store.urlToId || {};
505
+ History.store.stateToId = History.store.stateToId || {};
506
+
507
+ /**
508
+ * History.idToState
509
+ * 1-1: State ID to State Object
510
+ */
511
+ History.idToState = History.idToState || {};
512
+
513
+ /**
514
+ * History.stateToId
515
+ * 1-1: State String to State ID
516
+ */
517
+ History.stateToId = History.stateToId || {};
518
+
519
+ /**
520
+ * History.urlToId
521
+ * 1-1: State URL to State ID
522
+ */
523
+ History.urlToId = History.urlToId || {};
524
+
525
+ /**
526
+ * History.storedStates
527
+ * Store the states in an array
528
+ */
529
+ History.storedStates = History.storedStates || [];
530
+
531
+ /**
532
+ * History.savedStates
533
+ * Saved the states in an array
534
+ */
535
+ History.savedStates = History.savedStates || [];
536
+
537
+ /**
538
+ * History.getState()
539
+ * Get an object containing the data, title and url of the current state
540
+ * @param {Boolean} friendly
541
+ * @param {Boolean} create
542
+ * @return {Object} State
543
+ */
544
+ History.getState = function(friendly, create) {
545
+ // Prepare
546
+ if (typeof friendly === 'undefined') {
547
+ friendly = true;
548
+ }
549
+ if (typeof create === 'undefined') {
550
+ create = true;
551
+ }
552
+
553
+ // Fetch
554
+ var State = History.getLastSavedState();
555
+
556
+ // Create
557
+ if (!State && create) {
558
+ State = History.createStateObject();
559
+ }
560
+
561
+ // Adjust
562
+ if (friendly) {
563
+ State = History.cloneObject(State);
564
+ State.url = State.cleanUrl || State.url;
565
+ }
566
+
567
+ // Return
568
+ return State;
569
+ };
570
+
571
+ /**
572
+ * History.getIdByState(State)
573
+ * Gets a ID for a State
574
+ * @param {State} newState
575
+ * @return {String} id
576
+ */
577
+ History.getIdByState = function(newState) {
578
+
579
+ // Fetch ID
580
+ var id = History.extractId(newState.url);
581
+ if (!id) {
582
+ // Find ID via State String
583
+ var str = History.getStateString(newState);
584
+ if (typeof History.stateToId[str] !== 'undefined') {
585
+ id = History.stateToId[str];
586
+ }
587
+ else if (typeof History.store.stateToId[str] !== 'undefined') {
588
+ id = History.store.stateToId[str];
589
+ }
590
+ else {
591
+ // Generate a new ID
592
+ while (true) {
593
+ id = String(Math.floor(Math.random() * 1000));
594
+ if (typeof History.idToState[id] === 'undefined' && typeof History.store.idToState[id] === 'undefined') {
595
+ break;
596
+ }
597
+ }
598
+
599
+ // Apply the new State to the ID
600
+ History.stateToId[str] = id;
601
+ History.idToState[id] = newState;
602
+ }
603
+ }
604
+
605
+ // Return ID
606
+ return id;
607
+ };
608
+
609
+ /**
610
+ * History.normalizeState(State)
611
+ * Expands a State Object
612
+ * @param {object} State
613
+ * @return {object}
614
+ */
615
+ History.normalizeState = function(oldState) {
616
+ // Prepare
617
+ if (!oldState || (typeof oldState !== 'object')) {
618
+ oldState = {};
619
+ }
620
+
621
+ // Check
622
+ if (typeof oldState.normalized !== 'undefined') {
623
+ return oldState;
624
+ }
625
+
626
+ // Adjust
627
+ if (!oldState.data || (typeof oldState.data !== 'object')) {
628
+ oldState.data = {};
629
+ }
630
+
631
+ // ----------------------------------------------------------------------
632
+
633
+ // Create
634
+ var newState = {};
635
+ newState.normalized = true;
636
+ newState.title = oldState.title || '';
637
+ newState.url = History.getFullUrl(History.unescapeString(oldState.url || document.location.href));
638
+ newState.hash = History.getShortUrl(newState.url);
639
+ newState.data = History.cloneObject(oldState.data);
640
+
641
+ // Fetch ID
642
+ newState.id = History.getIdByState(newState);
643
+
644
+ // ----------------------------------------------------------------------
645
+
646
+ // Clean the URL
647
+ newState.cleanUrl = newState.url.replace(/\??\&_suid.*/, '');
648
+ newState.url = newState.cleanUrl;
649
+
650
+ // Check to see if we have more than just a url
651
+ var dataNotEmpty = !History.isEmptyObject(newState.data);
652
+
653
+ // Apply
654
+ if (newState.title || dataNotEmpty) {
655
+ // Add ID to Hash
656
+ newState.hash = History.getShortUrl(newState.url).replace(/\??\&_suid.*/, '');
657
+ if (!/\?/.test(newState.hash)) {
658
+ newState.hash += '?';
659
+ }
660
+ newState.hash += '&_suid=' + newState.id;
661
+ }
662
+
663
+ // Create the Hashed URL
664
+ newState.hashedUrl = History.getFullUrl(newState.hash);
665
+
666
+ // ----------------------------------------------------------------------
667
+
668
+ // Update the URL if we have a duplicate
669
+ if ((History.emulated.pushState || History.bugs.safariPoll) && History.hasUrlDuplicate(newState)) {
670
+ newState.url = newState.hashedUrl;
671
+ }
672
+
673
+ // ----------------------------------------------------------------------
674
+
675
+ // Return
676
+ return newState;
677
+ };
678
+
679
+ /**
680
+ * History.createStateObject(data,title,url)
681
+ * Creates a object based on the data, title and url state params
682
+ * @param {object} data
683
+ * @param {string} title
684
+ * @param {string} url
685
+ * @return {object}
686
+ */
687
+ History.createStateObject = function(data, title, url) {
688
+ // Hashify
689
+ var State = {
690
+ 'data': data,
691
+ 'title': title,
692
+ 'url': url
693
+ };
694
+
695
+ // Expand the State
696
+ State = History.normalizeState(State);
697
+
698
+ // Return object
699
+ return State;
700
+ };
701
+
702
+ /**
703
+ * History.getStateById(id)
704
+ * Get a state by it's UID
705
+ * @param {String} id
706
+ */
707
+ History.getStateById = function(id) {
708
+ // Prepare
709
+ id = String(id);
710
+
711
+ // Retrieve
712
+ var State = History.idToState[id] || History.store.idToState[id] || undefined;
713
+
714
+ // Return State
715
+ return State;
716
+ };
717
+
718
+ /**
719
+ * Get a State's String
720
+ * @param {State} passedState
721
+ */
722
+ History.getStateString = function(passedState) {
723
+ // Prepare
724
+ var State = History.normalizeState(passedState);
725
+
726
+ // Clean
727
+ var cleanedState = {
728
+ data: State.data,
729
+ title: passedState.title,
730
+ url: passedState.url
731
+ };
732
+
733
+ // Fetch
734
+ var str = JSON.stringify(cleanedState);
735
+
736
+ // Return
737
+ return str;
738
+ };
739
+
740
+ /**
741
+ * Get a State's ID
742
+ * @param {State} passedState
743
+ * @return {String} id
744
+ */
745
+ History.getStateId = function(passedState) {
746
+ // Prepare
747
+ var State = History.normalizeState(passedState);
748
+
749
+ // Fetch
750
+ var id = State.id;
751
+
752
+ // Return
753
+ return id;
754
+ };
755
+
756
+ /**
757
+ * History.getHashByState(State)
758
+ * Creates a Hash for the State Object
759
+ * @param {State} passedState
760
+ * @return {String} hash
761
+ */
762
+ History.getHashByState = function(passedState) {
763
+ // Prepare
764
+ var hash, State = History.normalizeState(passedState);
765
+
766
+ // Fetch
767
+ hash = State.hash;
768
+
769
+ // Return
770
+ return hash;
771
+ };
772
+
773
+ /**
774
+ * History.extractId(url_or_hash)
775
+ * Get a State ID by it's URL or Hash
776
+ * @param {string} url_or_hash
777
+ * @return {string} id
778
+ */
779
+ History.extractId = function (url_or_hash) {
780
+ // Prepare
781
+ var id;
782
+
783
+ // Extract
784
+ var parts,url;
785
+ parts = /(.*)\&_suid=([0-9]+)$/.exec(url_or_hash);
786
+ url = parts ? (parts[1] || url_or_hash) : url_or_hash;
787
+ id = parts ? String(parts[2] || '') : '';
788
+
789
+ // Return
790
+ return id || false;
791
+ };
792
+
793
+ /**
794
+ * History.isTraditionalAnchor
795
+ * Checks to see if the url is a traditional anchor or not
796
+ * @param {String} url_or_hash
797
+ * @return {Boolean}
798
+ */
799
+ History.isTraditionalAnchor = function(url_or_hash) {
800
+ // Check
801
+ var isTraditional = !(/[\/\?\.]/.test(url_or_hash));
802
+
803
+ // Return
804
+ return isTraditional;
805
+ };
806
+
807
+ /**
808
+ * History.extractState
809
+ * Get a State by it's URL or Hash
810
+ * @param {String} url_or_hash
811
+ * @return {State|null}
812
+ */
813
+ History.extractState = function(url_or_hash, create) {
814
+ // Prepare
815
+ var State = null;
816
+ create = create || false;
817
+
818
+ // Fetch SUID
819
+ var id = History.extractId(url_or_hash);
820
+ if (id) {
821
+ State = History.getStateById(id);
822
+ }
823
+
824
+ // Fetch SUID returned no State
825
+ if (!State) {
826
+ // Fetch URL
827
+ var url = History.getFullUrl(url_or_hash);
828
+
829
+ // Check URL
830
+ id = History.getIdByUrl(url) || false;
831
+ if (id) {
832
+ State = History.getStateById(id);
833
+ }
834
+
835
+ // Create State
836
+ if (!State && create && !History.isTraditionalAnchor(url_or_hash)) {
837
+ State = History.createStateObject(null, null, url);
838
+ }
839
+ }
840
+
841
+ // Return
842
+ return State;
843
+ };
844
+
845
+ /**
846
+ * History.getIdByUrl()
847
+ * Get a State ID by a State URL
848
+ */
849
+ History.getIdByUrl = function(url) {
850
+ // Fetch
851
+ var id = History.urlToId[url] || History.store.urlToId[url] || undefined;
852
+
853
+ // Return
854
+ return id;
855
+ };
856
+
857
+ /**
858
+ * History.getLastSavedState()
859
+ * Get an object containing the data, title and url of the current state
860
+ * @return {Object} State
861
+ */
862
+ History.getLastSavedState = function() {
863
+ return History.savedStates[History.savedStates.length - 1] || undefined;
864
+ };
865
+
866
+ /**
867
+ * History.getLastStoredState()
868
+ * Get an object containing the data, title and url of the current state
869
+ * @return {Object} State
870
+ */
871
+ History.getLastStoredState = function() {
872
+ return History.storedStates[History.storedStates.length - 1] || undefined;
873
+ };
874
+
875
+ /**
876
+ * History.hasUrlDuplicate
877
+ * Checks if a Url will have a url conflict
878
+ * @param {Object} newState
879
+ * @return {Boolean} hasDuplicate
880
+ */
881
+ History.hasUrlDuplicate = function(newState) {
882
+ // Prepare
883
+ var hasDuplicate = false;
884
+
885
+ // Fetch
886
+ var oldState = History.extractState(newState.url);
887
+
888
+ // Check
889
+ hasDuplicate = oldState && oldState.id !== newState.id;
890
+
891
+ // Return
892
+ return hasDuplicate;
893
+ };
894
+
895
+ /**
896
+ * History.storeState
897
+ * Store a State
898
+ * @param {Object} newState
899
+ * @return {Object} newState
900
+ */
901
+ History.storeState = function(newState) {
902
+ // Store the State
903
+ History.urlToId[newState.url] = newState.id;
904
+
905
+ // Push the State
906
+ History.storedStates.push(History.cloneObject(newState));
907
+
908
+ // Return newState
909
+ return newState;
910
+ };
911
+
912
+ /**
913
+ * History.isLastSavedState(newState)
914
+ * Tests to see if the state is the last state
915
+ * @param {Object} newState
916
+ * @return {boolean} isLast
917
+ */
918
+ History.isLastSavedState = function(newState) {
919
+ // Prepare
920
+ var isLast = false;
921
+
922
+ // Check
923
+ if (History.savedStates.length) {
924
+ var
925
+ newId = newState.id,
926
+ oldState = History.getLastSavedState(),
927
+ oldId = oldState.id;
928
+
929
+ // Check
930
+ isLast = (newId === oldId);
931
+ }
932
+
933
+ // Return
934
+ return isLast;
935
+ };
936
+
937
+ /**
938
+ * History.saveState
939
+ * Push a State
940
+ * @param {Object} newState
941
+ * @return {boolean} changed
942
+ */
943
+ History.saveState = function(newState) {
944
+ // Check Hash
945
+ if (History.isLastSavedState(newState)) {
946
+ return false;
947
+ }
948
+
949
+ // Push the State
950
+ History.savedStates.push(History.cloneObject(newState));
951
+
952
+ // Return true
953
+ return true;
954
+ };
955
+
956
+ /**
957
+ * History.getStateByIndex()
958
+ * Gets a state by the index
959
+ * @param {integer} index
960
+ * @return {Object}
961
+ */
962
+ History.getStateByIndex = function(index) {
963
+ // Prepare
964
+ var State = null;
965
+
966
+ // Handle
967
+ if (typeof index === 'undefined') {
968
+ // Get the last inserted
969
+ State = History.savedStates[History.savedStates.length - 1];
970
+ }
971
+ else if (index < 0) {
972
+ // Get from the end
973
+ State = History.savedStates[History.savedStates.length + index];
974
+ }
975
+ else {
976
+ // Get from the beginning
977
+ State = History.savedStates[index];
978
+ }
979
+
980
+ // Return State
981
+ return State;
982
+ };
983
+
984
+ // ----------------------------------------------------------------------
985
+ // Hash Helpers
986
+
987
+ /**
988
+ * History.getHash()
989
+ * Gets the current document hash
990
+ * @return {string}
991
+ */
992
+ History.getHash = function() {
993
+ var hash = History.unescapeHash(document.location.hash);
994
+ return hash;
995
+ };
996
+
997
+ /**
998
+ * History.unescapeString()
999
+ * Unescape a string
1000
+ * @param {String} str
1001
+ * @return {string}
1002
+ */
1003
+ History.unescapeString = function(str) {
1004
+ // Prepare
1005
+ var result = str;
1006
+
1007
+ // Unescape hash
1008
+ var tmp;
1009
+ while (true) {
1010
+ tmp = window.unescape(result);
1011
+ if (tmp === result) {
1012
+ break;
1013
+ }
1014
+ result = tmp;
1015
+ }
1016
+
1017
+ // Return result
1018
+ return result;
1019
+ };
1020
+
1021
+ /**
1022
+ * History.unescapeHash()
1023
+ * normalize and Unescape a Hash
1024
+ * @param {String} hash
1025
+ * @return {string}
1026
+ */
1027
+ History.unescapeHash = function(hash) {
1028
+ // Prepare
1029
+ var result = History.normalizeHash(hash);
1030
+
1031
+ // Unescape hash
1032
+ result = History.unescapeString(result);
1033
+
1034
+ // Return result
1035
+ return result;
1036
+ };
1037
+
1038
+ /**
1039
+ * History.normalizeHash()
1040
+ * normalize a hash across browsers
1041
+ * @return {string}
1042
+ */
1043
+ History.normalizeHash = function(hash) {
1044
+ var result = hash.replace(/[^#]*#/, '').replace(/#.*/, '');
1045
+
1046
+ // Return result
1047
+ return result;
1048
+ };
1049
+
1050
+ /**
1051
+ * History.setHash(hash)
1052
+ * Sets the document hash
1053
+ * @param {string} hash
1054
+ * @return {History}
1055
+ */
1056
+ History.setHash = function(hash, queue) {
1057
+ // Handle Queueing
1058
+ if (queue !== false && History.busy()) {
1059
+ // Wait + Push to Queue
1060
+ //History.debug('History.setHash: we must wait', arguments);
1061
+ History.pushQueue({
1062
+ scope: History,
1063
+ callback: History.setHash,
1064
+ args: arguments,
1065
+ queue: queue
1066
+ });
1067
+ return false;
1068
+ }
1069
+
1070
+ // Log
1071
+ //History.debug('History.setHash: called',hash);
1072
+
1073
+ // Prepare
1074
+ var adjustedHash = History.escapeHash(hash);
1075
+
1076
+ // Make Busy + Continue
1077
+ History.busy(true);
1078
+
1079
+ // Check if hash is a state
1080
+ var State = History.extractState(hash, true);
1081
+ if (State && !History.emulated.pushState) {
1082
+ // Hash is a state so skip the setHash
1083
+ //History.debug('History.setHash: Hash is a state so skipping the hash set with a direct pushState call',arguments);
1084
+
1085
+ // PushState
1086
+ History.pushState(State.data, State.title, State.url, false);
1087
+ }
1088
+ else if (document.location.hash !== adjustedHash) {
1089
+ // Hash is a proper hash, so apply it
1090
+
1091
+ // Handle browser bugs
1092
+ if (History.bugs.setHash) {
1093
+ // Fix Safari Bug https://bugs.webkit.org/show_bug.cgi?id=56249
1094
+
1095
+ // Fetch the base page
1096
+ var pageUrl = History.getPageUrl();
1097
+
1098
+ // Safari hash apply
1099
+ History.pushState(null, null, pageUrl + '#' + adjustedHash, false);
1100
+ }
1101
+ else {
1102
+ // Normal hash apply
1103
+ document.location.hash = adjustedHash;
1104
+ }
1105
+ }
1106
+
1107
+ // Chain
1108
+ return History;
1109
+ };
1110
+
1111
+ /**
1112
+ * History.escape()
1113
+ * normalize and Escape a Hash
1114
+ * @return {string}
1115
+ */
1116
+ History.escapeHash = function(hash) {
1117
+ var result = History.normalizeHash(hash);
1118
+
1119
+ // Escape hash
1120
+ result = window.escape(result);
1121
+
1122
+ // IE6 Escape Bug
1123
+ if (!History.bugs.hashEscape) {
1124
+ // Restore common parts
1125
+ result = result
1126
+ .replace(/\%21/g, '!')
1127
+ .replace(/\%26/g, '&')
1128
+ .replace(/\%3D/g, '=')
1129
+ .replace(/\%3F/g, '?');
1130
+ }
1131
+
1132
+ // Return result
1133
+ return result;
1134
+ };
1135
+
1136
+ /**
1137
+ * History.getHashByUrl(url)
1138
+ * Extracts the Hash from a URL
1139
+ * @param {string} url
1140
+ * @return {string} url
1141
+ */
1142
+ History.getHashByUrl = function(url) {
1143
+ // Extract the hash
1144
+ var hash = String(url)
1145
+ .replace(/([^#]*)#?([^#]*)#?(.*)/, '$2')
1146
+ ;
1147
+
1148
+ // Unescape hash
1149
+ hash = History.unescapeHash(hash);
1150
+
1151
+ // Return hash
1152
+ return hash;
1153
+ };
1154
+
1155
+ /**
1156
+ * History.setTitle(title)
1157
+ * Applies the title to the document
1158
+ * @param {State} newState
1159
+ * @return {Boolean}
1160
+ */
1161
+ History.setTitle = function(newState) {
1162
+ // Prepare
1163
+ var title = newState.title;
1164
+
1165
+ // Initial
1166
+ if (!title) {
1167
+ var firstState = History.getStateByIndex(0);
1168
+ if (firstState && firstState.url === newState.url) {
1169
+ title = firstState.title || History.options.initialTitle;
1170
+ }
1171
+ }
1172
+
1173
+ // Apply
1174
+ try {
1175
+ document.getElementsByTagName('title')[0].innerHTML = title.replace('<', '&lt;').replace('>', '&gt;').replace(' & ', ' &amp; ');
1176
+ }
1177
+ catch (Exception) {
1178
+ }
1179
+ document.title = title;
1180
+
1181
+ // Chain
1182
+ return History;
1183
+ };
1184
+
1185
+ // ----------------------------------------------------------------------
1186
+ // Queueing
1187
+
1188
+ /**
1189
+ * History.queues
1190
+ * The list of queues to use
1191
+ * First In, First Out
1192
+ */
1193
+ History.queues = [];
1194
+
1195
+ /**
1196
+ * History.busy(value)
1197
+ * @param {boolean} value [optional]
1198
+ * @return {boolean} busy
1199
+ */
1200
+ History.busy = function(value) {
1201
+ // Apply
1202
+ if (typeof value !== 'undefined') {
1203
+ //History.debug('History.busy: changing ['+(History.busy.flag||false)+'] to ['+(value||false)+']', History.queues.length);
1204
+ History.busy.flag = value;
1205
+ }
1206
+ // Default
1207
+ else if (typeof History.busy.flag === 'undefined') {
1208
+ History.busy.flag = false;
1209
+ }
1210
+
1211
+ // Queue
1212
+ if (!History.busy.flag) {
1213
+ // Execute the next item in the queue
1214
+ clearTimeout(History.busy.timeout);
1215
+ var fireNext = function() {
1216
+ if (History.busy.flag) return;
1217
+ for (var i = History.queues.length - 1; i >= 0; --i) {
1218
+ var queue = History.queues[i];
1219
+ if (queue.length === 0) continue;
1220
+ var item = queue.shift();
1221
+ History.fireQueueItem(item);
1222
+ History.busy.timeout = setTimeout(fireNext, History.options.busyDelay);
1223
+ }
1224
+ };
1225
+ History.busy.timeout = setTimeout(fireNext, History.options.busyDelay);
1226
+ }
1227
+
1228
+ // Return
1229
+ return History.busy.flag;
1230
+ };
1231
+
1232
+ /**
1233
+ * History.fireQueueItem(item)
1234
+ * Fire a Queue Item
1235
+ * @param {Object} item
1236
+ * @return {Mixed} result
1237
+ */
1238
+ History.fireQueueItem = function(item) {
1239
+ return item.callback.apply(item.scope || History, item.args || []);
1240
+ };
1241
+
1242
+ /**
1243
+ * History.pushQueue(callback,args)
1244
+ * Add an item to the queue
1245
+ * @param {Object} item [scope,callback,args,queue]
1246
+ */
1247
+ History.pushQueue = function(item) {
1248
+ // Prepare the queue
1249
+ History.queues[item.queue || 0] = History.queues[item.queue || 0] || [];
1250
+
1251
+ // Add to the queue
1252
+ History.queues[item.queue || 0].push(item);
1253
+
1254
+ // Chain
1255
+ return History;
1256
+ };
1257
+
1258
+ /**
1259
+ * History.queue (item,queue), (func,queue), (func), (item)
1260
+ * Either firs the item now if not busy, or adds it to the queue
1261
+ */
1262
+ History.queue = function(item, queue) {
1263
+ // Prepare
1264
+ if (typeof item === 'function') {
1265
+ item = {
1266
+ callback: item
1267
+ };
1268
+ }
1269
+ if (typeof queue !== 'undefined') {
1270
+ item.queue = queue;
1271
+ }
1272
+
1273
+ // Handle
1274
+ if (History.busy()) {
1275
+ History.pushQueue(item);
1276
+ } else {
1277
+ History.fireQueueItem(item);
1278
+ }
1279
+
1280
+ // Chain
1281
+ return History;
1282
+ };
1283
+
1284
+ /**
1285
+ * History.clearQueue()
1286
+ * Clears the Queue
1287
+ */
1288
+ History.clearQueue = function() {
1289
+ History.busy.flag = false;
1290
+ History.queues = [];
1291
+ return History;
1292
+ };
1293
+
1294
+
1295
+ // ----------------------------------------------------------------------
1296
+ // IE Bug Fix
1297
+
1298
+ /**
1299
+ * History.stateChanged
1300
+ * States whether or not the state has changed since the last double check was initialised
1301
+ */
1302
+ History.stateChanged = false;
1303
+
1304
+ /**
1305
+ * History.doubleChecker
1306
+ * Contains the timeout used for the double checks
1307
+ */
1308
+ History.doubleChecker = false;
1309
+
1310
+ /**
1311
+ * History.doubleCheckComplete()
1312
+ * Complete a double check
1313
+ * @return {History}
1314
+ */
1315
+ History.doubleCheckComplete = function() {
1316
+ // Update
1317
+ History.stateChanged = true;
1318
+
1319
+ // Clear
1320
+ History.doubleCheckClear();
1321
+
1322
+ // Chain
1323
+ return History;
1324
+ };
1325
+
1326
+ /**
1327
+ * History.doubleCheckClear()
1328
+ * Clear a double check
1329
+ * @return {History}
1330
+ */
1331
+ History.doubleCheckClear = function() {
1332
+ // Clear
1333
+ if (History.doubleChecker) {
1334
+ clearTimeout(History.doubleChecker);
1335
+ History.doubleChecker = false;
1336
+ }
1337
+
1338
+ // Chain
1339
+ return History;
1340
+ };
1341
+
1342
+ /**
1343
+ * History.doubleCheck()
1344
+ * Create a double check
1345
+ * @return {History}
1346
+ */
1347
+ History.doubleCheck = function(tryAgain) {
1348
+ // Reset
1349
+ History.stateChanged = false;
1350
+ History.doubleCheckClear();
1351
+
1352
+ // Fix IE6,IE7 bug where calling history.back or history.forward does not actually change the hash (whereas doing it manually does)
1353
+ // Fix Safari 5 bug where sometimes the state does not change: https://bugs.webkit.org/show_bug.cgi?id=42940
1354
+ if (History.bugs.ieDoubleCheck) {
1355
+ // Apply Check
1356
+ History.doubleChecker = setTimeout(
1357
+ function() {
1358
+ History.doubleCheckClear();
1359
+ if (!History.stateChanged) {
1360
+ //History.debug('History.doubleCheck: State has not yet changed, trying again', arguments);
1361
+ // Re-Attempt
1362
+ tryAgain();
1363
+ }
1364
+ return true;
1365
+ },
1366
+ History.options.doubleCheckInterval
1367
+ );
1368
+ }
1369
+
1370
+ // Chain
1371
+ return History;
1372
+ };
1373
+
1374
+ // ----------------------------------------------------------------------
1375
+ // Safari Bug Fix
1376
+
1377
+ /**
1378
+ * History.safariStatePoll()
1379
+ * Poll the current state
1380
+ * @return {History}
1381
+ */
1382
+ History.safariStatePoll = function() {
1383
+ // Poll the URL
1384
+
1385
+ // Get the Last State which has the new URL
1386
+ var
1387
+ urlState = History.extractState(document.location.href),
1388
+ newState;
1389
+
1390
+ // Check for a difference
1391
+ if (!History.isLastSavedState(urlState)) {
1392
+ newState = urlState;
1393
+ }
1394
+ else {
1395
+ return;
1396
+ }
1397
+
1398
+ // Check if we have a state with that url
1399
+ // If not create it
1400
+ if (!newState) {
1401
+ //History.debug('History.safariStatePoll: new');
1402
+ newState = History.createStateObject();
1403
+ }
1404
+
1405
+ // Apply the New State
1406
+ //History.debug('History.safariStatePoll: trigger');
1407
+ History.Adapter.trigger(window, 'popstate');
1408
+
1409
+ // Chain
1410
+ return History;
1411
+ };
1412
+
1413
+ // ----------------------------------------------------------------------
1414
+ // State Aliases
1415
+
1416
+ /**
1417
+ * History.back(queue)
1418
+ * Send the browser history back one item
1419
+ * @param {Integer} queue [optional]
1420
+ */
1421
+ History.back = function(queue) {
1422
+ //History.debug('History.back: called', arguments);
1423
+
1424
+ // Handle Queueing
1425
+ if (queue !== false && History.busy()) {
1426
+ // Wait + Push to Queue
1427
+ //History.debug('History.back: we must wait', arguments);
1428
+ History.pushQueue({
1429
+ scope: History,
1430
+ callback: History.back,
1431
+ args: arguments,
1432
+ queue: queue
1433
+ });
1434
+ return false;
1435
+ }
1436
+
1437
+ // Make Busy + Continue
1438
+ History.busy(true);
1439
+
1440
+ // Fix certain browser bugs that prevent the state from changing
1441
+ History.doubleCheck(function() {
1442
+ History.back(false);
1443
+ });
1444
+
1445
+ // Go back
1446
+ history.go(-1);
1447
+
1448
+ // End back closure
1449
+ return true;
1450
+ };
1451
+
1452
+ /**
1453
+ * History.forward(queue)
1454
+ * Send the browser history forward one item
1455
+ * @param {Integer} queue [optional]
1456
+ */
1457
+ History.forward = function(queue) {
1458
+ //History.debug('History.forward: called', arguments);
1459
+
1460
+ // Handle Queueing
1461
+ if (queue !== false && History.busy()) {
1462
+ // Wait + Push to Queue
1463
+ //History.debug('History.forward: we must wait', arguments);
1464
+ History.pushQueue({
1465
+ scope: History,
1466
+ callback: History.forward,
1467
+ args: arguments,
1468
+ queue: queue
1469
+ });
1470
+ return false;
1471
+ }
1472
+
1473
+ // Make Busy + Continue
1474
+ History.busy(true);
1475
+
1476
+ // Fix certain browser bugs that prevent the state from changing
1477
+ History.doubleCheck(function() {
1478
+ History.forward(false);
1479
+ });
1480
+
1481
+ // Go forward
1482
+ history.go(1);
1483
+
1484
+ // End forward closure
1485
+ return true;
1486
+ };
1487
+
1488
+ /**
1489
+ * History.go(index,queue)
1490
+ * Send the browser history back or forward index times
1491
+ * @param {Integer} queue [optional]
1492
+ */
1493
+ History.go = function(index, queue) {
1494
+ //History.debug('History.go: called', arguments);
1495
+
1496
+ // Prepare
1497
+ var i;
1498
+
1499
+ // Handle
1500
+ if (index > 0) {
1501
+ // Forward
1502
+ for (i = 1; i <= index; ++i) {
1503
+ History.forward(queue);
1504
+ }
1505
+ }
1506
+ else if (index < 0) {
1507
+ // Backward
1508
+ for (i = -1; i >= index; --i) {
1509
+ History.back(queue);
1510
+ }
1511
+ }
1512
+ else {
1513
+ throw new Error('History.go: History.go requires a positive or negative integer passed.');
1514
+ }
1515
+
1516
+ // Chain
1517
+ return History;
1518
+ };
1519
+
1520
+
1521
+ // ----------------------------------------------------------------------
1522
+ // Initialise
1523
+
1524
+ /**
1525
+ * Create the initial State
1526
+ */
1527
+ History.saveState(History.storeState(History.extractState(document.location.href, true)));
1528
+
1529
+ /**
1530
+ * Bind for Saving Store
1531
+ */
1532
+ if (amplify) {
1533
+ History.onUnload = function() {
1534
+ // Prepare
1535
+ var
1536
+ currentStore = amplify.store('History.store') || {},
1537
+ item;
1538
+
1539
+ // Ensure
1540
+ currentStore.idToState = currentStore.idToState || {};
1541
+ currentStore.urlToId = currentStore.urlToId || {};
1542
+ currentStore.stateToId = currentStore.stateToId || {};
1543
+
1544
+ // Sync
1545
+ for (item in History.idToState) {
1546
+ if (!History.idToState.hasOwnProperty(item)) {
1547
+ continue;
1548
+ }
1549
+ currentStore.idToState[item] = History.idToState[item];
1550
+ }
1551
+ for (item in History.urlToId) {
1552
+ if (!History.urlToId.hasOwnProperty(item)) {
1553
+ continue;
1554
+ }
1555
+ currentStore.urlToId[item] = History.urlToId[item];
1556
+ }
1557
+ for (item in History.stateToId) {
1558
+ if (!History.stateToId.hasOwnProperty(item)) {
1559
+ continue;
1560
+ }
1561
+ currentStore.stateToId[item] = History.stateToId[item];
1562
+ }
1563
+
1564
+ // Update
1565
+ History.store = currentStore;
1566
+
1567
+ // Store
1568
+ amplify.store('History.store', currentStore);
1569
+ };
1570
+ // For Internet Explorer
1571
+ setInterval(History.onUnload, History.options.storeInterval);
1572
+ // For Other Browsers
1573
+ History.Adapter.bind(window, 'beforeunload', History.onUnload);
1574
+ History.Adapter.bind(window, 'unload', History.onUnload);
1575
+ // Both are enabled for consistency
1576
+ }
1577
+
1578
+
1579
+ // ----------------------------------------------------------------------
1580
+ // HTML5 State Support
1581
+
1582
+ if (History.emulated.pushState) {
1583
+ /*
1584
+ * Provide Skeleton for HTML4 Browsers
1585
+ */
1586
+
1587
+ // Prepare
1588
+ var emptyFunction = function() {
1589
+ };
1590
+ History.pushState = History.pushState || emptyFunction;
1591
+ History.replaceState = History.replaceState || emptyFunction;
1592
+ }
1593
+ else {
1594
+ /*
1595
+ * Use native HTML5 History API Implementation
1596
+ */
1597
+
1598
+ /**
1599
+ * History.onPopState(event,extra)
1600
+ * Refresh the Current State
1601
+ */
1602
+ History.onPopState = function(event) {
1603
+ // Reset the double check
1604
+ History.doubleCheckComplete();
1605
+
1606
+ // Check for a Hash, and handle apporiatly
1607
+ var currentHash = History.getHash();
1608
+ if (currentHash) {
1609
+ // Expand Hash
1610
+ var currentState = History.extractState(currentHash || document.location.href, true);
1611
+ if (currentState) {
1612
+ // We were able to parse it, it must be a State!
1613
+ // Let's forward to replaceState
1614
+ //History.debug('History.onPopState: state anchor', currentHash, currentState);
1615
+ History.replaceState(currentState.data, currentState.title, currentState.url, false);
1616
+ }
1617
+ else {
1618
+ // Traditional Anchor
1619
+ //History.debug('History.onPopState: traditional anchor', currentHash);
1620
+ History.Adapter.trigger(window, 'anchorchange');
1621
+ History.busy(false);
1622
+ }
1623
+
1624
+ // We don't care for hashes
1625
+ History.expectedStateId = false;
1626
+ return false;
1627
+ }
1628
+
1629
+ // Prepare
1630
+ var newState = false;
1631
+
1632
+ // Prepare
1633
+ event = event || {};
1634
+ if (typeof event.state === 'undefined') {
1635
+ // jQuery
1636
+ if (typeof event.originalEvent !== 'undefined' && typeof event.originalEvent.state !== 'undefined') {
1637
+ event.state = event.originalEvent.state || false;
1638
+ }
1639
+ // MooTools
1640
+ else if (typeof event.event !== 'undefined' && typeof event.event.state !== 'undefined') {
1641
+ event.state = event.event.state || false;
1642
+ }
1643
+ }
1644
+
1645
+ // Ensure
1646
+ event.state = (event.state || false);
1647
+
1648
+ // Fetch State
1649
+ if (event.state) {
1650
+ // Vanilla: Back/forward button was used
1651
+ newState = History.getStateById(event.state);
1652
+ }
1653
+ else if (History.expectedStateId) {
1654
+ // Vanilla: A new state was pushed, and popstate was called manually
1655
+ newState = History.getStateById(History.expectedStateId);
1656
+ }
1657
+ else {
1658
+ // Initial State
1659
+ newState = History.extractState(document.location.href);
1660
+ }
1661
+
1662
+ // The State did not exist in our store
1663
+ if (!newState) {
1664
+ // Regenerate the State
1665
+ newState = History.createStateObject(null, null, document.location.href);
1666
+ }
1667
+
1668
+ // Clean
1669
+ History.expectedStateId = false;
1670
+
1671
+ // Check if we are the same state
1672
+ if (History.isLastSavedState(newState)) {
1673
+ // There has been no change (just the page's hash has finally propagated)
1674
+ //History.debug('History.onPopState: no change', newState, History.savedStates);
1675
+ History.busy(false);
1676
+ return false;
1677
+ }
1678
+
1679
+ // Store the State
1680
+ History.storeState(newState);
1681
+ History.saveState(newState);
1682
+
1683
+ // Force update of the title
1684
+ History.setTitle(newState);
1685
+
1686
+ // Fire Our Event
1687
+ History.Adapter.trigger(window, 'statechange');
1688
+ History.busy(false);
1689
+
1690
+ // Return true
1691
+ return true;
1692
+ };
1693
+ History.Adapter.bind(window, 'popstate', History.onPopState);
1694
+
1695
+ /**
1696
+ * History.pushState(data,title,url)
1697
+ * Add a new State to the history object, become it, and trigger onpopstate
1698
+ * We have to trigger for HTML4 compatibility
1699
+ * @param {object} data
1700
+ * @param {string} title
1701
+ * @param {string} url
1702
+ * @return {true}
1703
+ */
1704
+ History.pushState = function(data, title, url, queue) {
1705
+ //History.debug('History.pushState: called', arguments);
1706
+
1707
+ // Check the State
1708
+ if (History.getHashByUrl(url) && History.emulated.pushState) {
1709
+ throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1710
+ }
1711
+
1712
+ // Handle Queueing
1713
+ if (queue !== false && History.busy()) {
1714
+ // Wait + Push to Queue
1715
+ //History.debug('History.pushState: we must wait', arguments);
1716
+ History.pushQueue({
1717
+ scope: History,
1718
+ callback: History.pushState,
1719
+ args: arguments,
1720
+ queue: queue
1721
+ });
1722
+ return false;
1723
+ }
1724
+
1725
+ // Make Busy + Continue
1726
+ History.busy(true);
1727
+
1728
+ // Create the newState
1729
+ var newState = History.createStateObject(data, title, url);
1730
+
1731
+ // Check it
1732
+ if (History.isLastSavedState(newState)) {
1733
+ // Won't be a change
1734
+ History.busy(false);
1735
+ }
1736
+ else {
1737
+ // Store the newState
1738
+ History.storeState(newState);
1739
+ History.expectedStateId = newState.id;
1740
+
1741
+ // Push the newState
1742
+ history.pushState(newState.id, newState.title, newState.url);
1743
+
1744
+ // Fire HTML5 Event
1745
+ History.Adapter.trigger(window, 'popstate');
1746
+ }
1747
+
1748
+ // End pushState closure
1749
+ return true;
1750
+ };
1751
+
1752
+ /**
1753
+ * History.replaceState(data,title,url)
1754
+ * Replace the State and trigger onpopstate
1755
+ * We have to trigger for HTML4 compatibility
1756
+ * @param {object} data
1757
+ * @param {string} title
1758
+ * @param {string} url
1759
+ * @return {true}
1760
+ */
1761
+ History.replaceState = function(data, title, url, queue) {
1762
+ //History.debug('History.replaceState: called', arguments);
1763
+
1764
+ // Check the State
1765
+ if (History.getHashByUrl(url) && History.emulated.pushState) {
1766
+ throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).');
1767
+ }
1768
+
1769
+ // Handle Queueing
1770
+ if (queue !== false && History.busy()) {
1771
+ // Wait + Push to Queue
1772
+ //History.debug('History.replaceState: we must wait', arguments);
1773
+ History.pushQueue({
1774
+ scope: History,
1775
+ callback: History.replaceState,
1776
+ args: arguments,
1777
+ queue: queue
1778
+ });
1779
+ return false;
1780
+ }
1781
+
1782
+ // Make Busy + Continue
1783
+ History.busy(true);
1784
+
1785
+ // Create the newState
1786
+ var newState = History.createStateObject(data, title, url);
1787
+
1788
+ // Check it
1789
+ if (History.isLastSavedState(newState)) {
1790
+ // Won't be a change
1791
+ History.busy(false);
1792
+ }
1793
+ else {
1794
+ // Store the newState
1795
+ History.storeState(newState);
1796
+ History.expectedStateId = newState.id;
1797
+
1798
+ // Push the newState
1799
+ history.replaceState(newState.id, newState.title, newState.url);
1800
+
1801
+ // Fire HTML5 Event
1802
+ History.Adapter.trigger(window, 'popstate');
1803
+ }
1804
+
1805
+ // End replaceState closure
1806
+ return true;
1807
+ };
1808
+
1809
+ // Be aware, the following is only for native pushState implementations
1810
+ // If you are wanting to include something for all browsers
1811
+ // Then include it above this if block
1812
+
1813
+ /**
1814
+ * Setup Safari Fix
1815
+ */
1816
+ if (History.bugs.safariPoll) {
1817
+ setInterval(History.safariStatePoll, History.options.safariPollInterval);
1818
+ }
1819
+
1820
+ /**
1821
+ * Ensure Cross Browser Compatibility
1822
+ */
1823
+ if (navigator.vendor === 'Apple Computer, Inc.' || (navigator.appCodeName || '') === 'Mozilla') {
1824
+ /**
1825
+ * Fix Safari HashChange Issue
1826
+ */
1827
+
1828
+ // Setup Alias
1829
+ History.Adapter.bind(window, 'hashchange', function() {
1830
+ History.Adapter.trigger(window, 'popstate');
1831
+ });
1832
+
1833
+ // Initialise Alias
1834
+ if (History.getHash()) {
1835
+ History.Adapter.onDomLoad(function() {
1836
+ History.Adapter.trigger(window, 'hashchange');
1837
+ });
1838
+ }
1839
+ }
1840
+
1841
+ } // !History.emulated.pushState
1842
+
1843
+ }; // History.initCore
1844
+
1845
+ // Try and Initialise History
1846
+ History.init();
1677
1847
 
1678
1848
  })(window);