locomotivecms 3.0.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (906) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +63 -0
  3. data/LICENSE +21 -0
  4. data/README.md +76 -0
  5. data/app/api/locomotive/api.rb +55 -0
  6. data/app/api/locomotive/api/entities/account_entity.rb +17 -0
  7. data/app/api/locomotive/api/entities/base_entity.rb +26 -0
  8. data/app/api/locomotive/api/entities/content_asset_entity.rb +44 -0
  9. data/app/api/locomotive/api/entities/content_entry_entity.rb +85 -0
  10. data/app/api/locomotive/api/entities/content_type_entity.rb +31 -0
  11. data/app/api/locomotive/api/entities/content_type_field_entity.rb +34 -0
  12. data/app/api/locomotive/api/entities/editable_element_entity.rb +17 -0
  13. data/app/api/locomotive/api/entities/membership_entity.rb +30 -0
  14. data/app/api/locomotive/api/entities/page_entity.rb +56 -0
  15. data/app/api/locomotive/api/entities/site_entity.rb +22 -0
  16. data/app/api/locomotive/api/entities/snippet_entity.rb +13 -0
  17. data/app/api/locomotive/api/entities/theme_asset_entity.rb +36 -0
  18. data/app/api/locomotive/api/entities/translation_entity.rb +14 -0
  19. data/app/api/locomotive/api/exception_rescuers.rb +42 -0
  20. data/app/api/locomotive/api/forms/account_form.rb +13 -0
  21. data/app/api/locomotive/api/forms/base_form.rb +79 -0
  22. data/app/api/locomotive/api/forms/content_asset_form.rb +13 -0
  23. data/app/api/locomotive/api/forms/content_entry_form.rb +94 -0
  24. data/app/api/locomotive/api/forms/content_type_field_form.rb +58 -0
  25. data/app/api/locomotive/api/forms/content_type_form.rb +55 -0
  26. data/app/api/locomotive/api/forms/editable_element_form.rb +33 -0
  27. data/app/api/locomotive/api/forms/membership_form.rb +11 -0
  28. data/app/api/locomotive/api/forms/my_account_form.rb +14 -0
  29. data/app/api/locomotive/api/forms/page_form.rb +69 -0
  30. data/app/api/locomotive/api/forms/site_form.rb +24 -0
  31. data/app/api/locomotive/api/forms/snippet_form.rb +14 -0
  32. data/app/api/locomotive/api/forms/theme_asset_form.rb +13 -0
  33. data/app/api/locomotive/api/forms/translation_form.rb +13 -0
  34. data/app/api/locomotive/api/helpers/authentication_helper.rb +39 -0
  35. data/app/api/locomotive/api/helpers/pagination_helper.rb +16 -0
  36. data/app/api/locomotive/api/helpers/params_helper.rb +14 -0
  37. data/app/api/locomotive/api/helpers/persistence_helper.rb +140 -0
  38. data/app/api/locomotive/api/middlewares/locale_middleware.rb +38 -0
  39. data/app/api/locomotive/api/middlewares/logger_middleware.rb +46 -0
  40. data/app/api/locomotive/api/resources/account_resource.rb +93 -0
  41. data/app/api/locomotive/api/resources/content_asset_resource.rb +84 -0
  42. data/app/api/locomotive/api/resources/content_entry_resource.rb +109 -0
  43. data/app/api/locomotive/api/resources/content_type_resource.rb +139 -0
  44. data/app/api/locomotive/api/resources/current_site_resource.rb +62 -0
  45. data/app/api/locomotive/api/resources/membership_resource.rb +88 -0
  46. data/app/api/locomotive/api/resources/my_account_resource.rb +72 -0
  47. data/app/api/locomotive/api/resources/page_resource.rb +123 -0
  48. data/app/api/locomotive/api/resources/site_resource.rb +124 -0
  49. data/app/api/locomotive/api/resources/snippet_resource.rb +93 -0
  50. data/app/api/locomotive/api/resources/theme_asset_resource.rb +96 -0
  51. data/app/api/locomotive/api/resources/token_resource.rb +29 -0
  52. data/app/api/locomotive/api/resources/translation_resource.rb +95 -0
  53. data/app/api/locomotive/api/resources/version_resource.rb +19 -0
  54. data/app/assets/images/locomotive/background/body.png +0 -0
  55. data/app/assets/images/locomotive/datepicker/ui-widget-content-top.png +0 -0
  56. data/app/assets/images/locomotive/form/error-arrow.png +0 -0
  57. data/app/assets/images/locomotive/form/input-sep.png +0 -0
  58. data/app/assets/images/locomotive/icons/flags/bf.png +0 -0
  59. data/app/assets/images/locomotive/icons/flags/bg.png +0 -0
  60. data/app/assets/images/locomotive/icons/flags/cs.png +0 -0
  61. data/app/assets/images/locomotive/icons/flags/de.png +0 -0
  62. data/app/assets/images/locomotive/icons/flags/en.png +0 -0
  63. data/app/assets/images/locomotive/icons/flags/es.png +0 -0
  64. data/app/assets/images/locomotive/icons/flags/et.png +0 -0
  65. data/app/assets/images/locomotive/icons/flags/fr.png +0 -0
  66. data/app/assets/images/locomotive/icons/flags/it.png +0 -0
  67. data/app/assets/images/locomotive/icons/flags/ja.png +0 -0
  68. data/app/assets/images/locomotive/icons/flags/mg.png +0 -0
  69. data/app/assets/images/locomotive/icons/flags/nb.png +0 -0
  70. data/app/assets/images/locomotive/icons/flags/nl.png +0 -0
  71. data/app/assets/images/locomotive/icons/flags/pl.png +0 -0
  72. data/app/assets/images/locomotive/icons/flags/pt-BR.png +0 -0
  73. data/app/assets/images/locomotive/icons/flags/pt.png +0 -0
  74. data/app/assets/images/locomotive/icons/flags/ru.png +0 -0
  75. data/app/assets/images/locomotive/icons/flags/sk.png +0 -0
  76. data/app/assets/images/locomotive/icons/flags/sr.png +0 -0
  77. data/app/assets/images/locomotive/icons/flags/zh-CN.png +0 -0
  78. data/app/assets/images/locomotive/icons/start.png +0 -0
  79. data/app/assets/images/locomotive/list/empty.png +0 -0
  80. data/app/assets/images/locomotive/list/item-left.png +0 -0
  81. data/app/assets/images/locomotive/logo.png +0 -0
  82. data/app/assets/images/locomotive/nocoffee.png +0 -0
  83. data/app/assets/images/locomotive/plugins/sites_picker_top_arrow.png +0 -0
  84. data/app/assets/images/locomotive/rails.png +0 -0
  85. data/app/assets/images/locomotive/site.png +0 -0
  86. data/app/assets/images/locomotive/user.png +0 -0
  87. data/app/assets/javascripts/locomotive.js +21 -0
  88. data/app/assets/javascripts/locomotive/application.js.coffee +8 -0
  89. data/app/assets/javascripts/locomotive/not_logged_in.js.coffee +1 -0
  90. data/app/assets/javascripts/locomotive/utils/backbone_patches.js.coffee +6 -0
  91. data/app/assets/javascripts/locomotive/utils/core_ext.js +75 -0
  92. data/app/assets/javascripts/locomotive/utils/layout_utils.js.coffee +25 -0
  93. data/app/assets/javascripts/locomotive/utils/rails_ujs.js.coffee +20 -0
  94. data/app/assets/javascripts/locomotive/utils/select2.js.coffee +45 -0
  95. data/app/assets/javascripts/locomotive/utils/wysihtml5.js.coffee +39 -0
  96. data/app/assets/javascripts/locomotive/views/accounts/new_view.js.coffee +7 -0
  97. data/app/assets/javascripts/locomotive/views/application_view.js.coffee +120 -0
  98. data/app/assets/javascripts/locomotive/views/content_assets/dropzone_view.js.coffee +80 -0
  99. data/app/assets/javascripts/locomotive/views/content_assets/edit_image_view.js.coffee +149 -0
  100. data/app/assets/javascripts/locomotive/views/content_assets/index_view.js.coffee +59 -0
  101. data/app/assets/javascripts/locomotive/views/content_assets/picker_view.js.coffee +81 -0
  102. data/app/assets/javascripts/locomotive/views/content_entries/edit_view.js.coffee +5 -0
  103. data/app/assets/javascripts/locomotive/views/content_entries/index_view.js.coffee +15 -0
  104. data/app/assets/javascripts/locomotive/views/content_entries/new_view.js.coffee +4 -0
  105. data/app/assets/javascripts/locomotive/views/current_site/edit_view.js.coffee +7 -0
  106. data/app/assets/javascripts/locomotive/views/custom_fields/select_options/edit_view.js.coffee +46 -0
  107. data/app/assets/javascripts/locomotive/views/dashboard/show_view.js.coffee +5 -0
  108. data/app/assets/javascripts/locomotive/views/editable_elements/index_view.js.coffee +5 -0
  109. data/app/assets/javascripts/locomotive/views/inputs/array_view.js.coffee +124 -0
  110. data/app/assets/javascripts/locomotive/views/inputs/document_picker_view.js.coffee +24 -0
  111. data/app/assets/javascripts/locomotive/views/inputs/file_view.js.coffee +85 -0
  112. data/app/assets/javascripts/locomotive/views/inputs/rte/file_view.js.coffee +116 -0
  113. data/app/assets/javascripts/locomotive/views/inputs/rte/link_view.js.coffee +83 -0
  114. data/app/assets/javascripts/locomotive/views/inputs/rte_view.js.coffee.erb +54 -0
  115. data/app/assets/javascripts/locomotive/views/memberships/edit_view.js.coffee +7 -0
  116. data/app/assets/javascripts/locomotive/views/memberships/new_view.js.coffee +7 -0
  117. data/app/assets/javascripts/locomotive/views/my_account/edit_view.js.coffee +44 -0
  118. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +163 -0
  119. data/app/assets/javascripts/locomotive/views/pages/edit_view.js.coffee +48 -0
  120. data/app/assets/javascripts/locomotive/views/pages/index_view.js.coffee +11 -0
  121. data/app/assets/javascripts/locomotive/views/pages/list_view.js.coffee +79 -0
  122. data/app/assets/javascripts/locomotive/views/pages/new_view.js.coffee +8 -0
  123. data/app/assets/javascripts/locomotive/views/shared/drawer_view.js.coffee +82 -0
  124. data/app/assets/javascripts/locomotive/views/shared/form_view.js.coffee +251 -0
  125. data/app/assets/javascripts/locomotive/views/shared/header_view.js.coffee +12 -0
  126. data/app/assets/javascripts/locomotive/views/shared/list_item_view.js.coffee +22 -0
  127. data/app/assets/javascripts/locomotive/views/shared/list_view.js.coffee +40 -0
  128. data/app/assets/javascripts/locomotive/views/shared/sidebar_view.js.coffee +11 -0
  129. data/app/assets/javascripts/locomotive/views/sites/new_view.js.coffee +5 -0
  130. data/app/assets/stylesheets/locomotive/application.scss +29 -0
  131. data/app/assets/stylesheets/locomotive/base/_all.scss +6 -0
  132. data/app/assets/stylesheets/locomotive/base/_buttons.scss +13 -0
  133. data/app/assets/stylesheets/locomotive/base/_fonts.scss +29 -0
  134. data/app/assets/stylesheets/locomotive/base/_form.scss +13 -0
  135. data/app/assets/stylesheets/locomotive/base/_iframe.scss +4 -0
  136. data/app/assets/stylesheets/locomotive/base/_nav.scss +38 -0
  137. data/app/assets/stylesheets/locomotive/base/_typography.scss +5 -0
  138. data/app/assets/stylesheets/locomotive/base/form/_api_key.scss +25 -0
  139. data/app/assets/stylesheets/locomotive/base/form/_array_input.scss +137 -0
  140. data/app/assets/stylesheets/locomotive/base/form/_base.scss +70 -0
  141. data/app/assets/stylesheets/locomotive/base/form/_code.scss +15 -0
  142. data/app/assets/stylesheets/locomotive/base/form/_date.scss +11 -0
  143. data/app/assets/stylesheets/locomotive/base/form/_document_picker.scss +87 -0
  144. data/app/assets/stylesheets/locomotive/base/form/_file_input.scss +80 -0
  145. data/app/assets/stylesheets/locomotive/base/form/_popover.scss +44 -0
  146. data/app/assets/stylesheets/locomotive/base/form/_rte.scss +30 -0
  147. data/app/assets/stylesheets/locomotive/base/form/_select2.scss +107 -0
  148. data/app/assets/stylesheets/locomotive/base/form/_toggle.scss +62 -0
  149. data/app/assets/stylesheets/locomotive/base/not_logged_in/_all.scss +4 -0
  150. data/app/assets/stylesheets/locomotive/base/not_logged_in/_buttons.scss +10 -0
  151. data/app/assets/stylesheets/locomotive/base/not_logged_in/_form.scss +72 -0
  152. data/app/assets/stylesheets/locomotive/base/not_logged_in/_messages.scss +4 -0
  153. data/app/assets/stylesheets/locomotive/base/not_logged_in/_typography.scss +12 -0
  154. data/app/assets/stylesheets/locomotive/components/_content_assets.scss +186 -0
  155. data/app/assets/stylesheets/locomotive/components/_drawer.scss +34 -0
  156. data/app/assets/stylesheets/locomotive/components/_header.scss +3 -0
  157. data/app/assets/stylesheets/locomotive/components/_list.scss +102 -0
  158. data/app/assets/stylesheets/locomotive/components/_main.scss +31 -0
  159. data/app/assets/stylesheets/locomotive/components/_misc.scss +1 -0
  160. data/app/assets/stylesheets/locomotive/components/_sidebar.scss +5 -0
  161. data/app/assets/stylesheets/locomotive/components/_sites.scss +130 -0
  162. data/app/assets/stylesheets/locomotive/components/_transitions.scss +78 -0
  163. data/app/assets/stylesheets/locomotive/components/header/_account.scss +57 -0
  164. data/app/assets/stylesheets/locomotive/components/header/_base.scss +109 -0
  165. data/app/assets/stylesheets/locomotive/components/header/_responsive.scss +34 -0
  166. data/app/assets/stylesheets/locomotive/components/misc/_nav.scss +62 -0
  167. data/app/assets/stylesheets/locomotive/components/not_logged_in/_passwords.scss +9 -0
  168. data/app/assets/stylesheets/locomotive/components/not_logged_in/_sign_in_and_up.scss +24 -0
  169. data/app/assets/stylesheets/locomotive/components/sidebar/_base.scss +57 -0
  170. data/app/assets/stylesheets/locomotive/components/sidebar/_content_types.scss +30 -0
  171. data/app/assets/stylesheets/locomotive/components/sidebar/_link.scss +36 -0
  172. data/app/assets/stylesheets/locomotive/components/sidebar/_my_account.scss +21 -0
  173. data/app/assets/stylesheets/locomotive/components/sidebar/_pages_tree.scss +108 -0
  174. data/app/assets/stylesheets/locomotive/globals/_all.scss +3 -0
  175. data/app/assets/stylesheets/locomotive/globals/_bootstrap.scss +841 -0
  176. data/app/assets/stylesheets/locomotive/globals/_colors.scss +1 -0
  177. data/app/assets/stylesheets/locomotive/globals/_mixins.scss +65 -0
  178. data/app/assets/stylesheets/locomotive/globals/_variables.scss +114 -0
  179. data/app/assets/stylesheets/locomotive/layouts/_main.scss +62 -0
  180. data/app/assets/stylesheets/locomotive/layouts/_not_logged_in.scss +34 -0
  181. data/app/assets/stylesheets/locomotive/layouts/_responsive.scss +12 -0
  182. data/app/assets/stylesheets/locomotive/not_logged_in.scss +11 -0
  183. data/app/cells/locomotive/content_locale_picker/show.html.haml +7 -0
  184. data/app/cells/locomotive/content_locale_picker_cell.rb +21 -0
  185. data/app/controllers/locomotive/accounts_controller.rb +26 -0
  186. data/app/controllers/locomotive/api/accounts_controller.rb +60 -0
  187. data/app/controllers/locomotive/api/base_controller.rb +35 -0
  188. data/app/controllers/locomotive/api/content_assets_controller.rb +51 -0
  189. data/app/controllers/locomotive/api/content_entries_controller.rb +71 -0
  190. data/app/controllers/locomotive/api/content_types_controller.rb +52 -0
  191. data/app/controllers/locomotive/api/current_site_controller.rb +34 -0
  192. data/app/controllers/locomotive/api/memberships_controller.rb +52 -0
  193. data/app/controllers/locomotive/api/my_account_controller.rb +46 -0
  194. data/app/controllers/locomotive/api/pages_controller.rb +53 -0
  195. data/app/controllers/locomotive/api/sites_controller.rb +58 -0
  196. data/app/controllers/locomotive/api/snippets_controller.rb +52 -0
  197. data/app/controllers/locomotive/api/theme_assets_controller.rb +51 -0
  198. data/app/controllers/locomotive/api/tokens_controller.rb +36 -0
  199. data/app/controllers/locomotive/api/translations_controller.rb +51 -0
  200. data/app/controllers/locomotive/api/version_controller.rb +11 -0
  201. data/app/controllers/locomotive/base_controller.rb +24 -0
  202. data/app/controllers/locomotive/concerns/account_controller.rb +40 -0
  203. data/app/controllers/locomotive/concerns/authorization_controller.rb +31 -0
  204. data/app/controllers/locomotive/concerns/exception_controller.rb +32 -0
  205. data/app/controllers/locomotive/concerns/locale_helpers_controller.rb +60 -0
  206. data/app/controllers/locomotive/concerns/membership_controller.rb +35 -0
  207. data/app/controllers/locomotive/concerns/site_dispatcher_controller.rb +42 -0
  208. data/app/controllers/locomotive/concerns/store_location_controller.rb +33 -0
  209. data/app/controllers/locomotive/concerns/timezone_controller.rb +13 -0
  210. data/app/controllers/locomotive/concerns/token_authentication_controller.rb +48 -0
  211. data/app/controllers/locomotive/concerns/url_helpers_controller.rb +32 -0
  212. data/app/controllers/locomotive/concerns/within_site_controller.rb +61 -0
  213. data/app/controllers/locomotive/content_assets_controller.rb +82 -0
  214. data/app/controllers/locomotive/content_entries_controller.rb +110 -0
  215. data/app/controllers/locomotive/current_site_controller.rb +62 -0
  216. data/app/controllers/locomotive/custom_fields/select_options_controller.rb +54 -0
  217. data/app/controllers/locomotive/dashboard_controller.rb +10 -0
  218. data/app/controllers/locomotive/editable_elements_controller.rb +25 -0
  219. data/app/controllers/locomotive/memberships_controller.rb +55 -0
  220. data/app/controllers/locomotive/my_account_controller.rb +40 -0
  221. data/app/controllers/locomotive/pages_controller.rb +66 -0
  222. data/app/controllers/locomotive/passwords_controller.rb +19 -0
  223. data/app/controllers/locomotive/registrations_controller.rb +21 -0
  224. data/app/controllers/locomotive/sessions_controller.rb +31 -0
  225. data/app/controllers/locomotive/sites_controller.rb +37 -0
  226. data/app/controllers/locomotive/translations_controller.rb +54 -0
  227. data/app/helpers/locomotive/accounts_helper.rb +9 -0
  228. data/app/helpers/locomotive/base_helper.rb +223 -0
  229. data/app/helpers/locomotive/content_assets_helper.rb +31 -0
  230. data/app/helpers/locomotive/content_entries_helper.rb +71 -0
  231. data/app/helpers/locomotive/content_types_helper.rb +46 -0
  232. data/app/helpers/locomotive/custom_fields_helper.rb +190 -0
  233. data/app/helpers/locomotive/installation_helper.rb +9 -0
  234. data/app/helpers/locomotive/memberships_helper.rb +19 -0
  235. data/app/helpers/locomotive/my_account_helper.rb +17 -0
  236. data/app/helpers/locomotive/pages_helper.rb +61 -0
  237. data/app/helpers/locomotive/shared/accounts_helper.rb +20 -0
  238. data/app/helpers/locomotive/shared/pages_helper.rb +87 -0
  239. data/app/helpers/locomotive/shared/sites_helper.rb +15 -0
  240. data/app/helpers/locomotive/sites_helper.rb +31 -0
  241. data/app/helpers/locomotive/translations_helper.rb +19 -0
  242. data/app/inputs/locomotive/api_key_input.rb +24 -0
  243. data/app/inputs/locomotive/array_input.rb +85 -0
  244. data/app/inputs/locomotive/code_input.rb +51 -0
  245. data/app/inputs/locomotive/document_picker_input.rb +52 -0
  246. data/app/inputs/locomotive/editable_select_input.rb +11 -0
  247. data/app/inputs/locomotive/file_input.rb +88 -0
  248. data/app/inputs/locomotive/locale_input.rb +41 -0
  249. data/app/inputs/locomotive/locales_input.rb +9 -0
  250. data/app/inputs/locomotive/rte_input.rb +51 -0
  251. data/app/inputs/locomotive/small_code_input.rb +23 -0
  252. data/app/inputs/locomotive/toggle_input.rb +21 -0
  253. data/app/mailers/locomotive/devise_mailer.rb +10 -0
  254. data/app/mailers/locomotive/notifications.rb +19 -0
  255. data/app/models/locomotive/account.rb +97 -0
  256. data/app/models/locomotive/concerns/account/api_key.rb +97 -0
  257. data/app/models/locomotive/concerns/account/devise_patch.rb +30 -0
  258. data/app/models/locomotive/concerns/asset/checksum.rb +33 -0
  259. data/app/models/locomotive/concerns/asset/types.rb +36 -0
  260. data/app/models/locomotive/concerns/asset/vignette.rb +35 -0
  261. data/app/models/locomotive/concerns/content_entry/counter.rb +27 -0
  262. data/app/models/locomotive/concerns/content_entry/csv.rb +82 -0
  263. data/app/models/locomotive/concerns/content_entry/localized.rb +80 -0
  264. data/app/models/locomotive/concerns/content_entry/next_previous.rb +49 -0
  265. data/app/models/locomotive/concerns/content_entry/notifications.rb +33 -0
  266. data/app/models/locomotive/concerns/content_entry/slug.rb +86 -0
  267. data/app/models/locomotive/concerns/content_type/class_helpers.rb +73 -0
  268. data/app/models/locomotive/concerns/content_type/default_values.rb +66 -0
  269. data/app/models/locomotive/concerns/content_type/group_by.rb +46 -0
  270. data/app/models/locomotive/concerns/content_type/item_template.rb +49 -0
  271. data/app/models/locomotive/concerns/content_type/label.rb +22 -0
  272. data/app/models/locomotive/concerns/content_type/order_by.rb +44 -0
  273. data/app/models/locomotive/concerns/content_type/sync.rb +78 -0
  274. data/app/models/locomotive/concerns/page/editable_elements.rb +134 -0
  275. data/app/models/locomotive/concerns/page/layout.rb +42 -0
  276. data/app/models/locomotive/concerns/page/listed.rb +18 -0
  277. data/app/models/locomotive/concerns/page/parse.rb +133 -0
  278. data/app/models/locomotive/concerns/page/redirect.rb +25 -0
  279. data/app/models/locomotive/concerns/page/render.rb +99 -0
  280. data/app/models/locomotive/concerns/page/templatized.rb +208 -0
  281. data/app/models/locomotive/concerns/page/tree.rb +108 -0
  282. data/app/models/locomotive/concerns/shared/seo.rb +16 -0
  283. data/app/models/locomotive/concerns/shared/slug.rb +34 -0
  284. data/app/models/locomotive/concerns/shared/userstamp.rb +15 -0
  285. data/app/models/locomotive/concerns/site/access_points.rb +75 -0
  286. data/app/models/locomotive/concerns/site/locales.rb +139 -0
  287. data/app/models/locomotive/concerns/site/timezone.rb +32 -0
  288. data/app/models/locomotive/content_asset.rb +45 -0
  289. data/app/models/locomotive/content_entry.rb +155 -0
  290. data/app/models/locomotive/content_type.rb +132 -0
  291. data/app/models/locomotive/editable_control.rb +52 -0
  292. data/app/models/locomotive/editable_element.rb +151 -0
  293. data/app/models/locomotive/editable_file.rb +91 -0
  294. data/app/models/locomotive/editable_long_text.rb +5 -0
  295. data/app/models/locomotive/editable_short_text.rb +5 -0
  296. data/app/models/locomotive/editable_text.rb +93 -0
  297. data/app/models/locomotive/membership.rb +52 -0
  298. data/app/models/locomotive/page.rb +149 -0
  299. data/app/models/locomotive/site.rb +116 -0
  300. data/app/models/locomotive/snippet.rb +28 -0
  301. data/app/models/locomotive/theme_asset.rb +187 -0
  302. data/app/models/locomotive/translation.rb +41 -0
  303. data/app/policies/locomotive/account_policy.rb +33 -0
  304. data/app/policies/locomotive/application_policy.rb +79 -0
  305. data/app/policies/locomotive/content_asset_policy.rb +21 -0
  306. data/app/policies/locomotive/content_entry_policy.rb +21 -0
  307. data/app/policies/locomotive/content_type_policy.rb +21 -0
  308. data/app/policies/locomotive/membership_policy.rb +36 -0
  309. data/app/policies/locomotive/page_policy.rb +21 -0
  310. data/app/policies/locomotive/site_policy.rb +62 -0
  311. data/app/policies/locomotive/snippet_policy.rb +21 -0
  312. data/app/policies/locomotive/theme_asset_policy.rb +21 -0
  313. data/app/policies/locomotive/translation_policy.rb +21 -0
  314. data/app/presenters/locomotive/account_presenter.rb +20 -0
  315. data/app/presenters/locomotive/base_presenter.rb +144 -0
  316. data/app/presenters/locomotive/content_asset_presenter.rb +51 -0
  317. data/app/presenters/locomotive/content_entry_presenter.rb +177 -0
  318. data/app/presenters/locomotive/content_field_presenter.rb +76 -0
  319. data/app/presenters/locomotive/content_type_presenter.rb +82 -0
  320. data/app/presenters/locomotive/editable_control_presenter.rb +19 -0
  321. data/app/presenters/locomotive/editable_element_presenter.rb +46 -0
  322. data/app/presenters/locomotive/editable_file_presenter.rb +36 -0
  323. data/app/presenters/locomotive/editable_text_presenter.rb +40 -0
  324. data/app/presenters/locomotive/membership_presenter.rb +35 -0
  325. data/app/presenters/locomotive/page_presenter.rb +81 -0
  326. data/app/presenters/locomotive/site_presenter.rb +40 -0
  327. data/app/presenters/locomotive/snippet_presenter.rb +22 -0
  328. data/app/presenters/locomotive/theme_asset_presenter.rb +61 -0
  329. data/app/presenters/locomotive/translation_presenter.rb +9 -0
  330. data/app/services/locomotive/content_asset_service.rb +22 -0
  331. data/app/services/locomotive/content_entry_service.rb +175 -0
  332. data/app/services/locomotive/content_type_service.rb +15 -0
  333. data/app/services/locomotive/custom_field_finder_service.rb +8 -0
  334. data/app/services/locomotive/custom_field_service.rb +26 -0
  335. data/app/services/locomotive/membership_service.rb +45 -0
  336. data/app/services/locomotive/page_parsing_service.rb +67 -0
  337. data/app/services/locomotive/page_service.rb +64 -0
  338. data/app/services/locomotive/site_service.rb +41 -0
  339. data/app/uploaders/locomotive/content_asset_uploader.rb +13 -0
  340. data/app/uploaders/locomotive/editable_file_uploader.rb +15 -0
  341. data/app/uploaders/locomotive/picture_uploader.rb +17 -0
  342. data/app/uploaders/locomotive/theme_asset_uploader.rb +35 -0
  343. data/app/views/locomotive/accounts/new.html.haml +17 -0
  344. data/app/views/locomotive/content_assets/_dropzone.html.haml +13 -0
  345. data/app/views/locomotive/content_assets/_list.html.haml +36 -0
  346. data/app/views/locomotive/content_assets/_nav.html.haml +17 -0
  347. data/app/views/locomotive/content_assets/_search_form.html.haml +5 -0
  348. data/app/views/locomotive/content_assets/edit_in_drawer.html.haml +26 -0
  349. data/app/views/locomotive/content_assets/index.html.haml +19 -0
  350. data/app/views/locomotive/content_assets/index_in_drawer.html.haml +20 -0
  351. data/app/views/locomotive/content_entries/_entry.html.haml +22 -0
  352. data/app/views/locomotive/content_entries/_list.html.haml +29 -0
  353. data/app/views/locomotive/content_entries/edit.html.haml +14 -0
  354. data/app/views/locomotive/content_entries/form/_actions.html.haml +1 -0
  355. data/app/views/locomotive/content_entries/form/_advanced.html.haml +5 -0
  356. data/app/views/locomotive/content_entries/form/_main.html.haml +4 -0
  357. data/app/views/locomotive/content_entries/form/_panes.html.haml +4 -0
  358. data/app/views/locomotive/content_entries/form/_seo.html.haml +6 -0
  359. data/app/views/locomotive/content_entries/form/_tabs.html.haml +9 -0
  360. data/app/views/locomotive/content_entries/index.html.haml +43 -0
  361. data/app/views/locomotive/content_entries/new.html.haml +14 -0
  362. data/app/views/locomotive/current_site/_domain.html.haml +15 -0
  363. data/app/views/locomotive/current_site/_locale.html.haml +18 -0
  364. data/app/views/locomotive/current_site/_membership.html.haml +21 -0
  365. data/app/views/locomotive/current_site/edit.html.haml +13 -0
  366. data/app/views/locomotive/current_site/form/_access_points.html.haml +7 -0
  367. data/app/views/locomotive/current_site/form/_advanced.html.haml +17 -0
  368. data/app/views/locomotive/current_site/form/_main.html.haml +7 -0
  369. data/app/views/locomotive/current_site/form/_panes.html.haml +4 -0
  370. data/app/views/locomotive/current_site/form/_seo.html.haml +7 -0
  371. data/app/views/locomotive/current_site/form/_tabs.html.haml +14 -0
  372. data/app/views/locomotive/custom_fields/select_options/_option.html.haml +25 -0
  373. data/app/views/locomotive/custom_fields/select_options/edit.html.haml +14 -0
  374. data/app/views/locomotive/dashboard/show.html.haml +0 -0
  375. data/app/views/locomotive/devise_mailer/reset_password_instructions.html.haml +12 -0
  376. data/app/views/locomotive/editable_elements/index.html.haml +2 -0
  377. data/app/views/locomotive/errors/404.html.haml +7 -0
  378. data/app/views/locomotive/errors/500.html.haml +7 -0
  379. data/app/views/locomotive/errors/no_page.html.haml +1 -0
  380. data/app/views/locomotive/errors/no_site.html.haml +1 -0
  381. data/app/views/locomotive/layouts/application.html.haml +42 -0
  382. data/app/views/locomotive/layouts/error.html.haml +1 -0
  383. data/app/views/locomotive/layouts/not_logged_in.html.haml +18 -0
  384. data/app/views/locomotive/layouts/preview.html.haml +31 -0
  385. data/app/views/locomotive/layouts/without_site.html.haml +18 -0
  386. data/app/views/locomotive/memberships/edit.html.haml +15 -0
  387. data/app/views/locomotive/memberships/new.html.haml +15 -0
  388. data/app/views/locomotive/my_account/edit.html.haml +14 -0
  389. data/app/views/locomotive/my_account/form/_actions.html.haml +6 -0
  390. data/app/views/locomotive/my_account/form/_api.html.haml +3 -0
  391. data/app/views/locomotive/my_account/form/_credentials.html.haml +8 -0
  392. data/app/views/locomotive/my_account/form/_main.html.haml +6 -0
  393. data/app/views/locomotive/my_account/form/_panes.html.haml +4 -0
  394. data/app/views/locomotive/my_account/form/_tabs.html.haml +7 -0
  395. data/app/views/locomotive/notifications/new_content_entry.html.haml +31 -0
  396. data/app/views/locomotive/pages/_editable_elements.html.haml +64 -0
  397. data/app/views/locomotive/pages/_form.html.haml +66 -0
  398. data/app/views/locomotive/pages/_page.html.haml +44 -0
  399. data/app/views/locomotive/pages/edit.html.haml +14 -0
  400. data/app/views/locomotive/pages/form/_actions.html.haml +1 -0
  401. data/app/views/locomotive/pages/form/_main.html.haml +12 -0
  402. data/app/views/locomotive/pages/form/_panes.html.haml +4 -0
  403. data/app/views/locomotive/pages/form/_seo.html.haml +6 -0
  404. data/app/views/locomotive/pages/form/_tabs.html.haml +12 -0
  405. data/app/views/locomotive/pages/index.html.haml +22 -0
  406. data/app/views/locomotive/pages/new.html.haml +19 -0
  407. data/app/views/locomotive/pages/show.html.haml +2 -0
  408. data/app/views/locomotive/passwords/edit.html.haml +18 -0
  409. data/app/views/locomotive/passwords/new.html.haml +17 -0
  410. data/app/views/locomotive/public/sitemaps/show.xml.builder +31 -0
  411. data/app/views/locomotive/registrations/new.html.haml +19 -0
  412. data/app/views/locomotive/sessions/new.html.haml +22 -0
  413. data/app/views/locomotive/shared/_footer.html.haml +2 -0
  414. data/app/views/locomotive/shared/_form_actions.html.haml +14 -0
  415. data/app/views/locomotive/shared/_head.html.haml +40 -0
  416. data/app/views/locomotive/shared/_header.html.haml +30 -0
  417. data/app/views/locomotive/shared/_locale_picker_link.html.haml +6 -0
  418. data/app/views/locomotive/shared/_main_app_head.html.haml +1 -0
  419. data/app/views/locomotive/shared/_main_app_head_before_backbone.html.haml +1 -0
  420. data/app/views/locomotive/shared/_main_app_header.html.haml +1 -0
  421. data/app/views/locomotive/shared/_sidebar.html.haml +13 -0
  422. data/app/views/locomotive/shared/_sidebar_without_site.html.haml +3 -0
  423. data/app/views/locomotive/shared/actions/_contents.html.haml +7 -0
  424. data/app/views/locomotive/shared/header/_account.html.haml +7 -0
  425. data/app/views/locomotive/shared/header/_account_menu.html.haml +5 -0
  426. data/app/views/locomotive/shared/header/_brand.html.haml +4 -0
  427. data/app/views/locomotive/shared/header/_site.html.haml +8 -0
  428. data/app/views/locomotive/shared/rte/_image_popover.html.haml +18 -0
  429. data/app/views/locomotive/shared/rte/_link_popover.html.haml +19 -0
  430. data/app/views/locomotive/shared/rte/_toolbar.html.haml +62 -0
  431. data/app/views/locomotive/shared/sidebar/_content_types.html.haml +15 -0
  432. data/app/views/locomotive/shared/sidebar/_link.html.haml +10 -0
  433. data/app/views/locomotive/shared/sidebar/_my_account.html.haml +8 -0
  434. data/app/views/locomotive/shared/sidebar/_page.html.haml +25 -0
  435. data/app/views/locomotive/shared/sidebar/_pages.html.haml +11 -0
  436. data/app/views/locomotive/sites/_site.html.haml +16 -0
  437. data/app/views/locomotive/sites/index.html.haml +23 -0
  438. data/app/views/locomotive/sites/new.html.haml +12 -0
  439. data/app/views/locomotive/translations/_form.html.haml +12 -0
  440. data/app/views/locomotive/translations/edit.html.haml +15 -0
  441. data/app/views/locomotive/translations/index.html.haml +30 -0
  442. data/app/views/locomotive/translations/new.html.haml +12 -0
  443. data/config/cucumber.yml +8 -0
  444. data/config/initializers/csv_renderer.rb +10 -0
  445. data/config/initializers/deny_phantomjs_ttf.rb +29 -0
  446. data/config/initializers/devise.rb +15 -0
  447. data/config/initializers/haml.rb +2 -0
  448. data/config/initializers/locomotive_loaded_first.rb +19 -0
  449. data/config/initializers/simple_form.rb +73 -0
  450. data/config/locales/admin_ui.bg.yml +351 -0
  451. data/config/locales/admin_ui.cs.yml +363 -0
  452. data/config/locales/admin_ui.de.yml +341 -0
  453. data/config/locales/admin_ui.en.yml +385 -0
  454. data/config/locales/admin_ui.es.yml +327 -0
  455. data/config/locales/admin_ui.et.yml +335 -0
  456. data/config/locales/admin_ui.fr.yml +360 -0
  457. data/config/locales/admin_ui.it.yml +324 -0
  458. data/config/locales/admin_ui.ja.yml +341 -0
  459. data/config/locales/admin_ui.nb.yml +322 -0
  460. data/config/locales/admin_ui.nl.yml +290 -0
  461. data/config/locales/admin_ui.pl.yml +326 -0
  462. data/config/locales/admin_ui.pt-BR.yml +319 -0
  463. data/config/locales/admin_ui.pt.yml +320 -0
  464. data/config/locales/admin_ui.ru.yml +342 -0
  465. data/config/locales/admin_ui.sk.yml +363 -0
  466. data/config/locales/admin_ui.sr.yml +356 -0
  467. data/config/locales/admin_ui.zh-CN.yml +352 -0
  468. data/config/locales/carrierwave.bg.yml +4 -0
  469. data/config/locales/carrierwave.cs.yml +4 -0
  470. data/config/locales/carrierwave.de.yml +4 -0
  471. data/config/locales/carrierwave.en.yml +4 -0
  472. data/config/locales/carrierwave.es.yml +4 -0
  473. data/config/locales/carrierwave.et.yml +4 -0
  474. data/config/locales/carrierwave.fr.yml +4 -0
  475. data/config/locales/carrierwave.it.yml +4 -0
  476. data/config/locales/carrierwave.ja.yml +4 -0
  477. data/config/locales/carrierwave.nb.yml +4 -0
  478. data/config/locales/carrierwave.nl.yml +4 -0
  479. data/config/locales/carrierwave.pl.yml +4 -0
  480. data/config/locales/carrierwave.pt-BR.yml +4 -0
  481. data/config/locales/carrierwave.pt.yml +4 -0
  482. data/config/locales/carrierwave.ru.yml +4 -0
  483. data/config/locales/carrierwave.sk.yml +4 -0
  484. data/config/locales/carrierwave.sr.yml +4 -0
  485. data/config/locales/carrierwave.zh-CN.yml +4 -0
  486. data/config/locales/default.bg.yml +231 -0
  487. data/config/locales/default.cs.yml +249 -0
  488. data/config/locales/default.de.yml +252 -0
  489. data/config/locales/default.en.yml +57 -0
  490. data/config/locales/default.es.yml +219 -0
  491. data/config/locales/default.et.yml +240 -0
  492. data/config/locales/default.fr.yml +229 -0
  493. data/config/locales/default.it.yml +246 -0
  494. data/config/locales/default.ja.yml +98 -0
  495. data/config/locales/default.nb.yml +313 -0
  496. data/config/locales/default.nl.yml +175 -0
  497. data/config/locales/default.pl.yml +317 -0
  498. data/config/locales/default.pt-BR.yml +212 -0
  499. data/config/locales/default.pt.yml +212 -0
  500. data/config/locales/default.ru.yml +293 -0
  501. data/config/locales/default.sk.yml +249 -0
  502. data/config/locales/default.sr.yml +276 -0
  503. data/config/locales/default.zh-CN.yml +226 -0
  504. data/config/locales/devise.bg.yml +64 -0
  505. data/config/locales/devise.cs.yml +64 -0
  506. data/config/locales/devise.de.yml +63 -0
  507. data/config/locales/devise.en.yml +64 -0
  508. data/config/locales/devise.es.yml +64 -0
  509. data/config/locales/devise.et.yml +65 -0
  510. data/config/locales/devise.fr.yml +68 -0
  511. data/config/locales/devise.it.yml +64 -0
  512. data/config/locales/devise.ja.yml +63 -0
  513. data/config/locales/devise.nb.yml +65 -0
  514. data/config/locales/devise.nl.yml +64 -0
  515. data/config/locales/devise.pl.yml +64 -0
  516. data/config/locales/devise.pt-BR.yml +62 -0
  517. data/config/locales/devise.pt.yml +62 -0
  518. data/config/locales/devise.ru.yml +64 -0
  519. data/config/locales/devise.sk.yml +64 -0
  520. data/config/locales/devise.sr.yml +64 -0
  521. data/config/locales/devise.zh-CN.yml +64 -0
  522. data/config/locales/flash.bg.yml +115 -0
  523. data/config/locales/flash.cs.yml +115 -0
  524. data/config/locales/flash.de.yml +106 -0
  525. data/config/locales/flash.en.yml +118 -0
  526. data/config/locales/flash.es.yml +106 -0
  527. data/config/locales/flash.et.yml +106 -0
  528. data/config/locales/flash.fr.yml +106 -0
  529. data/config/locales/flash.it.yml +106 -0
  530. data/config/locales/flash.ja.yml +115 -0
  531. data/config/locales/flash.nb.yml +106 -0
  532. data/config/locales/flash.nl.yml +106 -0
  533. data/config/locales/flash.pl.yml +106 -0
  534. data/config/locales/flash.pt-BR.yml +106 -0
  535. data/config/locales/flash.pt.yml +106 -0
  536. data/config/locales/flash.ru.yml +106 -0
  537. data/config/locales/flash.sk.yml +115 -0
  538. data/config/locales/flash.sr.yml +115 -0
  539. data/config/locales/flash.zh-CN.yml +115 -0
  540. data/config/locales/formtastic.bg.yml +113 -0
  541. data/config/locales/formtastic.cs.yml +125 -0
  542. data/config/locales/formtastic.de.yml +106 -0
  543. data/config/locales/formtastic.es.yml +84 -0
  544. data/config/locales/formtastic.et.yml +103 -0
  545. data/config/locales/formtastic.fr.yml +109 -0
  546. data/config/locales/formtastic.it.yml +99 -0
  547. data/config/locales/formtastic.ja.yml +103 -0
  548. data/config/locales/formtastic.nb.yml +103 -0
  549. data/config/locales/formtastic.nl.yml +85 -0
  550. data/config/locales/formtastic.pl.yml +105 -0
  551. data/config/locales/formtastic.pt-BR.yml +70 -0
  552. data/config/locales/formtastic.pt.yml +70 -0
  553. data/config/locales/formtastic.ru.yml +106 -0
  554. data/config/locales/formtastic.sk.yml +125 -0
  555. data/config/locales/formtastic.sr.yml +112 -0
  556. data/config/locales/formtastic.zh-CN.yml +112 -0
  557. data/config/locales/inputs.en.yml +14 -0
  558. data/config/locales/simple_form.en.yml +170 -0
  559. data/config/routes.rb +69 -0
  560. data/features/api/accounts.feature +43 -0
  561. data/features/api/authentication.feature +41 -0
  562. data/features/api/authorization/accounts.feature +165 -0
  563. data/features/api/authorization/content_assets.feature +147 -0
  564. data/features/api/authorization/content_entries.feature +202 -0
  565. data/features/api/authorization/content_types.feature +237 -0
  566. data/features/api/authorization/current_site.feature +30 -0
  567. data/features/api/authorization/memberships.feature +225 -0
  568. data/features/api/authorization/pages.feature +189 -0
  569. data/features/api/authorization/sites.feature +212 -0
  570. data/features/api/authorization/snippets.feature +179 -0
  571. data/features/api/authorization/theme_assets.feature +185 -0
  572. data/features/api/authorization/translations.feature +253 -0
  573. data/features/api/content_entries.feature +184 -0
  574. data/features/api/content_types.feature +156 -0
  575. data/features/api/editable_elements.feature +190 -0
  576. data/features/api/entries_custom_fields.feature +150 -0
  577. data/features/api/memberships.feature +26 -0
  578. data/features/api/pages.feature +72 -0
  579. data/features/backoffice/authorization/account_settings.feature +28 -0
  580. data/features/backoffice/authorization/content_type.feature +35 -0
  581. data/features/backoffice/authorization/current_site.feature +53 -0
  582. data/features/backoffice/authorization/inline_front_end_editing.feature +46 -0
  583. data/features/backoffice/authorization/pages.feature +95 -0
  584. data/features/backoffice/authorization/theme_assets.feature +50 -0
  585. data/features/backoffice/content_types/edit.feature +20 -0
  586. data/features/backoffice/content_types/email.feature +26 -0
  587. data/features/backoffice/content_types/has_many.feature +80 -0
  588. data/features/backoffice/content_types/integer.feature +26 -0
  589. data/features/backoffice/content_types/localized.feature +63 -0
  590. data/features/backoffice/content_types/many_to_many.feature +70 -0
  591. data/features/backoffice/content_types/tags.feature +22 -0
  592. data/features/backoffice/content_types/uniqueness.feature +29 -0
  593. data/features/backoffice/contents.feature +93 -0
  594. data/features/backoffice/editable_elements.feature +22 -0
  595. data/features/backoffice/installation.feature +33 -0
  596. data/features/backoffice/login.feature +33 -0
  597. data/features/backoffice/mounting.feature +13 -0
  598. data/features/backoffice/my_account.feature +22 -0
  599. data/features/backoffice/pages.feature +73 -0
  600. data/features/backoffice/regressions.feature +19 -0
  601. data/features/backoffice/site.feature +71 -0
  602. data/features/backoffice/snippets.feature +39 -0
  603. data/features/backoffice/theme_assets.feature +72 -0
  604. data/features/backoffice/translations.feature +50 -0
  605. data/features/public/basic.feature +30 -0
  606. data/features/public/contact_form.feature +98 -0
  607. data/features/public/content_entries.feature +69 -0
  608. data/features/public/editable_elements.feature +138 -0
  609. data/features/public/has_many.feature +8 -0
  610. data/features/public/inheritance.feature +157 -0
  611. data/features/public/inline_front_end_editing.feature +26 -0
  612. data/features/public/many_to_many.feature +64 -0
  613. data/features/public/new_contact_form.feature +95 -0
  614. data/features/public/pages.feature +116 -0
  615. data/features/public/pagination.feature +8 -0
  616. data/features/public/robots.feature +22 -0
  617. data/features/public/session.feature +40 -0
  618. data/features/public/sitemap.feature +74 -0
  619. data/features/public/snippets.feature +21 -0
  620. data/features/public/tablerow.feature +42 -0
  621. data/features/public/tags.feature +45 -0
  622. data/features/step_definitions/api_steps.rb +179 -0
  623. data/features/step_definitions/backoffice/mounting_steps.rb +22 -0
  624. data/features/step_definitions/backoffice_steps.rb +47 -0
  625. data/features/step_definitions/content_assets_steps.rb +12 -0
  626. data/features/step_definitions/content_types_steps.rb +135 -0
  627. data/features/step_definitions/current_site_steps.rb +43 -0
  628. data/features/step_definitions/editable_elements_steps.rb +24 -0
  629. data/features/step_definitions/membership_steps.rb +19 -0
  630. data/features/step_definitions/more_web_steps.rb +131 -0
  631. data/features/step_definitions/page_steps.rb +133 -0
  632. data/features/step_definitions/pagination_steps.rb +35 -0
  633. data/features/step_definitions/pickle_steps.rb +100 -0
  634. data/features/step_definitions/relationships_steps.rb +110 -0
  635. data/features/step_definitions/site_steps.rb +111 -0
  636. data/features/step_definitions/snippet_steps.rb +37 -0
  637. data/features/step_definitions/theme_asset_steps.rb +64 -0
  638. data/features/step_definitions/translation_steps.rb +7 -0
  639. data/features/step_definitions/web_steps.rb +225 -0
  640. data/features/step_definitions/within_steps.rb +14 -0
  641. data/features/support/cleaner.rb +4 -0
  642. data/features/support/env.rb +82 -0
  643. data/features/support/factory_girl.rb +2 -0
  644. data/features/support/http.rb +22 -0
  645. data/features/support/locales.rb +5 -0
  646. data/features/support/paths.rb +62 -0
  647. data/features/support/pickle.rb +24 -0
  648. data/features/support/selectors.rb +57 -0
  649. data/lib/generators/locomotive/install/install_generator.rb +49 -0
  650. data/lib/generators/locomotive/install/templates/README +25 -0
  651. data/lib/generators/locomotive/install/templates/carrierwave.rb +28 -0
  652. data/lib/generators/locomotive/install/templates/devise.rb +190 -0
  653. data/lib/generators/locomotive/install/templates/dragonfly.rb +22 -0
  654. data/lib/generators/locomotive/install/templates/locomotive.rb +54 -0
  655. data/lib/generators/locomotive/install/templates/mongoid.yml +81 -0
  656. data/lib/locomotive.rb +77 -0
  657. data/lib/locomotive/action_controller.rb +3 -0
  658. data/lib/locomotive/action_controller/responder.rb +79 -0
  659. data/lib/locomotive/action_controller/ssl.rb +15 -0
  660. data/lib/locomotive/carrierwave.rb +14 -0
  661. data/lib/locomotive/carrierwave/asset.rb +72 -0
  662. data/lib/locomotive/carrierwave/base.rb +15 -0
  663. data/lib/locomotive/carrierwave/patches.rb +32 -0
  664. data/lib/locomotive/configuration.rb +96 -0
  665. data/lib/locomotive/core_ext.rb +79 -0
  666. data/lib/locomotive/custom_fields.rb +70 -0
  667. data/lib/locomotive/dependencies.rb +39 -0
  668. data/lib/locomotive/devise.rb +22 -0
  669. data/lib/locomotive/dragonfly.rb +63 -0
  670. data/lib/locomotive/engine.rb +60 -0
  671. data/lib/locomotive/haml.rb +1 -0
  672. data/lib/locomotive/kaminari.rb +36 -0
  673. data/lib/locomotive/logger.rb +11 -0
  674. data/lib/locomotive/middlewares.rb +2 -0
  675. data/lib/locomotive/middlewares/permalink.rb +22 -0
  676. data/lib/locomotive/middlewares/site.rb +58 -0
  677. data/lib/locomotive/mongoid.rb +4 -0
  678. data/lib/locomotive/mongoid/document.rb +19 -0
  679. data/lib/locomotive/mongoid/liquid.rb +39 -0
  680. data/lib/locomotive/mongoid/patches.rb +182 -0
  681. data/lib/locomotive/mongoid/presenter.rb +76 -0
  682. data/lib/locomotive/presentable.rb +216 -0
  683. data/lib/locomotive/previous_liquid/asset_host.rb +51 -0
  684. data/lib/locomotive/previous_liquid/drops/base.rb +40 -0
  685. data/lib/locomotive/previous_liquid/drops/content_entry.rb +78 -0
  686. data/lib/locomotive/previous_liquid/drops/content_types.rb +119 -0
  687. data/lib/locomotive/previous_liquid/drops/current_user.rb +21 -0
  688. data/lib/locomotive/previous_liquid/drops/page.rb +115 -0
  689. data/lib/locomotive/previous_liquid/drops/proxy_collection.rb +64 -0
  690. data/lib/locomotive/previous_liquid/drops/session_proxy.rb +16 -0
  691. data/lib/locomotive/previous_liquid/drops/site.rb +29 -0
  692. data/lib/locomotive/previous_liquid/drops/uploader.rb +21 -0
  693. data/lib/locomotive/previous_liquid/errors.rb +8 -0
  694. data/lib/locomotive/previous_liquid/filters/base.rb +61 -0
  695. data/lib/locomotive/previous_liquid/filters/date.rb +82 -0
  696. data/lib/locomotive/previous_liquid/filters/html.rb +117 -0
  697. data/lib/locomotive/previous_liquid/filters/misc.rb +75 -0
  698. data/lib/locomotive/previous_liquid/filters/resize.rb +18 -0
  699. data/lib/locomotive/previous_liquid/filters/text.rb +53 -0
  700. data/lib/locomotive/previous_liquid/filters/translate.rb +38 -0
  701. data/lib/locomotive/previous_liquid/patches.rb +21 -0
  702. data/lib/locomotive/previous_liquid/tags/consume.rb +104 -0
  703. data/lib/locomotive/previous_liquid/tags/csrf.rb +40 -0
  704. data/lib/locomotive/previous_liquid/tags/editable.rb +4 -0
  705. data/lib/locomotive/previous_liquid/tags/editable/base.rb +88 -0
  706. data/lib/locomotive/previous_liquid/tags/editable/control.rb +41 -0
  707. data/lib/locomotive/previous_liquid/tags/editable/file.rb +43 -0
  708. data/lib/locomotive/previous_liquid/tags/editable/text.rb +79 -0
  709. data/lib/locomotive/previous_liquid/tags/extends.rb +47 -0
  710. data/lib/locomotive/previous_liquid/tags/fetch_page.rb +36 -0
  711. data/lib/locomotive/previous_liquid/tags/google_analytics.rb +39 -0
  712. data/lib/locomotive/previous_liquid/tags/hybrid.rb +25 -0
  713. data/lib/locomotive/previous_liquid/tags/inherited_block.rb +31 -0
  714. data/lib/locomotive/previous_liquid/tags/inline_editor.rb +40 -0
  715. data/lib/locomotive/previous_liquid/tags/javascript.rb +16 -0
  716. data/lib/locomotive/previous_liquid/tags/link_to.rb +43 -0
  717. data/lib/locomotive/previous_liquid/tags/locale_switcher.rb +83 -0
  718. data/lib/locomotive/previous_liquid/tags/model_form.rb +75 -0
  719. data/lib/locomotive/previous_liquid/tags/nav.rb +164 -0
  720. data/lib/locomotive/previous_liquid/tags/paginate.rb +114 -0
  721. data/lib/locomotive/previous_liquid/tags/path_helper.rb +85 -0
  722. data/lib/locomotive/previous_liquid/tags/path_to.rb +21 -0
  723. data/lib/locomotive/previous_liquid/tags/seo.rb +72 -0
  724. data/lib/locomotive/previous_liquid/tags/session_assign.rb +39 -0
  725. data/lib/locomotive/previous_liquid/tags/snippet.rb +75 -0
  726. data/lib/locomotive/previous_liquid/tags/with_scope.rb +65 -0
  727. data/lib/locomotive/rails.rb +1 -0
  728. data/lib/locomotive/rails/action_view.rb +6 -0
  729. data/lib/locomotive/regexps.rb +13 -0
  730. data/lib/locomotive/simple_form.rb +137 -0
  731. data/lib/locomotive/simple_token_authentication.rb +11 -0
  732. data/lib/locomotive/steam_adaptor.rb +26 -0
  733. data/lib/locomotive/version.rb +3 -0
  734. data/lib/locomotivecms.rb +1 -0
  735. data/lib/tasks/development.rake +59 -0
  736. data/lib/tasks/locomotive.rake +126 -0
  737. data/public/favicon.ico +0 -0
  738. data/spec/dummy/Rakefile +6 -0
  739. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  740. data/spec/dummy/app/assets/javascripts/locomotive_misc.js.coffee +2 -0
  741. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  742. data/spec/dummy/app/cells/locomotive/main_menu_cell.rb +9 -0
  743. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  744. data/spec/dummy/app/controllers/foo_controller.rb +6 -0
  745. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  746. data/spec/dummy/app/models/foo.rb +7 -0
  747. data/spec/dummy/app/views/foo/index.html.haml +1 -0
  748. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  749. data/spec/dummy/app/views/locomotive/shared/_main_app_head.html.haml +1 -0
  750. data/spec/dummy/config.ru +7 -0
  751. data/spec/dummy/config/application.rb +49 -0
  752. data/spec/dummy/config/boot.rb +10 -0
  753. data/spec/dummy/config/environment.rb +5 -0
  754. data/spec/dummy/config/environments/development.rb +46 -0
  755. data/spec/dummy/config/environments/production.rb +44 -0
  756. data/spec/dummy/config/environments/test.rb +39 -0
  757. data/spec/dummy/config/initializers/assets.rb +13 -0
  758. data/spec/dummy/config/initializers/carrierwave.rb +8 -0
  759. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  760. data/spec/dummy/config/initializers/devise.rb +190 -0
  761. data/spec/dummy/config/initializers/dragonfly.rb +24 -0
  762. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  763. data/spec/dummy/config/initializers/haml.rb +2 -0
  764. data/spec/dummy/config/initializers/locomotive.rb +57 -0
  765. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  766. data/spec/dummy/config/initializers/session_store.rb +3 -0
  767. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  768. data/spec/dummy/config/locales/en.yml +10 -0
  769. data/spec/dummy/config/locales/fr.yml +10 -0
  770. data/spec/dummy/config/mongoid.yml +117 -0
  771. data/spec/dummy/config/routes.rb +14 -0
  772. data/spec/dummy/config/secrets.yml +25 -0
  773. data/spec/dummy/public/404.html +26 -0
  774. data/spec/dummy/public/422.html +26 -0
  775. data/spec/dummy/public/500.html +26 -0
  776. data/spec/dummy/script/rails +6 -0
  777. data/spec/fixtures/assets/5k.png +0 -0
  778. data/spec/fixtures/assets/5k@2x.png +0 -0
  779. data/spec/fixtures/assets/5k_2.png +0 -0
  780. data/spec/fixtures/assets/application.js +1 -0
  781. data/spec/fixtures/assets/main.css +1 -0
  782. data/spec/fixtures/assets/specs.pdf +0 -0
  783. data/spec/fixtures/assets/wrong.txt +1 -0
  784. data/spec/fixtures/images/logo1.jpg +0 -0
  785. data/spec/fixtures/images/logo2.jpg +0 -0
  786. data/spec/fixtures/images/rails.png +0 -0
  787. data/spec/fixtures/images/rails_2.png +0 -0
  788. data/spec/fixtures/portfolio/Gemfile +21 -0
  789. data/spec/fixtures/portfolio/app/content_types/messages.yml +57 -0
  790. data/spec/fixtures/portfolio/app/content_types/projects.yml +74 -0
  791. data/spec/fixtures/portfolio/app/views/pages/404.liquid.haml +10 -0
  792. data/spec/fixtures/portfolio/app/views/pages/index.liquid.haml +213 -0
  793. data/spec/fixtures/portfolio/app/views/snippets/footer.liquid.haml +2 -0
  794. data/spec/fixtures/portfolio/config.ru +3 -0
  795. data/spec/fixtures/portfolio/config/deploy.yml +18 -0
  796. data/spec/fixtures/portfolio/config/site.yml +33 -0
  797. data/spec/fixtures/portfolio/config/translations.yml +8 -0
  798. data/spec/fixtures/portfolio/data/messages.yml +1 -0
  799. data/spec/fixtures/portfolio/data/projects.yml +41 -0
  800. data/spec/fixtures/portfolio/icon.png +0 -0
  801. data/spec/fixtures/portfolio/public/javascripts/bootstrap.min.js +6 -0
  802. data/spec/fixtures/portfolio/public/javascripts/cbpAnimatedHeader.js +44 -0
  803. data/spec/fixtures/portfolio/public/javascripts/cbpAnimatedHeader.min.js +11 -0
  804. data/spec/fixtures/portfolio/public/javascripts/classie.js +80 -0
  805. data/spec/fixtures/portfolio/public/javascripts/contact_me.js +65 -0
  806. data/spec/fixtures/portfolio/public/javascripts/freelancer.js +37 -0
  807. data/spec/fixtures/portfolio/public/javascripts/jqBootstrapValidation.js +912 -0
  808. data/spec/fixtures/portfolio/public/samples/portfolio/cabin.png +0 -0
  809. data/spec/fixtures/portfolio/public/samples/portfolio/cake.png +0 -0
  810. data/spec/fixtures/portfolio/public/samples/portfolio/circus.png +0 -0
  811. data/spec/fixtures/portfolio/public/samples/portfolio/game.png +0 -0
  812. data/spec/fixtures/portfolio/public/samples/portfolio/safe.png +0 -0
  813. data/spec/fixtures/portfolio/public/samples/portfolio/submarine.png +0 -0
  814. data/spec/fixtures/portfolio/public/samples/profile.png +0 -0
  815. data/spec/fixtures/portfolio/public/stylesheets/bootstrap.min.css +7 -0
  816. data/spec/fixtures/portfolio/public/stylesheets/freelancer.css +445 -0
  817. data/spec/lib/action_view_spec.rb +15 -0
  818. data/spec/lib/core_ext_spec.rb +37 -0
  819. data/spec/lib/locomotive/configuration_spec.rb +15 -0
  820. data/spec/lib/locomotive/liquid/tags/editable/file_spec.rb +72 -0
  821. data/spec/lib/locomotive/liquid/tags/editable/text_spec.rb +85 -0
  822. data/spec/lib/locomotive/liquid/tags/extends_spec.rb +58 -0
  823. data/spec/mailers/locomotive/notifications_spec.rb +47 -0
  824. data/spec/models/locomotive/account_spec.rb +125 -0
  825. data/spec/models/locomotive/concerns/content_entry/counter_spec.rb +53 -0
  826. data/spec/models/locomotive/concerns/content_entry/csv_spec.rb +30 -0
  827. data/spec/models/locomotive/concerns/page/editable_elements_spec.rb +73 -0
  828. data/spec/models/locomotive/concerns/page/layout_spec.rb +50 -0
  829. data/spec/models/locomotive/concerns/page/redirect_spec.rb +28 -0
  830. data/spec/models/locomotive/concerns/page/render_spec.rb +84 -0
  831. data/spec/models/locomotive/concerns/site/access_points_spec.rb +15 -0
  832. data/spec/models/locomotive/concerns/site/locales_spec.rb +52 -0
  833. data/spec/models/locomotive/content_asset_spec.rb +58 -0
  834. data/spec/models/locomotive/content_entry_spec.rb +411 -0
  835. data/spec/models/locomotive/content_type_spec.rb +405 -0
  836. data/spec/models/locomotive/editable_control_spec.rb +79 -0
  837. data/spec/models/locomotive/editable_file_spec.rb +94 -0
  838. data/spec/models/locomotive/editable_text_spec.rb +219 -0
  839. data/spec/models/locomotive/membership_spec.rb +43 -0
  840. data/spec/models/locomotive/page_spec.rb +432 -0
  841. data/spec/models/locomotive/site_spec.rb +206 -0
  842. data/spec/models/locomotive/snippet_spec.rb +19 -0
  843. data/spec/models/locomotive/theme_asset_spec.rb +168 -0
  844. data/spec/requests/admin_ssl_spec.rb +51 -0
  845. data/spec/requests/site_spec.rb +36 -0
  846. data/spec/support/asset_host_stubs.rb +17 -0
  847. data/spec/support/carrierwave.rb +39 -0
  848. data/spec/support/controller.rb +32 -0
  849. data/spec/support/entity.rb +3 -0
  850. data/spec/support/factories.rb +313 -0
  851. data/spec/support/locomotive.rb +35 -0
  852. data/spec/support/matchers.rb +98 -0
  853. data/spec/support/middlewares.rb +3 -0
  854. data/spec/support/pundit_matcher.rb +50 -0
  855. data/spec/support/response.rb +12 -0
  856. data/spec/support/sequences.rb +16 -0
  857. data/spec/support/shared_contexts/api_header_setup.rb +7 -0
  858. data/spec/support/shared_contexts/api_site_setup.rb +13 -0
  859. data/vendor/assets/images/select2-spinner.gif +0 -0
  860. data/vendor/assets/images/select2.png +0 -0
  861. data/vendor/assets/images/select2x2.png +0 -0
  862. data/vendor/assets/javascripts/locomotive/bootstrap-datetimepicker.js +1395 -0
  863. data/vendor/assets/javascripts/locomotive/bootstrap-growl.js +312 -0
  864. data/vendor/assets/javascripts/locomotive/bootstrap-switch.js +532 -0
  865. data/vendor/assets/javascripts/locomotive/bootstrap-tagsinput.min.js +6 -0
  866. data/vendor/assets/javascripts/locomotive/canvas-to-blob.min.js +1 -0
  867. data/vendor/assets/javascripts/locomotive/cmd.js +31 -0
  868. data/vendor/assets/javascripts/locomotive/cookies.js +117 -0
  869. data/vendor/assets/javascripts/locomotive/cropper.js +9 -0
  870. data/vendor/assets/javascripts/locomotive/datepicker_i18n.js.erb +28 -0
  871. data/vendor/assets/javascripts/locomotive/editable_field.js +50 -0
  872. data/vendor/assets/javascripts/locomotive/form_submit_notification.js +39 -0
  873. data/vendor/assets/javascripts/locomotive/jquery-ui-timepicker-addon.js +2134 -0
  874. data/vendor/assets/javascripts/locomotive/liquid_mode.js +42 -0
  875. data/vendor/assets/javascripts/locomotive/moment.js +2808 -0
  876. data/vendor/assets/javascripts/locomotive/resize.js +9 -0
  877. data/vendor/assets/javascripts/locomotive/resizeImage.js +235 -0
  878. data/vendor/assets/javascripts/locomotive/slugify.js +47 -0
  879. data/vendor/assets/javascripts/locomotive/subscribe.js +367 -0
  880. data/vendor/assets/javascripts/locomotive/vendor.js +3 -0
  881. data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced.js +562 -0
  882. data/vendor/assets/javascripts/locomotive/wysihtml5/parser_rules/advanced_unwrap.js +666 -0
  883. data/vendor/assets/javascripts/locomotive/wysihtml5x-toolbar.js +15080 -0
  884. data/vendor/assets/stylesheets/locomotive/bootstrap-datetimepicker.css +235 -0
  885. data/vendor/assets/stylesheets/locomotive/bootstrap-switch.css +206 -0
  886. data/vendor/assets/stylesheets/locomotive/bootstrap-tagsinput.css +46 -0
  887. data/vendor/assets/stylesheets/locomotive/cropper.css +9 -0
  888. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  889. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  890. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  891. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  892. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  893. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  894. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  895. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  896. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_222222_256x240.png +0 -0
  897. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_2e83ff_256x240.png +0 -0
  898. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_454545_256x240.png +0 -0
  899. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_888888_256x240.png +0 -0
  900. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_cd0a0a_256x240.png +0 -0
  901. data/vendor/assets/stylesheets/locomotive/jquery/images/ui-icons_ffffff_256x240.png +0 -0
  902. data/vendor/assets/stylesheets/locomotive/jquery/ui.css.scss +406 -0
  903. data/vendor/assets/stylesheets/locomotive/liquid_mode.css +7 -0
  904. data/vendor/assets/stylesheets/locomotive/wysihtml5_editor.css +133 -0
  905. data/vendor/assets/stylesheets/locomotive/wysihtml5_reset.css +7 -0
  906. metadata +1735 -0
@@ -0,0 +1,3 @@
1
+ def env_for(url, opts = {})
2
+ Rack::MockRequest.env_for(url, opts)
3
+ end
@@ -0,0 +1,50 @@
1
+ module Pundit
2
+ module RSpec
3
+ module Matchers
4
+ extend ::RSpec::Matchers::DSL
5
+
6
+ matcher :permit do |user, site, resource|
7
+ match_for_should do |policy|
8
+ permissions.all? { |permission| puts permission.inspect; policy.new(user, site, resource).public_send(permission) }
9
+ end
10
+
11
+ match_for_should_not do |policy|
12
+ permissions.none? { |permission| policy.new(user, site, resource).public_send(permission) }
13
+ end
14
+
15
+ failure_message_for_should do |policy|
16
+ "Expected #{policy} to grant #{permissions.to_sentence} on #{resource}/#{site} but it didn't"
17
+ end
18
+
19
+ failure_message_for_should_not do |policy|
20
+ "Expected #{policy} not to grant #{permissions.to_sentence} on #{resource}/#{site} but it did"
21
+ end
22
+
23
+ def permissions
24
+ current_example = ::RSpec.respond_to?(:current_example) ? ::RSpec.current_example : example
25
+ current_example.metadata[:permissions]
26
+ end
27
+ end
28
+ end
29
+
30
+ module DSL
31
+ def permissions(*list, &block)
32
+ describe(list.to_sentence, permissions: list, caller: caller) { instance_eval(&block) }
33
+ end
34
+ end
35
+
36
+ module PolicyExampleGroup
37
+ include Pundit::RSpec::Matchers
38
+
39
+ def self.included(base)
40
+ base.metadata[:type] = :policy
41
+ base.extend Pundit::RSpec::DSL
42
+ super
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ RSpec.configure do |config|
49
+ config.include Pundit::RSpec::PolicyExampleGroup, type: :policy, file_path: /spec\/policies/
50
+ end
@@ -0,0 +1,12 @@
1
+ def parsed_response
2
+ parsed_response = parse_json(last_response.body)
3
+ if parsed_response.respond_to?(:with_indifferent_access)
4
+ parsed_response.with_indifferent_access
5
+ else
6
+ parsed_response
7
+ end
8
+ end
9
+
10
+ def parse_json(response)
11
+ JSON.parse(response)
12
+ end
@@ -0,0 +1,16 @@
1
+ def random(range=(1..8))
2
+ chars = ["A".."Z","0".."9"].collect { |r| Array(r) }.join
3
+ range.collect { chars[rand(chars.size)] }.join
4
+ end
5
+
6
+ FactoryGirl.define do
7
+ sequence(:email) { |n| "foo#{n}_#{random}@bar.com" }
8
+
9
+ sequence :handle do |n|
10
+ "handle-#{random}-#{n}"
11
+ end
12
+
13
+ sequence :name do |n|
14
+ "name_#{random}_#{n}"
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ shared_context 'api header setup' do
2
+ before do
3
+ header 'X-Locomotive-Account-Token', account.authentication_token
4
+ header 'X-Locomotive-Account-Email', account.email
5
+ header 'X-Locomotive-Site-Handle', site.handle
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ shared_context 'api site setup' do
2
+ include Rack::Test::Methods
3
+ let!(:site) { create(:site, domains: %w{www.acme.com}) }
4
+
5
+ let!(:account) { create(:account) }
6
+ let(:params) { { locale: :en } }
7
+
8
+ let!(:membership) do
9
+ create(:admin, account: account, site: site, role: 'admin')
10
+ end
11
+
12
+ subject { parsed_response }
13
+ end
Binary file
Binary file
@@ -0,0 +1,1395 @@
1
+ /*
2
+ //! version : 3.1.1
3
+ =========================================================
4
+ bootstrap-datetimepicker.js
5
+ https://github.com/Eonasdan/bootstrap-datetimepicker
6
+ =========================================================
7
+ The MIT License (MIT)
8
+
9
+ Copyright (c) 2014 Jonathan Peterson
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+ */
29
+ ;(function (root, factory) {
30
+ 'use strict';
31
+ if (typeof define === 'function' && define.amd) {
32
+ // AMD is used - Register as an anonymous module.
33
+ define(['jquery', 'moment'], factory);
34
+ } else {
35
+ // AMD is not used - Attempt to fetch dependencies from scope.
36
+ if (!jQuery) {
37
+ throw new Error('bootstrap-datetimepicker requires jQuery to be loaded first');
38
+ }
39
+ if (!moment) {
40
+ throw new Error('bootstrap-datetimepicker requires moment.js to be loaded first');
41
+ }
42
+ factory(root.jQuery, moment);
43
+ }
44
+ }(this, function ($, moment) {
45
+ 'use strict';
46
+ if (typeof moment === 'undefined') {
47
+ throw new Error('momentjs is required');
48
+ }
49
+
50
+ var dpgId = 0,
51
+
52
+ DateTimePicker = function (element, options) {
53
+ var defaults = $.fn.datetimepicker.defaults,
54
+
55
+ icons = {
56
+ time: 'glyphicon glyphicon-time',
57
+ date: 'glyphicon glyphicon-calendar',
58
+ up: 'glyphicon glyphicon-chevron-up',
59
+ down: 'glyphicon glyphicon-chevron-down'
60
+ },
61
+
62
+ picker = this,
63
+ errored = false,
64
+ dDate,
65
+
66
+ init = function () {
67
+ var icon = false, localeData, rInterval;
68
+ picker.options = $.extend({}, defaults, options);
69
+ picker.options.icons = $.extend({}, icons, picker.options.icons);
70
+
71
+ picker.element = $(element);
72
+
73
+ dataToOptions();
74
+
75
+ if (!(picker.options.pickTime || picker.options.pickDate)) {
76
+ throw new Error('Must choose at least one picker');
77
+ }
78
+
79
+ picker.id = dpgId++;
80
+ moment.locale(picker.options.language);
81
+ picker.date = moment();
82
+ picker.unset = false;
83
+ picker.isInput = picker.element.is('input');
84
+ picker.component = false;
85
+
86
+ if (picker.element.hasClass('input-group')) {
87
+ if (picker.element.find('.datepickerbutton').size() === 0) {//in case there is more then one 'input-group-addon' Issue #48
88
+ picker.component = picker.element.find('[class^="input-group-"]');
89
+ }
90
+ else {
91
+ picker.component = picker.element.find('.datepickerbutton');
92
+ }
93
+ }
94
+ picker.format = picker.options.format;
95
+
96
+ localeData = moment().localeData();
97
+
98
+ if (!picker.format) {
99
+ picker.format = (picker.options.pickDate ? localeData.longDateFormat('L') : '');
100
+ if (picker.options.pickDate && picker.options.pickTime) {
101
+ picker.format += ' ';
102
+ }
103
+ picker.format += (picker.options.pickTime ? localeData.longDateFormat('LT') : '');
104
+ if (picker.options.useSeconds) {
105
+ if (localeData.longDateFormat('LT').indexOf(' A') !== -1) {
106
+ picker.format = picker.format.split(' A')[0] + ':ss A';
107
+ }
108
+ else {
109
+ picker.format += ':ss';
110
+ }
111
+ }
112
+ }
113
+
114
+ if (picker.options.use24hours !== undefined) {
115
+ picker.use24hours = picker.options.use24hours
116
+ } else {
117
+ picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0);
118
+ }
119
+
120
+ // if (picker.options.use24hours == undefined) {
121
+ // picker.use24hours = (picker.format.toLowerCase().indexOf('a') < 0 && picker.format.indexOf('h') < 0);
122
+ // }
123
+
124
+ if (picker.component) {
125
+ icon = picker.component.find('span');
126
+ }
127
+
128
+ if (picker.options.pickTime) {
129
+ if (icon) {
130
+ icon.addClass(picker.options.icons.time);
131
+ }
132
+ }
133
+ if (picker.options.pickDate) {
134
+ if (icon) {
135
+ icon.removeClass(picker.options.icons.time);
136
+ icon.addClass(picker.options.icons.date);
137
+ }
138
+ }
139
+
140
+ picker.options.widgetParent =
141
+ typeof picker.options.widgetParent === 'string' && picker.options.widgetParent ||
142
+ picker.element.parents().filter(function () {
143
+ return 'scroll' === $(this).css('overflow-y');
144
+ }).get(0) ||
145
+ 'body';
146
+
147
+ picker.widget = $(getTemplate()).appendTo(picker.options.widgetParent);
148
+
149
+ picker.minViewMode = picker.options.minViewMode || 0;
150
+ if (typeof picker.minViewMode === 'string') {
151
+ switch (picker.minViewMode) {
152
+ case 'months':
153
+ picker.minViewMode = 1;
154
+ break;
155
+ case 'years':
156
+ picker.minViewMode = 2;
157
+ break;
158
+ default:
159
+ picker.minViewMode = 0;
160
+ break;
161
+ }
162
+ }
163
+ picker.viewMode = picker.options.viewMode || 0;
164
+ if (typeof picker.viewMode === 'string') {
165
+ switch (picker.viewMode) {
166
+ case 'months':
167
+ picker.viewMode = 1;
168
+ break;
169
+ case 'years':
170
+ picker.viewMode = 2;
171
+ break;
172
+ default:
173
+ picker.viewMode = 0;
174
+ break;
175
+ }
176
+ }
177
+
178
+ picker.viewMode = Math.max(picker.viewMode, picker.minViewMode);
179
+
180
+ picker.options.disabledDates = indexGivenDates(picker.options.disabledDates);
181
+ picker.options.enabledDates = indexGivenDates(picker.options.enabledDates);
182
+
183
+ picker.startViewMode = picker.viewMode;
184
+ picker.setMinDate(picker.options.minDate);
185
+ picker.setMaxDate(picker.options.maxDate);
186
+ fillDow();
187
+ fillMonths();
188
+ fillHours();
189
+ fillMinutes();
190
+ fillSeconds();
191
+ update();
192
+ showMode();
193
+ attachDatePickerEvents();
194
+ if (picker.options.defaultDate !== '' && getPickerInput().val() === '') {
195
+ picker.setValue(picker.options.defaultDate);
196
+ }
197
+ if (picker.options.minuteStepping !== 1) {
198
+ rInterval = picker.options.minuteStepping;
199
+ picker.date.minutes((Math.round(picker.date.minutes() / rInterval) * rInterval) % 60).seconds(0);
200
+ }
201
+ },
202
+
203
+ getPickerInput = function () {
204
+ var input;
205
+
206
+ if (picker.isInput) {
207
+ return picker.element;
208
+ }
209
+ input = picker.element.find('.datepickerinput');
210
+ if (input.size() === 0) {
211
+ input = picker.element.find('input');
212
+ }
213
+ else if (!input.is('input')) {
214
+ throw new Error('CSS class "datepickerinput" cannot be applied to non input element');
215
+ }
216
+ return input;
217
+ },
218
+
219
+ dataToOptions = function () {
220
+ var eData;
221
+ if (picker.element.is('input')) {
222
+ eData = picker.element.data();
223
+ }
224
+ else {
225
+ eData = picker.element.find('input').data();
226
+ }
227
+ if (eData.dateFormat !== undefined) {
228
+ picker.options.format = eData.dateFormat;
229
+ }
230
+ if (eData.datePickdate !== undefined) {
231
+ picker.options.pickDate = eData.datePickdate;
232
+ }
233
+ if (eData.datePicktime !== undefined) {
234
+ picker.options.pickTime = eData.datePicktime;
235
+ }
236
+ if (eData.dateUseminutes !== undefined) {
237
+ picker.options.useMinutes = eData.dateUseminutes;
238
+ }
239
+ if (eData.dateUseseconds !== undefined) {
240
+ picker.options.useSeconds = eData.dateUseseconds;
241
+ }
242
+ if (eData.dateUsecurrent !== undefined) {
243
+ picker.options.useCurrent = eData.dateUsecurrent;
244
+ }
245
+ if (eData.calendarWeeks !== undefined) {
246
+ picker.options.calendarWeeks = eData.calendarWeeks;
247
+ }
248
+ if (eData.dateMinutestepping !== undefined) {
249
+ picker.options.minuteStepping = eData.dateMinutestepping;
250
+ }
251
+ if (eData.dateMindate !== undefined) {
252
+ picker.options.minDate = eData.dateMindate;
253
+ }
254
+ if (eData.dateMaxdate !== undefined) {
255
+ picker.options.maxDate = eData.dateMaxdate;
256
+ }
257
+ if (eData.dateShowtoday !== undefined) {
258
+ picker.options.showToday = eData.dateShowtoday;
259
+ }
260
+ if (eData.dateCollapse !== undefined) {
261
+ picker.options.collapse = eData.dateCollapse;
262
+ }
263
+ if (eData.dateLanguage !== undefined) {
264
+ picker.options.language = eData.dateLanguage;
265
+ }
266
+ if (eData.dateDefaultdate !== undefined) {
267
+ picker.options.defaultDate = eData.dateDefaultdate;
268
+ }
269
+ if (eData.dateDisableddates !== undefined) {
270
+ picker.options.disabledDates = eData.dateDisableddates;
271
+ }
272
+ if (eData.dateEnableddates !== undefined) {
273
+ picker.options.enabledDates = eData.dateEnableddates;
274
+ }
275
+ if (eData.dateIcons !== undefined) {
276
+ picker.options.icons = eData.dateIcons;
277
+ }
278
+ if (eData.dateUsestrict !== undefined) {
279
+ picker.options.useStrict = eData.dateUsestrict;
280
+ }
281
+ if (eData.dateDirection !== undefined) {
282
+ picker.options.direction = eData.dateDirection;
283
+ }
284
+ if (eData.dateSidebyside !== undefined) {
285
+ picker.options.sideBySide = eData.dateSidebyside;
286
+ }
287
+ if (eData.dateDaysofweekdisabled !== undefined) {
288
+ picker.options.daysOfWeekDisabled = eData.dateDaysofweekdisabled;
289
+ }
290
+ if (eData.use24hours !== undefined) {
291
+ picker.options.use24hours = eData.use24hours;
292
+ }
293
+ // $.each(defaults, function (key) {
294
+ // var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
295
+ // if (eData[attributeName] !== undefined) {
296
+ // picker.options[key] = eData[attributeName];
297
+ // }
298
+ // });
299
+ },
300
+
301
+ place = function () {
302
+ var position = 'absolute',
303
+ offset = picker.component ? picker.component.offset() : picker.element.offset(),
304
+ $window = $(window),
305
+ parentOffset = $(picker.options.widgetParent).offset(),
306
+ placePosition;
307
+
308
+ picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth();
309
+ offset.top = offset.top + picker.element.outerHeight() - parentOffset.top;
310
+
311
+ if (picker.options.direction === 'up') {
312
+ placePosition = 'top';
313
+ } else if (picker.options.direction === 'bottom') {
314
+ placePosition = 'bottom';
315
+ } else if (picker.options.direction === 'auto') {
316
+ if ((offset.top + picker.widget.height() + parentOffset.top > $window.height() + $window.scrollTop()) && (picker.widget.height() + picker.element.outerHeight() < offset.top)) {
317
+ placePosition = 'top';
318
+ } else {
319
+ placePosition = 'bottom';
320
+ }
321
+ }
322
+ if (placePosition === 'top') {
323
+ offset.bottom = $window.height() - offset.top + 3; // + picker.element.outerHeight() + 3;
324
+ picker.widget.addClass('top').removeClass('bottom');
325
+ } else {
326
+ offset.top += 1;
327
+ picker.widget.addClass('bottom').removeClass('top');
328
+ }
329
+
330
+ if (picker.options.width !== undefined) {
331
+ picker.widget.width(picker.options.width);
332
+ }
333
+
334
+ if (picker.options.orientation === 'left') {
335
+ picker.widget.addClass('left-oriented');
336
+ offset.left = offset.left - picker.widget.width() + 20;
337
+ }
338
+
339
+ if (isInFixed()) {
340
+ position = 'fixed';
341
+ offset.top -= $window.scrollTop();
342
+ offset.left -= $window.scrollLeft();
343
+ }
344
+
345
+ if ($window.width() < offset.left + picker.widget.outerWidth()) {
346
+ offset.right = $window.width() - offset.left - picker.width;
347
+ offset.left = 'auto';
348
+ picker.widget.addClass('pull-right');
349
+ } else {
350
+ offset.right = 'auto';
351
+ picker.widget.removeClass('pull-right');
352
+ }
353
+
354
+ if (placePosition === 'top') {
355
+ picker.widget.css({
356
+ position: position,
357
+ bottom: offset.bottom,
358
+ top: 'auto',
359
+ left: offset.left,
360
+ right: offset.right
361
+ });
362
+ } else {
363
+ picker.widget.css({
364
+ position: position,
365
+ top: offset.top,
366
+ bottom: 'auto',
367
+ left: offset.left,
368
+ right: offset.right
369
+ });
370
+ }
371
+ },
372
+
373
+ notifyChange = function (oldDate, eventType) {
374
+ if (moment(picker.date).isSame(moment(oldDate)) && !errored) {
375
+ return;
376
+ }
377
+ errored = false;
378
+ picker.element.trigger({
379
+ type: 'dp.change',
380
+ date: moment(picker.date),
381
+ oldDate: moment(oldDate)
382
+ });
383
+
384
+ if (eventType !== 'change') {
385
+ picker.element.change();
386
+ }
387
+ },
388
+
389
+ notifyError = function (date) {
390
+ errored = true;
391
+ picker.element.trigger({
392
+ type: 'dp.error',
393
+ date: moment(date, picker.format, picker.options.useStrict)
394
+ });
395
+ },
396
+
397
+ update = function (newDate) {
398
+ moment.locale(picker.options.language);
399
+ var dateStr = newDate;
400
+ if (!dateStr) {
401
+ dateStr = getPickerInput().val();
402
+ if (dateStr) {
403
+ picker.date = moment(dateStr, picker.format, picker.options.useStrict);
404
+ }
405
+ if (!picker.date) {
406
+ picker.date = moment();
407
+ }
408
+ }
409
+ picker.viewDate = moment(picker.date).startOf('month');
410
+ fillDate();
411
+ fillTime();
412
+ },
413
+
414
+ fillDow = function () {
415
+ moment.locale(picker.options.language);
416
+ var html = $('<tr>'), weekdaysMin = moment.weekdaysMin(), i;
417
+ if (picker.options.calendarWeeks === true) {
418
+ html.append('<th class="cw">#</th>');
419
+ }
420
+ if (moment().localeData()._week.dow === 0) { // starts on Sunday
421
+ for (i = 0; i < 7; i++) {
422
+ html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
423
+ }
424
+ } else {
425
+ for (i = 1; i < 8; i++) {
426
+ if (i === 7) {
427
+ html.append('<th class="dow">' + weekdaysMin[0] + '</th>');
428
+ } else {
429
+ html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
430
+ }
431
+ }
432
+ }
433
+ picker.widget.find('.datepicker-days thead').append(html);
434
+ },
435
+
436
+ fillMonths = function () {
437
+ moment.locale(picker.options.language);
438
+ var html = '', i, monthsShort = moment.monthsShort();
439
+ for (i = 0; i < 12; i++) {
440
+ html += '<span class="month">' + monthsShort[i] + '</span>';
441
+ }
442
+ picker.widget.find('.datepicker-months td').append(html);
443
+ },
444
+
445
+ fillDate = function () {
446
+ if (!picker.options.pickDate) {
447
+ return;
448
+ }
449
+ moment.locale(picker.options.language);
450
+ var year = picker.viewDate.year(),
451
+ month = picker.viewDate.month(),
452
+ startYear = picker.options.minDate.year(),
453
+ startMonth = picker.options.minDate.month(),
454
+ endYear = picker.options.maxDate.year(),
455
+ endMonth = picker.options.maxDate.month(),
456
+ currentDate,
457
+ prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = moment.months();
458
+
459
+ picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled');
460
+ picker.widget.find('.datepicker-months').find('.disabled').removeClass('disabled');
461
+ picker.widget.find('.datepicker-years').find('.disabled').removeClass('disabled');
462
+
463
+ picker.widget.find('.datepicker-days th:eq(1)').text(
464
+ months[month] + ' ' + year);
465
+
466
+ prevMonth = moment(picker.viewDate, picker.format, picker.options.useStrict).subtract(1, 'months');
467
+ days = prevMonth.daysInMonth();
468
+ prevMonth.date(days).startOf('week');
469
+ if ((year === startYear && month <= startMonth) || year < startYear) {
470
+ picker.widget.find('.datepicker-days th:eq(0)').addClass('disabled');
471
+ }
472
+ if ((year === endYear && month >= endMonth) || year > endYear) {
473
+ picker.widget.find('.datepicker-days th:eq(2)').addClass('disabled');
474
+ }
475
+
476
+ nextMonth = moment(prevMonth).add(42, 'd');
477
+ while (prevMonth.isBefore(nextMonth)) {
478
+ if (prevMonth.weekday() === moment().startOf('week').weekday()) {
479
+ row = $('<tr>');
480
+ html.push(row);
481
+ if (picker.options.calendarWeeks === true) {
482
+ row.append('<td class="cw">' + prevMonth.week() + '</td>');
483
+ }
484
+ }
485
+ clsName = '';
486
+ if (prevMonth.year() < year || (prevMonth.year() === year && prevMonth.month() < month)) {
487
+ clsName += ' old';
488
+ } else if (prevMonth.year() > year || (prevMonth.year() === year && prevMonth.month() > month)) {
489
+ clsName += ' new';
490
+ }
491
+ if (prevMonth.isSame(moment({y: picker.date.year(), M: picker.date.month(), d: picker.date.date()}))) {
492
+ clsName += ' active';
493
+ }
494
+ if (isInDisableDates(prevMonth, 'day') || !isInEnableDates(prevMonth)) {
495
+ clsName += ' disabled';
496
+ }
497
+ if (picker.options.showToday === true) {
498
+ if (prevMonth.isSame(moment(), 'day')) {
499
+ clsName += ' today';
500
+ }
501
+ }
502
+ if (picker.options.daysOfWeekDisabled) {
503
+ for (i = 0; i < picker.options.daysOfWeekDisabled.length; i++) {
504
+ if (prevMonth.day() === picker.options.daysOfWeekDisabled[i]) {
505
+ clsName += ' disabled';
506
+ break;
507
+ }
508
+ }
509
+ }
510
+ row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>');
511
+
512
+ currentDate = prevMonth.date();
513
+ prevMonth.add(1, 'd');
514
+
515
+ if (currentDate === prevMonth.date()) {
516
+ prevMonth.add(1, 'd');
517
+ }
518
+ }
519
+ picker.widget.find('.datepicker-days tbody').empty().append(html);
520
+ currentYear = picker.date.year();
521
+ months = picker.widget.find('.datepicker-months').find('th:eq(1)').text(year).end().find('span').removeClass('active');
522
+ if (currentYear === year) {
523
+ months.eq(picker.date.month()).addClass('active');
524
+ }
525
+ if (year - 1 < startYear) {
526
+ picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled');
527
+ }
528
+ if (year + 1 > endYear) {
529
+ picker.widget.find('.datepicker-months th:eq(2)').addClass('disabled');
530
+ }
531
+ for (i = 0; i < 12; i++) {
532
+ if ((year === startYear && startMonth > i) || (year < startYear)) {
533
+ $(months[i]).addClass('disabled');
534
+ } else if ((year === endYear && endMonth < i) || (year > endYear)) {
535
+ $(months[i]).addClass('disabled');
536
+ }
537
+ }
538
+
539
+ html = '';
540
+ year = parseInt(year / 10, 10) * 10;
541
+ yearCont = picker.widget.find('.datepicker-years').find(
542
+ 'th:eq(1)').text(year + '-' + (year + 9)).parents('table').find('td');
543
+ picker.widget.find('.datepicker-years').find('th').removeClass('disabled');
544
+ if (startYear > year) {
545
+ picker.widget.find('.datepicker-years').find('th:eq(0)').addClass('disabled');
546
+ }
547
+ if (endYear < year + 9) {
548
+ picker.widget.find('.datepicker-years').find('th:eq(2)').addClass('disabled');
549
+ }
550
+ year -= 1;
551
+ for (i = -1; i < 11; i++) {
552
+ html += '<span class="year' + (i === -1 || i === 10 ? ' old' : '') + (currentYear === year ? ' active' : '') + ((year < startYear || year > endYear) ? ' disabled' : '') + '">' + year + '</span>';
553
+ year += 1;
554
+ }
555
+ yearCont.html(html);
556
+ },
557
+
558
+ fillHours = function () {
559
+ moment.locale(picker.options.language);
560
+ var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j;
561
+ table.parent().hide();
562
+ if (picker.use24hours) {
563
+ current = 0;
564
+ for (i = 0; i < 6; i += 1) {
565
+ html += '<tr>';
566
+ for (j = 0; j < 4; j += 1) {
567
+ html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
568
+ current++;
569
+ }
570
+ html += '</tr>';
571
+ }
572
+ }
573
+ else {
574
+ current = 1;
575
+ for (i = 0; i < 3; i += 1) {
576
+ html += '<tr>';
577
+ for (j = 0; j < 4; j += 1) {
578
+ html += '<td class="hour">' + padLeft(current.toString()) + '</td>';
579
+ current++;
580
+ }
581
+ html += '</tr>';
582
+ }
583
+ }
584
+ table.html(html);
585
+ },
586
+
587
+ fillMinutes = function () {
588
+ var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping;
589
+ table.parent().hide();
590
+ if (step === 1) {
591
+ step = 5;
592
+ }
593
+ for (i = 0; i < Math.ceil(60 / step / 4) ; i++) {
594
+ html += '<tr>';
595
+ for (j = 0; j < 4; j += 1) {
596
+ if (current < 60) {
597
+ html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
598
+ current += step;
599
+ } else {
600
+ html += '<td></td>';
601
+ }
602
+ }
603
+ html += '</tr>';
604
+ }
605
+ table.html(html);
606
+ },
607
+
608
+ fillSeconds = function () {
609
+ var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j;
610
+ table.parent().hide();
611
+ for (i = 0; i < 3; i++) {
612
+ html += '<tr>';
613
+ for (j = 0; j < 4; j += 1) {
614
+ html += '<td class="second">' + padLeft(current.toString()) + '</td>';
615
+ current += 5;
616
+ }
617
+ html += '</tr>';
618
+ }
619
+ table.html(html);
620
+ },
621
+
622
+ fillTime = function () {
623
+ if (!picker.date) {
624
+ return;
625
+ }
626
+ var timeComponents = picker.widget.find('.timepicker span[data-time-component]'),
627
+ hour = picker.date.hours(),
628
+ period = picker.date.format('A');
629
+ if (!picker.use24hours) {
630
+ if (hour === 0) {
631
+ hour = 12;
632
+ } else if (hour !== 12) {
633
+ hour = hour % 12;
634
+ }
635
+ picker.widget.find('.timepicker [data-action=togglePeriod]').text(period);
636
+ }
637
+ timeComponents.filter('[data-time-component=hours]').text(padLeft(hour));
638
+ timeComponents.filter('[data-time-component=minutes]').text(padLeft(picker.date.minutes()));
639
+ timeComponents.filter('[data-time-component=seconds]').text(padLeft(picker.date.second()));
640
+ },
641
+
642
+ click = function (e) {
643
+ e.stopPropagation();
644
+ e.preventDefault();
645
+ picker.unset = false;
646
+ var target = $(e.target).closest('span, td, th'), month, year, step, day, oldDate = moment(picker.date);
647
+ if (target.length === 1) {
648
+ if (!target.is('.disabled')) {
649
+ switch (target[0].nodeName.toLowerCase()) {
650
+ case 'th':
651
+ switch (target[0].className) {
652
+ case 'picker-switch':
653
+ showMode(1);
654
+ break;
655
+ case 'prev':
656
+ case 'next':
657
+ step = dpGlobal.modes[picker.viewMode].navStep;
658
+ if (target[0].className === 'prev') {
659
+ step = step * -1;
660
+ }
661
+ picker.viewDate.add(step, dpGlobal.modes[picker.viewMode].navFnc);
662
+ fillDate();
663
+ break;
664
+ }
665
+ break;
666
+ case 'span':
667
+ if (target.is('.month')) {
668
+ month = target.parent().find('span').index(target);
669
+ picker.viewDate.month(month);
670
+ } else {
671
+ year = parseInt(target.text(), 10) || 0;
672
+ picker.viewDate.year(year);
673
+ }
674
+ if (picker.viewMode === picker.minViewMode) {
675
+ picker.date = moment({
676
+ y: picker.viewDate.year(),
677
+ M: picker.viewDate.month(),
678
+ d: picker.viewDate.date(),
679
+ h: picker.date.hours(),
680
+ m: picker.date.minutes(),
681
+ s: picker.date.seconds()
682
+ });
683
+ set();
684
+ notifyChange(oldDate, e.type);
685
+ }
686
+ showMode(-1);
687
+ fillDate();
688
+ break;
689
+ case 'td':
690
+ if (target.is('.day')) {
691
+ day = parseInt(target.text(), 10) || 1;
692
+ month = picker.viewDate.month();
693
+ year = picker.viewDate.year();
694
+ if (target.is('.old')) {
695
+ if (month === 0) {
696
+ month = 11;
697
+ year -= 1;
698
+ } else {
699
+ month -= 1;
700
+ }
701
+ } else if (target.is('.new')) {
702
+ if (month === 11) {
703
+ month = 0;
704
+ year += 1;
705
+ } else {
706
+ month += 1;
707
+ }
708
+ }
709
+ picker.date = moment({
710
+ y: year,
711
+ M: month,
712
+ d: day,
713
+ h: picker.date.hours(),
714
+ m: picker.date.minutes(),
715
+ s: picker.date.seconds()
716
+ }
717
+ );
718
+ picker.viewDate = moment({
719
+ y: year, M: month, d: Math.min(28, day)
720
+ });
721
+ fillDate();
722
+ set();
723
+ notifyChange(oldDate, e.type);
724
+ }
725
+ break;
726
+ }
727
+ }
728
+ }
729
+ },
730
+
731
+ actions = {
732
+ incrementHours: function () {
733
+ checkDate('add', 'hours', 1);
734
+ },
735
+
736
+ incrementMinutes: function () {
737
+ checkDate('add', 'minutes', picker.options.minuteStepping);
738
+ },
739
+
740
+ incrementSeconds: function () {
741
+ checkDate('add', 'seconds', 1);
742
+ },
743
+
744
+ decrementHours: function () {
745
+ checkDate('subtract', 'hours', 1);
746
+ },
747
+
748
+ decrementMinutes: function () {
749
+ checkDate('subtract', 'minutes', picker.options.minuteStepping);
750
+ },
751
+
752
+ decrementSeconds: function () {
753
+ checkDate('subtract', 'seconds', 1);
754
+ },
755
+
756
+ togglePeriod: function () {
757
+ var hour = picker.date.hours();
758
+ if (hour >= 12) {
759
+ hour -= 12;
760
+ } else {
761
+ hour += 12;
762
+ }
763
+ picker.date.hours(hour);
764
+ },
765
+
766
+ showPicker: function () {
767
+ picker.widget.find('.timepicker > div:not(.timepicker-picker)').hide();
768
+ picker.widget.find('.timepicker .timepicker-picker').show();
769
+ },
770
+
771
+ showHours: function () {
772
+ picker.widget.find('.timepicker .timepicker-picker').hide();
773
+ picker.widget.find('.timepicker .timepicker-hours').show();
774
+ },
775
+
776
+ showMinutes: function () {
777
+ picker.widget.find('.timepicker .timepicker-picker').hide();
778
+ picker.widget.find('.timepicker .timepicker-minutes').show();
779
+ },
780
+
781
+ showSeconds: function () {
782
+ picker.widget.find('.timepicker .timepicker-picker').hide();
783
+ picker.widget.find('.timepicker .timepicker-seconds').show();
784
+ },
785
+
786
+ selectHour: function (e) {
787
+ var hour = parseInt($(e.target).text(), 10);
788
+ if (!picker.use24hours) {
789
+ if (picker.date.hours() >= 12) {
790
+ if (hour !== 12) {
791
+ hour += 12;
792
+ }
793
+ } else {
794
+ if (hour === 12) {
795
+ hour = 0;
796
+ }
797
+ }
798
+ }
799
+ picker.date.hours(hour);
800
+ actions.showPicker.call(picker);
801
+ },
802
+
803
+ selectMinute: function (e) {
804
+ picker.date.minutes(parseInt($(e.target).text(), 10));
805
+ actions.showPicker.call(picker);
806
+ },
807
+
808
+ selectSecond: function (e) {
809
+ picker.date.seconds(parseInt($(e.target).text(), 10));
810
+ actions.showPicker.call(picker);
811
+ }
812
+ },
813
+
814
+ doAction = function (e) {
815
+ var oldDate = moment(picker.date),
816
+ action = $(e.currentTarget).data('action'),
817
+ rv = actions[action].apply(picker, arguments);
818
+ stopEvent(e);
819
+ if (!picker.date) {
820
+ picker.date = moment({y: 1970});
821
+ }
822
+ set();
823
+ fillTime();
824
+ notifyChange(oldDate, e.type);
825
+ return rv;
826
+ },
827
+
828
+ stopEvent = function (e) {
829
+ e.stopPropagation();
830
+ e.preventDefault();
831
+ },
832
+
833
+ keydown = function (e) {
834
+ if (e.keyCode === 27) { // allow escape to hide picker
835
+ picker.hide();
836
+ }
837
+ },
838
+
839
+ change = function (e) {
840
+ moment.locale(picker.options.language);
841
+ var input = $(e.target), oldDate = moment(picker.date), newDate = moment(input.val(), picker.format, picker.options.useStrict);
842
+ if (newDate.isValid() && !isInDisableDates(newDate) && isInEnableDates(newDate)) {
843
+ update();
844
+ picker.setValue(newDate);
845
+ notifyChange(oldDate, e.type);
846
+ set();
847
+ }
848
+ else {
849
+ picker.viewDate = oldDate;
850
+ picker.unset = true;
851
+ notifyChange(oldDate, e.type);
852
+ notifyError(newDate);
853
+ }
854
+ },
855
+
856
+ showMode = function (dir) {
857
+ if (dir) {
858
+ picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir));
859
+ }
860
+ picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show();
861
+ },
862
+
863
+ attachDatePickerEvents = function () {
864
+ var $this, $parent, expanded, closed, collapseData;
865
+ picker.widget.on('click', '.datepicker *', $.proxy(click, this)); // this handles date picker clicks
866
+ picker.widget.on('click', '[data-action]', $.proxy(doAction, this)); // this handles time picker clicks
867
+ picker.widget.on('mousedown', $.proxy(stopEvent, this));
868
+ picker.element.on('keydown', $.proxy(keydown, this));
869
+ if (picker.options.pickDate && picker.options.pickTime) {
870
+ picker.widget.on('click.togglePicker', '.accordion-toggle', function (e) {
871
+ e.stopPropagation();
872
+ $this = $(this);
873
+ $parent = $this.closest('ul');
874
+ expanded = $parent.find('.in');
875
+ closed = $parent.find('.collapse:not(.in)');
876
+
877
+ if (expanded && expanded.length) {
878
+ collapseData = expanded.data('collapse');
879
+ if (collapseData && collapseData.transitioning) {
880
+ return;
881
+ }
882
+ expanded.collapse('hide');
883
+ closed.collapse('show');
884
+ $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
885
+ if (picker.component) {
886
+ picker.component.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
887
+ }
888
+ }
889
+ });
890
+ }
891
+ if (picker.isInput) {
892
+ picker.element.on({
893
+ 'click': $.proxy(picker.show, this),
894
+ 'focus': $.proxy(picker.show, this),
895
+ 'change': $.proxy(change, this),
896
+ 'blur': $.proxy(picker.hide, this)
897
+ });
898
+ } else {
899
+ picker.element.on({
900
+ 'change': $.proxy(change, this)
901
+ }, 'input');
902
+ if (picker.component) {
903
+ picker.component.on('click', $.proxy(picker.show, this));
904
+ picker.component.on('mousedown', $.proxy(stopEvent, this));
905
+ } else {
906
+ picker.element.on('click', $.proxy(picker.show, this));
907
+ }
908
+ }
909
+ },
910
+
911
+ attachDatePickerGlobalEvents = function () {
912
+ $(window).on(
913
+ 'resize.datetimepicker' + picker.id, $.proxy(place, this));
914
+ if (!picker.isInput) {
915
+ $(document).on(
916
+ 'mousedown.datetimepicker' + picker.id, $.proxy(picker.hide, this));
917
+ }
918
+ },
919
+
920
+ detachDatePickerEvents = function () {
921
+ picker.widget.off('click', '.datepicker *', picker.click);
922
+ picker.widget.off('click', '[data-action]');
923
+ picker.widget.off('mousedown', picker.stopEvent);
924
+ if (picker.options.pickDate && picker.options.pickTime) {
925
+ picker.widget.off('click.togglePicker');
926
+ }
927
+ if (picker.isInput) {
928
+ picker.element.off({
929
+ 'focus': picker.show,
930
+ 'change': picker.change,
931
+ 'click': picker.show,
932
+ 'blur' : picker.hide
933
+ });
934
+ } else {
935
+ picker.element.off({
936
+ 'change': picker.change
937
+ }, 'input');
938
+ if (picker.component) {
939
+ picker.component.off('click', picker.show);
940
+ picker.component.off('mousedown', picker.stopEvent);
941
+ } else {
942
+ picker.element.off('click', picker.show);
943
+ }
944
+ }
945
+ },
946
+
947
+ detachDatePickerGlobalEvents = function () {
948
+ $(window).off('resize.datetimepicker' + picker.id);
949
+ if (!picker.isInput) {
950
+ $(document).off('mousedown.datetimepicker' + picker.id);
951
+ }
952
+ },
953
+
954
+ isInFixed = function () {
955
+ if (picker.element) {
956
+ var parents = picker.element.parents(), inFixed = false, i;
957
+ for (i = 0; i < parents.length; i++) {
958
+ if ($(parents[i]).css('position') === 'fixed') {
959
+ inFixed = true;
960
+ break;
961
+ }
962
+ }
963
+ return inFixed;
964
+ } else {
965
+ return false;
966
+ }
967
+ },
968
+
969
+ set = function () {
970
+ moment.locale(picker.options.language);
971
+ var formatted = '';
972
+ if (!picker.unset) {
973
+ formatted = moment(picker.date).format(picker.format);
974
+ }
975
+ getPickerInput().val(formatted);
976
+ picker.element.data('date', formatted);
977
+ if (!picker.options.pickTime) {
978
+ picker.hide();
979
+ }
980
+ },
981
+
982
+ checkDate = function (direction, unit, amount) {
983
+ moment.locale(picker.options.language);
984
+ var newDate;
985
+ if (direction === 'add') {
986
+ newDate = moment(picker.date);
987
+ if (newDate.hours() === 23) {
988
+ newDate.add(amount, unit);
989
+ }
990
+ newDate.add(amount, unit);
991
+ }
992
+ else {
993
+ newDate = moment(picker.date).subtract(amount, unit);
994
+ }
995
+ if (isInDisableDates(moment(newDate.subtract(amount, unit))) || isInDisableDates(newDate)) {
996
+ notifyError(newDate.format(picker.format));
997
+ return;
998
+ }
999
+
1000
+ if (direction === 'add') {
1001
+ picker.date.add(amount, unit);
1002
+ }
1003
+ else {
1004
+ picker.date.subtract(amount, unit);
1005
+ }
1006
+ picker.unset = false;
1007
+ },
1008
+
1009
+ isInDisableDates = function (date, timeUnit) {
1010
+ moment.locale(picker.options.language);
1011
+ var maxDate = moment(picker.options.maxDate, picker.format, picker.options.useStrict),
1012
+ minDate = moment(picker.options.minDate, picker.format, picker.options.useStrict);
1013
+
1014
+ if (timeUnit) {
1015
+ maxDate = maxDate.endOf(timeUnit);
1016
+ minDate = minDate.startOf(timeUnit);
1017
+ }
1018
+
1019
+ if (date.isAfter(maxDate) || date.isBefore(minDate)) {
1020
+ return true;
1021
+ }
1022
+ if (picker.options.disabledDates === false) {
1023
+ return false;
1024
+ }
1025
+ return picker.options.disabledDates[date.format('YYYY-MM-DD')] === true;
1026
+ },
1027
+ isInEnableDates = function (date) {
1028
+ moment.locale(picker.options.language);
1029
+ if (picker.options.enabledDates === false) {
1030
+ return true;
1031
+ }
1032
+ return picker.options.enabledDates[date.format('YYYY-MM-DD')] === true;
1033
+ },
1034
+
1035
+ indexGivenDates = function (givenDatesArray) {
1036
+ // Store given enabledDates and disabledDates as keys.
1037
+ // This way we can check their existence in O(1) time instead of looping through whole array.
1038
+ // (for example: picker.options.enabledDates['2014-02-27'] === true)
1039
+ var givenDatesIndexed = {}, givenDatesCount = 0, i;
1040
+ for (i = 0; i < givenDatesArray.length; i++) {
1041
+ if (moment.isMoment(givenDatesArray[i]) || givenDatesArray[i] instanceof Date) {
1042
+ dDate = moment(givenDatesArray[i]);
1043
+ } else {
1044
+ dDate = moment(givenDatesArray[i], picker.format, picker.options.useStrict);
1045
+ }
1046
+ if (dDate.isValid()) {
1047
+ givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
1048
+ givenDatesCount++;
1049
+ }
1050
+ }
1051
+ if (givenDatesCount > 0) {
1052
+ return givenDatesIndexed;
1053
+ }
1054
+ return false;
1055
+ },
1056
+
1057
+ padLeft = function (string) {
1058
+ string = string.toString();
1059
+ if (string.length >= 2) {
1060
+ return string;
1061
+ }
1062
+ return '0' + string;
1063
+ },
1064
+
1065
+ getTemplate = function () {
1066
+ var
1067
+ headTemplate =
1068
+ '<thead>' +
1069
+ '<tr>' +
1070
+ '<th class="prev">&lsaquo;</th><th colspan="' + (picker.options.calendarWeeks ? '6' : '5') + '" class="picker-switch"></th><th class="next">&rsaquo;</th>' +
1071
+ '</tr>' +
1072
+ '</thead>',
1073
+ contTemplate =
1074
+ '<tbody><tr><td colspan="' + (picker.options.calendarWeeks ? '8' : '7') + '"></td></tr></tbody>',
1075
+ template = '<div class="datepicker-days">' +
1076
+ '<table class="table-condensed">' + headTemplate + '<tbody></tbody></table>' +
1077
+ '</div>' +
1078
+ '<div class="datepicker-months">' +
1079
+ '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
1080
+ '</div>' +
1081
+ '<div class="datepicker-years">' +
1082
+ '<table class="table-condensed">' + headTemplate + contTemplate + '</table>' +
1083
+ '</div>',
1084
+ ret = '';
1085
+ if (picker.options.pickDate && picker.options.pickTime) {
1086
+ ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + (picker.use24hours ? ' usetwentyfour' : '') + ' dropdown-menu" style="z-index:9999 !important;">';
1087
+ if (picker.options.sideBySide) {
1088
+ ret += '<div class="row">' +
1089
+ '<div class="col-sm-6 datepicker">' + template + '</div>' +
1090
+ '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' +
1091
+ '</div>';
1092
+ } else {
1093
+ ret += '<ul class="list-unstyled">' +
1094
+ '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' +
1095
+ '<div class="datepicker">' + template + '</div>' +
1096
+ '</li>' +
1097
+ '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
1098
+ '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' +
1099
+ '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
1100
+ '</li>' +
1101
+ '</ul>';
1102
+ }
1103
+ ret += '</div>';
1104
+ return ret;
1105
+ }
1106
+ if (picker.options.pickTime) {
1107
+ return (
1108
+ '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
1109
+ '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
1110
+ '</div>'
1111
+ );
1112
+ }
1113
+ return (
1114
+ '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
1115
+ '<div class="datepicker">' + template + '</div>' +
1116
+ '</div>'
1117
+ );
1118
+ },
1119
+
1120
+ dpGlobal = {
1121
+ modes: [
1122
+ {
1123
+ clsName: 'days',
1124
+ navFnc: 'month',
1125
+ navStep: 1
1126
+ },
1127
+ {
1128
+ clsName: 'months',
1129
+ navFnc: 'year',
1130
+ navStep: 1
1131
+ },
1132
+ {
1133
+ clsName: 'years',
1134
+ navFnc: 'year',
1135
+ navStep: 10
1136
+ }
1137
+ ]
1138
+ },
1139
+
1140
+ tpGlobal = {
1141
+ hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
1142
+ minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
1143
+ secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'
1144
+ };
1145
+
1146
+ tpGlobal.getTemplate = function () {
1147
+ return (
1148
+ '<div class="timepicker-picker">' +
1149
+ '<table class="table-condensed">' +
1150
+ '<tr>' +
1151
+ '<td><a href="#" class="btn" data-action="incrementHours"><span class="' + picker.options.icons.up + '"></span></a></td>' +
1152
+ '<td class="separator"></td>' +
1153
+ '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' +
1154
+ (picker.options.useSeconds ?
1155
+ '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') +
1156
+ (picker.use24hours ? '' : '<td class="separator"></td>') +
1157
+ '</tr>' +
1158
+ '<tr>' +
1159
+ '<td>' + tpGlobal.hourTemplate + '</td> ' +
1160
+ '<td class="separator">:</td>' +
1161
+ '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' +
1162
+ (picker.options.useSeconds ?
1163
+ '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') +
1164
+ (picker.use24hours ? '' : '<td class="separator"></td>' +
1165
+ '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') +
1166
+ '</tr>' +
1167
+ '<tr>' +
1168
+ '<td><a href="#" class="btn" data-action="decrementHours"><span class="' + picker.options.icons.down + '"></span></a></td>' +
1169
+ '<td class="separator"></td>' +
1170
+ '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' +
1171
+ (picker.options.useSeconds ?
1172
+ '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') +
1173
+ (picker.use24hours ? '' : '<td class="separator"></td>') +
1174
+ '</tr>' +
1175
+ '</table>' +
1176
+ '</div>' +
1177
+ '<div class="timepicker-hours" data-action="selectHour">' +
1178
+ '<table class="table-condensed"></table>' +
1179
+ '</div>' +
1180
+ '<div class="timepicker-minutes" data-action="selectMinute">' +
1181
+ '<table class="table-condensed"></table>' +
1182
+ '</div>' +
1183
+ (picker.options.useSeconds ?
1184
+ '<div class="timepicker-seconds" data-action="selectSecond"><table class="table-condensed"></table></div>' : '')
1185
+ );
1186
+ };
1187
+
1188
+ picker.destroy = function () {
1189
+ detachDatePickerEvents();
1190
+ detachDatePickerGlobalEvents();
1191
+ picker.widget.remove();
1192
+ picker.element.removeData('DateTimePicker');
1193
+ if (picker.component) {
1194
+ picker.component.removeData('DateTimePicker');
1195
+ }
1196
+ };
1197
+
1198
+ picker.show = function (e) {
1199
+ if (picker.options.useCurrent) {
1200
+ if (getPickerInput().val() === '') {
1201
+ if (picker.options.minuteStepping !== 1) {
1202
+ var mDate = moment(),
1203
+ rInterval = picker.options.minuteStepping;
1204
+ mDate.minutes((Math.round(mDate.minutes() / rInterval) * rInterval) % 60).seconds(0);
1205
+ picker.setValue(mDate.format(picker.format));
1206
+ } else {
1207
+ picker.setValue(moment().format(picker.format));
1208
+ }
1209
+ notifyChange('', e.type);
1210
+ }
1211
+ }
1212
+ // if this is a click event on the input field and picker is already open don't hide it
1213
+ if (e && e.type === 'click' && picker.isInput && picker.widget.hasClass('picker-open')) {
1214
+ return;
1215
+ }
1216
+ if (picker.widget.hasClass('picker-open')) {
1217
+ picker.widget.hide();
1218
+ picker.widget.removeClass('picker-open');
1219
+ }
1220
+ else {
1221
+ picker.widget.show();
1222
+ picker.widget.addClass('picker-open');
1223
+ }
1224
+ picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight();
1225
+ place();
1226
+ picker.element.trigger({
1227
+ type: 'dp.show',
1228
+ date: moment(picker.date)
1229
+ });
1230
+ attachDatePickerGlobalEvents();
1231
+ if (e) {
1232
+ stopEvent(e);
1233
+ }
1234
+ };
1235
+
1236
+ picker.disable = function () {
1237
+ var input = picker.element.find('input');
1238
+ if (input.prop('disabled')) {
1239
+ return;
1240
+ }
1241
+ input.prop('disabled', true);
1242
+ detachDatePickerEvents();
1243
+ };
1244
+
1245
+ picker.enable = function () {
1246
+ var input = picker.element.find('input');
1247
+ if (!input.prop('disabled')) {
1248
+ return;
1249
+ }
1250
+ input.prop('disabled', false);
1251
+ attachDatePickerEvents();
1252
+ };
1253
+
1254
+ picker.hide = function () {
1255
+ // Ignore event if in the middle of a picker transition
1256
+ var collapse = picker.widget.find('.collapse'), i, collapseData;
1257
+ for (i = 0; i < collapse.length; i++) {
1258
+ collapseData = collapse.eq(i).data('collapse');
1259
+ if (collapseData && collapseData.transitioning) {
1260
+ return;
1261
+ }
1262
+ }
1263
+ picker.widget.hide();
1264
+ picker.widget.removeClass('picker-open');
1265
+ picker.viewMode = picker.startViewMode;
1266
+ showMode();
1267
+ picker.element.trigger({
1268
+ type: 'dp.hide',
1269
+ date: moment(picker.date)
1270
+ });
1271
+ detachDatePickerGlobalEvents();
1272
+ };
1273
+
1274
+ picker.setValue = function (newDate) {
1275
+ moment.locale(picker.options.language);
1276
+ if (!newDate) {
1277
+ picker.unset = true;
1278
+ set();
1279
+ } else {
1280
+ picker.unset = false;
1281
+ }
1282
+ if (!moment.isMoment(newDate)) {
1283
+ newDate = (newDate instanceof Date) ? moment(newDate) : moment(newDate, picker.format, picker.options.useStrict);
1284
+ } else {
1285
+ newDate = newDate.locale(picker.options.language);
1286
+ }
1287
+ if (newDate.isValid()) {
1288
+ picker.date = newDate;
1289
+ set();
1290
+ picker.viewDate = moment({y: picker.date.year(), M: picker.date.month()});
1291
+ fillDate();
1292
+ fillTime();
1293
+ }
1294
+ else {
1295
+ notifyError(newDate);
1296
+ }
1297
+ };
1298
+
1299
+ picker.getDate = function () {
1300
+ if (picker.unset) {
1301
+ return null;
1302
+ }
1303
+ return moment(picker.date);
1304
+ };
1305
+
1306
+ picker.setDate = function (date) {
1307
+ var oldDate = moment(picker.date);
1308
+ if (!date) {
1309
+ picker.setValue(null);
1310
+ } else {
1311
+ picker.setValue(date);
1312
+ }
1313
+ notifyChange(oldDate, 'function');
1314
+ };
1315
+
1316
+ picker.setDisabledDates = function (dates) {
1317
+ picker.options.disabledDates = indexGivenDates(dates);
1318
+ if (picker.viewDate) {
1319
+ update();
1320
+ }
1321
+ };
1322
+
1323
+ picker.setEnabledDates = function (dates) {
1324
+ picker.options.enabledDates = indexGivenDates(dates);
1325
+ if (picker.viewDate) {
1326
+ update();
1327
+ }
1328
+ };
1329
+
1330
+ picker.setMaxDate = function (date) {
1331
+ if (date === undefined) {
1332
+ return;
1333
+ }
1334
+ if (moment.isMoment(date) || date instanceof Date) {
1335
+ picker.options.maxDate = moment(date);
1336
+ } else {
1337
+ picker.options.maxDate = moment(date, picker.format, picker.options.useStrict);
1338
+ }
1339
+ if (picker.viewDate) {
1340
+ update();
1341
+ }
1342
+ };
1343
+
1344
+ picker.setMinDate = function (date) {
1345
+ if (date === undefined) {
1346
+ return;
1347
+ }
1348
+ if (moment.isMoment(date) || date instanceof Date) {
1349
+ picker.options.minDate = moment(date);
1350
+ } else {
1351
+ picker.options.minDate = moment(date, picker.format, picker.options.useStrict);
1352
+ }
1353
+ if (picker.viewDate) {
1354
+ update();
1355
+ }
1356
+ };
1357
+
1358
+ init();
1359
+ };
1360
+
1361
+ $.fn.datetimepicker = function (options) {
1362
+ return this.each(function () {
1363
+ var $this = $(this),
1364
+ data = $this.data('DateTimePicker');
1365
+ if (!data) {
1366
+ $this.data('DateTimePicker', new DateTimePicker(this, options));
1367
+ }
1368
+ });
1369
+ };
1370
+
1371
+ $.fn.datetimepicker.defaults = {
1372
+ format: false,
1373
+ pickDate: true,
1374
+ pickTime: true,
1375
+ useMinutes: true,
1376
+ useSeconds: false,
1377
+ useCurrent: true,
1378
+ calendarWeeks: false,
1379
+ minuteStepping: 1,
1380
+ minDate: moment({y: 1900}),
1381
+ maxDate: moment().add(100, 'y'),
1382
+ showToday: true,
1383
+ collapse: true,
1384
+ language: moment.locale(),
1385
+ defaultDate: '',
1386
+ disabledDates: false,
1387
+ enabledDates: false,
1388
+ icons: {},
1389
+ useStrict: false,
1390
+ direction: 'auto',
1391
+ sideBySide: false,
1392
+ daysOfWeekDisabled: [],
1393
+ widgetParent: false
1394
+ };
1395
+ }));