compass-jquery-plugin 0.3.2.5 → 0.3.2.6

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