compass-jquery-plugin 0.3.2.6 → 0.3.2.7.nil

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