rails_admin 3.0.0.beta2 → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (250) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/Rakefile +11 -0
  4. data/app/assets/javascripts/rails_admin.js +4 -4
  5. data/app/assets/stylesheets/rails_admin.scss +31 -0
  6. data/app/controllers/rails_admin/application_controller.rb +1 -1
  7. data/app/controllers/rails_admin/main_controller.rb +10 -18
  8. data/app/helpers/rails_admin/application_helper.rb +12 -13
  9. data/app/helpers/rails_admin/form_builder.rb +3 -3
  10. data/app/helpers/rails_admin/main_helper.rb +1 -1
  11. data/app/views/kaminari/ra-twitter-bootstrap/_gap.html.erb +2 -2
  12. data/app/views/kaminari/ra-twitter-bootstrap/_next_page.html.erb +4 -4
  13. data/app/views/kaminari/ra-twitter-bootstrap/_page.html.erb +4 -4
  14. data/app/views/kaminari/ra-twitter-bootstrap/_paginator.html.erb +12 -10
  15. data/app/views/kaminari/ra-twitter-bootstrap/_prev_page.html.erb +4 -4
  16. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_next_page.html.erb +4 -4
  17. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_paginator.html.erb +6 -4
  18. data/app/views/kaminari/ra-twitter-bootstrap/without_count/_prev_page.html.erb +4 -4
  19. data/app/views/layouts/rails_admin/_navigation.html.erb +12 -16
  20. data/app/views/layouts/rails_admin/_secondary_navigation.html.erb +8 -8
  21. data/app/views/layouts/rails_admin/_sidebar_navigation.html.erb +1 -5
  22. data/app/views/layouts/rails_admin/application.html.erb +4 -7
  23. data/app/views/layouts/rails_admin/{pjax.html.erb → content.html.erb} +7 -5
  24. data/app/views/layouts/rails_admin/modal.js.erb +1 -1
  25. data/app/views/rails_admin/main/_dashboard_history.html.erb +1 -1
  26. data/app/views/rails_admin/main/_delete_notice.html.erb +2 -2
  27. data/app/views/rails_admin/main/_form_boolean.html.erb +6 -8
  28. data/app/views/rails_admin/main/_form_colorpicker.html.erb +5 -1
  29. data/app/views/rails_admin/main/_form_datetime.html.erb +8 -7
  30. data/app/views/rails_admin/main/_form_enumeration.html.erb +5 -1
  31. data/app/views/rails_admin/main/_form_file_upload.html.erb +1 -1
  32. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +14 -14
  33. data/app/views/rails_admin/main/_form_filtering_select.html.erb +16 -21
  34. data/app/views/rails_admin/main/_form_multiple_file_upload.html.erb +1 -1
  35. data/app/views/rails_admin/main/_form_nested_many.html.erb +4 -4
  36. data/app/views/rails_admin/main/_form_nested_one.html.erb +4 -4
  37. data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +11 -6
  38. data/app/views/rails_admin/main/_submit_buttons.html.erb +8 -8
  39. data/app/views/rails_admin/main/bulk_delete.html.erb +1 -1
  40. data/app/views/rails_admin/main/dashboard.html.erb +4 -4
  41. data/app/views/rails_admin/main/delete.html.erb +1 -1
  42. data/app/views/rails_admin/main/edit.html.erb +1 -1
  43. data/app/views/rails_admin/main/export.html.erb +35 -32
  44. data/app/views/rails_admin/main/history.html.erb +16 -14
  45. data/app/views/rails_admin/main/index.html.erb +38 -35
  46. data/app/views/rails_admin/main/new.html.erb +1 -1
  47. data/config/locales/rails_admin.en.yml +0 -1
  48. data/lib/generators/rails_admin/install_generator.rb +0 -1
  49. data/lib/generators/rails_admin/templates/webpack.config.js +0 -3
  50. data/lib/rails_admin/adapters/active_record/object_extension.rb +1 -1
  51. data/lib/rails_admin/adapters/active_record/property.rb +1 -1
  52. data/lib/rails_admin/adapters/active_record.rb +7 -3
  53. data/lib/rails_admin/adapters/mongoid/property.rb +3 -3
  54. data/lib/rails_admin/adapters/mongoid.rb +2 -2
  55. data/lib/rails_admin/config/actions/base.rb +1 -6
  56. data/lib/rails_admin/config/actions/dashboard.rb +13 -9
  57. data/lib/rails_admin/config/actions/delete.rb +4 -0
  58. data/lib/rails_admin/config/actions/edit.rb +4 -0
  59. data/lib/rails_admin/config/actions/new.rb +5 -0
  60. data/lib/rails_admin/config/actions/show_in_app.rb +0 -4
  61. data/lib/rails_admin/config/fields/association.rb +6 -1
  62. data/lib/rails_admin/config/fields/base.rb +1 -1
  63. data/lib/rails_admin/config/fields/types/action_text.rb +1 -1
  64. data/lib/rails_admin/config/fields/types/date.rb +7 -0
  65. data/lib/rails_admin/config/fields/types/datetime.rb +9 -4
  66. data/lib/rails_admin/config/fields/types/has_many_association.rb +4 -0
  67. data/lib/rails_admin/config/fields/types/has_one_association.rb +4 -0
  68. data/lib/rails_admin/config/fields/types/time.rb +9 -0
  69. data/lib/rails_admin/config/has_fields.rb +4 -0
  70. data/lib/rails_admin/config/model.rb +8 -0
  71. data/lib/rails_admin/config/sections/list.rb +4 -4
  72. data/lib/rails_admin/config.rb +4 -1
  73. data/lib/rails_admin/engine.rb +2 -5
  74. data/lib/rails_admin/support/datetime.rb +50 -53
  75. data/lib/rails_admin/support/esmodule_preprocessor.rb +2 -1
  76. data/lib/rails_admin/version.rb +1 -1
  77. data/package.json +7 -5
  78. data/src/rails_admin/base.js +3 -6
  79. data/src/rails_admin/filter-box.js +36 -37
  80. data/src/rails_admin/filtering-select.js +3 -6
  81. data/src/rails_admin/i18n.js +0 -3
  82. data/src/rails_admin/nested-form-hooks.js +16 -8
  83. data/src/rails_admin/remote-form.js +18 -15
  84. data/src/rails_admin/styles/base/theming.scss +80 -155
  85. data/src/rails_admin/styles/base/variables.scss +2 -0
  86. data/src/rails_admin/styles/base.scss +8 -45
  87. data/src/rails_admin/styles/filtering-multiselect.scss +2 -2
  88. data/src/rails_admin/styles/filtering-select.scss +1 -1
  89. data/src/rails_admin/styles/widgets.scss +1 -10
  90. data/src/rails_admin/ui.js +4 -54
  91. data/src/rails_admin/widgets.js +38 -48
  92. data/vendor/assets/javascripts/rails_admin/bootstrap.js +5046 -0
  93. data/vendor/assets/javascripts/rails_admin/flatpickr-with-locales.js +10683 -0
  94. data/vendor/assets/javascripts/rails_admin/popper.js +1974 -0
  95. data/vendor/assets/stylesheets/rails_admin/bootstrap/_accordion.scss +118 -0
  96. data/vendor/assets/stylesheets/rails_admin/bootstrap/_alert.scss +57 -0
  97. data/vendor/assets/stylesheets/rails_admin/bootstrap/_badge.scss +29 -0
  98. data/vendor/assets/stylesheets/rails_admin/bootstrap/_breadcrumb.scss +28 -0
  99. data/vendor/assets/stylesheets/rails_admin/bootstrap/_button-group.scss +139 -0
  100. data/vendor/assets/stylesheets/rails_admin/bootstrap/_buttons.scss +64 -110
  101. data/vendor/assets/stylesheets/rails_admin/bootstrap/_card.scss +216 -0
  102. data/vendor/assets/stylesheets/rails_admin/bootstrap/_carousel.scss +162 -176
  103. data/vendor/assets/stylesheets/rails_admin/bootstrap/_close.scss +31 -26
  104. data/vendor/assets/stylesheets/rails_admin/bootstrap/_containers.scss +41 -0
  105. data/vendor/assets/stylesheets/rails_admin/bootstrap/_dropdown.scss +240 -0
  106. data/vendor/assets/stylesheets/rails_admin/bootstrap/_forms.scss +9 -538
  107. data/vendor/assets/stylesheets/rails_admin/bootstrap/_functions.scss +302 -0
  108. data/vendor/assets/stylesheets/rails_admin/bootstrap/_grid.scss +18 -69
  109. data/vendor/assets/stylesheets/rails_admin/bootstrap/_helpers.scss +9 -0
  110. data/vendor/assets/stylesheets/rails_admin/bootstrap/_images.scss +42 -0
  111. data/vendor/assets/stylesheets/rails_admin/bootstrap/_list-group.scss +127 -84
  112. data/vendor/assets/stylesheets/rails_admin/bootstrap/_mixins.scss +26 -22
  113. data/vendor/assets/stylesheets/rails_admin/bootstrap/_modal.scss +209 -0
  114. data/vendor/assets/stylesheets/rails_admin/bootstrap/_nav.scss +139 -0
  115. data/vendor/assets/stylesheets/rails_admin/bootstrap/_navbar.scss +218 -542
  116. data/vendor/assets/stylesheets/rails_admin/bootstrap/_offcanvas.scss +83 -0
  117. data/vendor/assets/stylesheets/rails_admin/bootstrap/_pagination.scss +46 -70
  118. data/vendor/assets/stylesheets/rails_admin/bootstrap/_placeholders.scss +51 -0
  119. data/vendor/assets/stylesheets/rails_admin/bootstrap/_popover.scss +158 -0
  120. data/vendor/assets/stylesheets/rails_admin/bootstrap/_progress.scss +48 -0
  121. data/vendor/assets/stylesheets/rails_admin/bootstrap/_reboot.scss +625 -0
  122. data/vendor/assets/stylesheets/rails_admin/bootstrap/_root.scss +54 -0
  123. data/vendor/assets/stylesheets/rails_admin/bootstrap/_spinners.scss +69 -0
  124. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tables.scss +100 -178
  125. data/vendor/assets/stylesheets/rails_admin/bootstrap/_toasts.scss +51 -0
  126. data/vendor/assets/stylesheets/rails_admin/bootstrap/_tooltip.scss +97 -77
  127. data/vendor/assets/stylesheets/rails_admin/bootstrap/_transitions.scss +27 -0
  128. data/vendor/assets/stylesheets/rails_admin/bootstrap/_type.scss +54 -254
  129. data/vendor/assets/stylesheets/rails_admin/bootstrap/_utilities.scss +628 -55
  130. data/vendor/assets/stylesheets/rails_admin/bootstrap/_variables.scss +1572 -781
  131. data/vendor/assets/stylesheets/rails_admin/bootstrap/bootstrap.scss +38 -35
  132. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_floating-labels.scss +63 -0
  133. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-check.scss +152 -0
  134. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-control.scss +219 -0
  135. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-range.scss +91 -0
  136. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-select.scss +72 -0
  137. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_form-text.scss +11 -0
  138. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_input-group.scss +121 -0
  139. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_labels.scss +36 -0
  140. data/vendor/assets/stylesheets/rails_admin/bootstrap/forms/_validation.scss +12 -0
  141. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_clearfix.scss +3 -0
  142. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_colored-links.scss +12 -0
  143. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_position.scss +30 -0
  144. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_ratio.scss +26 -0
  145. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stacks.scss +15 -0
  146. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_stretched-link.scss +15 -0
  147. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_text-truncation.scss +7 -0
  148. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_visually-hidden.scss +8 -0
  149. data/vendor/assets/stylesheets/rails_admin/bootstrap/helpers/_vr.scss +8 -0
  150. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_alert.scss +11 -0
  151. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_backdrop.scss +14 -0
  152. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_border-radius.scss +72 -12
  153. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_box-shadow.scss +18 -0
  154. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_breakpoints.scss +127 -0
  155. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_buttons.scss +113 -30
  156. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_caret.scss +64 -0
  157. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_clearfix.scss +5 -18
  158. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_color-scheme.scss +7 -0
  159. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_container.scss +9 -0
  160. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_deprecate.scss +10 -0
  161. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_forms.scss +130 -70
  162. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_gradients.scss +27 -38
  163. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_grid.scss +127 -98
  164. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_image.scss +6 -24
  165. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_list-group.scss +13 -20
  166. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_lists.scss +7 -0
  167. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_pagination.scss +24 -16
  168. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_reset-text.scss +17 -0
  169. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_resize.scss +1 -1
  170. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_table-variants.scss +21 -0
  171. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/{_text-overflow.scss → _text-truncate.scss} +2 -2
  172. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_transition.scss +26 -0
  173. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_utilities.scss +89 -0
  174. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_visually-hidden.scss +29 -0
  175. data/vendor/assets/stylesheets/rails_admin/bootstrap/utilities/_api.scss +47 -0
  176. data/vendor/assets/stylesheets/rails_admin/bootstrap/vendor/_rfs.scss +354 -0
  177. data/vendor/assets/stylesheets/rails_admin/flatpickr.css +791 -0
  178. metadata +80 -91
  179. data/app/assets/stylesheets/rails_admin.scss.erb +0 -76
  180. data/lib/generators/rails_admin/templates/environment.js +0 -6
  181. data/src/rails_admin/styles/themes/cerulean/mixins.scss +0 -0
  182. data/src/rails_admin/styles/themes/cerulean/theming.scss +0 -135
  183. data/src/rails_admin/styles/themes/cerulean/variables.scss +0 -830
  184. data/src/rails_admin/styles/themes/default/mixins.scss +0 -8
  185. data/src/rails_admin/styles/themes/default/theming.scss +0 -11
  186. data/src/rails_admin/styles/themes/default/variables.scss +0 -12
  187. data/src/rails_admin/vendor/jquery.pjax.js +0 -899
  188. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-affix.js +0 -164
  189. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-alert.js +0 -95
  190. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-button.js +0 -125
  191. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-carousel.js +0 -246
  192. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-collapse.js +0 -212
  193. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-dropdown.js +0 -165
  194. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-modal.js +0 -358
  195. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-popover.js +0 -123
  196. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-scrollspy.js +0 -172
  197. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-tab.js +0 -155
  198. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-tooltip.js +0 -677
  199. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-transition.js +0 -59
  200. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap-typeahead.js +0 -1782
  201. data/vendor/assets/javascripts/rails_admin/bootstrap/bootstrap.js +0 -13
  202. data/vendor/assets/javascripts/rails_admin/bootstrap-datetimepicker.js +0 -2611
  203. data/vendor/assets/javascripts/rails_admin/jquery.pjax.js +0 -898
  204. data/vendor/assets/javascripts/rails_admin/moment-with-locales.js +0 -18085
  205. data/vendor/assets/stylesheets/rails_admin/_bootstrap-datetimepicker.scss +0 -343
  206. data/vendor/assets/stylesheets/rails_admin/bootstrap/_alerts.scss +0 -68
  207. data/vendor/assets/stylesheets/rails_admin/bootstrap/_badges.scss +0 -57
  208. data/vendor/assets/stylesheets/rails_admin/bootstrap/_breadcrumbs.scss +0 -26
  209. data/vendor/assets/stylesheets/rails_admin/bootstrap/_button-groups.scss +0 -240
  210. data/vendor/assets/stylesheets/rails_admin/bootstrap/_code.scss +0 -68
  211. data/vendor/assets/stylesheets/rails_admin/bootstrap/_component-animations.scss +0 -35
  212. data/vendor/assets/stylesheets/rails_admin/bootstrap/_dropdowns.scss +0 -215
  213. data/vendor/assets/stylesheets/rails_admin/bootstrap/_glyphicons.scss +0 -237
  214. data/vendor/assets/stylesheets/rails_admin/bootstrap/_input-groups.scss +0 -166
  215. data/vendor/assets/stylesheets/rails_admin/bootstrap/_jumbotron.scss +0 -48
  216. data/vendor/assets/stylesheets/rails_admin/bootstrap/_labels.scss +0 -66
  217. data/vendor/assets/stylesheets/rails_admin/bootstrap/_media.scss +0 -56
  218. data/vendor/assets/stylesheets/rails_admin/bootstrap/_modals.scss +0 -150
  219. data/vendor/assets/stylesheets/rails_admin/bootstrap/_navs.scss +0 -242
  220. data/vendor/assets/stylesheets/rails_admin/bootstrap/_normalize.scss +0 -425
  221. data/vendor/assets/stylesheets/rails_admin/bootstrap/_pager.scss +0 -55
  222. data/vendor/assets/stylesheets/rails_admin/bootstrap/_panels.scss +0 -243
  223. data/vendor/assets/stylesheets/rails_admin/bootstrap/_popovers.scss +0 -133
  224. data/vendor/assets/stylesheets/rails_admin/bootstrap/_print.scss +0 -101
  225. data/vendor/assets/stylesheets/rails_admin/bootstrap/_progress-bars.scss +0 -105
  226. data/vendor/assets/stylesheets/rails_admin/bootstrap/_responsive-embed.scss +0 -34
  227. data/vendor/assets/stylesheets/rails_admin/bootstrap/_responsive-utilities.scss +0 -174
  228. data/vendor/assets/stylesheets/rails_admin/bootstrap/_scaffolding.scss +0 -150
  229. data/vendor/assets/stylesheets/rails_admin/bootstrap/_theme.scss +0 -258
  230. data/vendor/assets/stylesheets/rails_admin/bootstrap/_thumbnails.scss +0 -38
  231. data/vendor/assets/stylesheets/rails_admin/bootstrap/_wells.scss +0 -29
  232. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_alerts.scss +0 -14
  233. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_background-variant.scss +0 -11
  234. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_center-block.scss +0 -7
  235. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_grid-framework.scss +0 -81
  236. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_hide-text.scss +0 -21
  237. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_labels.scss +0 -12
  238. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_nav-divider.scss +0 -10
  239. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_nav-vertical-align.scss +0 -9
  240. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_opacity.scss +0 -8
  241. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_panels.scss +0 -24
  242. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_progress-bar.scss +0 -10
  243. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_reset-filter.scss +0 -8
  244. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_responsive-visibility.scss +0 -21
  245. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_size.scss +0 -10
  246. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_tab-focus.scss +0 -9
  247. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_table-row.scss +0 -28
  248. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_text-emphasis.scss +0 -11
  249. data/vendor/assets/stylesheets/rails_admin/bootstrap/mixins/_vendor-prefixes.scss +0 -219
  250. data/vendor/assets/stylesheets/rails_admin/bootstrap-datetimepicker-build.scss +0 -16
@@ -1,2611 +0,0 @@
1
- /*!
2
- * Bootstrap Datetime Picker v4.17.49
3
- * Copyright 2015-2020 Jonathan Peterson
4
- * Licensed under MIT (https://github.com/Eonasdan/bootstrap-datetimepicker/blob/master/LICENSE)
5
- */
6
- /*global define:false */
7
- /*global exports:false */
8
- /*global require:false */
9
- /*global jQuery:false */
10
- /*global moment:false */
11
- (function (factory) {
12
- 'use strict';
13
- if (typeof define === 'function' && define.amd) {
14
- // AMD is used - Register as an anonymous module.
15
- define(['jquery', 'moment'], factory);
16
- } else if (typeof exports === 'object') {
17
- module.exports = factory(require('jquery'), require('moment'));
18
- } else {
19
- // Neither AMD nor CommonJS used. Use global variables.
20
- if (typeof jQuery === 'undefined') {
21
- throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
22
- }
23
- if (typeof moment === 'undefined') {
24
- throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
25
- }
26
- factory(jQuery, moment);
27
- }
28
- }(function ($, moment) {
29
- 'use strict';
30
- if (!moment) {
31
- throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
32
- }
33
-
34
- var dateTimePicker = function (element, options) {
35
- var picker = {},
36
- date,
37
- viewDate,
38
- unset = true,
39
- input,
40
- component = false,
41
- widget = false,
42
- use24Hours,
43
- minViewModeNumber = 0,
44
- actualFormat,
45
- parseFormats,
46
- currentViewMode,
47
- datePickerModes = [
48
- {
49
- clsName: 'days',
50
- navFnc: 'M',
51
- navStep: 1
52
- },
53
- {
54
- clsName: 'months',
55
- navFnc: 'y',
56
- navStep: 1
57
- },
58
- {
59
- clsName: 'years',
60
- navFnc: 'y',
61
- navStep: 10
62
- },
63
- {
64
- clsName: 'decades',
65
- navFnc: 'y',
66
- navStep: 100
67
- }
68
- ],
69
- viewModes = ['days', 'months', 'years', 'decades'],
70
- verticalModes = ['top', 'bottom', 'auto'],
71
- horizontalModes = ['left', 'right', 'auto'],
72
- toolbarPlacements = ['default', 'top', 'bottom'],
73
- keyMap = {
74
- 'up': 38,
75
- 38: 'up',
76
- 'down': 40,
77
- 40: 'down',
78
- 'left': 37,
79
- 37: 'left',
80
- 'right': 39,
81
- 39: 'right',
82
- 'tab': 9,
83
- 9: 'tab',
84
- 'escape': 27,
85
- 27: 'escape',
86
- 'enter': 13,
87
- 13: 'enter',
88
- 'pageUp': 33,
89
- 33: 'pageUp',
90
- 'pageDown': 34,
91
- 34: 'pageDown',
92
- 'shift': 16,
93
- 16: 'shift',
94
- 'control': 17,
95
- 17: 'control',
96
- 'space': 32,
97
- 32: 'space',
98
- 't': 84,
99
- 84: 't',
100
- 'delete': 46,
101
- 46: 'delete'
102
- },
103
- keyState = {},
104
-
105
- /********************************************************************************
106
- *
107
- * Private functions
108
- *
109
- ********************************************************************************/
110
-
111
- hasTimeZone = function () {
112
- return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '';
113
- },
114
-
115
- getMoment = function (d) {
116
- var returnMoment;
117
-
118
- if (d === undefined || d === null) {
119
- returnMoment = moment(); //TODO should this use format? and locale?
120
- } else if (moment.isDate(d) || moment.isMoment(d)) {
121
- // If the date that is passed in is already a Date() or moment() object,
122
- // pass it directly to moment.
123
- returnMoment = moment(d);
124
- } else if (hasTimeZone()) { // There is a string to parse and a default time zone
125
- // parse with the tz function which takes a default time zone if it is not in the format string
126
- returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone);
127
- } else {
128
- returnMoment = moment(d, parseFormats, options.useStrict);
129
- }
130
-
131
- if (hasTimeZone()) {
132
- returnMoment.tz(options.timeZone);
133
- }
134
-
135
- return returnMoment;
136
- },
137
-
138
- isEnabled = function (granularity) {
139
- if (typeof granularity !== 'string' || granularity.length > 1) {
140
- throw new TypeError('isEnabled expects a single character string parameter');
141
- }
142
- switch (granularity) {
143
- case 'y':
144
- return actualFormat.indexOf('Y') !== -1;
145
- case 'M':
146
- return actualFormat.indexOf('M') !== -1;
147
- case 'd':
148
- return actualFormat.toLowerCase().indexOf('d') !== -1;
149
- case 'h':
150
- case 'H':
151
- return actualFormat.toLowerCase().indexOf('h') !== -1;
152
- case 'm':
153
- return actualFormat.indexOf('m') !== -1;
154
- case 's':
155
- return actualFormat.indexOf('s') !== -1;
156
- default:
157
- return false;
158
- }
159
- },
160
-
161
- hasTime = function () {
162
- return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
163
- },
164
-
165
- hasDate = function () {
166
- return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
167
- },
168
-
169
- getDatePickerTemplate = function () {
170
- var headTemplate = $('<thead>')
171
- .append($('<tr>')
172
- .append($('<th>').addClass('prev').attr('data-action', 'previous')
173
- .append($('<span>').addClass(options.icons.previous))
174
- )
175
- .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
176
- .append($('<th>').addClass('next').attr('data-action', 'next')
177
- .append($('<span>').addClass(options.icons.next))
178
- )
179
- ),
180
- contTemplate = $('<tbody>')
181
- .append($('<tr>')
182
- .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
183
- );
184
-
185
- return [
186
- $('<div>').addClass('datepicker-days')
187
- .append($('<table>').addClass('table-condensed')
188
- .append(headTemplate)
189
- .append($('<tbody>'))
190
- ),
191
- $('<div>').addClass('datepicker-months')
192
- .append($('<table>').addClass('table-condensed')
193
- .append(headTemplate.clone())
194
- .append(contTemplate.clone())
195
- ),
196
- $('<div>').addClass('datepicker-years')
197
- .append($('<table>').addClass('table-condensed')
198
- .append(headTemplate.clone())
199
- .append(contTemplate.clone())
200
- ),
201
- $('<div>').addClass('datepicker-decades')
202
- .append($('<table>').addClass('table-condensed')
203
- .append(headTemplate.clone())
204
- .append(contTemplate.clone())
205
- )
206
- ];
207
- },
208
-
209
- getTimePickerMainTemplate = function () {
210
- var topRow = $('<tr>'),
211
- middleRow = $('<tr>'),
212
- bottomRow = $('<tr>');
213
-
214
- if (isEnabled('h')) {
215
- topRow.append($('<td>')
216
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('<span>').addClass(options.icons.up))));
217
- middleRow.append($('<td>')
218
- .append($('<span>').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours')));
219
- bottomRow.append($('<td>')
220
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('<span>').addClass(options.icons.down))));
221
- }
222
- if (isEnabled('m')) {
223
- if (isEnabled('h')) {
224
- topRow.append($('<td>').addClass('separator'));
225
- middleRow.append($('<td>').addClass('separator').html(':'));
226
- bottomRow.append($('<td>').addClass('separator'));
227
- }
228
- topRow.append($('<td>')
229
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes')
230
- .append($('<span>').addClass(options.icons.up))));
231
- middleRow.append($('<td>')
232
- .append($('<span>').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes')));
233
- bottomRow.append($('<td>')
234
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes')
235
- .append($('<span>').addClass(options.icons.down))));
236
- }
237
- if (isEnabled('s')) {
238
- if (isEnabled('m')) {
239
- topRow.append($('<td>').addClass('separator'));
240
- middleRow.append($('<td>').addClass('separator').html(':'));
241
- bottomRow.append($('<td>').addClass('separator'));
242
- }
243
- topRow.append($('<td>')
244
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds')
245
- .append($('<span>').addClass(options.icons.up))));
246
- middleRow.append($('<td>')
247
- .append($('<span>').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds')));
248
- bottomRow.append($('<td>')
249
- .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds')
250
- .append($('<span>').addClass(options.icons.down))));
251
- }
252
-
253
- if (!use24Hours) {
254
- topRow.append($('<td>').addClass('separator'));
255
- middleRow.append($('<td>')
256
- .append($('<button>').addClass('btn btn-primary').attr({ 'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod })));
257
- bottomRow.append($('<td>').addClass('separator'));
258
- }
259
-
260
- return $('<div>').addClass('timepicker-picker')
261
- .append($('<table>').addClass('table-condensed')
262
- .append([topRow, middleRow, bottomRow]));
263
- },
264
-
265
- getTimePickerTemplate = function () {
266
- var hoursView = $('<div>').addClass('timepicker-hours')
267
- .append($('<table>').addClass('table-condensed')),
268
- minutesView = $('<div>').addClass('timepicker-minutes')
269
- .append($('<table>').addClass('table-condensed')),
270
- secondsView = $('<div>').addClass('timepicker-seconds')
271
- .append($('<table>').addClass('table-condensed')),
272
- ret = [getTimePickerMainTemplate()];
273
-
274
- if (isEnabled('h')) {
275
- ret.push(hoursView);
276
- }
277
- if (isEnabled('m')) {
278
- ret.push(minutesView);
279
- }
280
- if (isEnabled('s')) {
281
- ret.push(secondsView);
282
- }
283
-
284
- return ret;
285
- },
286
-
287
- getToolbar = function () {
288
- var row = [];
289
- if (options.showTodayButton) {
290
- row.push($('<td>').append($('<a>').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('<span>').addClass(options.icons.today))));
291
- }
292
- if (!options.sideBySide && hasDate() && hasTime()) {
293
- row.push($('<td>').append($('<a>').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('<span>').addClass(options.icons.time))));
294
- }
295
- if (options.showClear) {
296
- row.push($('<td>').append($('<a>').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('<span>').addClass(options.icons.clear))));
297
- }
298
- if (options.showClose) {
299
- row.push($('<td>').append($('<a>').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('<span>').addClass(options.icons.close))));
300
- }
301
- return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
302
- },
303
-
304
- getTemplate = function () {
305
- var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
306
- dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
307
- timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
308
- content = $('<ul>').addClass('list-unstyled'),
309
- toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
310
-
311
- if (options.inline) {
312
- template.removeClass('dropdown-menu');
313
- }
314
-
315
- if (use24Hours) {
316
- template.addClass('usetwentyfour');
317
- }
318
-
319
- if (isEnabled('s') && !use24Hours) {
320
- template.addClass('wider');
321
- }
322
-
323
- if (options.sideBySide && hasDate() && hasTime()) {
324
- template.addClass('timepicker-sbs');
325
- if (options.toolbarPlacement === 'top') {
326
- template.append(toolbar);
327
- }
328
- template.append(
329
- $('<div>').addClass('row')
330
- .append(dateView.addClass('col-md-6'))
331
- .append(timeView.addClass('col-md-6'))
332
- );
333
- if (options.toolbarPlacement === 'bottom') {
334
- template.append(toolbar);
335
- }
336
- return template;
337
- }
338
-
339
- if (options.toolbarPlacement === 'top') {
340
- content.append(toolbar);
341
- }
342
- if (hasDate()) {
343
- content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView));
344
- }
345
- if (options.toolbarPlacement === 'default') {
346
- content.append(toolbar);
347
- }
348
- if (hasTime()) {
349
- content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
350
- }
351
- if (options.toolbarPlacement === 'bottom') {
352
- content.append(toolbar);
353
- }
354
- return template.append(content);
355
- },
356
-
357
- dataToOptions = function () {
358
- var eData,
359
- dataOptions = {};
360
-
361
- if (element.is('input') || options.inline) {
362
- eData = element.data();
363
- } else {
364
- eData = element.find('input').data();
365
- }
366
-
367
- if (eData.dateOptions && eData.dateOptions instanceof Object) {
368
- dataOptions = $.extend(true, dataOptions, eData.dateOptions);
369
- }
370
-
371
- $.each(options, function (key) {
372
- var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
373
- if (eData[attributeName] !== undefined) {
374
- dataOptions[key] = eData[attributeName];
375
- }
376
- });
377
- return dataOptions;
378
- },
379
-
380
- place = function () {
381
- var position = (component || element).position(),
382
- offset = (component || element).offset(),
383
- vertical = options.widgetPositioning.vertical,
384
- horizontal = options.widgetPositioning.horizontal,
385
- parent;
386
-
387
- if (options.widgetParent) {
388
- parent = options.widgetParent.append(widget);
389
- } else if (element.is('input')) {
390
- parent = element.after(widget).parent();
391
- } else if (options.inline) {
392
- parent = element.append(widget);
393
- return;
394
- } else {
395
- parent = element;
396
- element.children().first().after(widget);
397
- }
398
-
399
- // Top and bottom logic
400
- if (vertical === 'auto') {
401
- if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
402
- widget.height() + element.outerHeight() < offset.top) {
403
- vertical = 'top';
404
- } else {
405
- vertical = 'bottom';
406
- }
407
- }
408
-
409
- // Left and right logic
410
- if (horizontal === 'auto') {
411
- if (parent.width() < offset.left + widget.outerWidth() / 2 &&
412
- offset.left + widget.outerWidth() > $(window).width()) {
413
- horizontal = 'right';
414
- } else {
415
- horizontal = 'left';
416
- }
417
- }
418
-
419
- if (vertical === 'top') {
420
- widget.addClass('top').removeClass('bottom');
421
- } else {
422
- widget.addClass('bottom').removeClass('top');
423
- }
424
-
425
- if (horizontal === 'right') {
426
- widget.addClass('pull-right');
427
- } else {
428
- widget.removeClass('pull-right');
429
- }
430
-
431
- // find the first parent element that has a non-static css positioning
432
- if (parent.css('position') === 'static') {
433
- parent = parent.parents().filter(function () {
434
- return $(this).css('position') !== 'static';
435
- }).first();
436
- }
437
-
438
- if (parent.length === 0) {
439
- throw new Error('datetimepicker component should be placed within a non-static positioned container');
440
- }
441
-
442
- widget.css({
443
- top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
444
- bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto',
445
- left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
446
- right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
447
- });
448
- },
449
-
450
- notifyEvent = function (e) {
451
- if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
452
- return;
453
- }
454
- element.trigger(e);
455
- },
456
-
457
- viewUpdate = function (e) {
458
- if (e === 'y') {
459
- e = 'YYYY';
460
- }
461
- notifyEvent({
462
- type: 'dp.update',
463
- change: e,
464
- viewDate: viewDate.clone()
465
- });
466
- },
467
-
468
- showMode = function (dir) {
469
- if (!widget) {
470
- return;
471
- }
472
- if (dir) {
473
- currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
474
- }
475
- widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
476
- },
477
-
478
- fillDow = function () {
479
- var row = $('<tr>'),
480
- currentDate = viewDate.clone().startOf('w').startOf('d');
481
-
482
- if (options.calendarWeeks === true) {
483
- row.append($('<th>').addClass('cw').text('#'));
484
- }
485
-
486
- while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
487
- row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
488
- currentDate.add(1, 'd');
489
- }
490
- widget.find('.datepicker-days thead').append(row);
491
- },
492
-
493
- isInDisabledDates = function (testDate) {
494
- return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
495
- },
496
-
497
- isInEnabledDates = function (testDate) {
498
- return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
499
- },
500
-
501
- isInDisabledHours = function (testDate) {
502
- return options.disabledHours[testDate.format('H')] === true;
503
- },
504
-
505
- isInEnabledHours = function (testDate) {
506
- return options.enabledHours[testDate.format('H')] === true;
507
- },
508
-
509
- isValid = function (targetMoment, granularity) {
510
- if (!targetMoment.isValid()) {
511
- return false;
512
- }
513
- if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
514
- return false;
515
- }
516
- if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
517
- return false;
518
- }
519
- if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
520
- return false;
521
- }
522
- if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
523
- return false;
524
- }
525
- if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
526
- return false;
527
- }
528
- if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
529
- return false;
530
- }
531
- if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
532
- return false;
533
- }
534
- if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
535
- var found = false;
536
- $.each(options.disabledTimeIntervals, function () {
537
- if (targetMoment.isBetween(this[0], this[1])) {
538
- found = true;
539
- return false;
540
- }
541
- });
542
- if (found) {
543
- return false;
544
- }
545
- }
546
- return true;
547
- },
548
-
549
- fillMonths = function () {
550
- var spans = [],
551
- monthsShort = viewDate.clone().startOf('y').startOf('d');
552
- while (monthsShort.isSame(viewDate, 'y')) {
553
- spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
554
- monthsShort.add(1, 'M');
555
- }
556
- widget.find('.datepicker-months td').empty().append(spans);
557
- },
558
-
559
- updateMonths = function () {
560
- var monthsView = widget.find('.datepicker-months'),
561
- monthsViewHeader = monthsView.find('th'),
562
- months = monthsView.find('tbody').find('span');
563
-
564
- monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
565
- monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
566
- monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);
567
-
568
- monthsView.find('.disabled').removeClass('disabled');
569
-
570
- if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
571
- monthsViewHeader.eq(0).addClass('disabled');
572
- }
573
-
574
- monthsViewHeader.eq(1).text(viewDate.year());
575
-
576
- if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
577
- monthsViewHeader.eq(2).addClass('disabled');
578
- }
579
-
580
- months.removeClass('active');
581
- if (date.isSame(viewDate, 'y') && !unset) {
582
- months.eq(date.month()).addClass('active');
583
- }
584
-
585
- months.each(function (index) {
586
- if (!isValid(viewDate.clone().month(index), 'M')) {
587
- $(this).addClass('disabled');
588
- }
589
- });
590
- },
591
-
592
- updateYears = function () {
593
- var yearsView = widget.find('.datepicker-years'),
594
- yearsViewHeader = yearsView.find('th'),
595
- startYear = viewDate.clone().subtract(5, 'y'),
596
- endYear = viewDate.clone().add(6, 'y'),
597
- html = '';
598
-
599
- yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade);
600
- yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
601
- yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade);
602
-
603
- yearsView.find('.disabled').removeClass('disabled');
604
-
605
- if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
606
- yearsViewHeader.eq(0).addClass('disabled');
607
- }
608
-
609
- yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());
610
-
611
- if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
612
- yearsViewHeader.eq(2).addClass('disabled');
613
- }
614
-
615
- while (!startYear.isAfter(endYear, 'y')) {
616
- html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
617
- startYear.add(1, 'y');
618
- }
619
-
620
- yearsView.find('td').html(html);
621
- },
622
-
623
- updateDecades = function () {
624
- var decadesView = widget.find('.datepicker-decades'),
625
- decadesViewHeader = decadesView.find('th'),
626
- startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }),
627
- endDecade = startDecade.clone().add(100, 'y'),
628
- startedAt = startDecade.clone(),
629
- minDateDecade = false,
630
- maxDateDecade = false,
631
- endDecadeYear,
632
- html = '';
633
-
634
- decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
635
- decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
636
-
637
- decadesView.find('.disabled').removeClass('disabled');
638
-
639
- if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
640
- decadesViewHeader.eq(0).addClass('disabled');
641
- }
642
-
643
- decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
644
-
645
- if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
646
- decadesViewHeader.eq(2).addClass('disabled');
647
- }
648
-
649
- while (!startDecade.isAfter(endDecade, 'y')) {
650
- endDecadeYear = startDecade.year() + 12;
651
- minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear;
652
- maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear;
653
- html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') +
654
- (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
655
- startDecade.add(12, 'y');
656
- }
657
- html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
658
-
659
- decadesView.find('td').html(html);
660
- decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year()));
661
- },
662
-
663
- fillDate = function () {
664
- var daysView = widget.find('.datepicker-days'),
665
- daysViewHeader = daysView.find('th'),
666
- currentDate,
667
- html = [],
668
- row,
669
- clsNames = [],
670
- i;
671
-
672
- if (!hasDate()) {
673
- return;
674
- }
675
-
676
- daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
677
- daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
678
- daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);
679
-
680
- daysView.find('.disabled').removeClass('disabled');
681
- daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
682
-
683
- if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
684
- daysViewHeader.eq(0).addClass('disabled');
685
- }
686
- if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
687
- daysViewHeader.eq(2).addClass('disabled');
688
- }
689
-
690
- currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
691
-
692
- for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
693
- if (currentDate.weekday() === 0) {
694
- row = $('<tr>');
695
- if (options.calendarWeeks) {
696
- row.append('<td class="cw">' + currentDate.week() + '</td>');
697
- }
698
- html.push(row);
699
- }
700
- clsNames = ['day'];
701
- if (currentDate.isBefore(viewDate, 'M')) {
702
- clsNames.push('old');
703
- }
704
- if (currentDate.isAfter(viewDate, 'M')) {
705
- clsNames.push('new');
706
- }
707
- if (currentDate.isSame(date, 'd') && !unset) {
708
- clsNames.push('active');
709
- }
710
- if (!isValid(currentDate, 'd')) {
711
- clsNames.push('disabled');
712
- }
713
- if (currentDate.isSame(getMoment(), 'd')) {
714
- clsNames.push('today');
715
- }
716
- if (currentDate.day() === 0 || currentDate.day() === 6) {
717
- clsNames.push('weekend');
718
- }
719
- notifyEvent({
720
- type: 'dp.classify',
721
- date: currentDate,
722
- classNames: clsNames
723
- });
724
- row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="' + clsNames.join(' ') + '">' + currentDate.date() + '</td>');
725
- currentDate.add(1, 'd');
726
- }
727
-
728
- daysView.find('tbody').empty().append(html);
729
-
730
- updateMonths();
731
-
732
- updateYears();
733
-
734
- updateDecades();
735
- },
736
-
737
- fillHours = function () {
738
- var table = widget.find('.timepicker-hours table'),
739
- currentHour = viewDate.clone().startOf('d'),
740
- html = [],
741
- row = $('<tr>');
742
-
743
- if (viewDate.hour() > 11 && !use24Hours) {
744
- currentHour.hour(12);
745
- }
746
- while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
747
- if (currentHour.hour() % 4 === 0) {
748
- row = $('<tr>');
749
- html.push(row);
750
- }
751
- row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
752
- currentHour.add(1, 'h');
753
- }
754
- table.empty().append(html);
755
- },
756
-
757
- fillMinutes = function () {
758
- var table = widget.find('.timepicker-minutes table'),
759
- currentMinute = viewDate.clone().startOf('h'),
760
- html = [],
761
- row = $('<tr>'),
762
- step = options.stepping === 1 ? 5 : options.stepping;
763
-
764
- while (viewDate.isSame(currentMinute, 'h')) {
765
- if (currentMinute.minute() % (step * 4) === 0) {
766
- row = $('<tr>');
767
- html.push(row);
768
- }
769
- row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
770
- currentMinute.add(step, 'm');
771
- }
772
- table.empty().append(html);
773
- },
774
-
775
- fillSeconds = function () {
776
- var table = widget.find('.timepicker-seconds table'),
777
- currentSecond = viewDate.clone().startOf('m'),
778
- html = [],
779
- row = $('<tr>');
780
-
781
- while (viewDate.isSame(currentSecond, 'm')) {
782
- if (currentSecond.second() % 20 === 0) {
783
- row = $('<tr>');
784
- html.push(row);
785
- }
786
- row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
787
- currentSecond.add(5, 's');
788
- }
789
-
790
- table.empty().append(html);
791
- },
792
-
793
- fillTime = function () {
794
- var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
795
-
796
- if (!use24Hours) {
797
- toggle = widget.find('.timepicker [data-action=togglePeriod]');
798
- newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
799
-
800
- toggle.text(date.format('A'));
801
-
802
- if (isValid(newDate, 'h')) {
803
- toggle.removeClass('disabled');
804
- } else {
805
- toggle.addClass('disabled');
806
- }
807
- }
808
- timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
809
- timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
810
- timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
811
-
812
- fillHours();
813
- fillMinutes();
814
- fillSeconds();
815
- },
816
-
817
- update = function () {
818
- if (!widget) {
819
- return;
820
- }
821
- fillDate();
822
- fillTime();
823
- },
824
-
825
- setValue = function (targetMoment) {
826
- var oldDate = unset ? null : date;
827
-
828
- // case of calling setValue(null or false)
829
- if (!targetMoment) {
830
- unset = true;
831
- input.val('');
832
- element.data('date', '');
833
- notifyEvent({
834
- type: 'dp.change',
835
- date: false,
836
- oldDate: oldDate
837
- });
838
- update();
839
- return;
840
- }
841
-
842
- targetMoment = targetMoment.clone().locale(options.locale);
843
-
844
- if (hasTimeZone()) {
845
- targetMoment.tz(options.timeZone);
846
- }
847
-
848
- if (options.stepping !== 1) {
849
- targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0);
850
-
851
- while (options.minDate && targetMoment.isBefore(options.minDate)) {
852
- targetMoment.add(options.stepping, 'minutes');
853
- }
854
- }
855
-
856
- if (isValid(targetMoment)) {
857
- date = targetMoment;
858
- viewDate = date.clone();
859
- input.val(date.format(actualFormat));
860
- element.data('date', date.format(actualFormat));
861
- unset = false;
862
- update();
863
- notifyEvent({
864
- type: 'dp.change',
865
- date: date.clone(),
866
- oldDate: oldDate
867
- });
868
- } else {
869
- if (!options.keepInvalid) {
870
- input.val(unset ? '' : date.format(actualFormat));
871
- } else {
872
- notifyEvent({
873
- type: 'dp.change',
874
- date: targetMoment,
875
- oldDate: oldDate
876
- });
877
- }
878
- notifyEvent({
879
- type: 'dp.error',
880
- date: targetMoment,
881
- oldDate: oldDate
882
- });
883
- }
884
- },
885
-
886
- /**
887
- * Hides the widget. Possibly will emit dp.hide
888
- */
889
- hide = function () {
890
- var transitioning = false;
891
- if (!widget) {
892
- return picker;
893
- }
894
- // Ignore event if in the middle of a picker transition
895
- widget.find('.collapse').each(function () {
896
- var collapseData = $(this).data('collapse');
897
- if (collapseData && collapseData.transitioning) {
898
- transitioning = true;
899
- return false;
900
- }
901
- return true;
902
- });
903
- if (transitioning) {
904
- return picker;
905
- }
906
- if (component && component.hasClass('btn')) {
907
- component.toggleClass('active');
908
- }
909
- widget.hide();
910
-
911
- $(window).off('resize', place);
912
- widget.off('click', '[data-action]');
913
- widget.off('mousedown', false);
914
-
915
- widget.remove();
916
- widget = false;
917
-
918
- notifyEvent({
919
- type: 'dp.hide',
920
- date: date.clone()
921
- });
922
-
923
- input.blur();
924
-
925
- viewDate = date.clone();
926
-
927
- return picker;
928
- },
929
-
930
- clear = function () {
931
- setValue(null);
932
- },
933
-
934
- parseInputDate = function (inputDate) {
935
- if (options.parseInputDate === undefined) {
936
- if (!moment.isMoment(inputDate) || inputDate instanceof Date) {
937
- inputDate = getMoment(inputDate);
938
- }
939
- } else {
940
- inputDate = options.parseInputDate(inputDate);
941
- }
942
- //inputDate.locale(options.locale);
943
- return inputDate;
944
- },
945
-
946
- /********************************************************************************
947
- *
948
- * Widget UI interaction functions
949
- *
950
- ********************************************************************************/
951
- actions = {
952
- next: function () {
953
- var navFnc = datePickerModes[currentViewMode].navFnc;
954
- viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
955
- fillDate();
956
- viewUpdate(navFnc);
957
- },
958
-
959
- previous: function () {
960
- var navFnc = datePickerModes[currentViewMode].navFnc;
961
- viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
962
- fillDate();
963
- viewUpdate(navFnc);
964
- },
965
-
966
- pickerSwitch: function () {
967
- showMode(1);
968
- },
969
-
970
- selectMonth: function (e) {
971
- var month = $(e.target).closest('tbody').find('span').index($(e.target));
972
- viewDate.month(month);
973
- if (currentViewMode === minViewModeNumber) {
974
- setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
975
- if (!options.inline) {
976
- hide();
977
- }
978
- } else {
979
- showMode(-1);
980
- fillDate();
981
- }
982
- viewUpdate('M');
983
- },
984
-
985
- selectYear: function (e) {
986
- var year = parseInt($(e.target).text(), 10) || 0;
987
- viewDate.year(year);
988
- if (currentViewMode === minViewModeNumber) {
989
- setValue(date.clone().year(viewDate.year()));
990
- if (!options.inline) {
991
- hide();
992
- }
993
- } else {
994
- showMode(-1);
995
- fillDate();
996
- }
997
- viewUpdate('YYYY');
998
- },
999
-
1000
- selectDecade: function (e) {
1001
- var year = parseInt($(e.target).data('selection'), 10) || 0;
1002
- viewDate.year(year);
1003
- if (currentViewMode === minViewModeNumber) {
1004
- setValue(date.clone().year(viewDate.year()));
1005
- if (!options.inline) {
1006
- hide();
1007
- }
1008
- } else {
1009
- showMode(-1);
1010
- fillDate();
1011
- }
1012
- viewUpdate('YYYY');
1013
- },
1014
-
1015
- selectDay: function (e) {
1016
- var day = viewDate.clone();
1017
- if ($(e.target).is('.old')) {
1018
- day.subtract(1, 'M');
1019
- }
1020
- if ($(e.target).is('.new')) {
1021
- day.add(1, 'M');
1022
- }
1023
- setValue(day.date(parseInt($(e.target).text(), 10)));
1024
- if (!hasTime() && !options.keepOpen && !options.inline) {
1025
- hide();
1026
- }
1027
- },
1028
-
1029
- incrementHours: function () {
1030
- var newDate = date.clone().add(1, 'h');
1031
- if (isValid(newDate, 'h')) {
1032
- setValue(newDate);
1033
- }
1034
- },
1035
-
1036
- incrementMinutes: function () {
1037
- var newDate = date.clone().add(options.stepping, 'm');
1038
- if (isValid(newDate, 'm')) {
1039
- setValue(newDate);
1040
- }
1041
- },
1042
-
1043
- incrementSeconds: function () {
1044
- var newDate = date.clone().add(1, 's');
1045
- if (isValid(newDate, 's')) {
1046
- setValue(newDate);
1047
- }
1048
- },
1049
-
1050
- decrementHours: function () {
1051
- var newDate = date.clone().subtract(1, 'h');
1052
- if (isValid(newDate, 'h')) {
1053
- setValue(newDate);
1054
- }
1055
- },
1056
-
1057
- decrementMinutes: function () {
1058
- var newDate = date.clone().subtract(options.stepping, 'm');
1059
- if (isValid(newDate, 'm')) {
1060
- setValue(newDate);
1061
- }
1062
- },
1063
-
1064
- decrementSeconds: function () {
1065
- var newDate = date.clone().subtract(1, 's');
1066
- if (isValid(newDate, 's')) {
1067
- setValue(newDate);
1068
- }
1069
- },
1070
-
1071
- togglePeriod: function () {
1072
- setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
1073
- },
1074
-
1075
- togglePicker: function (e) {
1076
- var $this = $(e.target),
1077
- $parent = $this.closest('ul'),
1078
- expanded = $parent.find('.in'),
1079
- closed = $parent.find('.collapse:not(.in)'),
1080
- collapseData;
1081
-
1082
- if (expanded && expanded.length) {
1083
- collapseData = expanded.data('collapse');
1084
- if (collapseData && collapseData.transitioning) {
1085
- return;
1086
- }
1087
- if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
1088
- expanded.collapse('hide');
1089
- closed.collapse('show');
1090
- } else { // otherwise just toggle in class on the two views
1091
- expanded.removeClass('in');
1092
- closed.addClass('in');
1093
- }
1094
- if ($this.is('span')) {
1095
- $this.toggleClass(options.icons.time + ' ' + options.icons.date);
1096
- } else {
1097
- $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1098
- }
1099
-
1100
- // NOTE: uncomment if toggled state will be restored in show()
1101
- //if (component) {
1102
- // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
1103
- //}
1104
- }
1105
- },
1106
-
1107
- showPicker: function () {
1108
- widget.find('.timepicker > div:not(.timepicker-picker)').hide();
1109
- widget.find('.timepicker .timepicker-picker').show();
1110
- },
1111
-
1112
- showHours: function () {
1113
- widget.find('.timepicker .timepicker-picker').hide();
1114
- widget.find('.timepicker .timepicker-hours').show();
1115
- },
1116
-
1117
- showMinutes: function () {
1118
- widget.find('.timepicker .timepicker-picker').hide();
1119
- widget.find('.timepicker .timepicker-minutes').show();
1120
- },
1121
-
1122
- showSeconds: function () {
1123
- widget.find('.timepicker .timepicker-picker').hide();
1124
- widget.find('.timepicker .timepicker-seconds').show();
1125
- },
1126
-
1127
- selectHour: function (e) {
1128
- var hour = parseInt($(e.target).text(), 10);
1129
-
1130
- if (!use24Hours) {
1131
- if (date.hours() >= 12) {
1132
- if (hour !== 12) {
1133
- hour += 12;
1134
- }
1135
- } else {
1136
- if (hour === 12) {
1137
- hour = 0;
1138
- }
1139
- }
1140
- }
1141
- setValue(date.clone().hours(hour));
1142
- actions.showPicker.call(picker);
1143
- },
1144
-
1145
- selectMinute: function (e) {
1146
- setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
1147
- actions.showPicker.call(picker);
1148
- },
1149
-
1150
- selectSecond: function (e) {
1151
- setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
1152
- actions.showPicker.call(picker);
1153
- },
1154
-
1155
- clear: clear,
1156
-
1157
- today: function () {
1158
- var todaysDate = getMoment();
1159
- if (isValid(todaysDate, 'd')) {
1160
- setValue(todaysDate);
1161
- }
1162
- },
1163
-
1164
- close: hide
1165
- },
1166
-
1167
- doAction = function (e) {
1168
- if ($(e.currentTarget).is('.disabled')) {
1169
- return false;
1170
- }
1171
- actions[$(e.currentTarget).data('action')].apply(picker, arguments);
1172
- return false;
1173
- },
1174
-
1175
- /**
1176
- * Shows the widget. Possibly will emit dp.show and dp.change
1177
- */
1178
- show = function () {
1179
- var currentMoment,
1180
- useCurrentGranularity = {
1181
- 'year': function (m) {
1182
- return m.month(0).date(1).hours(0).seconds(0).minutes(0);
1183
- },
1184
- 'month': function (m) {
1185
- return m.date(1).hours(0).seconds(0).minutes(0);
1186
- },
1187
- 'day': function (m) {
1188
- return m.hours(0).seconds(0).minutes(0);
1189
- },
1190
- 'hour': function (m) {
1191
- return m.seconds(0).minutes(0);
1192
- },
1193
- 'minute': function (m) {
1194
- return m.seconds(0);
1195
- }
1196
- };
1197
-
1198
- if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
1199
- return picker;
1200
- }
1201
- if (input.val() !== undefined && input.val().trim().length !== 0) {
1202
- setValue(parseInputDate(input.val().trim()));
1203
- } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) {
1204
- currentMoment = getMoment();
1205
- if (typeof options.useCurrent === 'string') {
1206
- currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
1207
- }
1208
- setValue(currentMoment);
1209
- }
1210
- widget = getTemplate();
1211
-
1212
- fillDow();
1213
- fillMonths();
1214
-
1215
- widget.find('.timepicker-hours').hide();
1216
- widget.find('.timepicker-minutes').hide();
1217
- widget.find('.timepicker-seconds').hide();
1218
-
1219
- update();
1220
- showMode();
1221
-
1222
- $(window).on('resize', place);
1223
- widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
1224
- widget.on('mousedown', false);
1225
-
1226
- if (component && component.hasClass('btn')) {
1227
- component.toggleClass('active');
1228
- }
1229
- place();
1230
- widget.show();
1231
- if (options.focusOnShow && !input.is(':focus')) {
1232
- input.focus();
1233
- }
1234
-
1235
- notifyEvent({
1236
- type: 'dp.show'
1237
- });
1238
- return picker;
1239
- },
1240
-
1241
- /**
1242
- * Shows or hides the widget
1243
- */
1244
- toggle = function () {
1245
- return (widget ? hide() : show());
1246
- },
1247
-
1248
- keydown = function (e) {
1249
- var handler = null,
1250
- index,
1251
- index2,
1252
- pressedKeys = [],
1253
- pressedModifiers = {},
1254
- currentKey = e.which,
1255
- keyBindKeys,
1256
- allModifiersPressed,
1257
- pressed = 'p';
1258
-
1259
- keyState[currentKey] = pressed;
1260
-
1261
- for (index in keyState) {
1262
- if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
1263
- pressedKeys.push(index);
1264
- if (parseInt(index, 10) !== currentKey) {
1265
- pressedModifiers[index] = true;
1266
- }
1267
- }
1268
- }
1269
-
1270
- for (index in options.keyBinds) {
1271
- if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
1272
- keyBindKeys = index.split(' ');
1273
- if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
1274
- allModifiersPressed = true;
1275
- for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
1276
- if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
1277
- allModifiersPressed = false;
1278
- break;
1279
- }
1280
- }
1281
- if (allModifiersPressed) {
1282
- handler = options.keyBinds[index];
1283
- break;
1284
- }
1285
- }
1286
- }
1287
- }
1288
-
1289
- if (handler) {
1290
- handler.call(picker, widget);
1291
- e.stopPropagation();
1292
- e.preventDefault();
1293
- }
1294
- },
1295
-
1296
- keyup = function (e) {
1297
- keyState[e.which] = 'r';
1298
- e.stopPropagation();
1299
- e.preventDefault();
1300
- },
1301
-
1302
- change = function (e) {
1303
- var val = $(e.target).val().trim(),
1304
- parsedDate = val ? parseInputDate(val) : null;
1305
- setValue(parsedDate);
1306
- e.stopImmediatePropagation();
1307
- return false;
1308
- },
1309
-
1310
- attachDatePickerElementEvents = function () {
1311
- input.on({
1312
- 'change': change,
1313
- 'blur': options.debug ? '' : hide,
1314
- 'keydown': keydown,
1315
- 'keyup': keyup,
1316
- 'focus': options.allowInputToggle ? show : ''
1317
- });
1318
-
1319
- if (element.is('input')) {
1320
- input.on({
1321
- 'focus': show
1322
- });
1323
- } else if (component) {
1324
- component.on('click', toggle);
1325
- component.on('mousedown', false);
1326
- }
1327
- },
1328
-
1329
- detachDatePickerElementEvents = function () {
1330
- input.off({
1331
- 'change': change,
1332
- 'blur': blur,
1333
- 'keydown': keydown,
1334
- 'keyup': keyup,
1335
- 'focus': options.allowInputToggle ? hide : ''
1336
- });
1337
-
1338
- if (element.is('input')) {
1339
- input.off({
1340
- 'focus': show
1341
- });
1342
- } else if (component) {
1343
- component.off('click', toggle);
1344
- component.off('mousedown', false);
1345
- }
1346
- },
1347
-
1348
- indexGivenDates = function (givenDatesArray) {
1349
- // Store given enabledDates and disabledDates as keys.
1350
- // This way we can check their existence in O(1) time instead of looping through whole array.
1351
- // (for example: options.enabledDates['2014-02-27'] === true)
1352
- var givenDatesIndexed = {};
1353
- $.each(givenDatesArray, function () {
1354
- var dDate = parseInputDate(this);
1355
- if (dDate.isValid()) {
1356
- givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
1357
- }
1358
- });
1359
- return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
1360
- },
1361
-
1362
- indexGivenHours = function (givenHoursArray) {
1363
- // Store given enabledHours and disabledHours as keys.
1364
- // This way we can check their existence in O(1) time instead of looping through whole array.
1365
- // (for example: options.enabledHours['2014-02-27'] === true)
1366
- var givenHoursIndexed = {};
1367
- $.each(givenHoursArray, function () {
1368
- givenHoursIndexed[this] = true;
1369
- });
1370
- return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
1371
- },
1372
-
1373
- initFormatting = function () {
1374
- var format = options.format || 'L LT';
1375
-
1376
- actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
1377
- var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
1378
- return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
1379
- return date.localeData().longDateFormat(formatInput2) || formatInput2;
1380
- });
1381
- });
1382
-
1383
-
1384
- parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
1385
- if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
1386
- parseFormats.push(actualFormat);
1387
- }
1388
-
1389
- use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
1390
-
1391
- if (isEnabled('y')) {
1392
- minViewModeNumber = 2;
1393
- }
1394
- if (isEnabled('M')) {
1395
- minViewModeNumber = 1;
1396
- }
1397
- if (isEnabled('d')) {
1398
- minViewModeNumber = 0;
1399
- }
1400
-
1401
- currentViewMode = Math.max(minViewModeNumber, currentViewMode);
1402
-
1403
- if (!unset) {
1404
- setValue(date);
1405
- }
1406
- };
1407
-
1408
- /********************************************************************************
1409
- *
1410
- * Public API functions
1411
- * =====================
1412
- *
1413
- * Important: Do not expose direct references to private objects or the options
1414
- * object to the outer world. Always return a clone when returning values or make
1415
- * a clone when setting a private variable.
1416
- *
1417
- ********************************************************************************/
1418
- picker.destroy = function () {
1419
- ///<summary>Destroys the widget and removes all attached event listeners</summary>
1420
- hide();
1421
- detachDatePickerElementEvents();
1422
- element.removeData('DateTimePicker');
1423
- element.removeData('date');
1424
- };
1425
-
1426
- picker.toggle = toggle;
1427
-
1428
- picker.show = show;
1429
-
1430
- picker.hide = hide;
1431
-
1432
- picker.disable = function () {
1433
- ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
1434
- ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
1435
- hide();
1436
- if (component && component.hasClass('btn')) {
1437
- component.addClass('disabled');
1438
- }
1439
- input.prop('disabled', true);
1440
- return picker;
1441
- };
1442
-
1443
- picker.enable = function () {
1444
- ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
1445
- if (component && component.hasClass('btn')) {
1446
- component.removeClass('disabled');
1447
- }
1448
- input.prop('disabled', false);
1449
- return picker;
1450
- };
1451
-
1452
- picker.ignoreReadonly = function (ignoreReadonly) {
1453
- if (arguments.length === 0) {
1454
- return options.ignoreReadonly;
1455
- }
1456
- if (typeof ignoreReadonly !== 'boolean') {
1457
- throw new TypeError('ignoreReadonly () expects a boolean parameter');
1458
- }
1459
- options.ignoreReadonly = ignoreReadonly;
1460
- return picker;
1461
- };
1462
-
1463
- picker.options = function (newOptions) {
1464
- if (arguments.length === 0) {
1465
- return $.extend(true, {}, options);
1466
- }
1467
-
1468
- if (!(newOptions instanceof Object)) {
1469
- throw new TypeError('options() options parameter should be an object');
1470
- }
1471
- $.extend(true, options, newOptions);
1472
- $.each(options, function (key, value) {
1473
- if (picker[key] !== undefined) {
1474
- picker[key](value);
1475
- } else {
1476
- throw new TypeError('option ' + key + ' is not recognized!');
1477
- }
1478
- });
1479
- return picker;
1480
- };
1481
-
1482
- picker.date = function (newDate) {
1483
- ///<signature helpKeyword="$.fn.datetimepicker.date">
1484
- ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
1485
- ///<returns type="Moment">date.clone()</returns>
1486
- ///</signature>
1487
- ///<signature>
1488
- ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
1489
- ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
1490
- ///</signature>
1491
- if (arguments.length === 0) {
1492
- if (unset) {
1493
- return null;
1494
- }
1495
- return date.clone();
1496
- }
1497
-
1498
- if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
1499
- throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
1500
- }
1501
-
1502
- setValue(newDate === null ? null : parseInputDate(newDate));
1503
- return picker;
1504
- };
1505
-
1506
- picker.format = function (newFormat) {
1507
- ///<summary>test su</summary>
1508
- ///<param name="newFormat">info about para</param>
1509
- ///<returns type="string|boolean">returns foo</returns>
1510
- if (arguments.length === 0) {
1511
- return options.format;
1512
- }
1513
-
1514
- if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
1515
- throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
1516
- }
1517
-
1518
- options.format = newFormat;
1519
- if (actualFormat) {
1520
- initFormatting(); // reinit formatting
1521
- }
1522
- return picker;
1523
- };
1524
-
1525
- picker.timeZone = function (newZone) {
1526
- if (arguments.length === 0) {
1527
- return options.timeZone;
1528
- }
1529
-
1530
- if (typeof newZone !== 'string') {
1531
- throw new TypeError('newZone() expects a string parameter');
1532
- }
1533
-
1534
- options.timeZone = newZone;
1535
-
1536
- return picker;
1537
- };
1538
-
1539
- picker.dayViewHeaderFormat = function (newFormat) {
1540
- if (arguments.length === 0) {
1541
- return options.dayViewHeaderFormat;
1542
- }
1543
-
1544
- if (typeof newFormat !== 'string') {
1545
- throw new TypeError('dayViewHeaderFormat() expects a string parameter');
1546
- }
1547
-
1548
- options.dayViewHeaderFormat = newFormat;
1549
- return picker;
1550
- };
1551
-
1552
- picker.extraFormats = function (formats) {
1553
- if (arguments.length === 0) {
1554
- return options.extraFormats;
1555
- }
1556
-
1557
- if (formats !== false && !(formats instanceof Array)) {
1558
- throw new TypeError('extraFormats() expects an array or false parameter');
1559
- }
1560
-
1561
- options.extraFormats = formats;
1562
- if (parseFormats) {
1563
- initFormatting(); // reinit formatting
1564
- }
1565
- return picker;
1566
- };
1567
-
1568
- picker.disabledDates = function (dates) {
1569
- ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
1570
- ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
1571
- ///<returns type="array">options.disabledDates</returns>
1572
- ///</signature>
1573
- ///<signature>
1574
- ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
1575
- ///options.enabledDates if such exist.</summary>
1576
- ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1577
- ///</signature>
1578
- if (arguments.length === 0) {
1579
- return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
1580
- }
1581
-
1582
- if (!dates) {
1583
- options.disabledDates = false;
1584
- update();
1585
- return picker;
1586
- }
1587
- if (!(dates instanceof Array)) {
1588
- throw new TypeError('disabledDates() expects an array parameter');
1589
- }
1590
- options.disabledDates = indexGivenDates(dates);
1591
- options.enabledDates = false;
1592
- update();
1593
- return picker;
1594
- };
1595
-
1596
- picker.enabledDates = function (dates) {
1597
- ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
1598
- ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
1599
- ///<returns type="array">options.enabledDates</returns>
1600
- ///</signature>
1601
- ///<signature>
1602
- ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
1603
- ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
1604
- ///</signature>
1605
- if (arguments.length === 0) {
1606
- return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
1607
- }
1608
-
1609
- if (!dates) {
1610
- options.enabledDates = false;
1611
- update();
1612
- return picker;
1613
- }
1614
- if (!(dates instanceof Array)) {
1615
- throw new TypeError('enabledDates() expects an array parameter');
1616
- }
1617
- options.enabledDates = indexGivenDates(dates);
1618
- options.disabledDates = false;
1619
- update();
1620
- return picker;
1621
- };
1622
-
1623
- picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
1624
- if (arguments.length === 0) {
1625
- return options.daysOfWeekDisabled.splice(0);
1626
- }
1627
-
1628
- if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
1629
- options.daysOfWeekDisabled = false;
1630
- update();
1631
- return picker;
1632
- }
1633
-
1634
- if (!(daysOfWeekDisabled instanceof Array)) {
1635
- throw new TypeError('daysOfWeekDisabled() expects an array parameter');
1636
- }
1637
- options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
1638
- currentValue = parseInt(currentValue, 10);
1639
- if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
1640
- return previousValue;
1641
- }
1642
- if (previousValue.indexOf(currentValue) === -1) {
1643
- previousValue.push(currentValue);
1644
- }
1645
- return previousValue;
1646
- }, []).sort();
1647
- if (options.useCurrent && !options.keepInvalid) {
1648
- var tries = 0;
1649
- while (!isValid(date, 'd')) {
1650
- date.add(1, 'd');
1651
- if (tries === 31) {
1652
- throw 'Tried 31 times to find a valid date';
1653
- }
1654
- tries++;
1655
- }
1656
- setValue(date);
1657
- }
1658
- update();
1659
- return picker;
1660
- };
1661
-
1662
- picker.maxDate = function (maxDate) {
1663
- if (arguments.length === 0) {
1664
- return options.maxDate ? options.maxDate.clone() : options.maxDate;
1665
- }
1666
-
1667
- if ((typeof maxDate === 'boolean') && maxDate === false) {
1668
- options.maxDate = false;
1669
- update();
1670
- return picker;
1671
- }
1672
-
1673
- if (typeof maxDate === 'string') {
1674
- if (maxDate === 'now' || maxDate === 'moment') {
1675
- maxDate = getMoment();
1676
- }
1677
- }
1678
-
1679
- var parsedDate = parseInputDate(maxDate);
1680
-
1681
- if (!parsedDate.isValid()) {
1682
- throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
1683
- }
1684
- if (options.minDate && parsedDate.isBefore(options.minDate)) {
1685
- throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
1686
- }
1687
- options.maxDate = parsedDate;
1688
- if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
1689
- setValue(options.maxDate);
1690
- }
1691
- if (viewDate.isAfter(parsedDate)) {
1692
- viewDate = parsedDate.clone().subtract(options.stepping, 'm');
1693
- }
1694
- update();
1695
- return picker;
1696
- };
1697
-
1698
- picker.minDate = function (minDate) {
1699
- if (arguments.length === 0) {
1700
- return options.minDate ? options.minDate.clone() : options.minDate;
1701
- }
1702
-
1703
- if ((typeof minDate === 'boolean') && minDate === false) {
1704
- options.minDate = false;
1705
- update();
1706
- return picker;
1707
- }
1708
-
1709
- if (typeof minDate === 'string') {
1710
- if (minDate === 'now' || minDate === 'moment') {
1711
- minDate = getMoment();
1712
- }
1713
- }
1714
-
1715
- var parsedDate = parseInputDate(minDate);
1716
-
1717
- if (!parsedDate.isValid()) {
1718
- throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
1719
- }
1720
- if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
1721
- throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
1722
- }
1723
- options.minDate = parsedDate;
1724
- if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
1725
- setValue(options.minDate);
1726
- }
1727
- if (viewDate.isBefore(parsedDate)) {
1728
- viewDate = parsedDate.clone().add(options.stepping, 'm');
1729
- }
1730
- update();
1731
- return picker;
1732
- };
1733
-
1734
- picker.defaultDate = function (defaultDate) {
1735
- ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
1736
- ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
1737
- ///<returns type="Moment">date.clone()</returns>
1738
- ///</signature>
1739
- ///<signature>
1740
- ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
1741
- ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
1742
- ///</signature>
1743
- if (arguments.length === 0) {
1744
- return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
1745
- }
1746
- if (!defaultDate) {
1747
- options.defaultDate = false;
1748
- return picker;
1749
- }
1750
-
1751
- if (typeof defaultDate === 'string') {
1752
- if (defaultDate === 'now' || defaultDate === 'moment') {
1753
- defaultDate = getMoment();
1754
- } else {
1755
- defaultDate = getMoment(defaultDate);
1756
- }
1757
- }
1758
-
1759
- var parsedDate = parseInputDate(defaultDate);
1760
- if (!parsedDate.isValid()) {
1761
- throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
1762
- }
1763
- if (!isValid(parsedDate)) {
1764
- throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
1765
- }
1766
-
1767
- options.defaultDate = parsedDate;
1768
-
1769
- if ((options.defaultDate && options.inline) || input.val().trim() === '') {
1770
- setValue(options.defaultDate);
1771
- }
1772
- return picker;
1773
- };
1774
-
1775
- picker.locale = function (locale) {
1776
- if (arguments.length === 0) {
1777
- return options.locale;
1778
- }
1779
-
1780
- if (!moment.localeData(locale)) {
1781
- throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
1782
- }
1783
-
1784
- options.locale = locale;
1785
- date.locale(options.locale);
1786
- viewDate.locale(options.locale);
1787
-
1788
- if (actualFormat) {
1789
- initFormatting(); // reinit formatting
1790
- }
1791
- if (widget) {
1792
- hide();
1793
- show();
1794
- }
1795
- return picker;
1796
- };
1797
-
1798
- picker.stepping = function (stepping) {
1799
- if (arguments.length === 0) {
1800
- return options.stepping;
1801
- }
1802
-
1803
- stepping = parseInt(stepping, 10);
1804
- if (isNaN(stepping) || stepping < 1) {
1805
- stepping = 1;
1806
- }
1807
- options.stepping = stepping;
1808
- return picker;
1809
- };
1810
-
1811
- picker.useCurrent = function (useCurrent) {
1812
- var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
1813
- if (arguments.length === 0) {
1814
- return options.useCurrent;
1815
- }
1816
-
1817
- if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
1818
- throw new TypeError('useCurrent() expects a boolean or string parameter');
1819
- }
1820
- if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
1821
- throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
1822
- }
1823
- options.useCurrent = useCurrent;
1824
- return picker;
1825
- };
1826
-
1827
- picker.collapse = function (collapse) {
1828
- if (arguments.length === 0) {
1829
- return options.collapse;
1830
- }
1831
-
1832
- if (typeof collapse !== 'boolean') {
1833
- throw new TypeError('collapse() expects a boolean parameter');
1834
- }
1835
- if (options.collapse === collapse) {
1836
- return picker;
1837
- }
1838
- options.collapse = collapse;
1839
- if (widget) {
1840
- hide();
1841
- show();
1842
- }
1843
- return picker;
1844
- };
1845
-
1846
- picker.icons = function (icons) {
1847
- if (arguments.length === 0) {
1848
- return $.extend({}, options.icons);
1849
- }
1850
-
1851
- if (!(icons instanceof Object)) {
1852
- throw new TypeError('icons() expects parameter to be an Object');
1853
- }
1854
- $.extend(options.icons, icons);
1855
- if (widget) {
1856
- hide();
1857
- show();
1858
- }
1859
- return picker;
1860
- };
1861
-
1862
- picker.tooltips = function (tooltips) {
1863
- if (arguments.length === 0) {
1864
- return $.extend({}, options.tooltips);
1865
- }
1866
-
1867
- if (!(tooltips instanceof Object)) {
1868
- throw new TypeError('tooltips() expects parameter to be an Object');
1869
- }
1870
- $.extend(options.tooltips, tooltips);
1871
- if (widget) {
1872
- hide();
1873
- show();
1874
- }
1875
- return picker;
1876
- };
1877
-
1878
- picker.useStrict = function (useStrict) {
1879
- if (arguments.length === 0) {
1880
- return options.useStrict;
1881
- }
1882
-
1883
- if (typeof useStrict !== 'boolean') {
1884
- throw new TypeError('useStrict() expects a boolean parameter');
1885
- }
1886
- options.useStrict = useStrict;
1887
- return picker;
1888
- };
1889
-
1890
- picker.sideBySide = function (sideBySide) {
1891
- if (arguments.length === 0) {
1892
- return options.sideBySide;
1893
- }
1894
-
1895
- if (typeof sideBySide !== 'boolean') {
1896
- throw new TypeError('sideBySide() expects a boolean parameter');
1897
- }
1898
- options.sideBySide = sideBySide;
1899
- if (widget) {
1900
- hide();
1901
- show();
1902
- }
1903
- return picker;
1904
- };
1905
-
1906
- picker.viewMode = function (viewMode) {
1907
- if (arguments.length === 0) {
1908
- return options.viewMode;
1909
- }
1910
-
1911
- if (typeof viewMode !== 'string') {
1912
- throw new TypeError('viewMode() expects a string parameter');
1913
- }
1914
-
1915
- if (viewModes.indexOf(viewMode) === -1) {
1916
- throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
1917
- }
1918
-
1919
- options.viewMode = viewMode;
1920
- currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
1921
-
1922
- showMode();
1923
- return picker;
1924
- };
1925
-
1926
- picker.toolbarPlacement = function (toolbarPlacement) {
1927
- if (arguments.length === 0) {
1928
- return options.toolbarPlacement;
1929
- }
1930
-
1931
- if (typeof toolbarPlacement !== 'string') {
1932
- throw new TypeError('toolbarPlacement() expects a string parameter');
1933
- }
1934
- if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
1935
- throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
1936
- }
1937
- options.toolbarPlacement = toolbarPlacement;
1938
-
1939
- if (widget) {
1940
- hide();
1941
- show();
1942
- }
1943
- return picker;
1944
- };
1945
-
1946
- picker.widgetPositioning = function (widgetPositioning) {
1947
- if (arguments.length === 0) {
1948
- return $.extend({}, options.widgetPositioning);
1949
- }
1950
-
1951
- if (({}).toString.call(widgetPositioning) !== '[object Object]') {
1952
- throw new TypeError('widgetPositioning() expects an object variable');
1953
- }
1954
- if (widgetPositioning.horizontal) {
1955
- if (typeof widgetPositioning.horizontal !== 'string') {
1956
- throw new TypeError('widgetPositioning() horizontal variable must be a string');
1957
- }
1958
- widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
1959
- if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
1960
- throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
1961
- }
1962
- options.widgetPositioning.horizontal = widgetPositioning.horizontal;
1963
- }
1964
- if (widgetPositioning.vertical) {
1965
- if (typeof widgetPositioning.vertical !== 'string') {
1966
- throw new TypeError('widgetPositioning() vertical variable must be a string');
1967
- }
1968
- widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
1969
- if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
1970
- throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
1971
- }
1972
- options.widgetPositioning.vertical = widgetPositioning.vertical;
1973
- }
1974
- update();
1975
- return picker;
1976
- };
1977
-
1978
- picker.calendarWeeks = function (calendarWeeks) {
1979
- if (arguments.length === 0) {
1980
- return options.calendarWeeks;
1981
- }
1982
-
1983
- if (typeof calendarWeeks !== 'boolean') {
1984
- throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
1985
- }
1986
-
1987
- options.calendarWeeks = calendarWeeks;
1988
- update();
1989
- return picker;
1990
- };
1991
-
1992
- picker.showTodayButton = function (showTodayButton) {
1993
- if (arguments.length === 0) {
1994
- return options.showTodayButton;
1995
- }
1996
-
1997
- if (typeof showTodayButton !== 'boolean') {
1998
- throw new TypeError('showTodayButton() expects a boolean parameter');
1999
- }
2000
-
2001
- options.showTodayButton = showTodayButton;
2002
- if (widget) {
2003
- hide();
2004
- show();
2005
- }
2006
- return picker;
2007
- };
2008
-
2009
- picker.showClear = function (showClear) {
2010
- if (arguments.length === 0) {
2011
- return options.showClear;
2012
- }
2013
-
2014
- if (typeof showClear !== 'boolean') {
2015
- throw new TypeError('showClear() expects a boolean parameter');
2016
- }
2017
-
2018
- options.showClear = showClear;
2019
- if (widget) {
2020
- hide();
2021
- show();
2022
- }
2023
- return picker;
2024
- };
2025
-
2026
- picker.widgetParent = function (widgetParent) {
2027
- if (arguments.length === 0) {
2028
- return options.widgetParent;
2029
- }
2030
-
2031
- if (typeof widgetParent === 'string') {
2032
- widgetParent = $(widgetParent);
2033
- }
2034
-
2035
- if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
2036
- throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
2037
- }
2038
-
2039
- options.widgetParent = widgetParent;
2040
- if (widget) {
2041
- hide();
2042
- show();
2043
- }
2044
- return picker;
2045
- };
2046
-
2047
- picker.keepOpen = function (keepOpen) {
2048
- if (arguments.length === 0) {
2049
- return options.keepOpen;
2050
- }
2051
-
2052
- if (typeof keepOpen !== 'boolean') {
2053
- throw new TypeError('keepOpen() expects a boolean parameter');
2054
- }
2055
-
2056
- options.keepOpen = keepOpen;
2057
- return picker;
2058
- };
2059
-
2060
- picker.focusOnShow = function (focusOnShow) {
2061
- if (arguments.length === 0) {
2062
- return options.focusOnShow;
2063
- }
2064
-
2065
- if (typeof focusOnShow !== 'boolean') {
2066
- throw new TypeError('focusOnShow() expects a boolean parameter');
2067
- }
2068
-
2069
- options.focusOnShow = focusOnShow;
2070
- return picker;
2071
- };
2072
-
2073
- picker.inline = function (inline) {
2074
- if (arguments.length === 0) {
2075
- return options.inline;
2076
- }
2077
-
2078
- if (typeof inline !== 'boolean') {
2079
- throw new TypeError('inline() expects a boolean parameter');
2080
- }
2081
-
2082
- options.inline = inline;
2083
- return picker;
2084
- };
2085
-
2086
- picker.clear = function () {
2087
- clear();
2088
- return picker;
2089
- };
2090
-
2091
- picker.keyBinds = function (keyBinds) {
2092
- if (arguments.length === 0) {
2093
- return options.keyBinds;
2094
- }
2095
-
2096
- options.keyBinds = keyBinds;
2097
- return picker;
2098
- };
2099
-
2100
- picker.getMoment = function (d) {
2101
- return getMoment(d);
2102
- };
2103
-
2104
- picker.debug = function (debug) {
2105
- if (typeof debug !== 'boolean') {
2106
- throw new TypeError('debug() expects a boolean parameter');
2107
- }
2108
-
2109
- options.debug = debug;
2110
- return picker;
2111
- };
2112
-
2113
- picker.allowInputToggle = function (allowInputToggle) {
2114
- if (arguments.length === 0) {
2115
- return options.allowInputToggle;
2116
- }
2117
-
2118
- if (typeof allowInputToggle !== 'boolean') {
2119
- throw new TypeError('allowInputToggle() expects a boolean parameter');
2120
- }
2121
-
2122
- options.allowInputToggle = allowInputToggle;
2123
- return picker;
2124
- };
2125
-
2126
- picker.showClose = function (showClose) {
2127
- if (arguments.length === 0) {
2128
- return options.showClose;
2129
- }
2130
-
2131
- if (typeof showClose !== 'boolean') {
2132
- throw new TypeError('showClose() expects a boolean parameter');
2133
- }
2134
-
2135
- options.showClose = showClose;
2136
- return picker;
2137
- };
2138
-
2139
- picker.keepInvalid = function (keepInvalid) {
2140
- if (arguments.length === 0) {
2141
- return options.keepInvalid;
2142
- }
2143
-
2144
- if (typeof keepInvalid !== 'boolean') {
2145
- throw new TypeError('keepInvalid() expects a boolean parameter');
2146
- }
2147
- options.keepInvalid = keepInvalid;
2148
- return picker;
2149
- };
2150
-
2151
- picker.datepickerInput = function (datepickerInput) {
2152
- if (arguments.length === 0) {
2153
- return options.datepickerInput;
2154
- }
2155
-
2156
- if (typeof datepickerInput !== 'string') {
2157
- throw new TypeError('datepickerInput() expects a string parameter');
2158
- }
2159
-
2160
- options.datepickerInput = datepickerInput;
2161
- return picker;
2162
- };
2163
-
2164
- picker.parseInputDate = function (parseInputDate) {
2165
- if (arguments.length === 0) {
2166
- return options.parseInputDate;
2167
- }
2168
-
2169
- if (typeof parseInputDate !== 'function') {
2170
- throw new TypeError('parseInputDate() sholud be as function');
2171
- }
2172
-
2173
- options.parseInputDate = parseInputDate;
2174
-
2175
- return picker;
2176
- };
2177
-
2178
- picker.disabledTimeIntervals = function (disabledTimeIntervals) {
2179
- ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
2180
- ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
2181
- ///<returns type="array">options.disabledTimeIntervals</returns>
2182
- ///</signature>
2183
- ///<signature>
2184
- ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2185
- ///options.enabledDates if such exist.</summary>
2186
- ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
2187
- ///</signature>
2188
- if (arguments.length === 0) {
2189
- return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
2190
- }
2191
-
2192
- if (!disabledTimeIntervals) {
2193
- options.disabledTimeIntervals = false;
2194
- update();
2195
- return picker;
2196
- }
2197
- if (!(disabledTimeIntervals instanceof Array)) {
2198
- throw new TypeError('disabledTimeIntervals() expects an array parameter');
2199
- }
2200
- options.disabledTimeIntervals = disabledTimeIntervals;
2201
- update();
2202
- return picker;
2203
- };
2204
-
2205
- picker.disabledHours = function (hours) {
2206
- ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
2207
- ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
2208
- ///<returns type="array">options.disabledHours</returns>
2209
- ///</signature>
2210
- ///<signature>
2211
- ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
2212
- ///options.enabledHours if such exist.</summary>
2213
- ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
2214
- ///</signature>
2215
- if (arguments.length === 0) {
2216
- return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
2217
- }
2218
-
2219
- if (!hours) {
2220
- options.disabledHours = false;
2221
- update();
2222
- return picker;
2223
- }
2224
- if (!(hours instanceof Array)) {
2225
- throw new TypeError('disabledHours() expects an array parameter');
2226
- }
2227
- options.disabledHours = indexGivenHours(hours);
2228
- options.enabledHours = false;
2229
- if (options.useCurrent && !options.keepInvalid) {
2230
- var tries = 0;
2231
- while (!isValid(date, 'h')) {
2232
- date.add(1, 'h');
2233
- if (tries === 24) {
2234
- throw 'Tried 24 times to find a valid date';
2235
- }
2236
- tries++;
2237
- }
2238
- setValue(date);
2239
- }
2240
- update();
2241
- return picker;
2242
- };
2243
-
2244
- picker.enabledHours = function (hours) {
2245
- ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
2246
- ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
2247
- ///<returns type="array">options.enabledHours</returns>
2248
- ///</signature>
2249
- ///<signature>
2250
- ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
2251
- ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
2252
- ///</signature>
2253
- if (arguments.length === 0) {
2254
- return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
2255
- }
2256
-
2257
- if (!hours) {
2258
- options.enabledHours = false;
2259
- update();
2260
- return picker;
2261
- }
2262
- if (!(hours instanceof Array)) {
2263
- throw new TypeError('enabledHours() expects an array parameter');
2264
- }
2265
- options.enabledHours = indexGivenHours(hours);
2266
- options.disabledHours = false;
2267
- if (options.useCurrent && !options.keepInvalid) {
2268
- var tries = 0;
2269
- while (!isValid(date, 'h')) {
2270
- date.add(1, 'h');
2271
- if (tries === 24) {
2272
- throw 'Tried 24 times to find a valid date';
2273
- }
2274
- tries++;
2275
- }
2276
- setValue(date);
2277
- }
2278
- update();
2279
- return picker;
2280
- };
2281
- /**
2282
- * Returns the component's model current viewDate, a moment object or null if not set. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.
2283
- * @param {Takes string, viewDate, moment, null parameter.} newDate
2284
- * @returns {viewDate.clone()}
2285
- */
2286
- picker.viewDate = function (newDate) {
2287
- if (arguments.length === 0) {
2288
- return viewDate.clone();
2289
- }
2290
-
2291
- if (!newDate) {
2292
- viewDate = date.clone();
2293
- return picker;
2294
- }
2295
-
2296
- if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
2297
- throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
2298
- }
2299
-
2300
- viewDate = parseInputDate(newDate);
2301
- viewUpdate();
2302
- return picker;
2303
- };
2304
-
2305
- // initializing element and component attributes
2306
- if (element.is('input')) {
2307
- input = element;
2308
- } else {
2309
- input = element.find(options.datepickerInput);
2310
- if (input.length === 0) {
2311
- input = element.find('input');
2312
- } else if (!input.is('input')) {
2313
- throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
2314
- }
2315
- }
2316
-
2317
- if (element.hasClass('input-group')) {
2318
- // in case there is more then one 'input-group-addon' Issue #48
2319
- if (element.find('.datepickerbutton').length === 0) {
2320
- component = element.find('.input-group-addon');
2321
- } else {
2322
- component = element.find('.datepickerbutton');
2323
- }
2324
- }
2325
-
2326
- if (!options.inline && !input.is('input')) {
2327
- throw new Error('Could not initialize DateTimePicker without an input element');
2328
- }
2329
-
2330
- // Set defaults for date here now instead of in var declaration
2331
- date = getMoment();
2332
- viewDate = date.clone();
2333
-
2334
- $.extend(true, options, dataToOptions());
2335
-
2336
- picker.options(options);
2337
-
2338
- initFormatting();
2339
-
2340
- attachDatePickerElementEvents();
2341
-
2342
- if (input.prop('disabled')) {
2343
- picker.disable();
2344
- }
2345
- if (input.is('input') && input.val().trim().length !== 0) {
2346
- setValue(parseInputDate(input.val().trim()));
2347
- }
2348
- else if (options.defaultDate && input.attr('placeholder') === undefined) {
2349
- setValue(options.defaultDate);
2350
- }
2351
- if (options.inline) {
2352
- show();
2353
- }
2354
- return picker;
2355
- };
2356
-
2357
- /********************************************************************************
2358
- *
2359
- * jQuery plugin constructor and defaults object
2360
- *
2361
- ********************************************************************************/
2362
-
2363
- /**
2364
- * See (http://jquery.com/).
2365
- * @name jQuery
2366
- * @class
2367
- * See the jQuery Library (http://jquery.com/) for full details. This just
2368
- * documents the function and classes that are added to jQuery by this plug-in.
2369
- */
2370
- /**
2371
- * See (http://jquery.com/)
2372
- * @name fn
2373
- * @class
2374
- * See the jQuery Library (http://jquery.com/) for full details. This just
2375
- * documents the function and classes that are added to jQuery by this plug-in.
2376
- * @memberOf jQuery
2377
- */
2378
- /**
2379
- * Show comments
2380
- * @class datetimepicker
2381
- * @memberOf jQuery.fn
2382
- */
2383
- $.fn.datetimepicker = function (options) {
2384
- options = options || {};
2385
-
2386
- var args = Array.prototype.slice.call(arguments, 1),
2387
- isInstance = true,
2388
- thisMethods = ['destroy', 'hide', 'show', 'toggle'],
2389
- returnValue;
2390
-
2391
- if (typeof options === 'object') {
2392
- return this.each(function () {
2393
- var $this = $(this),
2394
- _options;
2395
- if (!$this.data('DateTimePicker')) {
2396
- // create a private copy of the defaults object
2397
- _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
2398
- $this.data('DateTimePicker', dateTimePicker($this, _options));
2399
- }
2400
- });
2401
- } else if (typeof options === 'string') {
2402
- this.each(function () {
2403
- var $this = $(this),
2404
- instance = $this.data('DateTimePicker');
2405
- if (!instance) {
2406
- throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker');
2407
- }
2408
-
2409
- returnValue = instance[options].apply(instance, args);
2410
- isInstance = returnValue === instance;
2411
- });
2412
-
2413
- if (isInstance || $.inArray(options, thisMethods) > -1) {
2414
- return this;
2415
- }
2416
-
2417
- return returnValue;
2418
- }
2419
-
2420
- throw new TypeError('Invalid arguments for DateTimePicker: ' + options);
2421
- };
2422
-
2423
- $.fn.datetimepicker.defaults = {
2424
- timeZone: '',
2425
- format: false,
2426
- dayViewHeaderFormat: 'MMMM YYYY',
2427
- extraFormats: false,
2428
- stepping: 1,
2429
- minDate: false,
2430
- maxDate: false,
2431
- useCurrent: true,
2432
- collapse: true,
2433
- locale: moment.locale(),
2434
- defaultDate: false,
2435
- disabledDates: false,
2436
- enabledDates: false,
2437
- icons: {
2438
- time: 'glyphicon glyphicon-time',
2439
- date: 'glyphicon glyphicon-calendar',
2440
- up: 'glyphicon glyphicon-chevron-up',
2441
- down: 'glyphicon glyphicon-chevron-down',
2442
- previous: 'glyphicon glyphicon-chevron-left',
2443
- next: 'glyphicon glyphicon-chevron-right',
2444
- today: 'glyphicon glyphicon-screenshot',
2445
- clear: 'glyphicon glyphicon-trash',
2446
- close: 'glyphicon glyphicon-remove'
2447
- },
2448
- tooltips: {
2449
- today: 'Go to today',
2450
- clear: 'Clear selection',
2451
- close: 'Close the picker',
2452
- selectMonth: 'Select Month',
2453
- prevMonth: 'Previous Month',
2454
- nextMonth: 'Next Month',
2455
- selectYear: 'Select Year',
2456
- prevYear: 'Previous Year',
2457
- nextYear: 'Next Year',
2458
- selectDecade: 'Select Decade',
2459
- prevDecade: 'Previous Decade',
2460
- nextDecade: 'Next Decade',
2461
- prevCentury: 'Previous Century',
2462
- nextCentury: 'Next Century',
2463
- pickHour: 'Pick Hour',
2464
- incrementHour: 'Increment Hour',
2465
- decrementHour: 'Decrement Hour',
2466
- pickMinute: 'Pick Minute',
2467
- incrementMinute: 'Increment Minute',
2468
- decrementMinute: 'Decrement Minute',
2469
- pickSecond: 'Pick Second',
2470
- incrementSecond: 'Increment Second',
2471
- decrementSecond: 'Decrement Second',
2472
- togglePeriod: 'Toggle Period',
2473
- selectTime: 'Select Time'
2474
- },
2475
- useStrict: false,
2476
- sideBySide: false,
2477
- daysOfWeekDisabled: false,
2478
- calendarWeeks: false,
2479
- viewMode: 'days',
2480
- toolbarPlacement: 'default',
2481
- showTodayButton: false,
2482
- showClear: false,
2483
- showClose: false,
2484
- widgetPositioning: {
2485
- horizontal: 'auto',
2486
- vertical: 'auto'
2487
- },
2488
- widgetParent: null,
2489
- ignoreReadonly: false,
2490
- keepOpen: false,
2491
- focusOnShow: true,
2492
- inline: false,
2493
- keepInvalid: false,
2494
- datepickerInput: '.datepickerinput',
2495
- keyBinds: {
2496
- up: function (widget) {
2497
- if (!widget) {
2498
- return;
2499
- }
2500
- var d = this.date() || this.getMoment();
2501
- if (widget.find('.datepicker').is(':visible')) {
2502
- this.date(d.clone().subtract(7, 'd'));
2503
- } else {
2504
- this.date(d.clone().add(this.stepping(), 'm'));
2505
- }
2506
- },
2507
- down: function (widget) {
2508
- if (!widget) {
2509
- this.show();
2510
- return;
2511
- }
2512
- var d = this.date() || this.getMoment();
2513
- if (widget.find('.datepicker').is(':visible')) {
2514
- this.date(d.clone().add(7, 'd'));
2515
- } else {
2516
- this.date(d.clone().subtract(this.stepping(), 'm'));
2517
- }
2518
- },
2519
- 'control up': function (widget) {
2520
- if (!widget) {
2521
- return;
2522
- }
2523
- var d = this.date() || this.getMoment();
2524
- if (widget.find('.datepicker').is(':visible')) {
2525
- this.date(d.clone().subtract(1, 'y'));
2526
- } else {
2527
- this.date(d.clone().add(1, 'h'));
2528
- }
2529
- },
2530
- 'control down': function (widget) {
2531
- if (!widget) {
2532
- return;
2533
- }
2534
- var d = this.date() || this.getMoment();
2535
- if (widget.find('.datepicker').is(':visible')) {
2536
- this.date(d.clone().add(1, 'y'));
2537
- } else {
2538
- this.date(d.clone().subtract(1, 'h'));
2539
- }
2540
- },
2541
- left: function (widget) {
2542
- if (!widget) {
2543
- return;
2544
- }
2545
- var d = this.date() || this.getMoment();
2546
- if (widget.find('.datepicker').is(':visible')) {
2547
- this.date(d.clone().subtract(1, 'd'));
2548
- }
2549
- },
2550
- right: function (widget) {
2551
- if (!widget) {
2552
- return;
2553
- }
2554
- var d = this.date() || this.getMoment();
2555
- if (widget.find('.datepicker').is(':visible')) {
2556
- this.date(d.clone().add(1, 'd'));
2557
- }
2558
- },
2559
- pageUp: function (widget) {
2560
- if (!widget) {
2561
- return;
2562
- }
2563
- var d = this.date() || this.getMoment();
2564
- if (widget.find('.datepicker').is(':visible')) {
2565
- this.date(d.clone().subtract(1, 'M'));
2566
- }
2567
- },
2568
- pageDown: function (widget) {
2569
- if (!widget) {
2570
- return;
2571
- }
2572
- var d = this.date() || this.getMoment();
2573
- if (widget.find('.datepicker').is(':visible')) {
2574
- this.date(d.clone().add(1, 'M'));
2575
- }
2576
- },
2577
- enter: function () {
2578
- this.hide();
2579
- },
2580
- escape: function () {
2581
- this.hide();
2582
- },
2583
- //tab: function (widget) { //this break the flow of the form. disabling for now
2584
- // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
2585
- // if(toggle.length > 0) toggle.click();
2586
- //},
2587
- 'control space': function (widget) {
2588
- if (!widget) {
2589
- return;
2590
- }
2591
- if (widget.find('.timepicker').is(':visible')) {
2592
- widget.find('.btn[data-action="togglePeriod"]').click();
2593
- }
2594
- },
2595
- t: function () {
2596
- this.date(this.getMoment());
2597
- },
2598
- 'delete': function () {
2599
- this.clear();
2600
- }
2601
- },
2602
- debug: false,
2603
- allowInputToggle: false,
2604
- disabledTimeIntervals: false,
2605
- disabledHours: false,
2606
- enabledHours: false,
2607
- viewDate: false
2608
- };
2609
-
2610
- return $.fn.datetimepicker;
2611
- }));