tb_core 0.9.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.markdown +60 -0
  4. data/Rakefile +28 -0
  5. data/app/assets/images/back_disabled.jpg +0 -0
  6. data/app/assets/images/back_enabled.jpg +0 -0
  7. data/app/assets/images/favicon.ico +0 -0
  8. data/app/assets/images/forward_disabled.jpg +0 -0
  9. data/app/assets/images/forward_enabled.jpg +0 -0
  10. data/app/assets/images/sort_asc.png +0 -0
  11. data/app/assets/images/sort_asc_disabled.png +0 -0
  12. data/app/assets/images/sort_both.png +0 -0
  13. data/app/assets/images/sort_desc.png +0 -0
  14. data/app/assets/images/sort_desc_disabled.png +0 -0
  15. data/app/assets/images/spud/admin/down_arrow.gif +0 -0
  16. data/app/assets/images/spud/admin/flick/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  17. data/app/assets/images/spud/admin/flick/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  18. data/app/assets/images/spud/admin/flick/ui-bg_flat_55_ffffff_40x100.png +0 -0
  19. data/app/assets/images/spud/admin/flick/ui-bg_flat_75_ffffff_40x100.png +0 -0
  20. data/app/assets/images/spud/admin/flick/ui-bg_glass_65_ffffff_1x400.png +0 -0
  21. data/app/assets/images/spud/admin/flick/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  22. data/app/assets/images/spud/admin/flick/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  23. data/app/assets/images/spud/admin/flick/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  24. data/app/assets/images/spud/admin/flick/ui-icons_0073ea_256x240.png +0 -0
  25. data/app/assets/images/spud/admin/flick/ui-icons_454545_256x240.png +0 -0
  26. data/app/assets/images/spud/admin/flick/ui-icons_666666_256x240.png +0 -0
  27. data/app/assets/images/spud/admin/flick/ui-icons_ff0084_256x240.png +0 -0
  28. data/app/assets/images/spud/admin/flick/ui-icons_ffffff_256x240.png +0 -0
  29. data/app/assets/images/spud/admin/spud_logo.png +0 -0
  30. data/app/assets/images/spud/admin/spud_logo@2x.png +0 -0
  31. data/app/assets/images/spud/admin/up_arrow.gif +0 -0
  32. data/app/assets/images/spud/admin/users_thumb.png +0 -0
  33. data/app/assets/javascripts/spud/admin/application.js +133 -0
  34. data/app/assets/javascripts/spud/admin/dashboard.js +80 -0
  35. data/app/assets/javascripts/spud/admin/date_picker.js +56 -0
  36. data/app/assets/javascripts/spud/admin/editor.js +167 -0
  37. data/app/assets/javascripts/spud/admin/jquery.dataTables.min.js +151 -0
  38. data/app/assets/javascripts/spud/admin/preinit.js +1 -0
  39. data/app/assets/javascripts/spud/password_resets.js +2 -0
  40. data/app/assets/libs/bootstrap/css/bootstrap-responsive.css +1088 -0
  41. data/app/assets/libs/bootstrap/css/bootstrap.css +5893 -0
  42. data/app/assets/libs/bootstrap/img/glyphicons-halflings-white.png +0 -0
  43. data/app/assets/libs/bootstrap/img/glyphicons-halflings.png +0 -0
  44. data/app/assets/libs/bootstrap/js/bootstrap.js +2025 -0
  45. data/app/assets/libs/datepicker/css/datepicker.css +223 -0
  46. data/app/assets/libs/datepicker/js/bootstrap-datepicker.js +779 -0
  47. data/app/assets/libs/datepicker/less/datepicker.less +122 -0
  48. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  49. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_0_eeeeee_40x100.png +0 -0
  50. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_55_ffffff_40x100.png +0 -0
  51. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  52. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  53. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png +0 -0
  54. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_25_0073ea_1x100.png +0 -0
  55. data/app/assets/libs/jquery-ui/css/flick/images/ui-bg_highlight-soft_50_dddddd_1x100.png +0 -0
  56. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_0073ea_256x240.png +0 -0
  57. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_454545_256x240.png +0 -0
  58. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_666666_256x240.png +0 -0
  59. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_ff0084_256x240.png +0 -0
  60. data/app/assets/libs/jquery-ui/css/flick/images/ui-icons_ffffff_256x240.png +0 -0
  61. data/app/assets/libs/jquery-ui/css/flick/jquery-ui-1.9.1.custom.css +297 -0
  62. data/app/assets/libs/jquery-ui/css/flick/jquery-ui-1.9.1.custom.min.css +5 -0
  63. data/app/assets/libs/jquery-ui/js/jquery-ui-1.9.1.custom.js +4870 -0
  64. data/app/assets/libs/jquery-ui/js/jquery-ui-1.9.1.custom.min.js +6 -0
  65. data/app/assets/libs/tiny_mce/jquery.tinymce.js +1 -0
  66. data/app/assets/libs/tiny_mce/langs/en.js +1 -0
  67. data/app/assets/libs/tiny_mce/license.txt +504 -0
  68. data/app/assets/libs/tiny_mce/plugins/advhr/css/advhr.css +5 -0
  69. data/app/assets/libs/tiny_mce/plugins/advhr/editor_plugin.js +1 -0
  70. data/app/assets/libs/tiny_mce/plugins/advhr/editor_plugin_src.js +57 -0
  71. data/app/assets/libs/tiny_mce/plugins/advhr/js/rule.js +43 -0
  72. data/app/assets/libs/tiny_mce/plugins/advhr/langs/en_dlg.js +1 -0
  73. data/app/assets/libs/tiny_mce/plugins/advhr/rule.htm +58 -0
  74. data/app/assets/libs/tiny_mce/plugins/advimage/css/advimage.css +13 -0
  75. data/app/assets/libs/tiny_mce/plugins/advimage/editor_plugin.js +1 -0
  76. data/app/assets/libs/tiny_mce/plugins/advimage/editor_plugin_src.js +50 -0
  77. data/app/assets/libs/tiny_mce/plugins/advimage/image.htm +235 -0
  78. data/app/assets/libs/tiny_mce/plugins/advimage/img/sample.gif +0 -0
  79. data/app/assets/libs/tiny_mce/plugins/advimage/js/image.js +462 -0
  80. data/app/assets/libs/tiny_mce/plugins/advimage/langs/en_dlg.js +1 -0
  81. data/app/assets/libs/tiny_mce/plugins/advlink/css/advlink.css +8 -0
  82. data/app/assets/libs/tiny_mce/plugins/advlink/editor_plugin.js +1 -0
  83. data/app/assets/libs/tiny_mce/plugins/advlink/editor_plugin_src.js +61 -0
  84. data/app/assets/libs/tiny_mce/plugins/advlink/js/advlink.js +539 -0
  85. data/app/assets/libs/tiny_mce/plugins/advlink/langs/en_dlg.js +1 -0
  86. data/app/assets/libs/tiny_mce/plugins/advlink/link.htm +338 -0
  87. data/app/assets/libs/tiny_mce/plugins/advlist/editor_plugin.js +1 -0
  88. data/app/assets/libs/tiny_mce/plugins/advlist/editor_plugin_src.js +176 -0
  89. data/app/assets/libs/tiny_mce/plugins/autolink/editor_plugin.js +1 -0
  90. data/app/assets/libs/tiny_mce/plugins/autolink/editor_plugin_src.js +174 -0
  91. data/app/assets/libs/tiny_mce/plugins/autoresize/editor_plugin.js +1 -0
  92. data/app/assets/libs/tiny_mce/plugins/autoresize/editor_plugin_src.js +119 -0
  93. data/app/assets/libs/tiny_mce/plugins/contextmenu/editor_plugin.js +1 -0
  94. data/app/assets/libs/tiny_mce/plugins/contextmenu/editor_plugin_src.js +161 -0
  95. data/app/assets/libs/tiny_mce/plugins/directionality/editor_plugin.js +1 -0
  96. data/app/assets/libs/tiny_mce/plugins/directionality/editor_plugin_src.js +82 -0
  97. data/app/assets/libs/tiny_mce/plugins/example/dialog.htm +22 -0
  98. data/app/assets/libs/tiny_mce/plugins/example/editor_plugin.js +1 -0
  99. data/app/assets/libs/tiny_mce/plugins/example/editor_plugin_src.js +84 -0
  100. data/app/assets/libs/tiny_mce/plugins/example/img/example.gif +0 -0
  101. data/app/assets/libs/tiny_mce/plugins/example/js/dialog.js +19 -0
  102. data/app/assets/libs/tiny_mce/plugins/example/langs/en.js +3 -0
  103. data/app/assets/libs/tiny_mce/plugins/example/langs/en_dlg.js +3 -0
  104. data/app/assets/libs/tiny_mce/plugins/example_dependency/editor_plugin.js +1 -0
  105. data/app/assets/libs/tiny_mce/plugins/example_dependency/editor_plugin_src.js +50 -0
  106. data/app/assets/libs/tiny_mce/plugins/iespell/editor_plugin.js +1 -0
  107. data/app/assets/libs/tiny_mce/plugins/iespell/editor_plugin_src.js +54 -0
  108. data/app/assets/libs/tiny_mce/plugins/inlinepopups/editor_plugin.js +1 -0
  109. data/app/assets/libs/tiny_mce/plugins/inlinepopups/editor_plugin_src.js +699 -0
  110. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif +0 -0
  111. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif +0 -0
  112. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif +0 -0
  113. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif +0 -0
  114. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif +0 -0
  115. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif +0 -0
  116. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif +0 -0
  117. data/app/assets/libs/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css +90 -0
  118. data/app/assets/libs/tiny_mce/plugins/inlinepopups/template.htm +387 -0
  119. data/app/assets/libs/tiny_mce/plugins/layer/editor_plugin.js +1 -0
  120. data/app/assets/libs/tiny_mce/plugins/layer/editor_plugin_src.js +262 -0
  121. data/app/assets/libs/tiny_mce/plugins/lists/editor_plugin.js +1 -0
  122. data/app/assets/libs/tiny_mce/plugins/lists/editor_plugin_src.js +951 -0
  123. data/app/assets/libs/tiny_mce/plugins/media/css/media.css +17 -0
  124. data/app/assets/libs/tiny_mce/plugins/media/editor_plugin.js +1 -0
  125. data/app/assets/libs/tiny_mce/plugins/media/editor_plugin_src.js +890 -0
  126. data/app/assets/libs/tiny_mce/plugins/media/js/embed.js +73 -0
  127. data/app/assets/libs/tiny_mce/plugins/media/js/media.js +470 -0
  128. data/app/assets/libs/tiny_mce/plugins/media/langs/en_dlg.js +1 -0
  129. data/app/assets/libs/tiny_mce/plugins/media/media.htm +922 -0
  130. data/app/assets/libs/tiny_mce/plugins/media/moxieplayer.swf +0 -0
  131. data/app/assets/libs/tiny_mce/plugins/paste/editor_plugin.js +1 -0
  132. data/app/assets/libs/tiny_mce/plugins/paste/editor_plugin_src.js +871 -0
  133. data/app/assets/libs/tiny_mce/plugins/paste/js/pastetext.js +36 -0
  134. data/app/assets/libs/tiny_mce/plugins/paste/js/pasteword.js +51 -0
  135. data/app/assets/libs/tiny_mce/plugins/paste/langs/en_dlg.js +1 -0
  136. data/app/assets/libs/tiny_mce/plugins/paste/pastetext.htm +27 -0
  137. data/app/assets/libs/tiny_mce/plugins/paste/pasteword.htm +21 -0
  138. data/app/assets/libs/tiny_mce/plugins/spellchecker/css/content.css +1 -0
  139. data/app/assets/libs/tiny_mce/plugins/spellchecker/editor_plugin.js +1 -0
  140. data/app/assets/libs/tiny_mce/plugins/spellchecker/editor_plugin_src.js +436 -0
  141. data/app/assets/libs/tiny_mce/plugins/spellchecker/img/wline.gif +0 -0
  142. data/app/assets/libs/tiny_mce/plugins/style/css/props.css +14 -0
  143. data/app/assets/libs/tiny_mce/plugins/style/editor_plugin.js +1 -0
  144. data/app/assets/libs/tiny_mce/plugins/style/editor_plugin_src.js +71 -0
  145. data/app/assets/libs/tiny_mce/plugins/style/js/props.js +709 -0
  146. data/app/assets/libs/tiny_mce/plugins/style/langs/en_dlg.js +1 -0
  147. data/app/assets/libs/tiny_mce/plugins/style/props.htm +845 -0
  148. data/app/assets/libs/tiny_mce/plugins/style/readme.txt +19 -0
  149. data/app/assets/libs/tiny_mce/plugins/table/cell.htm +180 -0
  150. data/app/assets/libs/tiny_mce/plugins/table/css/cell.css +17 -0
  151. data/app/assets/libs/tiny_mce/plugins/table/css/row.css +25 -0
  152. data/app/assets/libs/tiny_mce/plugins/table/css/table.css +13 -0
  153. data/app/assets/libs/tiny_mce/plugins/table/editor_plugin.js +1 -0
  154. data/app/assets/libs/tiny_mce/plugins/table/editor_plugin_src.js +1428 -0
  155. data/app/assets/libs/tiny_mce/plugins/table/js/cell.js +319 -0
  156. data/app/assets/libs/tiny_mce/plugins/table/js/merge_cells.js +27 -0
  157. data/app/assets/libs/tiny_mce/plugins/table/js/row.js +237 -0
  158. data/app/assets/libs/tiny_mce/plugins/table/js/table.js +489 -0
  159. data/app/assets/libs/tiny_mce/plugins/table/langs/en_dlg.js +1 -0
  160. data/app/assets/libs/tiny_mce/plugins/table/merge_cells.htm +32 -0
  161. data/app/assets/libs/tiny_mce/plugins/table/row.htm +158 -0
  162. data/app/assets/libs/tiny_mce/plugins/table/table.htm +188 -0
  163. data/app/assets/libs/tiny_mce/plugins/tableDropdown/editor_plugin.js +140 -0
  164. data/app/assets/libs/tiny_mce/themes/advanced/about.htm +52 -0
  165. data/app/assets/libs/tiny_mce/themes/advanced/anchor.htm +26 -0
  166. data/app/assets/libs/tiny_mce/themes/advanced/charmap.htm +55 -0
  167. data/app/assets/libs/tiny_mce/themes/advanced/color_picker.htm +70 -0
  168. data/app/assets/libs/tiny_mce/themes/advanced/editor_template.js +1 -0
  169. data/app/assets/libs/tiny_mce/themes/advanced/editor_template_src.js +1467 -0
  170. data/app/assets/libs/tiny_mce/themes/advanced/image.htm +80 -0
  171. data/app/assets/libs/tiny_mce/themes/advanced/img/colorpicker.jpg +0 -0
  172. data/app/assets/libs/tiny_mce/themes/advanced/img/flash.gif +0 -0
  173. data/app/assets/libs/tiny_mce/themes/advanced/img/icons.gif +0 -0
  174. data/app/assets/libs/tiny_mce/themes/advanced/img/iframe.gif +0 -0
  175. data/app/assets/libs/tiny_mce/themes/advanced/img/pagebreak.gif +0 -0
  176. data/app/assets/libs/tiny_mce/themes/advanced/img/quicktime.gif +0 -0
  177. data/app/assets/libs/tiny_mce/themes/advanced/img/realmedia.gif +0 -0
  178. data/app/assets/libs/tiny_mce/themes/advanced/img/shockwave.gif +0 -0
  179. data/app/assets/libs/tiny_mce/themes/advanced/img/trans.gif +0 -0
  180. data/app/assets/libs/tiny_mce/themes/advanced/img/video.gif +0 -0
  181. data/app/assets/libs/tiny_mce/themes/advanced/img/windowsmedia.gif +0 -0
  182. data/app/assets/libs/tiny_mce/themes/advanced/js/about.js +73 -0
  183. data/app/assets/libs/tiny_mce/themes/advanced/js/anchor.js +44 -0
  184. data/app/assets/libs/tiny_mce/themes/advanced/js/charmap.js +363 -0
  185. data/app/assets/libs/tiny_mce/themes/advanced/js/color_picker.js +345 -0
  186. data/app/assets/libs/tiny_mce/themes/advanced/js/image.js +251 -0
  187. data/app/assets/libs/tiny_mce/themes/advanced/js/link.js +153 -0
  188. data/app/assets/libs/tiny_mce/themes/advanced/js/source_editor.js +78 -0
  189. data/app/assets/libs/tiny_mce/themes/advanced/langs/en.js +1 -0
  190. data/app/assets/libs/tiny_mce/themes/advanced/langs/en_dlg.js +1 -0
  191. data/app/assets/libs/tiny_mce/themes/advanced/link.htm +57 -0
  192. data/app/assets/libs/tiny_mce/themes/advanced/shortcuts.htm +47 -0
  193. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/content.css +51 -0
  194. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/dialog.css +118 -0
  195. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/buttons.png +0 -0
  196. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/items.gif +0 -0
  197. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif +0 -0
  198. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/menu_check.gif +0 -0
  199. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/progress.gif +0 -0
  200. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/img/tabs.gif +0 -0
  201. data/app/assets/libs/tiny_mce/themes/advanced/skins/default/ui.css +215 -0
  202. data/app/assets/libs/tiny_mce/themes/advanced/skins/highcontrast/content.css +25 -0
  203. data/app/assets/libs/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +106 -0
  204. data/app/assets/libs/tiny_mce/themes/advanced/skins/highcontrast/ui.css +102 -0
  205. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/content.css +49 -0
  206. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/dialog.css +118 -0
  207. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png +0 -0
  208. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png +0 -0
  209. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png +0 -0
  210. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/ui.css +218 -0
  211. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +8 -0
  212. data/app/assets/libs/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +5 -0
  213. data/app/assets/libs/tiny_mce/themes/advanced/source_editor.htm +25 -0
  214. data/app/assets/libs/tiny_mce/themes/simple/editor_template.js +1 -0
  215. data/app/assets/libs/tiny_mce/themes/simple/editor_template_src.js +84 -0
  216. data/app/assets/libs/tiny_mce/themes/simple/img/icons.gif +0 -0
  217. data/app/assets/libs/tiny_mce/themes/simple/langs/en.js +1 -0
  218. data/app/assets/libs/tiny_mce/themes/simple/skins/default/content.css +25 -0
  219. data/app/assets/libs/tiny_mce/themes/simple/skins/default/ui.css +32 -0
  220. data/app/assets/libs/tiny_mce/themes/simple/skins/o2k7/content.css +17 -0
  221. data/app/assets/libs/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png +0 -0
  222. data/app/assets/libs/tiny_mce/themes/simple/skins/o2k7/ui.css +35 -0
  223. data/app/assets/libs/tiny_mce/tiny_mce.js +1 -0
  224. data/app/assets/libs/tiny_mce/tiny_mce_popup.js +5 -0
  225. data/app/assets/libs/tiny_mce/tiny_mce_src.js +16753 -0
  226. data/app/assets/libs/tiny_mce/utils/editable_selects.js +70 -0
  227. data/app/assets/libs/tiny_mce/utils/form_utils.js +210 -0
  228. data/app/assets/libs/tiny_mce/utils/mctabs.js +162 -0
  229. data/app/assets/libs/tiny_mce/utils/validate.js +252 -0
  230. data/app/assets/stylesheets/spud/admin/application.css +480 -0
  231. data/app/assets/stylesheets/spud/admin/jquery-ui.css +568 -0
  232. data/app/assets/stylesheets/spud/admin/settings.css +4 -0
  233. data/app/assets/stylesheets/spud/admin/users.css +4 -0
  234. data/app/assets/stylesheets/spud/forms.css +108 -0
  235. data/app/assets/stylesheets/spud/login/application.css +302 -0
  236. data/app/assets/stylesheets/spud/login.css +58 -0
  237. data/app/assets/stylesheets/spud/password_resets.css +4 -0
  238. data/app/assets/stylesheets/spud/setup.css +4 -0
  239. data/app/assets/stylesheets/spud/sitemaps.css +4 -0
  240. data/app/assets/stylesheets/spud/user_sessions.css +4 -0
  241. data/app/assets/stylesheets/spud/users.css +4 -0
  242. data/app/controllers/spud/admin/application_controller.rb +61 -0
  243. data/app/controllers/spud/admin/dashboard_controller.rb +34 -0
  244. data/app/controllers/spud/admin/users_controller.rb +109 -0
  245. data/app/controllers/spud/application_controller.rb +89 -0
  246. data/app/controllers/spud/password_resets_controller.rb +50 -0
  247. data/app/controllers/spud/setup_controller.rb +21 -0
  248. data/app/controllers/spud/sitemaps_controller.rb +8 -0
  249. data/app/controllers/spud/user_sessions_controller.rb +33 -0
  250. data/app/controllers/spud/users_controller.rb +45 -0
  251. data/app/helpers/spud/admin/application_helper.rb +54 -0
  252. data/app/helpers/spud/application_helper.rb +22 -0
  253. data/app/helpers/spud/password_resets_helper.rb +2 -0
  254. data/app/mailers/spud/core_mailer.rb +12 -0
  255. data/app/models/concerns/spud_authentication.rb +10 -0
  256. data/app/models/spud_admin_permission.rb +5 -0
  257. data/app/models/spud_user.rb +26 -0
  258. data/app/models/spud_user_session.rb +3 -0
  259. data/app/models/spud_user_setting.rb +6 -0
  260. data/app/views/layouts/spud/admin/application.html.erb +72 -0
  261. data/app/views/layouts/spud/admin/detail.html.erb +31 -0
  262. data/app/views/layouts/spud/login/application.html.erb +17 -0
  263. data/app/views/layouts/spud/setup.html.erb +47 -0
  264. data/app/views/spud/admin/dashboard/index.html.erb +18 -0
  265. data/app/views/spud/admin/users/_edit.html.erb +14 -0
  266. data/app/views/spud/admin/users/_form.html.erb +90 -0
  267. data/app/views/spud/admin/users/_new.html.erb +15 -0
  268. data/app/views/spud/admin/users/edit.html.erb +3 -0
  269. data/app/views/spud/admin/users/index.html.erb +42 -0
  270. data/app/views/spud/admin/users/new.html.erb +3 -0
  271. data/app/views/spud/admin/users/show.html.erb +12 -0
  272. data/app/views/spud/core_mailer/forgot_password_notification.html.erb +14 -0
  273. data/app/views/spud/core_mailer/forgot_password_notification.text.erb +10 -0
  274. data/app/views/spud/password_resets/edit.html.erb +25 -0
  275. data/app/views/spud/password_resets/new.html.erb +14 -0
  276. data/app/views/spud/setup/index.html.erb +43 -0
  277. data/app/views/spud/sitemaps/show.xml.builder +12 -0
  278. data/app/views/spud/user_sessions/new.html.erb +27 -0
  279. data/app/views/spud/users/_form.html.erb +60 -0
  280. data/app/views/spud/users/settings.html.erb +12 -0
  281. data/config/routes.rb +18 -0
  282. data/db/migrate/20111214161011_create_spud_admin_permissions.rb +11 -0
  283. data/db/migrate/20111214161146_create_spud_users.rb +29 -0
  284. data/db/migrate/20120327124229_add_time_zone_to_spud_user.rb +6 -0
  285. data/db/migrate/20120328235431_add_scope_to_spud_admin_permissions.rb +6 -0
  286. data/db/migrate/20120329174000_create_spud_user_settings.rb +11 -0
  287. data/lib/spud_core/belongs_to_app.rb +59 -0
  288. data/lib/spud_core/configuration.rb +58 -0
  289. data/lib/spud_core/engine.rb +55 -0
  290. data/lib/spud_core/searchable.rb +11 -0
  291. data/lib/spud_core/test_files.rb +25 -0
  292. data/lib/spud_core/version.rb +5 -0
  293. data/lib/tasks/spud_core_tasks.rake +4 -0
  294. data/lib/tb_core.rb +6 -0
  295. data/spec/controllers/spud/admin/application_controller_spec.rb +49 -0
  296. data/spec/controllers/spud/admin/dashboard_controller_spec.rb +129 -0
  297. data/spec/controllers/spud/admin/users_controller_spec.rb +194 -0
  298. data/spec/controllers/spud/application_controller_spec.rb +6 -0
  299. data/spec/controllers/spud/password_reset_controller_spec.rb +93 -0
  300. data/spec/controllers/spud/setup_controller_spec.rb +56 -0
  301. data/spec/controllers/spud/sitemap_controllers_spec.rb +20 -0
  302. data/spec/controllers/spud/user_sessions_controller_spec.rb +51 -0
  303. data/spec/controllers/spud/users_controller_spec.rb +69 -0
  304. data/spec/dummy/README.rdoc +261 -0
  305. data/spec/dummy/Rakefile +7 -0
  306. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  307. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  308. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  309. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  310. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  311. data/spec/dummy/config/application.rb +58 -0
  312. data/spec/dummy/config/boot.rb +10 -0
  313. data/spec/dummy/config/database.yml +15 -0
  314. data/spec/dummy/config/environment.rb +5 -0
  315. data/spec/dummy/config/environments/development.rb +37 -0
  316. data/spec/dummy/config/environments/production.rb +67 -0
  317. data/spec/dummy/config/environments/test.rb +37 -0
  318. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  319. data/spec/dummy/config/initializers/inflections.rb +15 -0
  320. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  321. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  322. data/spec/dummy/config/initializers/session_store.rb +8 -0
  323. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  324. data/spec/dummy/config/locales/en.yml +5 -0
  325. data/spec/dummy/config/routes.rb +5 -0
  326. data/spec/dummy/config.ru +4 -0
  327. data/spec/dummy/db/schema.rb +59 -0
  328. data/spec/dummy/log/development.log +39 -0
  329. data/spec/dummy/log/test.log +37811 -0
  330. data/spec/dummy/public/404.html +26 -0
  331. data/spec/dummy/public/422.html +26 -0
  332. data/spec/dummy/public/500.html +25 -0
  333. data/spec/dummy/public/favicon.ico +0 -0
  334. data/spec/dummy/script/rails +6 -0
  335. data/spec/helpers/spud/admin/application_helper_spec.rb +150 -0
  336. data/spec/helpers/spud/application_helper_spec.rb +66 -0
  337. data/spec/lib/spud_core/configuration_spec.rb +34 -0
  338. data/spec/models/spud_user_spec.rb +27 -0
  339. data/spec/spec_helper.rb +40 -0
  340. data/spec/support/authlogic_helper.rb +2 -0
  341. metadata +652 -0
@@ -0,0 +1,779 @@
1
+ /* =========================================================
2
+ * bootstrap-datepicker.js
3
+ * http://www.eyecon.ro/bootstrap-datepicker
4
+ * =========================================================
5
+ * Copyright 2012 Stefan Petre
6
+ * Improvements by Andrew Rowls
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ * ========================================================= */
20
+
21
+ !function( $ ) {
22
+
23
+ function UTCDate(){
24
+ return new Date(Date.UTC.apply(Date, arguments));
25
+ }
26
+
27
+ // Picker object
28
+
29
+ var Datepicker = function(element, options) {
30
+ var that = this;
31
+
32
+ this.element = $(element);
33
+ this.language = options.language||this.element.data('date-language')||"en";
34
+ this.language = this.language in dates ? this.language : "en";
35
+ this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
36
+ this.picker = $(DPGlobal.template)
37
+ .appendTo('body')
38
+ .on({
39
+ click: $.proxy(this.click, this)
40
+ });
41
+ this.isInput = this.element.is('input');
42
+ this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
43
+ this.hasInput = this.component && this.element.find('input').length;
44
+ if(this.component && this.component.length === 0)
45
+ this.component = false;
46
+
47
+ if (this.isInput) {
48
+ this.element.on({
49
+ focus: $.proxy(this.show, this),
50
+ keyup: $.proxy(this.update, this),
51
+ keydown: $.proxy(this.keydown, this)
52
+ });
53
+ } else {
54
+ if (this.component && this.hasInput){
55
+ // For components that are not readonly, allow keyboard nav
56
+ this.element.find('input').on({
57
+ focus: $.proxy(this.show, this),
58
+ keyup: $.proxy(this.update, this),
59
+ keydown: $.proxy(this.keydown, this)
60
+ });
61
+
62
+ this.component.on('click', $.proxy(this.show, this));
63
+ } else {
64
+ this.element.on('click', $.proxy(this.show, this));
65
+ }
66
+ }
67
+
68
+ $(document).on('mousedown', function (e) {
69
+ // Clicked outside the datepicker, hide it
70
+ if ($(e.target).closest('.datepicker').length == 0) {
71
+ that.hide();
72
+ }
73
+ });
74
+
75
+ this.autoclose = false;
76
+ if ('autoclose' in options) {
77
+ this.autoclose = options.autoclose;
78
+ } else if ('dateAutoclose' in this.element.data()) {
79
+ this.autoclose = this.element.data('date-autoclose');
80
+ }
81
+
82
+ this.keyboardNavigation = true;
83
+ if ('keyboardNavigation' in options) {
84
+ this.keyboardNavigation = options.keyboardNavigation;
85
+ } else if ('dateKeyboardNavigation' in this.element.data()) {
86
+ this.keyboardNavigation = this.element.data('date-keyboard-navigation');
87
+ }
88
+
89
+ switch(options.startView || this.element.data('date-start-view')){
90
+ case 2:
91
+ case 'decade':
92
+ this.viewMode = this.startViewMode = 2;
93
+ break;
94
+ case 1:
95
+ case 'year':
96
+ this.viewMode = this.startViewMode = 1;
97
+ break;
98
+ case 0:
99
+ case 'month':
100
+ default:
101
+ this.viewMode = this.startViewMode = 0;
102
+ break;
103
+ }
104
+
105
+ this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
106
+ this.weekEnd = ((this.weekStart + 6) % 7);
107
+ this.startDate = -Infinity;
108
+ this.endDate = Infinity;
109
+ this.setStartDate(options.startDate||this.element.data('date-startdate'));
110
+ this.setEndDate(options.endDate||this.element.data('date-enddate'));
111
+ this.fillDow();
112
+ this.fillMonths();
113
+ this.update();
114
+ this.showMode();
115
+ };
116
+
117
+ Datepicker.prototype = {
118
+ constructor: Datepicker,
119
+
120
+ show: function(e) {
121
+ this.picker.show();
122
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
123
+ this.update();
124
+ this.place();
125
+ $(window).on('resize', $.proxy(this.place, this));
126
+ if (e ) {
127
+ e.stopPropagation();
128
+ e.preventDefault();
129
+ }
130
+ this.element.trigger({
131
+ type: 'show',
132
+ date: this.date
133
+ });
134
+ },
135
+
136
+ hide: function(e){
137
+ this.picker.hide();
138
+ $(window).off('resize', this.place);
139
+ this.viewMode = this.startViewMode;
140
+ this.showMode();
141
+ if (!this.isInput) {
142
+ $(document).off('mousedown', this.hide);
143
+ }
144
+ if (e && e.currentTarget.value)
145
+ this.setValue();
146
+ this.element.trigger({
147
+ type: 'hide',
148
+ date: this.date
149
+ });
150
+ },
151
+
152
+ setValue: function() {
153
+ var formatted = DPGlobal.formatDate(this.date, this.format, this.language);
154
+ if (!this.isInput) {
155
+ if (this.component){
156
+ this.element.find('input').prop('value', formatted);
157
+ }
158
+ this.element.data('date', formatted);
159
+ } else {
160
+ this.element.prop('value', formatted);
161
+ }
162
+ },
163
+
164
+ setStartDate: function(startDate){
165
+ this.startDate = startDate||-Infinity;
166
+ if (this.startDate !== -Infinity) {
167
+ this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language);
168
+ }
169
+ this.update();
170
+ this.updateNavArrows();
171
+ },
172
+
173
+ setEndDate: function(endDate){
174
+ this.endDate = endDate||Infinity;
175
+ if (this.endDate !== Infinity) {
176
+ this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language);
177
+ }
178
+ this.update();
179
+ this.updateNavArrows();
180
+ },
181
+
182
+ place: function(){
183
+ var zIndex = parseInt(this.element.parents().filter(function() {
184
+ return $(this).css('z-index') != 'auto';
185
+ }).first().css('z-index'))+10;
186
+ var offset = this.component ? this.component.offset() : this.element.offset();
187
+ this.picker.css({
188
+ top: offset.top + this.height,
189
+ left: offset.left,
190
+ zIndex: zIndex
191
+ });
192
+ },
193
+
194
+ update: function(){
195
+ this.date = DPGlobal.parseDate(
196
+ this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'),
197
+ this.format, this.language
198
+ );
199
+ if (this.date < this.startDate) {
200
+ this.viewDate = new Date(this.startDate);
201
+ } else if (this.date > this.endDate) {
202
+ this.viewDate = new Date(this.endDate);
203
+ } else {
204
+ this.viewDate = new Date(this.date);
205
+ }
206
+ this.fill();
207
+ },
208
+
209
+ fillDow: function(){
210
+ var dowCnt = this.weekStart;
211
+ var html = '<tr>';
212
+ while (dowCnt < this.weekStart + 7) {
213
+ html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
214
+ }
215
+ html += '</tr>';
216
+ this.picker.find('.datepicker-days thead').append(html);
217
+ },
218
+
219
+ fillMonths: function(){
220
+ var html = '';
221
+ var i = 0
222
+ while (i < 12) {
223
+ html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>';
224
+ }
225
+ this.picker.find('.datepicker-months td').html(html);
226
+ },
227
+
228
+ fill: function() {
229
+ var d = new Date(this.viewDate),
230
+ year = d.getUTCFullYear(),
231
+ month = d.getUTCMonth(),
232
+ startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,
233
+ startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
234
+ endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
235
+ endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
236
+ currentDate = this.date.valueOf();
237
+ this.picker.find('.datepicker-days th:eq(1)')
238
+ .text(dates[this.language].months[month]+' '+year);
239
+ this.updateNavArrows();
240
+ this.fillMonths();
241
+ var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
242
+ day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
243
+ prevMonth.setUTCDate(day);
244
+ prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7);
245
+ var nextMonth = new Date(prevMonth);
246
+ nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
247
+ nextMonth = nextMonth.valueOf();
248
+ var html = [];
249
+ var clsName;
250
+ while(prevMonth.valueOf() < nextMonth) {
251
+ if (prevMonth.getUTCDay() == this.weekStart) {
252
+ html.push('<tr>');
253
+ }
254
+ clsName = '';
255
+ if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
256
+ clsName += ' old';
257
+ } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {
258
+ clsName += ' new';
259
+ }
260
+ if (prevMonth.valueOf() == currentDate) {
261
+ clsName += ' active';
262
+ }
263
+ if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) {
264
+ clsName += ' disabled';
265
+ }
266
+ html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>');
267
+ if (prevMonth.getUTCDay() == this.weekEnd) {
268
+ html.push('</tr>');
269
+ }
270
+ prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
271
+ }
272
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
273
+ var currentYear = this.date.getUTCFullYear();
274
+
275
+ var months = this.picker.find('.datepicker-months')
276
+ .find('th:eq(1)')
277
+ .text(year)
278
+ .end()
279
+ .find('span').removeClass('active');
280
+ if (currentYear == year) {
281
+ months.eq(this.date.getUTCMonth()).addClass('active');
282
+ }
283
+ if (year < startYear || year > endYear) {
284
+ months.addClass('disabled');
285
+ }
286
+ if (year == startYear) {
287
+ months.slice(0, startMonth).addClass('disabled');
288
+ }
289
+ if (year == endYear) {
290
+ months.slice(endMonth+1).addClass('disabled');
291
+ }
292
+
293
+ html = '';
294
+ year = parseInt(year/10, 10) * 10;
295
+ var yearCont = this.picker.find('.datepicker-years')
296
+ .find('th:eq(1)')
297
+ .text(year + '-' + (year + 9))
298
+ .end()
299
+ .find('td');
300
+ year -= 1;
301
+ for (var i = -1; i < 11; i++) {
302
+ html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>';
303
+ year += 1;
304
+ }
305
+ yearCont.html(html);
306
+ },
307
+
308
+ updateNavArrows: function() {
309
+ var d = new Date(this.viewDate),
310
+ year = d.getUTCFullYear(),
311
+ month = d.getUTCMonth();
312
+ switch (this.viewMode) {
313
+ case 0:
314
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {
315
+ this.picker.find('.prev').css({visibility: 'hidden'});
316
+ } else {
317
+ this.picker.find('.prev').css({visibility: 'visible'});
318
+ }
319
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {
320
+ this.picker.find('.next').css({visibility: 'hidden'});
321
+ } else {
322
+ this.picker.find('.next').css({visibility: 'visible'});
323
+ }
324
+ break;
325
+ case 1:
326
+ case 2:
327
+ if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {
328
+ this.picker.find('.prev').css({visibility: 'hidden'});
329
+ } else {
330
+ this.picker.find('.prev').css({visibility: 'visible'});
331
+ }
332
+ if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {
333
+ this.picker.find('.next').css({visibility: 'hidden'});
334
+ } else {
335
+ this.picker.find('.next').css({visibility: 'visible'});
336
+ }
337
+ break;
338
+ }
339
+ },
340
+
341
+ click: function(e) {
342
+ e.stopPropagation();
343
+ e.preventDefault();
344
+ var target = $(e.target).closest('span, td, th');
345
+ if (target.length == 1) {
346
+ switch(target[0].nodeName.toLowerCase()) {
347
+ case 'th':
348
+ switch(target[0].className) {
349
+ case 'switch':
350
+ this.showMode(1);
351
+ break;
352
+ case 'prev':
353
+ case 'next':
354
+ var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);
355
+ switch(this.viewMode){
356
+ case 0:
357
+ this.viewDate = this.moveMonth(this.viewDate, dir);
358
+ break;
359
+ case 1:
360
+ case 2:
361
+ this.viewDate = this.moveYear(this.viewDate, dir);
362
+ break;
363
+ }
364
+ this.fill();
365
+ break;
366
+ }
367
+ break;
368
+ case 'span':
369
+ if (!target.is('.disabled')) {
370
+ this.viewDate.setUTCDate(1);
371
+ if (target.is('.month')) {
372
+ var month = target.parent().find('span').index(target);
373
+ this.viewDate.setUTCMonth(month);
374
+ this.element.trigger({
375
+ type: 'changeMonth',
376
+ date: this.viewDate
377
+ });
378
+ } else {
379
+ var year = parseInt(target.text(), 10)||0;
380
+ this.viewDate.setUTCFullYear(year);
381
+ this.element.trigger({
382
+ type: 'changeYear',
383
+ date: this.viewDate
384
+ });
385
+ }
386
+ this.showMode(-1);
387
+ this.fill();
388
+ }
389
+ break;
390
+ case 'td':
391
+ if (target.is('.day') && !target.is('.disabled')){
392
+ var day = parseInt(target.text(), 10)||1;
393
+ var year = this.viewDate.getUTCFullYear(),
394
+ month = this.viewDate.getUTCMonth();
395
+ if (target.is('.old')) {
396
+ if (month == 0) {
397
+ month = 11;
398
+ year -= 1;
399
+ } else {
400
+ month -= 1;
401
+ }
402
+ } else if (target.is('.new')) {
403
+ if (month == 11) {
404
+ month = 0;
405
+ year += 1;
406
+ } else {
407
+ month += 1;
408
+ }
409
+ }
410
+ this.date = UTCDate(year, month, day,0,0,0,0);
411
+ this.viewDate = UTCDate(year, month, day,0,0,0,0);
412
+ this.fill();
413
+ this.setValue();
414
+ this.element.trigger({
415
+ type: 'changeDate',
416
+ date: this.date
417
+ });
418
+ var element;
419
+ if (this.isInput) {
420
+ element = this.element;
421
+ } else if (this.component){
422
+ element = this.element.find('input');
423
+ }
424
+ if (element) {
425
+ element.change();
426
+ if (this.autoclose) {
427
+ this.hide();
428
+ }
429
+ }
430
+ }
431
+ break;
432
+ }
433
+ }
434
+ },
435
+
436
+ moveMonth: function(date, dir){
437
+ if (!dir) return date;
438
+ var new_date = new Date(date.valueOf()),
439
+ day = new_date.getUTCDate(),
440
+ month = new_date.getUTCMonth(),
441
+ mag = Math.abs(dir),
442
+ new_month, test;
443
+ dir = dir > 0 ? 1 : -1;
444
+ if (mag == 1){
445
+ test = dir == -1
446
+ // If going back one month, make sure month is not current month
447
+ // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
448
+ ? function(){ return new_date.getUTCMonth() == month; }
449
+ // If going forward one month, make sure month is as expected
450
+ // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
451
+ : function(){ return new_date.getUTCMonth() != new_month; };
452
+ new_month = month + dir;
453
+ new_date.setUTCMonth(new_month);
454
+ // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
455
+ if (new_month < 0 || new_month > 11)
456
+ new_month = (new_month + 12) % 12;
457
+ } else {
458
+ // For magnitudes >1, move one month at a time...
459
+ for (var i=0; i<mag; i++)
460
+ // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
461
+ new_date = this.moveMonth(new_date, dir);
462
+ // ...then reset the day, keeping it in the new month
463
+ new_month = new_date.getUTCMonth();
464
+ new_date.setUTCDate(day);
465
+ test = function(){ return new_month != new_date.getUTCMonth(); };
466
+ }
467
+ // Common date-resetting loop -- if date is beyond end of month, make it
468
+ // end of month
469
+ while (test()){
470
+ new_date.setUTCDate(--day);
471
+ new_date.setUTCMonth(new_month);
472
+ }
473
+ return new_date;
474
+ },
475
+
476
+ moveYear: function(date, dir){
477
+ return this.moveMonth(date, dir*12);
478
+ },
479
+
480
+ dateWithinRange: function(date){
481
+ return date >= this.startDate && date <= this.endDate;
482
+ },
483
+
484
+ keydown: function(e){
485
+ if (this.picker.is(':not(:visible)')){
486
+ if (e.keyCode == 27) // allow escape to hide and re-show picker
487
+ this.show();
488
+ return;
489
+ }
490
+ var dateChanged = false,
491
+ dir, day, month,
492
+ newDate, newViewDate;
493
+ switch(e.keyCode){
494
+ case 27: // escape
495
+ this.hide();
496
+ e.preventDefault();
497
+ break;
498
+ case 37: // left
499
+ case 39: // right
500
+ if (!this.keyboardNavigation) break;
501
+ dir = e.keyCode == 37 ? -1 : 1;
502
+ if (e.ctrlKey){
503
+ newDate = this.moveYear(this.date, dir);
504
+ newViewDate = this.moveYear(this.viewDate, dir);
505
+ } else if (e.shiftKey){
506
+ newDate = this.moveMonth(this.date, dir);
507
+ newViewDate = this.moveMonth(this.viewDate, dir);
508
+ } else {
509
+ newDate = new Date(this.date);
510
+ newDate.setUTCDate(this.date.getUTCDate() + dir);
511
+ newViewDate = new Date(this.viewDate);
512
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir);
513
+ }
514
+ if (this.dateWithinRange(newDate)){
515
+ this.date = newDate;
516
+ this.viewDate = newViewDate;
517
+ this.setValue();
518
+ this.update();
519
+ e.preventDefault();
520
+ dateChanged = true;
521
+ }
522
+ break;
523
+ case 38: // up
524
+ case 40: // down
525
+ if (!this.keyboardNavigation) break;
526
+ dir = e.keyCode == 38 ? -1 : 1;
527
+ if (e.ctrlKey){
528
+ newDate = this.moveYear(this.date, dir);
529
+ newViewDate = this.moveYear(this.viewDate, dir);
530
+ } else if (e.shiftKey){
531
+ newDate = this.moveMonth(this.date, dir);
532
+ newViewDate = this.moveMonth(this.viewDate, dir);
533
+ } else {
534
+ newDate = new Date(this.date);
535
+ newDate.setUTCDate(this.date.getUTCDate() + dir * 7);
536
+ newViewDate = new Date(this.viewDate);
537
+ newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7);
538
+ }
539
+ if (this.dateWithinRange(newDate)){
540
+ this.date = newDate;
541
+ this.viewDate = newViewDate;
542
+ this.setValue();
543
+ this.update();
544
+ e.preventDefault();
545
+ dateChanged = true;
546
+ }
547
+ break;
548
+ case 13: // enter
549
+ this.hide();
550
+ e.preventDefault();
551
+ break;
552
+ case 9: // tab
553
+ this.hide();
554
+ break;
555
+ }
556
+ if (dateChanged){
557
+ this.element.trigger({
558
+ type: 'changeDate',
559
+ date: this.date
560
+ });
561
+ var element;
562
+ if (this.isInput) {
563
+ element = this.element;
564
+ } else if (this.component){
565
+ element = this.element.find('input');
566
+ }
567
+ if (element) {
568
+ element.change();
569
+ }
570
+ }
571
+ },
572
+
573
+ showMode: function(dir) {
574
+ if (dir) {
575
+ this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
576
+ }
577
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
578
+ this.updateNavArrows();
579
+ }
580
+ };
581
+
582
+ $.fn.datepicker = function ( option ) {
583
+ var args = Array.apply(null, arguments);
584
+ args.shift();
585
+ return this.each(function () {
586
+ var $this = $(this),
587
+ data = $this.data('datepicker'),
588
+ options = typeof option == 'object' && option;
589
+ if (!data) {
590
+ $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
591
+ }
592
+ if (typeof option == 'string' && typeof data[option] == 'function') {
593
+ data[option].apply(data, args);
594
+ }
595
+ });
596
+ };
597
+
598
+ $.fn.datepicker.defaults = {
599
+ };
600
+ $.fn.datepicker.Constructor = Datepicker;
601
+ var dates = $.fn.datepicker.dates = {
602
+ en: {
603
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
604
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
605
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
606
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
607
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
608
+ }
609
+ }
610
+
611
+ var DPGlobal = {
612
+ modes: [
613
+ {
614
+ clsName: 'days',
615
+ navFnc: 'Month',
616
+ navStep: 1
617
+ },
618
+ {
619
+ clsName: 'months',
620
+ navFnc: 'FullYear',
621
+ navStep: 1
622
+ },
623
+ {
624
+ clsName: 'years',
625
+ navFnc: 'FullYear',
626
+ navStep: 10
627
+ }],
628
+ isLeapYear: function (year) {
629
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
630
+ },
631
+ getDaysInMonth: function (year, month) {
632
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
633
+ },
634
+ validParts: /dd?|mm?|MM?|yy(?:yy)?/g,
635
+ nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g,
636
+ parseFormat: function(format){
637
+ // IE treats \0 as a string end in inputs (truncating the value),
638
+ // so it's a bad format delimiter, anyway
639
+ var separators = format.replace(this.validParts, '\0').split('\0'),
640
+ parts = format.match(this.validParts);
641
+ if (!separators || !separators.length || !parts || parts.length == 0){
642
+ throw new Error("Invalid date format.");
643
+ }
644
+ return {separators: separators, parts: parts};
645
+ },
646
+ parseDate: function(date, format, language) {
647
+ if (date instanceof Date) return date;
648
+ if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) {
649
+ var part_re = /([-+]\d+)([dmwy])/,
650
+ parts = date.match(/([-+]\d+)([dmwy])/g),
651
+ part, dir;
652
+ date = new Date();
653
+ for (var i=0; i<parts.length; i++) {
654
+ part = part_re.exec(parts[i]);
655
+ dir = parseInt(part[1]);
656
+ switch(part[2]){
657
+ case 'd':
658
+ date.setUTCDate(date.getUTCDate() + dir);
659
+ break;
660
+ case 'm':
661
+ date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
662
+ break;
663
+ case 'w':
664
+ date.setUTCDate(date.getUTCDate() + dir * 7);
665
+ break;
666
+ case 'y':
667
+ date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
668
+ break;
669
+ }
670
+ }
671
+ return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
672
+ }
673
+ var parts = date && date.match(this.nonpunctuation) || [],
674
+ date = new Date(),
675
+ parsed = {},
676
+ setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
677
+ setters_map = {
678
+ yyyy: function(d,v){ return d.setUTCFullYear(v); },
679
+ yy: function(d,v){ return d.setUTCFullYear(2000+v); },
680
+ m: function(d,v){
681
+ v -= 1;
682
+ while (v<0) v += 12;
683
+ v %= 12;
684
+ d.setUTCMonth(v);
685
+ while (d.getUTCMonth() != v)
686
+ d.setUTCDate(d.getUTCDate()-1);
687
+ return d;
688
+ },
689
+ d: function(d,v){ return d.setUTCDate(v); }
690
+ },
691
+ val, filtered, part;
692
+ setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
693
+ setters_map['dd'] = setters_map['d'];
694
+ date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
695
+ if (parts.length == format.parts.length) {
696
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
697
+ val = parseInt(parts[i], 10);
698
+ part = format.parts[i];
699
+ if (isNaN(val)) {
700
+ switch(part) {
701
+ case 'MM':
702
+ filtered = $(dates[language].months).filter(function(){
703
+ var m = this.slice(0, parts[i].length),
704
+ p = parts[i].slice(0, m.length);
705
+ return m == p;
706
+ });
707
+ val = $.inArray(filtered[0], dates[language].months) + 1;
708
+ break;
709
+ case 'M':
710
+ filtered = $(dates[language].monthsShort).filter(function(){
711
+ var m = this.slice(0, parts[i].length),
712
+ p = parts[i].slice(0, m.length);
713
+ return m == p;
714
+ });
715
+ val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
716
+ break;
717
+ }
718
+ }
719
+ parsed[part] = val;
720
+ }
721
+ for (var i=0, s; i<setters_order.length; i++){
722
+ s = setters_order[i];
723
+ if (s in parsed)
724
+ setters_map[s](date, parsed[s])
725
+ }
726
+ }
727
+ return date;
728
+ },
729
+ formatDate: function(date, format, language){
730
+ var val = {
731
+ d: date.getUTCDate(),
732
+ m: date.getUTCMonth() + 1,
733
+ M: dates[language].monthsShort[date.getUTCMonth()],
734
+ MM: dates[language].months[date.getUTCMonth()],
735
+ yy: date.getUTCFullYear().toString().substring(2),
736
+ yyyy: date.getUTCFullYear()
737
+ };
738
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
739
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
740
+ var date = [],
741
+ seps = $.extend([], format.separators);
742
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
743
+ if (seps.length)
744
+ date.push(seps.shift())
745
+ date.push(val[format.parts[i]]);
746
+ }
747
+ return date.join('');
748
+ },
749
+ headTemplate: '<thead>'+
750
+ '<tr>'+
751
+ '<th class="prev"><i class="icon-arrow-left"/></th>'+
752
+ '<th colspan="5" class="switch"></th>'+
753
+ '<th class="next"><i class="icon-arrow-right"/></th>'+
754
+ '</tr>'+
755
+ '</thead>',
756
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
757
+ };
758
+ DPGlobal.template = '<div class="datepicker dropdown-menu">'+
759
+ '<div class="datepicker-days">'+
760
+ '<table class=" table-condensed">'+
761
+ DPGlobal.headTemplate+
762
+ '<tbody></tbody>'+
763
+ '</table>'+
764
+ '</div>'+
765
+ '<div class="datepicker-months">'+
766
+ '<table class="table-condensed">'+
767
+ DPGlobal.headTemplate+
768
+ DPGlobal.contTemplate+
769
+ '</table>'+
770
+ '</div>'+
771
+ '<div class="datepicker-years">'+
772
+ '<table class="table-condensed">'+
773
+ DPGlobal.headTemplate+
774
+ DPGlobal.contTemplate+
775
+ '</table>'+
776
+ '</div>'+
777
+ '</div>';
778
+
779
+ }( window.jQuery );