fomantic-ui 2.9.1-beta.16 → 2.9.1-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.eslintrc.js +109 -0
  2. package/.github/workflows/ci.yml +13 -3
  3. package/dist/components/accordion.css +1 -1
  4. package/dist/components/accordion.js +571 -598
  5. package/dist/components/accordion.min.css +1 -1
  6. package/dist/components/accordion.min.js +1 -1
  7. package/dist/components/ad.css +1 -1
  8. package/dist/components/ad.min.css +1 -1
  9. package/dist/components/api.js +1164 -1186
  10. package/dist/components/api.min.js +1 -1
  11. package/dist/components/breadcrumb.css +1 -1
  12. package/dist/components/breadcrumb.min.css +1 -1
  13. package/dist/components/button.css +1 -1
  14. package/dist/components/button.min.css +1 -1
  15. package/dist/components/calendar.css +1 -1
  16. package/dist/components/calendar.js +1897 -1818
  17. package/dist/components/calendar.min.css +1 -1
  18. package/dist/components/calendar.min.js +1 -1
  19. package/dist/components/card.css +1 -1
  20. package/dist/components/card.min.css +1 -1
  21. package/dist/components/checkbox.css +1 -1
  22. package/dist/components/checkbox.js +844 -841
  23. package/dist/components/checkbox.min.css +1 -1
  24. package/dist/components/checkbox.min.js +1 -1
  25. package/dist/components/comment.css +1 -1
  26. package/dist/components/comment.min.css +1 -1
  27. package/dist/components/container.css +3 -1
  28. package/dist/components/container.min.css +2 -2
  29. package/dist/components/dimmer.css +1 -1
  30. package/dist/components/dimmer.js +710 -737
  31. package/dist/components/dimmer.min.css +1 -1
  32. package/dist/components/dimmer.min.js +1 -1
  33. package/dist/components/divider.css +1 -1
  34. package/dist/components/divider.min.css +1 -1
  35. package/dist/components/dropdown.css +11 -8
  36. package/dist/components/dropdown.js +4163 -4234
  37. package/dist/components/dropdown.min.css +2 -2
  38. package/dist/components/dropdown.min.js +2 -2
  39. package/dist/components/embed.css +1 -1
  40. package/dist/components/embed.js +653 -675
  41. package/dist/components/embed.min.css +1 -1
  42. package/dist/components/embed.min.js +1 -1
  43. package/dist/components/feed.css +1 -1
  44. package/dist/components/feed.min.css +1 -1
  45. package/dist/components/flag.css +1 -1
  46. package/dist/components/flag.min.css +1 -1
  47. package/dist/components/flyout.css +6 -3
  48. package/dist/components/flyout.js +1466 -1467
  49. package/dist/components/flyout.min.css +2 -2
  50. package/dist/components/flyout.min.js +1 -1
  51. package/dist/components/form.css +1 -1
  52. package/dist/components/form.js +1981 -2004
  53. package/dist/components/form.min.css +1 -1
  54. package/dist/components/form.min.js +1 -1
  55. package/dist/components/grid.css +1 -1
  56. package/dist/components/grid.min.css +1 -1
  57. package/dist/components/header.css +1 -1
  58. package/dist/components/header.min.css +1 -1
  59. package/dist/components/icon.css +1 -1
  60. package/dist/components/icon.min.css +1 -1
  61. package/dist/components/image.css +1 -1
  62. package/dist/components/image.min.css +1 -1
  63. package/dist/components/input.css +1 -1
  64. package/dist/components/input.min.css +1 -1
  65. package/dist/components/item.css +1 -1
  66. package/dist/components/item.min.css +1 -1
  67. package/dist/components/label.css +1 -1
  68. package/dist/components/label.min.css +1 -1
  69. package/dist/components/list.css +1 -1
  70. package/dist/components/list.min.css +1 -1
  71. package/dist/components/loader.css +1 -1
  72. package/dist/components/loader.min.css +1 -1
  73. package/dist/components/message.css +1 -1
  74. package/dist/components/message.min.css +1 -1
  75. package/dist/components/modal.css +7 -1
  76. package/dist/components/modal.js +1493 -1487
  77. package/dist/components/modal.min.css +2 -2
  78. package/dist/components/modal.min.js +1 -1
  79. package/dist/components/nag.css +1 -1
  80. package/dist/components/nag.js +520 -529
  81. package/dist/components/nag.min.css +1 -1
  82. package/dist/components/nag.min.js +1 -1
  83. package/dist/components/placeholder.css +1 -1
  84. package/dist/components/placeholder.min.css +1 -1
  85. package/dist/components/popup.css +1 -1
  86. package/dist/components/popup.js +1439 -1456
  87. package/dist/components/popup.min.css +1 -1
  88. package/dist/components/popup.min.js +1 -1
  89. package/dist/components/progress.css +1 -1
  90. package/dist/components/progress.js +971 -997
  91. package/dist/components/progress.min.css +1 -1
  92. package/dist/components/progress.min.js +1 -1
  93. package/dist/components/rail.css +1 -1
  94. package/dist/components/rail.min.css +1 -1
  95. package/dist/components/rating.css +1 -1
  96. package/dist/components/rating.js +508 -524
  97. package/dist/components/rating.min.css +1 -1
  98. package/dist/components/rating.min.js +1 -1
  99. package/dist/components/reset.css +1 -1
  100. package/dist/components/reset.min.css +1 -1
  101. package/dist/components/reveal.css +1 -1
  102. package/dist/components/reveal.min.css +1 -1
  103. package/dist/components/search.css +3 -1
  104. package/dist/components/search.js +1500 -1534
  105. package/dist/components/search.min.css +2 -2
  106. package/dist/components/search.min.js +1 -1
  107. package/dist/components/segment.css +3 -1
  108. package/dist/components/segment.min.css +2 -2
  109. package/dist/components/shape.css +1 -1
  110. package/dist/components/shape.js +794 -809
  111. package/dist/components/shape.min.css +1 -1
  112. package/dist/components/shape.min.js +1 -1
  113. package/dist/components/sidebar.css +3 -1
  114. package/dist/components/sidebar.js +1079 -1104
  115. package/dist/components/sidebar.min.css +2 -2
  116. package/dist/components/sidebar.min.js +1 -1
  117. package/dist/components/site.css +1 -1
  118. package/dist/components/site.js +457 -472
  119. package/dist/components/site.min.css +1 -1
  120. package/dist/components/site.min.js +1 -1
  121. package/dist/components/slider.js +1289 -1311
  122. package/dist/components/slider.min.js +1 -1
  123. package/dist/components/state.js +641 -657
  124. package/dist/components/state.min.js +1 -1
  125. package/dist/components/statistic.css +1 -1
  126. package/dist/components/statistic.min.css +1 -1
  127. package/dist/components/step.css +1 -1
  128. package/dist/components/step.min.css +1 -1
  129. package/dist/components/sticky.css +1 -1
  130. package/dist/components/sticky.js +859 -903
  131. package/dist/components/sticky.min.css +1 -1
  132. package/dist/components/sticky.min.js +1 -1
  133. package/dist/components/tab.css +1 -1
  134. package/dist/components/tab.js +923 -963
  135. package/dist/components/tab.min.css +1 -1
  136. package/dist/components/tab.min.js +1 -1
  137. package/dist/components/table.css +5 -1
  138. package/dist/components/table.min.css +2 -2
  139. package/dist/components/text.css +1 -1
  140. package/dist/components/text.min.css +1 -1
  141. package/dist/components/toast.css +1 -1
  142. package/dist/components/toast.js +889 -891
  143. package/dist/components/toast.min.css +1 -1
  144. package/dist/components/toast.min.js +1 -1
  145. package/dist/components/transition.css +1 -1
  146. package/dist/components/transition.js +1043 -1077
  147. package/dist/components/transition.min.css +1 -1
  148. package/dist/components/transition.min.js +1 -1
  149. package/dist/components/visibility.js +1222 -1244
  150. package/dist/components/visibility.min.js +1 -1
  151. package/dist/semantic.css +84 -60
  152. package/dist/semantic.js +29033 -29475
  153. package/dist/semantic.min.css +2 -2
  154. package/dist/semantic.min.js +2 -2
  155. package/examples/assets/show-examples.js +13 -13
  156. package/gulpfile.js +9 -10
  157. package/package.json +5 -2
  158. package/scripts/nightly-version.js +81 -75
  159. package/src/definitions/behaviors/api.js +1163 -1185
  160. package/src/definitions/behaviors/form.js +1980 -2003
  161. package/src/definitions/behaviors/state.js +647 -663
  162. package/src/definitions/behaviors/visibility.js +1221 -1243
  163. package/src/definitions/collections/table.less +2 -0
  164. package/src/definitions/elements/container.less +1 -0
  165. package/src/definitions/elements/segment.less +1 -0
  166. package/src/definitions/globals/site.js +456 -471
  167. package/src/definitions/modules/accordion.js +570 -597
  168. package/src/definitions/modules/calendar.js +1896 -1817
  169. package/src/definitions/modules/checkbox.js +849 -846
  170. package/src/definitions/modules/dimmer.js +709 -736
  171. package/src/definitions/modules/dropdown.js +4162 -4233
  172. package/src/definitions/modules/dropdown.less +5 -8
  173. package/src/definitions/modules/embed.js +652 -674
  174. package/src/definitions/modules/flyout.js +1465 -1466
  175. package/src/definitions/modules/flyout.less +15 -12
  176. package/src/definitions/modules/modal.js +1492 -1486
  177. package/src/definitions/modules/modal.less +3 -0
  178. package/src/definitions/modules/nag.js +519 -528
  179. package/src/definitions/modules/popup.js +1438 -1455
  180. package/src/definitions/modules/progress.js +970 -996
  181. package/src/definitions/modules/rating.js +507 -523
  182. package/src/definitions/modules/search.js +1499 -1533
  183. package/src/definitions/modules/search.less +1 -0
  184. package/src/definitions/modules/shape.js +801 -816
  185. package/src/definitions/modules/sidebar.js +1078 -1103
  186. package/src/definitions/modules/sidebar.less +1 -0
  187. package/src/definitions/modules/slider.js +1288 -1310
  188. package/src/definitions/modules/sticky.js +875 -919
  189. package/src/definitions/modules/tab.js +922 -962
  190. package/src/definitions/modules/toast.js +888 -890
  191. package/src/definitions/modules/transition.js +1048 -1082
  192. package/src/themes/default/elements/container.variables +0 -7
  193. package/src/themes/default/elements/segment.variables +0 -7
  194. package/src/themes/default/globals/site.variables +7 -0
  195. package/src/themes/default/globals/variation.variables +1 -0
  196. package/tasks/admin/components/create.js +274 -276
  197. package/tasks/admin/components/init.js +123 -130
  198. package/tasks/admin/components/update.js +149 -157
  199. package/tasks/admin/distributions/create.js +184 -187
  200. package/tasks/admin/distributions/init.js +123 -130
  201. package/tasks/admin/distributions/update.js +145 -152
  202. package/tasks/admin/publish.js +5 -7
  203. package/tasks/admin/register.js +36 -38
  204. package/tasks/admin/release.js +8 -10
  205. package/tasks/build/assets.js +42 -39
  206. package/tasks/build/css.js +225 -216
  207. package/tasks/build/javascript.js +118 -113
  208. package/tasks/build.js +10 -10
  209. package/tasks/check-install.js +14 -16
  210. package/tasks/clean.js +5 -5
  211. package/tasks/collections/admin.js +34 -36
  212. package/tasks/collections/build.js +18 -20
  213. package/tasks/collections/docs.js +9 -11
  214. package/tasks/collections/install.js +9 -11
  215. package/tasks/collections/rtl.js +9 -11
  216. package/tasks/collections/various.js +8 -10
  217. package/tasks/config/admin/github.js +17 -17
  218. package/tasks/config/admin/oauth.example.js +4 -4
  219. package/tasks/config/admin/release.js +98 -98
  220. package/tasks/config/admin/templates/component-package.js +9 -10
  221. package/tasks/config/admin/templates/css-package.js +18 -20
  222. package/tasks/config/admin/templates/less-package.js +11 -13
  223. package/tasks/config/defaults.js +116 -116
  224. package/tasks/config/docs.js +23 -23
  225. package/tasks/config/npm/gulpfile.js +8 -9
  226. package/tasks/config/project/config.js +127 -134
  227. package/tasks/config/project/install.js +715 -713
  228. package/tasks/config/project/release.js +32 -38
  229. package/tasks/config/tasks.js +163 -164
  230. package/tasks/config/user.js +23 -29
  231. package/tasks/docs/build.js +97 -95
  232. package/tasks/docs/metadata.js +90 -96
  233. package/tasks/docs/serve.js +80 -81
  234. package/tasks/install.js +370 -378
  235. package/tasks/rtl/build.js +2 -2
  236. package/tasks/rtl/watch.js +2 -2
  237. package/tasks/version.js +4 -4
  238. package/tasks/watch.js +28 -30
  239. package/test/meteor/assets.js +10 -13
  240. package/test/meteor/fonts.js +12 -13
  241. package/test/modules/accordion.spec.js +6 -8
  242. package/test/modules/checkbox.spec.js +5 -7
  243. package/test/modules/dropdown.spec.js +5 -7
  244. package/test/modules/modal.spec.js +6 -8
  245. package/test/modules/module.spec.js +158 -178
  246. package/test/modules/popup.spec.js +5 -7
  247. package/test/modules/search.spec.js +5 -7
  248. package/test/modules/shape.spec.js +5 -7
  249. package/test/modules/sidebar.spec.js +5 -7
  250. package/test/modules/tab.spec.js +6 -8
  251. package/test/modules/transition.spec.js +5 -7
  252. package/test/modules/video.spec.js +5 -7
@@ -8,1892 +8,1971 @@
8
8
  *
9
9
  */
10
10
 
11
- ;(function ($, window, document, undefined) {
12
-
13
- 'use strict';
14
-
15
- function isFunction(obj) {
16
- return typeof obj === "function" && typeof obj.nodeType !== "number";
17
- }
18
-
19
- window = (typeof window != 'undefined' && window.Math == Math)
20
- ? window
21
- : (typeof self != 'undefined' && self.Math == Math)
22
- ? self
23
- : Function('return this')()
24
- ;
25
-
26
- $.fn.calendar = function(parameters) {
27
- var
28
- $allModules = $(this),
29
- $document = $(document),
30
-
31
- moduleSelector = $allModules.selector || '',
32
-
33
- time = new Date().getTime(),
34
- performance = [],
35
-
36
- query = arguments[0],
37
- methodInvoked = (typeof query == 'string'),
38
- queryArguments = [].slice.call(arguments, 1),
39
- returnedValue,
40
- timeGapTable = {
41
- '5': {'row': 4, 'column': 3 },
42
- '10': {'row': 3, 'column': 2 },
43
- '15': {'row': 2, 'column': 2 },
44
- '20': {'row': 3, 'column': 1 },
45
- '30': {'row': 2, 'column': 1 }
46
- },
47
- numberText = ['','one','two','three','four','five','six','seven','eight']
48
- ;
49
-
50
- $allModules
51
- .each(function () {
52
- var
53
- settings = ( $.isPlainObject(parameters) )
54
- ? $.extend(true, {}, $.fn.calendar.settings, parameters)
55
- : $.extend({}, $.fn.calendar.settings),
56
-
57
- className = settings.className,
58
- namespace = settings.namespace,
59
- selector = settings.selector,
60
- formatter = settings.formatter,
61
- parser = settings.parser,
62
- metadata = settings.metadata,
63
- timeGap = timeGapTable[settings.minTimeGap],
64
- error = settings.error,
65
-
66
- eventNamespace = '.' + namespace,
67
- moduleNamespace = 'module-' + namespace,
68
-
69
- $module = $(this),
70
- $input = $module.find(selector.input),
71
- $activator = $module.find(selector.activator),
72
-
73
- element = this,
74
- instance = $module.data(moduleNamespace),
75
- $container = instance && instance.popupId ? $document.find('#'+instance.popupId) : $module.find(selector.popup),
76
-
77
- isTouch,
78
- isTouchDown = false,
79
- isInverted = $module.hasClass(className.inverted),
80
- focusDateUsedForRange = false,
81
- selectionComplete = false,
82
- classObserver,
83
- module
84
- ;
85
-
86
- module = {
87
-
88
- initialize: function () {
89
- module.debug('Initializing calendar for', element, $module);
90
-
91
- isTouch = module.get.isTouch();
92
- module.setup.config();
93
- module.setup.popup();
94
- module.setup.inline();
95
- module.setup.input();
96
- module.setup.date();
97
- module.create.calendar();
98
-
99
- module.bind.events();
100
- module.observeChanges();
101
- module.instantiate();
102
- },
103
-
104
- instantiate: function () {
105
- module.verbose('Storing instance of calendar');
106
- instance = module;
107
- $module.data(moduleNamespace, instance);
108
- },
109
-
110
- destroy: function () {
111
- module.verbose('Destroying previous calendar for', element);
112
- $module.removeData(moduleNamespace);
113
- module.unbind.events();
114
- module.disconnect.classObserver();
115
- },
11
+ (function ($, window, document, undefined) {
12
+ 'use strict';
116
13
 
117
- setup: {
118
- config: function () {
119
- if (module.get.minDate() !== null) {
120
- module.set.minDate($module.data(metadata.minDate));
121
- }
122
- if (module.get.maxDate() !== null) {
123
- module.set.maxDate($module.data(metadata.maxDate));
124
- }
125
- module.setting('type', module.get.type());
126
- module.setting('on', settings.on || 'click');
127
- },
128
- popup: function () {
129
- if (settings.inline) {
130
- return;
131
- }
132
- if (!$activator.length) {
133
- $activator = $module.children().first();
134
- if (!$activator.length) {
135
- return;
136
- }
137
- }
138
- if ($.fn.popup === undefined) {
139
- module.error(error.popup);
140
- return;
141
- }
142
- if (!$container.length) {
143
- if(settings.context) {
144
- module.popupId = namespace + '_popup_' + (Math.random().toString(16) + '000000000').slice(2, 10);
145
- $container = $('<div/>',{id:module.popupId}).addClass(className.popup).appendTo($document.find(settings.context));
146
- } else {
147
- //prepend the popup element to the activator's parent so that it has less chance of messing with
148
- //the styling (eg input action button needs to be the last child to have correct border radius)
149
- var $activatorParent = $activator.parent(),
150
- domPositionFunction = $activatorParent.closest(selector.append).length !== 0 ? 'appendTo' : 'prependTo';
151
- $container = $('<div/>').addClass(className.popup)[domPositionFunction]($activatorParent);
152
- }
153
- }
154
- $container.addClass(className.calendar);
155
- if(isInverted){
156
- $container.addClass(className.inverted);
157
- }
158
- var onVisible = function () {
159
- module.refreshTooltips();
160
- return settings.onVisible.apply($container, arguments);
161
- };
162
- var onHidden = function () {
163
- module.blur();
164
- return settings.onHidden.apply($container, arguments)
165
- }
166
- if (!$input.length) {
167
- //no input, $container has to handle focus/blur
168
- $container.attr('tabindex', '0');
169
- onVisible = function () {
170
- module.refreshTooltips();
171
- module.focus();
172
- return settings.onVisible.apply($container, arguments);
173
- };
174
- }
175
- var onShow = function () {
176
- //reset the focus date onShow
177
- module.set.focusDate(module.get.date());
178
- module.set.mode(module.get.validatedMode(settings.startMode));
179
- return settings.onShow.apply($container, arguments);
180
- };
181
- var on = module.setting('on');
182
- var options = $.extend({}, settings.popupOptions, {
183
- popup: $container,
184
- movePopup: !settings.context,
185
- on: on,
186
- hoverable: on === 'hover',
187
- closable: on === 'click',
188
- onShow: onShow,
189
- onVisible: onVisible,
190
- onHide: settings.onHide,
191
- onHidden: onHidden
192
- });
193
- module.popup(options);
194
- },
195
- inline: function () {
196
- if ($activator.length && !settings.inline) {
197
- return;
198
- }
199
- settings.inline = true;
200
- $container = $('<div/>').addClass(className.calendar).appendTo($module);
201
- if (!$input.length) {
202
- $container.attr('tabindex', '0');
203
- }
204
- },
205
- input: function () {
206
- if (settings.touchReadonly && $input.length && isTouch) {
207
- $input.prop('readonly', true);
208
- }
209
- module.check.disabled();
210
- },
211
- date: function () {
212
- var date;
213
- if (settings.initialDate) {
214
- date = parser.date(settings.initialDate, settings);
215
- } else if ($module.data(metadata.date) !== undefined) {
216
- date = parser.date($module.data(metadata.date), settings);
217
- } else if ($input.length) {
218
- date = parser.date($input.val(), settings);
219
- }
220
- module.set.date(date, settings.formatInput, false);
221
- module.set.mode(module.get.mode(), false);
222
- }
223
- },
14
+ function isFunction(obj) {
15
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
16
+ }
224
17
 
225
- trigger: {
226
- change: function() {
18
+ window = (typeof window != 'undefined' && window.Math == Math)
19
+ ? window
20
+ : (typeof self != 'undefined' && self.Math == Math)
21
+ ? self
22
+ : Function('return this')();
23
+
24
+ $.fn.calendar = function (parameters) {
25
+ var
26
+ $allModules = $(this),
27
+ $document = $(document),
28
+
29
+ moduleSelector = $allModules.selector || '',
30
+
31
+ time = new Date().getTime(),
32
+ performance = [],
33
+
34
+ query = arguments[0],
35
+ methodInvoked = (typeof query == 'string'),
36
+ queryArguments = [].slice.call(arguments, 1),
37
+ returnedValue,
38
+ timeGapTable = {
39
+ 5: { row: 4, column: 3 },
40
+ 10: { row: 3, column: 2 },
41
+ 15: { row: 2, column: 2 },
42
+ 20: { row: 3, column: 1 },
43
+ 30: { row: 2, column: 1 },
44
+ },
45
+ numberText = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']
46
+ ;
47
+
48
+ $allModules.each(function () {
227
49
  var
228
- inputElement = $input[0]
50
+ settings = ($.isPlainObject(parameters))
51
+ ? $.extend(true, {}, $.fn.calendar.settings, parameters)
52
+ : $.extend({}, $.fn.calendar.settings),
53
+
54
+ className = settings.className,
55
+ namespace = settings.namespace,
56
+ selector = settings.selector,
57
+ formatter = settings.formatter,
58
+ parser = settings.parser,
59
+ metadata = settings.metadata,
60
+ timeGap = timeGapTable[settings.minTimeGap],
61
+ error = settings.error,
62
+
63
+ eventNamespace = '.' + namespace,
64
+ moduleNamespace = 'module-' + namespace,
65
+
66
+ $module = $(this),
67
+ $input = $module.find(selector.input),
68
+ $activator = $module.find(selector.activator),
69
+
70
+ element = this,
71
+ instance = $module.data(moduleNamespace),
72
+ $container = instance && instance.popupId ? $document.find('#' + instance.popupId) : $module.find(selector.popup),
73
+
74
+ isTouch,
75
+ isTouchDown = false,
76
+ isInverted = $module.hasClass(className.inverted),
77
+ focusDateUsedForRange = false,
78
+ selectionComplete = false,
79
+ classObserver,
80
+ module
229
81
  ;
230
- if(inputElement) {
231
- var events = document.createEvent('HTMLEvents');
232
- module.verbose('Triggering native change event');
233
- events.initEvent('change', true, false);
234
- inputElement.dispatchEvent(events);
235
- }
236
- }
237
- },
238
82
 
239
- create: {
240
- calendar: function () {
241
- var i, r, c, p, row, cell, pageGrid;
83
+ module = {
84
+
85
+ initialize: function () {
86
+ module.debug('Initializing calendar for', element, $module);
87
+
88
+ isTouch = module.get.isTouch();
89
+ module.setup.config();
90
+ module.setup.popup();
91
+ module.setup.inline();
92
+ module.setup.input();
93
+ module.setup.date();
94
+ module.create.calendar();
95
+
96
+ module.bind.events();
97
+ module.observeChanges();
98
+ module.instantiate();
99
+ },
100
+
101
+ instantiate: function () {
102
+ module.verbose('Storing instance of calendar');
103
+ instance = module;
104
+ $module.data(moduleNamespace, instance);
105
+ },
106
+
107
+ destroy: function () {
108
+ module.verbose('Destroying previous calendar for', element);
109
+ $module.removeData(moduleNamespace);
110
+ module.unbind.events();
111
+ module.disconnect.classObserver();
112
+ },
113
+
114
+ setup: {
115
+ config: function () {
116
+ if (module.get.minDate() !== null) {
117
+ module.set.minDate($module.data(metadata.minDate));
118
+ }
119
+ if (module.get.maxDate() !== null) {
120
+ module.set.maxDate($module.data(metadata.maxDate));
121
+ }
122
+ module.setting('type', module.get.type());
123
+ module.setting('on', settings.on || 'click');
124
+ },
125
+ popup: function () {
126
+ if (settings.inline) {
127
+ return;
128
+ }
129
+ if (!$activator.length) {
130
+ $activator = $module.children().first();
131
+ if (!$activator.length) {
132
+ return;
133
+ }
134
+ }
135
+ if ($.fn.popup === undefined) {
136
+ module.error(error.popup);
242
137
 
243
- var
244
- mode = module.get.mode(),
245
- today = new Date(),
246
- date = module.get.date(),
247
- focusDate = module.get.focusDate(),
248
- display = module.helper.dateInRange(focusDate || date || settings.initialDate || today)
249
- ;
138
+ return;
139
+ }
140
+ if (!$container.length) {
141
+ if (settings.context) {
142
+ module.popupId = namespace + '_popup_' + (Math.random().toString(16) + '000000000').slice(2, 10);
143
+ $container = $('<div/>', { id: module.popupId }).addClass(className.popup).appendTo($document.find(settings.context));
144
+ } else {
145
+ // prepend the popup element to the activator's parent so that it has less chance of messing with
146
+ // the styling (eg input action button needs to be the last child to have correct border radius)
147
+ var
148
+ $activatorParent = $activator.parent(),
149
+ domPositionFunction = $activatorParent.closest(selector.append).length !== 0 ? 'appendTo' : 'prependTo'
150
+ ;
151
+ $container = $('<div/>').addClass(className.popup)[domPositionFunction]($activatorParent);
152
+ }
153
+ }
154
+ $container.addClass(className.calendar);
155
+ if (isInverted) {
156
+ $container.addClass(className.inverted);
157
+ }
158
+ var onVisible = function () {
159
+ module.refreshTooltips();
160
+
161
+ return settings.onVisible.apply($container, arguments);
162
+ };
163
+ var onHidden = function () {
164
+ module.blur();
165
+
166
+ return settings.onHidden.apply($container, arguments);
167
+ };
168
+ if (!$input.length) {
169
+ // no input, $container has to handle focus/blur
170
+ $container.attr('tabindex', '0');
171
+ onVisible = function () {
172
+ module.refreshTooltips();
173
+ module.focus();
174
+
175
+ return settings.onVisible.apply($container, arguments);
176
+ };
177
+ }
178
+ var onShow = function () {
179
+ // reset the focus date onShow
180
+ module.set.focusDate(module.get.date());
181
+ module.set.mode(module.get.validatedMode(settings.startMode));
182
+
183
+ return settings.onShow.apply($container, arguments);
184
+ };
185
+ var on = module.setting('on');
186
+ var options = $.extend({}, settings.popupOptions, {
187
+ popup: $container,
188
+ movePopup: !settings.context,
189
+ on: on,
190
+ hoverable: on === 'hover',
191
+ closable: on === 'click',
192
+ onShow: onShow,
193
+ onVisible: onVisible,
194
+ onHide: settings.onHide,
195
+ onHidden: onHidden,
196
+ });
197
+ module.popup(options);
198
+ },
199
+ inline: function () {
200
+ if ($activator.length && !settings.inline) {
201
+ return;
202
+ }
203
+ settings.inline = true;
204
+ $container = $('<div/>').addClass(className.calendar).appendTo($module);
205
+ if (!$input.length) {
206
+ $container.attr('tabindex', '0');
207
+ }
208
+ },
209
+ input: function () {
210
+ if (settings.touchReadonly && $input.length && isTouch) {
211
+ $input.prop('readonly', true);
212
+ }
213
+ module.check.disabled();
214
+ },
215
+ date: function () {
216
+ var date;
217
+ if (settings.initialDate) {
218
+ date = parser.date(settings.initialDate, settings);
219
+ } else if ($module.data(metadata.date) !== undefined) {
220
+ date = parser.date($module.data(metadata.date), settings);
221
+ } else if ($input.length) {
222
+ date = parser.date($input.val(), settings);
223
+ }
224
+ module.set.date(date, settings.formatInput, false);
225
+ module.set.mode(module.get.mode(), false);
226
+ },
227
+ },
228
+
229
+ trigger: {
230
+ change: function () {
231
+ var
232
+ inputElement = $input[0]
233
+ ;
234
+ if (inputElement) {
235
+ var events = document.createEvent('HTMLEvents');
236
+ module.verbose('Triggering native change event');
237
+ events.initEvent('change', true, false);
238
+ inputElement.dispatchEvent(events);
239
+ }
240
+ },
241
+ },
242
+
243
+ create: {
244
+ calendar: function () {
245
+ var
246
+ i,
247
+ r,
248
+ c,
249
+ p,
250
+ row,
251
+ cell,
252
+ pageGrid
253
+ ;
254
+
255
+ var
256
+ mode = module.get.mode(),
257
+ today = new Date(),
258
+ date = module.get.date(),
259
+ focusDate = module.get.focusDate(),
260
+ display = module.helper.dateInRange(focusDate || date || settings.initialDate || today)
261
+ ;
262
+
263
+ if (!focusDate) {
264
+ focusDate = display;
265
+ module.set.focusDate(focusDate, false, false);
266
+ }
250
267
 
251
- if (!focusDate) {
252
- focusDate = display;
253
- module.set.focusDate(focusDate, false, false);
254
- }
268
+ var
269
+ isYear = mode === 'year',
270
+ isMonth = mode === 'month',
271
+ isDay = mode === 'day',
272
+ isHour = mode === 'hour',
273
+ isMinute = mode === 'minute',
274
+ isTimeOnly = settings.type === 'time'
275
+ ;
276
+
277
+ var multiMonth = Math.max(settings.multiMonth, 1);
278
+ var monthOffset = !isDay ? 0 : module.get.monthOffset();
279
+
280
+ var
281
+ minute = display.getMinutes(),
282
+ hour = display.getHours(),
283
+ day = display.getDate(),
284
+ startMonth = display.getMonth() + monthOffset,
285
+ year = display.getFullYear()
286
+ ;
287
+
288
+ var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap.column;
289
+ var rows = isDay || isHour ? 6 : timeGap.row;
290
+ var pages = isDay ? multiMonth : 1;
291
+
292
+ var container = $container;
293
+ var tooltipPosition = container.hasClass('left') ? 'right center' : 'left center';
294
+ container.empty();
295
+ if (pages > 1) {
296
+ pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
297
+ }
255
298
 
256
- var
257
- isYear = mode === 'year',
258
- isMonth = mode === 'month',
259
- isDay = mode === 'day',
260
- isHour = mode === 'hour',
261
- isMinute = mode === 'minute',
262
- isTimeOnly = settings.type === 'time'
263
- ;
299
+ for (p = 0; p < pages; p++) {
300
+ if (pages > 1) {
301
+ var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
302
+ container = pageColumn;
303
+ }
304
+
305
+ var month = startMonth + p;
306
+ var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
307
+ if (!settings.constantHeight && isDay) {
308
+ var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
309
+ rows = Math.ceil(requiredCells / 7);
310
+ }
311
+
312
+ var
313
+ yearChange = isYear ? 10 : isMonth ? 1 : 0,
314
+ monthChange = isDay ? 1 : 0,
315
+ dayChange = isHour || isMinute ? 1 : 0,
316
+ prevNextDay = isHour || isMinute ? day : 1,
317
+ prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour),
318
+ nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour),
319
+ prevLast = isYear
320
+ ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0)
321
+ : isMonth
322
+ ? new Date(year, 0, 0)
323
+ : isDay
324
+ ? new Date(year, month, 0)
325
+ : new Date(year, month, day, -1),
326
+ nextFirst = isYear
327
+ ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1)
328
+ : isMonth
329
+ ? new Date(year + 1, 0, 1)
330
+ : isDay
331
+ ? new Date(year, month + 1, 1)
332
+ : new Date(year, month, day + 1)
333
+ ;
334
+
335
+ var tempMode = mode;
336
+ if (isDay && settings.showWeekNumbers) {
337
+ tempMode += ' andweek';
338
+ }
339
+ var table = $('<table/>').addClass(className.table).addClass(tempMode).addClass(numberText[columns] + ' column').appendTo(container);
340
+ if (isInverted) {
341
+ table.addClass(className.inverted);
342
+ }
343
+ var textColumns = columns;
344
+ // no header for time-only mode
345
+ if (!isTimeOnly) {
346
+ var thead = $('<thead/>').appendTo(table);
347
+
348
+ row = $('<tr/>').appendTo(thead);
349
+ cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
350
+
351
+ var headerDate = isYear || isMonth
352
+ ? new Date(year, 0, 1)
353
+ : isDay
354
+ ? new Date(year, month, 1)
355
+ : new Date(year, month, day, hour, minute);
356
+ var headerText = $('<span/>').addClass(className.link).appendTo(cell);
357
+ headerText.text(module.helper.dateFormat(formatter[mode + 'Header'], headerDate));
358
+ var newMode = isMonth
359
+ ? (settings.disableYear ? 'day' : 'year')
360
+ : isDay
361
+ ? (settings.disableMonth ? 'year' : 'month')
362
+ : 'day';
363
+ headerText.data(metadata.mode, newMode);
364
+
365
+ if (p === 0) {
366
+ var prev = $('<span/>').addClass(className.prev).appendTo(cell);
367
+ prev.data(metadata.focusDate, prevDate);
368
+ prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
369
+ $('<i/>').addClass(className.prevIcon).appendTo(prev);
370
+ }
371
+
372
+ if (p === pages - 1) {
373
+ var next = $('<span/>').addClass(className.next).appendTo(cell);
374
+ next.data(metadata.focusDate, nextDate);
375
+ next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
376
+ $('<i/>').addClass(className.nextIcon).appendTo(next);
377
+ }
378
+ if (isDay) {
379
+ row = $('<tr/>').appendTo(thead);
380
+ if (settings.showWeekNumbers) {
381
+ cell = $('<th/>').appendTo(row);
382
+ cell.text(settings.text.weekNo);
383
+ cell.addClass(className.weekCell);
384
+ textColumns--;
385
+ }
386
+ for (i = 0; i < textColumns; i++) {
387
+ cell = $('<th/>').appendTo(row);
388
+ cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
389
+ }
390
+ }
391
+ }
392
+
393
+ var tbody = $('<tbody/>').appendTo(table);
394
+ i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
395
+ for (r = 0; r < rows; r++) {
396
+ row = $('<tr/>').appendTo(tbody);
397
+ if (isDay && settings.showWeekNumbers) {
398
+ cell = $('<th/>').appendTo(row);
399
+ cell.text(module.get.weekOfYear(year, month, i + 1 - settings.firstDayOfWeek));
400
+ cell.addClass(className.weekCell);
401
+ }
402
+ for (c = 0; c < textColumns; c++, i++) {
403
+ var cellDate = isYear
404
+ ? new Date(i, month, 1, hour, minute)
405
+ : isMonth
406
+ ? new Date(year, i, 1, hour, minute)
407
+ : isDay
408
+ ? new Date(year, month, i, hour, minute)
409
+ : isHour
410
+ ? new Date(year, month, day, i)
411
+ : new Date(year, month, day, hour, i * settings.minTimeGap);
412
+ var cellText = isYear
413
+ ? i
414
+ : isMonth
415
+ ? settings.text.monthsShort[i]
416
+ : isDay
417
+ ? cellDate.getDate()
418
+ : module.helper.dateFormat(formatter.cellTime, cellDate);
419
+ cell = $('<td/>').addClass(className.cell).appendTo(row);
420
+ cell.text(cellText);
421
+ cell.data(metadata.date, cellDate);
422
+ var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
423
+ var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
424
+ var eventDate;
425
+ if (disabled) {
426
+ var disabledDate = module.helper.findDayAsObject(cellDate, mode, settings.disabledDates);
427
+ if (disabledDate !== null && disabledDate[metadata.message]) {
428
+ cell.attr('data-tooltip', disabledDate[metadata.message]);
429
+ cell.attr('data-position', disabledDate[metadata.position] || tooltipPosition);
430
+ if (disabledDate[metadata.inverted] || (isInverted && disabledDate[metadata.inverted] === undefined)) {
431
+ cell.attr('data-inverted', '');
432
+ }
433
+ if (disabledDate[metadata.variation]) {
434
+ cell.attr('data-variation', disabledDate[metadata.variation]);
435
+ }
436
+ }
437
+ if (mode === 'hour') {
438
+ var disabledHour = module.helper.findHourAsObject(cellDate, mode, settings.disabledHours);
439
+ if (disabledHour !== null && disabledHour[metadata.message]) {
440
+ cell.attr('data-tooltip', disabledHour[metadata.message]);
441
+ cell.attr('data-position', disabledHour[metadata.position] || tooltipPosition);
442
+ if (disabledHour[metadata.inverted] || (isInverted && disabledHour[metadata.inverted] === undefined)) {
443
+ cell.attr('data-inverted', '');
444
+ }
445
+ if (disabledHour[metadata.variation]) {
446
+ cell.attr('data-variation', disabledHour[metadata.variation]);
447
+ }
448
+ }
449
+ }
450
+ } else {
451
+ eventDate = module.helper.findDayAsObject(cellDate, mode, settings.eventDates);
452
+ if (eventDate !== null) {
453
+ cell.addClass(eventDate[metadata.class] || settings.eventClass);
454
+ if (eventDate[metadata.message]) {
455
+ cell.attr('data-tooltip', eventDate[metadata.message]);
456
+ cell.attr('data-position', eventDate[metadata.position] || tooltipPosition);
457
+ if (eventDate[metadata.inverted] || (isInverted && eventDate[metadata.inverted] === undefined)) {
458
+ cell.attr('data-inverted', '');
459
+ }
460
+ if (eventDate[metadata.variation]) {
461
+ cell.attr('data-variation', eventDate[metadata.variation]);
462
+ }
463
+ }
464
+ }
465
+ }
466
+ var active = module.helper.dateEqual(cellDate, date, mode);
467
+ var isToday = module.helper.dateEqual(cellDate, today, mode);
468
+ cell.toggleClass(className.adjacentCell, adjacent && !eventDate);
469
+ cell.toggleClass(className.disabledCell, disabled);
470
+ cell.toggleClass(className.activeCell, active && !(adjacent && disabled));
471
+ if (!isHour && !isMinute) {
472
+ cell.toggleClass(className.todayCell, !adjacent && isToday);
473
+ }
474
+
475
+ // Allow for external modifications of each cell
476
+ var cellOptions = {
477
+ mode: mode,
478
+ adjacent: adjacent,
479
+ disabled: disabled,
480
+ active: active,
481
+ today: isToday,
482
+ };
483
+ formatter.cell(cell, cellDate, cellOptions);
484
+
485
+ if (module.helper.dateEqual(cellDate, focusDate, mode)) {
486
+ // ensure that the focus date is exactly equal to the cell date
487
+ // so that, if selected, the correct value is set
488
+ module.set.focusDate(cellDate, false, false);
489
+ }
490
+ }
491
+ }
492
+
493
+ if (settings.today) {
494
+ var todayRow = $('<tr/>').appendTo(tbody);
495
+ var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
496
+ todayButton.text(formatter.today(settings));
497
+ todayButton.data(metadata.date, today);
498
+ }
499
+
500
+ module.update.focus(false, table);
501
+
502
+ if (settings.inline) {
503
+ module.refreshTooltips();
504
+ }
505
+ }
506
+ },
507
+ },
508
+
509
+ update: {
510
+ focus: function (updateRange, container) {
511
+ container = container || $container;
512
+ var mode = module.get.mode();
513
+ var date = module.get.date();
514
+ var focusDate = module.get.focusDate();
515
+ var startDate = module.get.startDate();
516
+ var endDate = module.get.endDate();
517
+ var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
518
+
519
+ container.find('td').each(function () {
520
+ var $cell = $(this);
521
+ var cellDate = $cell.data(metadata.date);
522
+ if (!cellDate) {
523
+ return;
524
+ }
525
+ var disabled = $cell.hasClass(className.disabledCell);
526
+ var active = $cell.hasClass(className.activeCell);
527
+ var adjacent = $cell.hasClass(className.adjacentCell);
528
+ var focused = module.helper.dateEqual(cellDate, focusDate, mode);
529
+ var inRange = !rangeDate
530
+ ? false
531
+ : ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate))
532
+ || (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
533
+ $cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
534
+
535
+ if (module.helper.isTodayButton($cell)) {
536
+ return;
537
+ }
538
+ $cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
539
+ });
540
+ },
541
+ },
542
+
543
+ refresh: function () {
544
+ module.create.calendar();
545
+ },
546
+
547
+ refreshTooltips: function () {
548
+ var winWidth = $(window).width();
549
+ $container.find('td[data-position]').each(function () {
550
+ var $cell = $(this);
551
+ var tooltipWidth = window.getComputedStyle($cell[0], '::after').width.replace(/[^0-9\.]/g, '');
552
+ var tooltipPosition = $cell.attr('data-position');
553
+ // use a fallback width of 250 (calendar width) for IE/Edge (which return "auto")
554
+ var calcPosition = (winWidth - $cell.width() - (parseInt(tooltipWidth, 10) || 250)) > $cell.offset().left ? 'right' : 'left';
555
+ if (tooltipPosition.indexOf(calcPosition) === -1) {
556
+ $cell.attr('data-position', tooltipPosition.replace(/(left|right)/, calcPosition));
557
+ }
558
+ });
559
+ },
560
+
561
+ bind: {
562
+ events: function () {
563
+ module.debug('Binding events');
564
+ $container.on('mousedown' + eventNamespace, module.event.mousedown);
565
+ $container.on('touchstart' + eventNamespace, module.event.mousedown);
566
+ $container.on('mouseup' + eventNamespace, module.event.mouseup);
567
+ $container.on('touchend' + eventNamespace, module.event.mouseup);
568
+ $container.on('mouseover' + eventNamespace, module.event.mouseover);
569
+ if ($input.length) {
570
+ $input.on('input' + eventNamespace, module.event.inputChange);
571
+ $input.on('focus' + eventNamespace, module.event.inputFocus);
572
+ $input.on('blur' + eventNamespace, module.event.inputBlur);
573
+ $input.on('keydown' + eventNamespace, module.event.keydown);
574
+ } else {
575
+ $container.on('keydown' + eventNamespace, module.event.keydown);
576
+ }
577
+ },
578
+ },
579
+
580
+ unbind: {
581
+ events: function () {
582
+ module.debug('Unbinding events');
583
+ $container.off(eventNamespace);
584
+ if ($input.length) {
585
+ $input.off(eventNamespace);
586
+ }
587
+ },
588
+ },
589
+
590
+ event: {
591
+ mouseover: function (event) {
592
+ var target = $(event.target);
593
+ var date = target.data(metadata.date);
594
+ var mousedown = event.buttons === 1;
595
+ if (date) {
596
+ module.set.focusDate(date, false, true, mousedown);
597
+ }
598
+ },
599
+ mousedown: function (event) {
600
+ if ($input.length) {
601
+ // prevent the mousedown on the calendar causing the input to lose focus
602
+ event.preventDefault();
603
+ }
604
+ isTouchDown = event.type.indexOf('touch') >= 0;
605
+ var target = $(event.target);
606
+ var date = target.data(metadata.date);
607
+ if (date) {
608
+ module.set.focusDate(date, false, true, true);
609
+ }
610
+ },
611
+ mouseup: function (event) {
612
+ // ensure input has focus so that it receives keydown events for calendar navigation
613
+ module.focus();
614
+ event.preventDefault();
615
+ event.stopPropagation();
616
+ isTouchDown = false;
617
+ var target = $(event.target);
618
+ if (target.hasClass('disabled')) {
619
+ return;
620
+ }
621
+ var parent = target.parent();
622
+ if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
623
+ // clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
624
+ target = parent;
625
+ }
626
+ var date = target.data(metadata.date);
627
+ var focusDate = target.data(metadata.focusDate);
628
+ var mode = target.data(metadata.mode);
629
+ if (date && settings.onSelect.call(element, date, module.get.mode()) !== false) {
630
+ var forceSet = target.hasClass(className.today);
631
+ module.selectDate(date, forceSet);
632
+ } else if (focusDate) {
633
+ module.set.focusDate(focusDate);
634
+ } else if (mode) {
635
+ module.set.mode(mode);
636
+ }
637
+ },
638
+ keydown: function (event) {
639
+ var keyCode = event.which;
640
+ if (keyCode === 9) {
641
+ // tab
642
+ module.popup('hide');
643
+ }
264
644
 
265
- var multiMonth = Math.max(settings.multiMonth, 1);
266
- var monthOffset = !isDay ? 0 : module.get.monthOffset();
645
+ if (module.popup('is visible')) {
646
+ var mode = module.get.mode();
647
+ if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
648
+ // arrow keys
649
+ var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap.column : 3;
650
+ var increment = keyCode === 37 ? -1 : keyCode === 38 ? -bigIncrement : keyCode == 39 ? 1 : bigIncrement;
651
+ increment *= mode === 'minute' ? settings.minTimeGap : 1;
652
+ var focusDate = module.get.focusDate() || module.get.date() || new Date();
653
+ var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
654
+ var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
655
+ var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
656
+ var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
657
+ var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
658
+ var newFocusDate = new Date(year, month, day, hour, minute);
659
+ if (settings.type === 'time') {
660
+ newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
661
+ }
662
+ if (module.helper.isDateInRange(newFocusDate, mode)) {
663
+ module.set.focusDate(newFocusDate);
664
+ }
665
+ } else if (keyCode === 13) {
666
+ // enter
667
+ var date = module.get.focusDate();
668
+ if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
669
+ if (settings.onSelect.call(element, date, module.get.mode()) !== false) {
670
+ module.selectDate(date);
671
+ }
672
+ }
673
+ // disable form submission:
674
+ event.preventDefault();
675
+ event.stopPropagation();
676
+ } else if (keyCode === 27) {
677
+ module.popup('hide');
678
+ event.stopPropagation();
679
+ }
680
+ }
267
681
 
268
- var
269
- minute = display.getMinutes(),
270
- hour = display.getHours(),
271
- day = display.getDate(),
272
- startMonth = display.getMonth() + monthOffset,
273
- year = display.getFullYear()
274
- ;
682
+ if (keyCode === 38 || keyCode === 40) {
683
+ // arrow-up || arrow-down
684
+ event.preventDefault(); // don't scroll
685
+ module.popup('show');
686
+ }
687
+ },
688
+ inputChange: function () {
689
+ var val = $input.val();
690
+ var date = parser.date(val, settings);
691
+ module.set.date(date, false);
692
+ },
693
+ inputFocus: function () {
694
+ $container.addClass(className.active);
695
+ },
696
+ inputBlur: function () {
697
+ $container.removeClass(className.active);
698
+ if (settings.formatInput) {
699
+ var date = module.get.date();
700
+ var text = module.helper.dateFormat(formatter[settings.type], date);
701
+ $input.val(text);
702
+ }
703
+ if (selectionComplete) {
704
+ module.trigger.change();
705
+ selectionComplete = false;
706
+ }
707
+ },
708
+ class: {
709
+ mutation: function (mutations) {
710
+ mutations.forEach(function (mutation) {
711
+ if (mutation.attributeName === 'class') {
712
+ module.check.disabled();
713
+ }
714
+ });
715
+ },
716
+ },
717
+ },
718
+
719
+ observeChanges: function () {
720
+ if ('MutationObserver' in window) {
721
+ classObserver = new MutationObserver(module.event.class.mutation);
722
+ module.debug('Setting up mutation observer', classObserver);
723
+ module.observe.class();
724
+ }
725
+ },
275
726
 
276
- var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
277
- var rows = isDay || isHour ? 6 : timeGap['row'];
278
- var pages = isDay ? multiMonth : 1;
727
+ disconnect: {
728
+ classObserver: function () {
729
+ if ($input.length && classObserver) {
730
+ classObserver.disconnect();
731
+ }
732
+ },
733
+ },
734
+
735
+ observe: {
736
+ class: function () {
737
+ if ($input.length && classObserver) {
738
+ classObserver.observe($module[0], {
739
+ attributes: true,
740
+ });
741
+ }
742
+ },
743
+ },
744
+
745
+ is: {
746
+ disabled: function () {
747
+ return $module.hasClass(className.disabled);
748
+ },
749
+ },
750
+
751
+ check: {
752
+ disabled: function () {
753
+ $input.attr('tabindex', module.is.disabled() ? -1 : 0);
754
+ },
755
+ },
756
+
757
+ get: {
758
+ weekOfYear: function (weekYear, weekMonth, weekDay) {
759
+ // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
760
+ var ms1d = 864e5, // milliseconds in a day
761
+ ms7d = 7 * ms1d; // milliseconds in a week
762
+
763
+ return function () { // return a closure so constants get calculated only once
764
+ var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
765
+ AWN = Math.floor(DC3 / 7), // an Absolute Week Number
766
+ Wyr = new Date(AWN * ms7d).getUTCFullYear();
767
+
768
+ return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
769
+ }();
770
+ },
771
+ formattedDate: function (format, date) {
772
+ return module.helper.dateFormat(format || formatter[settings.type], date || module.get.date());
773
+ },
774
+ date: function () {
775
+ return module.helper.sanitiseDate($module.data(metadata.date)) || null;
776
+ },
777
+ inputDate: function () {
778
+ return $input.val();
779
+ },
780
+ focusDate: function () {
781
+ return $module.data(metadata.focusDate) || null;
782
+ },
783
+ startDate: function () {
784
+ var startModule = module.get.calendarModule(settings.startCalendar);
785
+
786
+ return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
787
+ },
788
+ endDate: function () {
789
+ var endModule = module.get.calendarModule(settings.endCalendar);
790
+
791
+ return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
792
+ },
793
+ minDate: function () {
794
+ return $module.data(metadata.minDate) || null;
795
+ },
796
+ maxDate: function () {
797
+ return $module.data(metadata.maxDate) || null;
798
+ },
799
+ monthOffset: function () {
800
+ return $module.data(metadata.monthOffset) || settings.monthOffset || 0;
801
+ },
802
+ mode: function () {
803
+ // only returns valid modes for the current settings
804
+ var mode = $module.data(metadata.mode) || settings.startMode;
805
+
806
+ return module.get.validatedMode(mode);
807
+ },
808
+ validatedMode: function (mode) {
809
+ var validModes = module.get.validModes();
810
+ if ($.inArray(mode, validModes) >= 0) {
811
+ return mode;
812
+ }
279
813
 
280
- var container = $container;
281
- var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
282
- container.empty();
283
- if (pages > 1) {
284
- pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
285
- }
814
+ return settings.type === 'time'
815
+ ? 'hour'
816
+ : settings.type === 'month'
817
+ ? 'month'
818
+ : settings.type === 'year' ? 'year' : 'day';
819
+ },
820
+ type: function () {
821
+ return $module.data(metadata.type) || settings.type;
822
+ },
823
+ validModes: function () {
824
+ var validModes = [];
825
+ if (settings.type !== 'time') {
826
+ if (!settings.disableYear || settings.type === 'year') {
827
+ validModes.push('year');
828
+ }
829
+ if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
830
+ validModes.push('month');
831
+ }
832
+ if (settings.type.indexOf('date') >= 0) {
833
+ validModes.push('day');
834
+ }
835
+ }
836
+ if (settings.type.indexOf('time') >= 0) {
837
+ validModes.push('hour');
838
+ if (!settings.disableMinute) {
839
+ validModes.push('minute');
840
+ }
841
+ }
286
842
 
287
- for (p = 0; p < pages; p++) {
288
- if (pages > 1) {
289
- var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
290
- container = pageColumn;
291
- }
292
-
293
- var month = startMonth + p;
294
- var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
295
- if (!settings.constantHeight && isDay) {
296
- var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
297
- rows = Math.ceil(requiredCells / 7);
298
- }
299
-
300
- var
301
- yearChange = isYear ? 10 : isMonth ? 1 : 0,
302
- monthChange = isDay ? 1 : 0,
303
- dayChange = isHour || isMinute ? 1 : 0,
304
- prevNextDay = isHour || isMinute ? day : 1,
305
- prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour),
306
- nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour),
307
- prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
308
- isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1),
309
- nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
310
- isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1)
311
- ;
312
-
313
- var tempMode = mode;
314
- if (isDay && settings.showWeekNumbers){
315
- tempMode += ' andweek';
316
- }
317
- var table = $('<table/>').addClass(className.table).addClass(tempMode).addClass(numberText[columns] + ' column').appendTo(container);
318
- if(isInverted){
319
- table.addClass(className.inverted);
320
- }
321
- var textColumns = columns;
322
- //no header for time-only mode
323
- if (!isTimeOnly) {
324
- var thead = $('<thead/>').appendTo(table);
325
-
326
- row = $('<tr/>').appendTo(thead);
327
- cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
328
-
329
- var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
330
- isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
331
- var headerText = $('<span/>').addClass(className.link).appendTo(cell);
332
- headerText.text(module.helper.dateFormat(formatter[mode+'Header'], headerDate));
333
- var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
334
- isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
335
- headerText.data(metadata.mode, newMode);
336
-
337
- if (p === 0) {
338
- var prev = $('<span/>').addClass(className.prev).appendTo(cell);
339
- prev.data(metadata.focusDate, prevDate);
340
- prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
341
- $('<i/>').addClass(className.prevIcon).appendTo(prev);
342
- }
843
+ return validModes;
844
+ },
845
+ isTouch: function () {
846
+ try {
847
+ document.createEvent('TouchEvent');
343
848
 
344
- if (p === pages - 1) {
345
- var next = $('<span/>').addClass(className.next).appendTo(cell);
346
- next.data(metadata.focusDate, nextDate);
347
- next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
348
- $('<i/>').addClass(className.nextIcon).appendTo(next);
349
- }
350
- if (isDay) {
351
- row = $('<tr/>').appendTo(thead);
352
- if(settings.showWeekNumbers) {
353
- cell = $('<th/>').appendTo(row);
354
- cell.text(settings.text.weekNo);
355
- cell.addClass(className.weekCell);
356
- textColumns--;
357
- }
358
- for (i = 0; i < textColumns; i++) {
359
- cell = $('<th/>').appendTo(row);
360
- cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
361
- }
362
- }
363
- }
364
-
365
- var tbody = $('<tbody/>').appendTo(table);
366
- i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
367
- for (r = 0; r < rows; r++) {
368
- row = $('<tr/>').appendTo(tbody);
369
- if(isDay && settings.showWeekNumbers){
370
- cell = $('<th/>').appendTo(row);
371
- cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
372
- cell.addClass(className.weekCell);
373
- }
374
- for (c = 0; c < textColumns; c++, i++) {
375
- var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
376
- isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
377
- isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
378
- var cellText = isYear ? i :
379
- isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
380
- module.helper.dateFormat(formatter.cellTime,cellDate);
381
- cell = $('<td/>').addClass(className.cell).appendTo(row);
382
- cell.text(cellText);
383
- cell.data(metadata.date, cellDate);
384
- var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
385
- var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
386
- var eventDate;
387
- if (disabled) {
388
- var disabledDate = module.helper.findDayAsObject(cellDate, mode, settings.disabledDates);
389
- if (disabledDate !== null && disabledDate[metadata.message]) {
390
- cell.attr("data-tooltip", disabledDate[metadata.message]);
391
- cell.attr("data-position", disabledDate[metadata.position] || tooltipPosition);
392
- if(disabledDate[metadata.inverted] || (isInverted && disabledDate[metadata.inverted] === undefined)) {
393
- cell.attr("data-inverted", '');
394
- }
395
- if(disabledDate[metadata.variation]) {
396
- cell.attr("data-variation", disabledDate[metadata.variation]);
397
- }
849
+ return true;
850
+ } catch (e) {
851
+ return false;
852
+ }
853
+ },
854
+ calendarModule: function (selector) {
855
+ if (!selector) {
856
+ return null;
857
+ }
858
+ if (!(selector instanceof $)) {
859
+ selector = $document.find(selector).first();
860
+ }
861
+
862
+ // assume range related calendars are using the same namespace
863
+ return selector.data(moduleNamespace);
864
+ },
865
+ },
866
+
867
+ set: {
868
+ date: function (date, updateInput, fireChange) {
869
+ updateInput = updateInput !== false;
870
+ fireChange = fireChange !== false;
871
+ date = module.helper.sanitiseDate(date);
872
+ date = module.helper.dateInRange(date);
873
+
874
+ var mode = module.get.mode();
875
+ var text = module.helper.dateFormat(formatter[settings.type], date);
876
+
877
+ if (fireChange && settings.onBeforeChange.call(element, date, text, mode) === false) {
878
+ return false;
879
+ }
880
+
881
+ module.set.focusDate(date);
882
+
883
+ if (settings.isDisabled(date, mode)) {
884
+ return false;
885
+ }
886
+
887
+ var endDate = module.get.endDate();
888
+ if (!!endDate && !!date && date > endDate) {
889
+ // selected date is greater than end date in range, so clear end date
890
+ module.set.endDate(undefined);
891
+ }
892
+ module.set.dataKeyValue(metadata.date, date);
893
+
894
+ if (updateInput && $input.length) {
895
+ $input.val(text);
896
+ }
897
+
898
+ if (fireChange) {
899
+ settings.onChange.call(element, date, text, mode);
900
+ }
901
+ },
902
+ startDate: function (date, refreshCalendar) {
903
+ date = module.helper.sanitiseDate(date);
904
+ var startModule = module.get.calendarModule(settings.startCalendar);
905
+ if (startModule) {
906
+ startModule.set.date(date);
907
+ }
908
+ module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
909
+ },
910
+ endDate: function (date, refreshCalendar) {
911
+ date = module.helper.sanitiseDate(date);
912
+ var endModule = module.get.calendarModule(settings.endCalendar);
913
+ if (endModule) {
914
+ endModule.set.date(date);
915
+ }
916
+ module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
917
+ },
918
+ focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
919
+ date = module.helper.sanitiseDate(date);
920
+ date = module.helper.dateInRange(date);
921
+ var isDay = module.get.mode() === 'day';
922
+ var oldFocusDate = module.get.focusDate();
923
+ if (isDay && date && oldFocusDate) {
924
+ var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
925
+ var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
926
+ if (monthDelta) {
927
+ var monthOffset = module.get.monthOffset() - monthDelta;
928
+ module.set.monthOffset(monthOffset, false);
929
+ }
930
+ }
931
+ var changed = module.set.dataKeyValue(metadata.focusDate, date, !!date && refreshCalendar);
932
+ updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
933
+ focusDateUsedForRange = updateRange;
934
+ if (updateFocus) {
935
+ module.update.focus(updateRange);
936
+ }
937
+ },
938
+ minDate: function (date) {
939
+ date = module.helper.sanitiseDate(date);
940
+ if (settings.maxDate !== null && settings.maxDate <= date) {
941
+ module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
942
+ } else {
943
+ module.setting('minDate', date);
944
+ module.set.dataKeyValue(metadata.minDate, date);
945
+ }
946
+ },
947
+ maxDate: function (date) {
948
+ date = module.helper.sanitiseDate(date);
949
+ if (settings.minDate !== null && settings.minDate >= date) {
950
+ module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
951
+ } else {
952
+ module.setting('maxDate', date);
953
+ module.set.dataKeyValue(metadata.maxDate, date);
954
+ }
955
+ },
956
+ monthOffset: function (monthOffset, refreshCalendar) {
957
+ var multiMonth = Math.max(settings.multiMonth, 1);
958
+ monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
959
+ module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
960
+ },
961
+ mode: function (mode, refreshCalendar) {
962
+ module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
963
+ },
964
+ dataKeyValue: function (key, value, refreshCalendar) {
965
+ var oldValue = $module.data(key);
966
+ var equal = oldValue === value || (oldValue <= value && oldValue >= value); // equality test for dates and string objects
967
+ if (value) {
968
+ $module.data(key, value);
969
+ } else {
970
+ $module.removeData(key);
971
+ }
972
+ refreshCalendar = refreshCalendar !== false && !equal;
973
+ if (refreshCalendar) {
974
+ module.refresh();
975
+ }
976
+
977
+ return !equal;
978
+ },
979
+ },
980
+
981
+ selectDate: function (date, forceSet) {
982
+ module.verbose('New date selection', date);
983
+ var mode = module.get.mode();
984
+ var complete = forceSet || mode === 'minute'
985
+ || (settings.disableMinute && mode === 'hour')
986
+ || (settings.type === 'date' && mode === 'day')
987
+ || (settings.type === 'month' && mode === 'month')
988
+ || (settings.type === 'year' && mode === 'year');
989
+ if (complete) {
990
+ var canceled = module.set.date(date) === false;
991
+ if (!canceled) {
992
+ selectionComplete = true;
993
+ if (settings.closable) {
994
+ module.popup('hide');
995
+ // if this is a range calendar, focus the container or input. This will open the popup from its event listeners.
996
+ var endModule = module.get.calendarModule(settings.endCalendar);
997
+ if (endModule) {
998
+ endModule.refresh();
999
+ if (endModule.setting('on') !== 'focus') {
1000
+ endModule.popup('show');
1001
+ }
1002
+ endModule.focus();
1003
+ }
1004
+ }
1005
+ }
1006
+ } else {
1007
+ var newMode = mode === 'year'
1008
+ ? (!settings.disableMonth ? 'month' : 'day')
1009
+ : mode === 'month'
1010
+ ? 'day'
1011
+ : mode === 'day' ? 'hour' : 'minute';
1012
+ module.set.mode(newMode);
1013
+ if (mode === 'hour' || (mode === 'day' && module.get.date())) {
1014
+ // the user has chosen enough to consider a valid date/time has been chosen
1015
+ module.set.date(date, true, false);
1016
+ } else {
1017
+ module.set.focusDate(date);
1018
+ }
398
1019
  }
399
- if (mode === 'hour') {
400
- var disabledHour = module.helper.findHourAsObject(cellDate, mode, settings.disabledHours);
401
- if (disabledHour !== null && disabledHour[metadata.message]) {
402
- cell.attr("data-tooltip", disabledHour[metadata.message]);
403
- cell.attr("data-position", disabledHour[metadata.position] || tooltipPosition);
404
- if(disabledHour[metadata.inverted] || (isInverted && disabledHour[metadata.inverted] === undefined)) {
405
- cell.attr("data-inverted", '');
406
- }
407
- if(disabledHour[metadata.variation]) {
408
- cell.attr("data-variation", disabledHour[metadata.variation]);
409
- }
410
- }
1020
+ },
1021
+
1022
+ changeDate: function (date) {
1023
+ module.set.date(date);
1024
+ },
1025
+
1026
+ clear: function () {
1027
+ module.set.date(undefined);
1028
+ },
1029
+
1030
+ popup: function () {
1031
+ return $activator.popup.apply($activator, arguments);
1032
+ },
1033
+
1034
+ focus: function () {
1035
+ if ($input.length) {
1036
+ $input.trigger('focus');
1037
+ } else {
1038
+ $container.trigger('focus');
411
1039
  }
412
- } else {
413
- eventDate = module.helper.findDayAsObject(cellDate, mode, settings.eventDates);
414
- if (eventDate !== null) {
415
- cell.addClass(eventDate[metadata.class] || settings.eventClass);
416
- if (eventDate[metadata.message]) {
417
- cell.attr("data-tooltip", eventDate[metadata.message]);
418
- cell.attr("data-position", eventDate[metadata.position] || tooltipPosition);
419
- if(eventDate[metadata.inverted] || (isInverted && eventDate[metadata.inverted] === undefined)) {
420
- cell.attr("data-inverted", '');
421
- }
422
- if(eventDate[metadata.variation]) {
423
- cell.attr("data-variation", eventDate[metadata.variation]);
424
- }
425
- }
1040
+ },
1041
+ blur: function () {
1042
+ if ($input.length) {
1043
+ $input.trigger('blur');
1044
+ } else {
1045
+ $container.trigger('blur');
426
1046
  }
427
- }
428
- var active = module.helper.dateEqual(cellDate, date, mode);
429
- var isToday = module.helper.dateEqual(cellDate, today, mode);
430
- cell.toggleClass(className.adjacentCell, adjacent && !eventDate);
431
- cell.toggleClass(className.disabledCell, disabled);
432
- cell.toggleClass(className.activeCell, active && !(adjacent && disabled));
433
- if (!isHour && !isMinute) {
434
- cell.toggleClass(className.todayCell, !adjacent && isToday);
435
- }
436
-
437
- // Allow for external modifications of each cell
438
- var cellOptions = {
439
- mode: mode,
440
- adjacent: adjacent,
441
- disabled: disabled,
442
- active: active,
443
- today: isToday
444
- };
445
- formatter.cell(cell, cellDate, cellOptions);
446
-
447
- if (module.helper.dateEqual(cellDate, focusDate, mode)) {
448
- //ensure that the focus date is exactly equal to the cell date
449
- //so that, if selected, the correct value is set
450
- module.set.focusDate(cellDate, false, false);
451
- }
452
- }
453
- }
1047
+ },
454
1048
 
455
- if (settings.today) {
456
- var todayRow = $('<tr/>').appendTo(tbody);
457
- var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
458
- todayButton.text(formatter.today(settings));
459
- todayButton.data(metadata.date, today);
460
- }
1049
+ helper: {
1050
+ dateFormat: function (format, date) {
1051
+ if (!(date instanceof Date)) {
1052
+ return '';
1053
+ }
1054
+ if (typeof format === 'function') {
1055
+ return format.call(module, date, settings);
1056
+ }
461
1057
 
462
- module.update.focus(false, table);
1058
+ var
1059
+ D = date.getDate(),
1060
+ M = date.getMonth(),
1061
+ Y = date.getFullYear(),
1062
+ d = date.getDay(),
1063
+ H = date.getHours(),
1064
+ m = date.getMinutes(),
1065
+ s = date.getSeconds(),
1066
+ w = module.get.weekOfYear(Y, M, D + 1 - settings.firstDayOfWeek),
1067
+ h = H % 12 || 12,
1068
+ a = H < 12 ? settings.text.am.toLowerCase() : settings.text.pm.toLowerCase(),
1069
+ tokens = {
1070
+ D: D,
1071
+ DD: ('0' + D).slice(-2),
1072
+ M: M + 1,
1073
+ MM: ('0' + (M + 1)).slice(-2),
1074
+ MMM: settings.text.monthsShort[M],
1075
+ MMMM: settings.text.months[M],
1076
+ Y: Y,
1077
+ YY: String(Y).slice(2),
1078
+ YYYY: Y,
1079
+ d: d,
1080
+ dd: settings.text.dayNamesShort[d].slice(0, 2),
1081
+ ddd: settings.text.dayNamesShort[d],
1082
+ dddd: settings.text.dayNames[d],
1083
+ h: h,
1084
+ hh: ('0' + h).slice(-2),
1085
+ H: H,
1086
+ HH: ('0' + H).slice(-2),
1087
+ m: m,
1088
+ mm: ('0' + m).slice(-2),
1089
+ s: s,
1090
+ ss: ('0' + s).slice(-2),
1091
+ a: a,
1092
+ A: a.toUpperCase(),
1093
+ S: ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D % 100 - D % 10 !== 10) * D % 10],
1094
+ w: w,
1095
+ ww: ('0' + w).slice(-2),
1096
+ }
1097
+ ;
1098
+
1099
+ return format.replace(settings.regExp.token, function (match) {
1100
+ if (match in tokens) {
1101
+ return tokens[match];
1102
+ }
1103
+
1104
+ return match.slice(1, match.length - 1);
1105
+ });
1106
+ },
1107
+ isDisabled: function (date, mode) {
1108
+ return (mode === 'day' || mode === 'month' || mode === 'year' || mode === 'hour') && (((mode === 'day' && settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function (d) {
1109
+ if (typeof d === 'string') {
1110
+ d = module.helper.sanitiseDate(d);
1111
+ }
1112
+ if (d instanceof Date) {
1113
+ return module.helper.dateEqual(date, d, mode);
1114
+ }
1115
+ if (d !== null && typeof d === 'object') {
1116
+ if (d[metadata.year]) {
1117
+ if (typeof d[metadata.year] === 'number') {
1118
+ return date.getFullYear() == d[metadata.year];
1119
+ } else if (Array.isArray(d[metadata.year])) {
1120
+ return d[metadata.year].indexOf(date.getFullYear()) > -1;
1121
+ }
1122
+ } else if (d[metadata.month]) {
1123
+ if (typeof d[metadata.month] === 'number') {
1124
+ return date.getMonth() == d[metadata.month];
1125
+ } else if (Array.isArray(d[metadata.month])) {
1126
+ return d[metadata.month].indexOf(date.getMonth()) > -1;
1127
+ } else if (d[metadata.month] instanceof Date) {
1128
+ var sdate = module.helper.sanitiseDate(d[metadata.month]);
1129
+
1130
+ return (date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear());
1131
+ }
1132
+ } else if (d[metadata.date] && mode === 'day') {
1133
+ if (d[metadata.date] instanceof Date) {
1134
+ return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
1135
+ } else if (Array.isArray(d[metadata.date])) {
1136
+ return d[metadata.date].some(function (idate) {
1137
+ return module.helper.dateEqual(date, idate, mode);
1138
+ });
1139
+ }
1140
+ }
1141
+ }
1142
+ })) || (mode === 'hour' && settings.disabledHours.some(function (d) {
1143
+ if (typeof d === 'string') {
1144
+ d = module.helper.sanitiseDate(d);
1145
+ }
1146
+ if (d instanceof Date) {
1147
+ return module.helper.dateEqual(date, d, mode);
1148
+ } else if (typeof d === 'number') {
1149
+ return date.getHours() === d;
1150
+ }
1151
+ if (d !== null && typeof d === 'object') {
1152
+ var blocked = true;
1153
+
1154
+ if (d[metadata.date]) {
1155
+ if (d[metadata.date] instanceof Date) {
1156
+ blocked = module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]));
1157
+ } else if (Array.isArray(d[metadata.date])) {
1158
+ return d[metadata.date].some(function (idate) {
1159
+ blocked = module.helper.dateEqual(date, idate, mode);
1160
+ });
1161
+ }
1162
+ }
1163
+
1164
+ if (d[metadata.days]) {
1165
+ if (typeof d[metadata.days] === 'number') {
1166
+ blocked = date.getDay() == d[metadata.days];
1167
+ } else if (Array.isArray(d[metadata.days])) {
1168
+ blocked = d[metadata.days].indexOf(date.getDay()) > -1;
1169
+ }
1170
+ }
1171
+
1172
+ if (d[metadata.hours]) {
1173
+ if (typeof d[metadata.hours] === 'number') {
1174
+ return blocked && date.getHours() == d[metadata.hours];
1175
+ } else if (Array.isArray(d[metadata.hours])) {
1176
+ return blocked && d[metadata.hours].indexOf(date.getHours()) > -1;
1177
+ }
1178
+ }
1179
+ }
1180
+ })));
1181
+ },
1182
+ isEnabled: function (date, mode) {
1183
+ if (mode === 'day') {
1184
+ return settings.enabledDates.length === 0 || settings.enabledDates.some(function (d) {
1185
+ if (typeof d === 'string') {
1186
+ d = module.helper.sanitiseDate(d);
1187
+ }
1188
+ if (d instanceof Date) {
1189
+ return module.helper.dateEqual(date, d, mode);
1190
+ }
1191
+ if (d !== null && typeof d === 'object' && d[metadata.date]) {
1192
+ return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
1193
+ }
1194
+ });
1195
+ } else {
1196
+ return true;
1197
+ }
1198
+ },
1199
+ findDayAsObject: function (date, mode, dates) {
1200
+ if (mode === 'day' || mode === 'month' || mode === 'year') {
1201
+ var d;
1202
+ for (var i = 0; i < dates.length; i++) {
1203
+ d = dates[i];
1204
+ if (typeof d === 'string') {
1205
+ d = module.helper.sanitiseDate(d);
1206
+ }
1207
+ if (d instanceof Date && module.helper.dateEqual(date, d, mode)) {
1208
+ var dateObject = {};
1209
+ dateObject[metadata.date] = d;
1210
+
1211
+ return dateObject;
1212
+ } else if (d !== null && typeof d === 'object') {
1213
+ if (d[metadata.year]) {
1214
+ if (typeof d[metadata.year] === 'number' && date.getFullYear() == d[metadata.year]) {
1215
+ return d;
1216
+ } else if (Array.isArray(d[metadata.year])) {
1217
+ if (d[metadata.year].indexOf(date.getFullYear()) > -1) {
1218
+ return d;
1219
+ }
1220
+ }
1221
+ } else if (d[metadata.month]) {
1222
+ if (typeof d[metadata.month] === 'number' && date.getMonth() == d[metadata.month]) {
1223
+ return d;
1224
+ } else if (Array.isArray(d[metadata.month])) {
1225
+ if (d[metadata.month].indexOf(date.getMonth()) > -1) {
1226
+ return d;
1227
+ }
1228
+ } else if (d[metadata.month] instanceof Date) {
1229
+ var sdate = module.helper.sanitiseDate(d[metadata.month]);
1230
+ if ((date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())) {
1231
+ return d;
1232
+ }
1233
+ }
1234
+ } else if (d[metadata.date] && mode === 'day') {
1235
+ if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode)) {
1236
+ return d;
1237
+ } else if (Array.isArray(d[metadata.date])) {
1238
+ if (d[metadata.date].some(function (idate) {
1239
+ return module.helper.dateEqual(date, idate, mode);
1240
+ })) {
1241
+ return d;
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ }
1247
+ }
463
1248
 
464
- if(settings.inline){
465
- module.refreshTooltips();
466
- }
467
- }
468
- }
469
- },
1249
+ return null;
1250
+ },
1251
+ findHourAsObject: function (date, mode, hours) {
1252
+ if (mode === 'hour') {
1253
+ var d;
1254
+ var hourCheck = function (date, d) {
1255
+ if (d[metadata.hours]) {
1256
+ if (typeof d[metadata.hours] === 'number' && date.getHours() == d[metadata.hours]) {
1257
+ return d;
1258
+ } else if (Array.isArray(d[metadata.hours])) {
1259
+ if (d[metadata.hours].indexOf(date.getHours()) > -1) {
1260
+ return d;
1261
+ }
1262
+ }
1263
+ }
1264
+ };
1265
+ for (var i = 0; i < hours.length; i++) {
1266
+ d = hours[i];
1267
+ if (typeof d === 'number' && date.getHours() == d) {
1268
+ return null;
1269
+ } else if (d !== null && typeof d === 'object') {
1270
+ if (d[metadata.days] && hourCheck(date, d)) {
1271
+ if (typeof d[metadata.days] === 'number' && date.getDay() == d[metadata.days]) {
1272
+ return d;
1273
+ } else if (Array.isArray(d[metadata.days])) {
1274
+ if (d[metadata.days].indexOf(date.getDay()) > -1) {
1275
+ return d;
1276
+ }
1277
+ }
1278
+ } else if (d[metadata.date] && hourCheck(date, d)) {
1279
+ if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]))) {
1280
+ return d;
1281
+ } else if (Array.isArray(d[metadata.date])) {
1282
+ if (d[metadata.date].some(function (idate) {
1283
+ return module.helper.dateEqual(date, idate, mode);
1284
+ })) {
1285
+ return d;
1286
+ }
1287
+ }
1288
+ } else if (hourCheck(date, d)) {
1289
+ return d;
1290
+ }
1291
+ }
1292
+ }
1293
+ }
470
1294
 
471
- update: {
472
- focus: function (updateRange, container) {
473
- container = container || $container;
474
- var mode = module.get.mode();
475
- var date = module.get.date();
476
- var focusDate = module.get.focusDate();
477
- var startDate = module.get.startDate();
478
- var endDate = module.get.endDate();
479
- var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
480
-
481
- container.find('td').each(function () {
482
- var $cell = $(this);
483
- var cellDate = $cell.data(metadata.date);
484
- if (!cellDate) {
485
- return;
486
- }
487
- var disabled = $cell.hasClass(className.disabledCell);
488
- var active = $cell.hasClass(className.activeCell);
489
- var adjacent = $cell.hasClass(className.adjacentCell);
490
- var focused = module.helper.dateEqual(cellDate, focusDate, mode);
491
- var inRange = !rangeDate ? false :
492
- ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
493
- (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
494
- $cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
495
-
496
- if (module.helper.isTodayButton($cell)) {
497
- return;
498
- }
499
- $cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
500
- });
501
- }
502
- },
1295
+ return null;
1296
+ },
1297
+ sanitiseDate: function (date) {
1298
+ if (!(date instanceof Date)) {
1299
+ date = parser.date('' + date, settings);
1300
+ }
1301
+ if (!date || isNaN(date.getTime())) {
1302
+ return null;
1303
+ }
503
1304
 
504
- refresh: function () {
505
- module.create.calendar();
506
- },
1305
+ return date;
1306
+ },
1307
+ dateDiff: function (date1, date2, mode) {
1308
+ mode = mode || 'day';
1309
+ var isTimeOnly = settings.type === 'time';
1310
+ var isYear = mode === 'year';
1311
+ var isYearOrMonth = isYear || mode === 'month';
1312
+ var isMinute = mode === 'minute';
1313
+ var isHourOrMinute = isMinute || mode === 'hour';
1314
+ // only care about a minute accuracy of settings.minTimeGap
1315
+ date1 = new Date(
1316
+ isTimeOnly ? 2000 : date1.getFullYear(),
1317
+ isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
1318
+ isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
1319
+ !isHourOrMinute ? 0 : date1.getHours(),
1320
+ !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap)
1321
+ );
1322
+ date2 = new Date(
1323
+ isTimeOnly ? 2000 : date2.getFullYear(),
1324
+ isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
1325
+ isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
1326
+ !isHourOrMinute ? 0 : date2.getHours(),
1327
+ !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap)
1328
+ );
1329
+
1330
+ return date2.getTime() - date1.getTime();
1331
+ },
1332
+ dateEqual: function (date1, date2, mode) {
1333
+ return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
1334
+ },
1335
+ isDateInRange: function (date, mode, minDate, maxDate) {
1336
+ if (!minDate && !maxDate) {
1337
+ var startDate = module.get.startDate();
1338
+ minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
1339
+ maxDate = settings.maxDate;
1340
+ }
1341
+ minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
1342
+
1343
+ return !(!date
1344
+ || (minDate && module.helper.dateDiff(date, minDate, mode) > 0)
1345
+ || (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
1346
+ },
1347
+ dateInRange: function (date, minDate, maxDate) {
1348
+ if (!minDate && !maxDate) {
1349
+ var startDate = module.get.startDate();
1350
+ minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
1351
+ maxDate = settings.maxDate;
1352
+ }
1353
+ minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
1354
+ var isTimeOnly = settings.type === 'time';
1355
+
1356
+ return !date
1357
+ ? date
1358
+ : (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0)
1359
+ ? (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate)
1360
+ : (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0)
1361
+ ? (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate)
1362
+ : date;
1363
+ },
1364
+ mergeDateTime: function (date, time) {
1365
+ return (!date || !time)
1366
+ ? time
1367
+ : new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
1368
+ },
1369
+ isTodayButton: function (element) {
1370
+ return element.text() === settings.text.today;
1371
+ },
1372
+ },
1373
+
1374
+ setting: function (name, value) {
1375
+ module.debug('Changing setting', name, value);
1376
+ if ($.isPlainObject(name)) {
1377
+ $.extend(true, settings, name);
1378
+ } else if (value !== undefined) {
1379
+ if ($.isPlainObject(settings[name])) {
1380
+ $.extend(true, settings[name], value);
1381
+ } else {
1382
+ settings[name] = value;
1383
+ }
1384
+ } else {
1385
+ return settings[name];
1386
+ }
1387
+ },
1388
+ internal: function (name, value) {
1389
+ if ($.isPlainObject(name)) {
1390
+ $.extend(true, module, name);
1391
+ } else if (value !== undefined) {
1392
+ module[name] = value;
1393
+ } else {
1394
+ return module[name];
1395
+ }
1396
+ },
1397
+ debug: function () {
1398
+ if (!settings.silent && settings.debug) {
1399
+ if (settings.performance) {
1400
+ module.performance.log(arguments);
1401
+ } else {
1402
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1403
+ module.debug.apply(console, arguments);
1404
+ }
1405
+ }
1406
+ },
1407
+ verbose: function () {
1408
+ if (!settings.silent && settings.verbose && settings.debug) {
1409
+ if (settings.performance) {
1410
+ module.performance.log(arguments);
1411
+ } else {
1412
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1413
+ module.verbose.apply(console, arguments);
1414
+ }
1415
+ }
1416
+ },
1417
+ error: function () {
1418
+ if (!settings.silent) {
1419
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1420
+ module.error.apply(console, arguments);
1421
+ }
1422
+ },
1423
+ performance: {
1424
+ log: function (message) {
1425
+ var
1426
+ currentTime,
1427
+ executionTime,
1428
+ previousTime
1429
+ ;
1430
+ if (settings.performance) {
1431
+ currentTime = new Date().getTime();
1432
+ previousTime = time || currentTime;
1433
+ executionTime = currentTime - previousTime;
1434
+ time = currentTime;
1435
+ performance.push({
1436
+ Name: message[0],
1437
+ Arguments: [].slice.call(message, 1) || '',
1438
+ Element: element,
1439
+ 'Execution Time': executionTime,
1440
+ });
1441
+ }
1442
+ clearTimeout(module.performance.timer);
1443
+ module.performance.timer = setTimeout(module.performance.display, 500);
1444
+ },
1445
+ display: function () {
1446
+ var
1447
+ title = settings.name + ':',
1448
+ totalTime = 0
1449
+ ;
1450
+ time = false;
1451
+ clearTimeout(module.performance.timer);
1452
+ $.each(performance, function (index, data) {
1453
+ totalTime += data['Execution Time'];
1454
+ });
1455
+ title += ' ' + totalTime + 'ms';
1456
+ if (moduleSelector) {
1457
+ title += ' \'' + moduleSelector + '\'';
1458
+ }
1459
+ if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1460
+ console.groupCollapsed(title);
1461
+ if (console.table) {
1462
+ console.table(performance);
1463
+ } else {
1464
+ $.each(performance, function (index, data) {
1465
+ console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
1466
+ });
1467
+ }
1468
+ console.groupEnd();
1469
+ }
1470
+ performance = [];
1471
+ },
1472
+ },
1473
+ invoke: function (query, passedArguments, context) {
1474
+ var
1475
+ object = instance,
1476
+ maxDepth,
1477
+ found,
1478
+ response
1479
+ ;
1480
+ passedArguments = passedArguments || queryArguments;
1481
+ context = context || element;
1482
+ if (typeof query == 'string' && object !== undefined) {
1483
+ query = query.split(/[\. ]/);
1484
+ maxDepth = query.length - 1;
1485
+ $.each(query, function (depth, value) {
1486
+ var camelCaseValue = (depth != maxDepth)
1487
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1488
+ : query
1489
+ ;
1490
+ if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
1491
+ object = object[camelCaseValue];
1492
+ } else if (object[camelCaseValue] !== undefined) {
1493
+ found = object[camelCaseValue];
1494
+
1495
+ return false;
1496
+ } else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
1497
+ object = object[value];
1498
+ } else if (object[value] !== undefined) {
1499
+ found = object[value];
1500
+
1501
+ return false;
1502
+ } else {
1503
+ module.error(error.method, query);
1504
+
1505
+ return false;
1506
+ }
1507
+ });
1508
+ }
1509
+ if (isFunction(found)) {
1510
+ response = found.apply(context, passedArguments);
1511
+ } else if (found !== undefined) {
1512
+ response = found;
1513
+ }
1514
+ if (Array.isArray(returnedValue)) {
1515
+ returnedValue.push(response);
1516
+ } else if (returnedValue !== undefined) {
1517
+ returnedValue = [returnedValue, response];
1518
+ } else if (response !== undefined) {
1519
+ returnedValue = response;
1520
+ }
507
1521
 
508
- refreshTooltips: function() {
509
- var winWidth = $(window).width();
510
- $container.find('td[data-position]').each(function () {
511
- var $cell = $(this);
512
- var tooltipWidth = window.getComputedStyle($cell[0], '::after').width.replace(/[^0-9\.]/g,'');
513
- var tooltipPosition = $cell.attr('data-position');
514
- // use a fallback width of 250 (calendar width) for IE/Edge (which return "auto")
515
- var calcPosition = (winWidth - $cell.width() - (parseInt(tooltipWidth,10) || 250)) > $cell.offset().left ? 'right' : 'left';
516
- if(tooltipPosition.indexOf(calcPosition) === -1) {
517
- $cell.attr('data-position',tooltipPosition.replace(/(left|right)/,calcPosition));
518
- }
519
- });
520
- },
1522
+ return found;
1523
+ },
1524
+ };
521
1525
 
522
- bind: {
523
- events: function () {
524
- module.debug('Binding events');
525
- $container.on('mousedown' + eventNamespace, module.event.mousedown);
526
- $container.on('touchstart' + eventNamespace, module.event.mousedown);
527
- $container.on('mouseup' + eventNamespace, module.event.mouseup);
528
- $container.on('touchend' + eventNamespace, module.event.mouseup);
529
- $container.on('mouseover' + eventNamespace, module.event.mouseover);
530
- if ($input.length) {
531
- $input.on('input' + eventNamespace, module.event.inputChange);
532
- $input.on('focus' + eventNamespace, module.event.inputFocus);
533
- $input.on('blur' + eventNamespace, module.event.inputBlur);
534
- $input.on('keydown' + eventNamespace, module.event.keydown);
1526
+ if (methodInvoked) {
1527
+ if (instance === undefined) {
1528
+ module.initialize();
1529
+ }
1530
+ module.invoke(query);
535
1531
  } else {
536
- $container.on('keydown' + eventNamespace, module.event.keydown);
537
- }
538
- }
1532
+ if (instance !== undefined) {
1533
+ instance.invoke('destroy');
1534
+ }
1535
+ module.initialize();
1536
+ }
1537
+ });
1538
+
1539
+ return (returnedValue !== undefined)
1540
+ ? returnedValue
1541
+ : this;
1542
+ };
1543
+
1544
+ $.fn.calendar.settings = {
1545
+
1546
+ name: 'Calendar',
1547
+ namespace: 'calendar',
1548
+
1549
+ silent: false,
1550
+ debug: false,
1551
+ verbose: false,
1552
+ performance: true,
1553
+
1554
+ context: false,
1555
+
1556
+ type: 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
1557
+ firstDayOfWeek: 0, // day for first day column (0 = Sunday)
1558
+ constantHeight: true, // add rows to shorter months to keep day calendar height consistent (6 rows)
1559
+ today: false, // show a 'today/now' button at the bottom of the calendar
1560
+ closable: true, // close the popup after selecting a date/time
1561
+ monthFirst: true, // month before day when parsing date from text
1562
+ touchReadonly: true, // set input to readonly on touch devices
1563
+ inline: false, // create the calendar inline instead of inside a popup
1564
+ on: null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
1565
+ initialDate: null, // date to display initially when no date is selected (null = now)
1566
+ startMode: false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
1567
+ minDate: null, // minimum date/time that can be selected, dates/times before are disabled
1568
+ maxDate: null, // maximum date/time that can be selected, dates/times after are disabled
1569
+ disableYear: false, // disable year selection mode
1570
+ disableMonth: false, // disable month selection mode
1571
+ disableMinute: false, // disable minute selection mode
1572
+ formatInput: true, // format the input text upon input blur and module creation
1573
+ startCalendar: null, // jquery object or selector for another calendar that represents the start date of a date range
1574
+ endCalendar: null, // jquery object or selector for another calendar that represents the end date of a date range
1575
+ multiMonth: 1, // show multiple months when in 'day' mode
1576
+ monthOffset: 0, // position current month by offset when multimonth > 1
1577
+ minTimeGap: 5,
1578
+ showWeekNumbers: false, // show Number of Week at the very first column of a dayView
1579
+ disabledHours: [], // specific hour(s) which won't be selectable and contain additional information.
1580
+ disabledDates: [], // specific day(s) which won't be selectable and contain additional information.
1581
+ disabledDaysOfWeek: [], // day(s) which won't be selectable(s) (0 = Sunday)
1582
+ enabledDates: [], // specific day(s) which will be selectable, all other days will be disabled
1583
+ eventDates: [], // specific day(s) which will be shown in a different color and using tooltips
1584
+ centuryBreak: 60, // starting short year until 99 where it will be assumed to belong to the last century
1585
+ currentCentury: 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
1586
+ selectAdjacentDays: false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
1587
+ // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
1588
+ popupOptions: {
1589
+ position: 'bottom left',
1590
+ lastResort: 'bottom left',
1591
+ prefer: 'opposite',
1592
+ observeChanges: false,
1593
+ hideOnScroll: false,
539
1594
  },
540
1595
 
541
- unbind: {
542
- events: function () {
543
- module.debug('Unbinding events');
544
- $container.off(eventNamespace);
545
- if ($input.length) {
546
- $input.off(eventNamespace);
547
- }
548
- }
1596
+ text: {
1597
+ days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
1598
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
1599
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1600
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1601
+ monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1602
+ today: 'Today',
1603
+ now: 'Now',
1604
+ am: 'AM',
1605
+ pm: 'PM',
1606
+ weekNo: 'Week',
549
1607
  },
550
1608
 
551
- event: {
552
- mouseover: function (event) {
553
- var target = $(event.target);
554
- var date = target.data(metadata.date);
555
- var mousedown = event.buttons === 1;
556
- if (date) {
557
- module.set.focusDate(date, false, true, mousedown);
558
- }
559
- },
560
- mousedown: function (event) {
561
- if ($input.length) {
562
- //prevent the mousedown on the calendar causing the input to lose focus
563
- event.preventDefault();
564
- }
565
- isTouchDown = event.type.indexOf('touch') >= 0;
566
- var target = $(event.target);
567
- var date = target.data(metadata.date);
568
- if (date) {
569
- module.set.focusDate(date, false, true, true);
570
- }
571
- },
572
- mouseup: function (event) {
573
- //ensure input has focus so that it receives keydown events for calendar navigation
574
- module.focus();
575
- event.preventDefault();
576
- event.stopPropagation();
577
- isTouchDown = false;
578
- var target = $(event.target);
579
- if (target.hasClass("disabled")) {
580
- return;
581
- }
582
- var parent = target.parent();
583
- if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
584
- //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
585
- target = parent;
586
- }
587
- var date = target.data(metadata.date);
588
- var focusDate = target.data(metadata.focusDate);
589
- var mode = target.data(metadata.mode);
590
- if (date && settings.onSelect.call(element, date, module.get.mode()) !== false) {
591
- var forceSet = target.hasClass(className.today);
592
- module.selectDate(date, forceSet);
593
- }
594
- else if (focusDate) {
595
- module.set.focusDate(focusDate);
596
- }
597
- else if (mode) {
598
- module.set.mode(mode);
599
- }
600
- },
601
- keydown: function (event) {
602
- var keyCode = event.which;
603
- if (keyCode === 9) {
604
- //tab
605
- module.popup('hide');
606
- }
1609
+ formatter: {
1610
+ yearHeader: function (date, settings) {
1611
+ var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
1612
+
1613
+ return (decadeYear - 9) + ' - ' + (decadeYear + 2);
1614
+ },
1615
+ monthHeader: 'YYYY',
1616
+ dayHeader: 'MMMM YYYY',
1617
+ hourHeader: 'MMMM D, YYYY',
1618
+ minuteHeader: 'MMMM D, YYYY',
1619
+ dayColumnHeader: function (day, settings) {
1620
+ return settings.text.days[day];
1621
+ },
1622
+ datetime: 'MMMM D, YYYY h:mm A',
1623
+ date: 'MMMM D, YYYY',
1624
+ time: 'h:mm A',
1625
+ cellTime: 'h:mm A',
1626
+ month: 'MMMM YYYY',
1627
+ year: 'YYYY',
1628
+ today: function (settings) {
1629
+ return settings.type === 'date' ? settings.text.today : settings.text.now;
1630
+ },
1631
+ cell: function (cell, date, cellOptions) {
1632
+ },
1633
+ },
607
1634
 
608
- if (module.popup('is visible')) {
609
- var mode = module.get.mode();
610
- if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
611
- //arrow keys
612
- var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
613
- var increment = keyCode === 37 ? -1 : keyCode === 38 ? -bigIncrement : keyCode == 39 ? 1 : bigIncrement;
614
- increment *= mode === 'minute' ? settings.minTimeGap : 1;
615
- var focusDate = module.get.focusDate() || module.get.date() || new Date();
616
- var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
617
- var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
618
- var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
619
- var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
620
- var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
621
- var newFocusDate = new Date(year, month, day, hour, minute);
622
- if (settings.type === 'time') {
623
- newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
1635
+ parser: {
1636
+ date: function (text, settings) {
1637
+ if (text instanceof Date) {
1638
+ return text;
624
1639
  }
625
- if (module.helper.isDateInRange(newFocusDate, mode)) {
626
- module.set.focusDate(newFocusDate);
1640
+ if (!text) {
1641
+ return null;
627
1642
  }
628
- } else if (keyCode === 13) {
629
- //enter
630
- var date = module.get.focusDate();
631
- if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
632
- if (settings.onSelect.call(element, date, module.get.mode()) !== false) {
633
- module.selectDate(date);
634
- }
1643
+ text = String(text).trim().replace(/([.:\/\-])\s+/g, '$1').replace(/\s+([.:\/-])/g, '$1').replace(/\s+/g, ' ');
1644
+ if (text.length === 0) {
1645
+ return null;
635
1646
  }
636
- //disable form submission:
637
- event.preventDefault();
638
- event.stopPropagation();
639
- } else if (keyCode === 27) {
640
- module.popup('hide');
641
- event.stopPropagation();
642
- }
643
- }
644
-
645
- if (keyCode === 38 || keyCode === 40) {
646
- //arrow-up || arrow-down
647
- event.preventDefault(); //don't scroll
648
- module.popup('show');
649
- }
650
- },
651
- inputChange: function () {
652
- var val = $input.val();
653
- var date = parser.date(val, settings);
654
- module.set.date(date, false);
655
- },
656
- inputFocus: function () {
657
- $container.addClass(className.active);
658
- },
659
- inputBlur: function () {
660
- $container.removeClass(className.active);
661
- if (settings.formatInput) {
662
- var date = module.get.date();
663
- var text = module.helper.dateFormat(formatter[settings.type], date);
664
- $input.val(text);
665
- }
666
- if(selectionComplete){
667
- module.trigger.change();
668
- selectionComplete = false;
669
- }
670
- },
671
- class: {
672
- mutation: function(mutations) {
673
- mutations.forEach(function(mutation) {
674
- if(mutation.attributeName === "class") {
675
- module.check.disabled();
1647
+ if (text.match(/^[0-9]{4}[\/\-\.][0-9]{1,2}[\/\-\.][0-9]{1,2}$/)) {
1648
+ text = text.replace(/[\/\-\.]/g, '/') + ' 00:00:00';
676
1649
  }
677
- });
678
- }
679
- }
680
- },
1650
+ // Reverse date and month in some cases
1651
+ text = settings.monthFirst || !text.match(/^[0-9]{1,2}[\/\-\.]/) ? text : text.replace(/[\/\-\.]/g, '/').replace(/([0-9]+)\/([0-9]+)/, '$2/$1');
1652
+ var textDate = new Date(text);
1653
+ var numberOnly = text.match(/^[0-9]+$/) !== null;
1654
+ if (!numberOnly && !isNaN(textDate.getDate())) {
1655
+ return textDate;
1656
+ }
1657
+ text = text.toLowerCase();
681
1658
 
682
- observeChanges: function() {
683
- if('MutationObserver' in window) {
684
- classObserver = new MutationObserver(module.event.class.mutation);
685
- module.debug('Setting up mutation observer', classObserver);
686
- module.observe.class();
687
- }
688
- },
1659
+ var
1660
+ i,
1661
+ j,
1662
+ k
1663
+ ;
1664
+ var
1665
+ minute = -1,
1666
+ hour = -1,
1667
+ day = -1,
1668
+ month = -1,
1669
+ year = -1
1670
+ ;
1671
+ var isAm = undefined;
689
1672
 
690
- disconnect: {
691
- classObserver: function() {
692
- if($input.length && classObserver) {
693
- classObserver.disconnect();
694
- }
695
- }
696
- },
1673
+ var isTimeOnly = settings.type === 'time';
1674
+ var isDateOnly = settings.type.indexOf('time') < 0;
697
1675
 
698
- observe: {
699
- class: function() {
700
- if($input.length && classObserver) {
701
- classObserver.observe($module[0], {
702
- attributes : true
703
- });
704
- }
705
- }
706
- },
1676
+ var
1677
+ words = text.split(settings.regExp.dateWords),
1678
+ word
1679
+ ;
1680
+ var
1681
+ numbers = text.split(settings.regExp.dateNumbers),
1682
+ number
1683
+ ;
707
1684
 
708
- is: {
709
- disabled: function() {
710
- return $module.hasClass(className.disabled);
711
- }
712
- },
1685
+ var parts;
1686
+ var monthString;
1687
+
1688
+ if (!isDateOnly) {
1689
+ // am/pm
1690
+ isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0
1691
+ ? true
1692
+ : $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
1693
+
1694
+ // time with ':'
1695
+ for (i = 0; i < numbers.length; i++) {
1696
+ number = numbers[i];
1697
+ if (number.indexOf(':') >= 0) {
1698
+ if (hour < 0 || minute < 0) {
1699
+ parts = number.split(':');
1700
+ for (k = 0; k < Math.min(2, parts.length); k++) {
1701
+ j = parseInt(parts[k]);
1702
+ if (isNaN(j)) {
1703
+ j = 0;
1704
+ }
1705
+ if (k === 0) {
1706
+ hour = j % 24;
1707
+ } else {
1708
+ minute = j % 60;
1709
+ }
1710
+ }
1711
+ }
1712
+ numbers.splice(i, 1);
1713
+ }
1714
+ }
1715
+ }
713
1716
 
714
- check: {
715
- disabled: function(){
716
- $input.attr('tabindex',module.is.disabled() ? -1 : 0);
717
- }
718
- },
1717
+ if (!isTimeOnly) {
1718
+ // textual month
1719
+ for (i = 0; i < words.length; i++) {
1720
+ word = words[i];
1721
+ if (word.length <= 0) {
1722
+ continue;
1723
+ }
1724
+ for (j = 0; j < settings.text.months.length; j++) {
1725
+ monthString = settings.text.months[j];
1726
+ monthString = monthString.substring(0, word.length).toLowerCase();
1727
+ if (monthString === word) {
1728
+ month = j + 1;
1729
+
1730
+ break;
1731
+ }
1732
+ }
1733
+ if (month >= 0) {
1734
+ break;
1735
+ }
1736
+ }
719
1737
 
720
- get: {
721
- weekOfYear: function(weekYear,weekMonth,weekDay) {
722
- // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
723
- var ms1d = 864e5, // milliseconds in a day
724
- ms7d = 7 * ms1d; // milliseconds in a week
725
-
726
- return function() { // return a closure so constants get calculated only once
727
- var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
728
- AWN = Math.floor(DC3 / 7), // an Absolute Week Number
729
- Wyr = new Date(AWN * ms7d).getUTCFullYear();
730
-
731
- return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
732
- }();
733
- },
734
- formattedDate: function(format, date) {
735
- return module.helper.dateFormat(format || formatter[settings.type], date || module.get.date());
736
- },
737
- date: function () {
738
- return module.helper.sanitiseDate($module.data(metadata.date)) || null;
739
- },
740
- inputDate: function() {
741
- return $input.val();
742
- },
743
- focusDate: function () {
744
- return $module.data(metadata.focusDate) || null;
745
- },
746
- startDate: function () {
747
- var startModule = module.get.calendarModule(settings.startCalendar);
748
- return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
749
- },
750
- endDate: function () {
751
- var endModule = module.get.calendarModule(settings.endCalendar);
752
- return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
753
- },
754
- minDate: function() {
755
- return $module.data(metadata.minDate) || null;
756
- },
757
- maxDate: function() {
758
- return $module.data(metadata.maxDate) || null;
759
- },
760
- monthOffset: function () {
761
- return $module.data(metadata.monthOffset) || settings.monthOffset || 0;
762
- },
763
- mode: function () {
764
- //only returns valid modes for the current settings
765
- var mode = $module.data(metadata.mode) || settings.startMode;
766
- return module.get.validatedMode(mode);
767
- },
768
- validatedMode: function(mode){
769
- var validModes = module.get.validModes();
770
- if ($.inArray(mode, validModes) >= 0) {
771
- return mode;
772
- }
773
- return settings.type === 'time' ? 'hour' :
774
- settings.type === 'month' ? 'month' :
775
- settings.type === 'year' ? 'year' : 'day';
776
- },
777
- type: function() {
778
- return $module.data(metadata.type) || settings.type;
779
- },
780
- validModes: function () {
781
- var validModes = [];
782
- if (settings.type !== 'time') {
783
- if (!settings.disableYear || settings.type === 'year') {
784
- validModes.push('year');
785
- }
786
- if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
787
- validModes.push('month');
788
- }
789
- if (settings.type.indexOf('date') >= 0) {
790
- validModes.push('day');
791
- }
792
- }
793
- if (settings.type.indexOf('time') >= 0) {
794
- validModes.push('hour');
795
- if (!settings.disableMinute) {
796
- validModes.push('minute');
797
- }
798
- }
799
- return validModes;
800
- },
801
- isTouch: function () {
802
- try {
803
- document.createEvent('TouchEvent');
804
- return true;
805
- }
806
- catch (e) {
807
- return false;
808
- }
809
- },
810
- calendarModule: function (selector) {
811
- if (!selector) {
812
- return null;
813
- }
814
- if (!(selector instanceof $)) {
815
- selector = $document.find(selector).first();
816
- }
817
- //assume range related calendars are using the same namespace
818
- return selector.data(moduleNamespace);
819
- }
820
- },
1738
+ // year > settings.centuryBreak
1739
+ for (i = 0; i < numbers.length; i++) {
1740
+ j = parseInt(numbers[i]);
1741
+ if (isNaN(j)) {
1742
+ continue;
1743
+ }
1744
+ if (j >= settings.centuryBreak && i === numbers.length - 1) {
1745
+ if (j <= 99) {
1746
+ j += settings.currentCentury - 100;
1747
+ }
1748
+ year = j;
1749
+ numbers.splice(i, 1);
1750
+
1751
+ break;
1752
+ }
1753
+ }
821
1754
 
822
- set: {
823
- date: function (date, updateInput, fireChange) {
824
- updateInput = updateInput !== false;
825
- fireChange = fireChange !== false;
826
- date = module.helper.sanitiseDate(date);
827
- date = module.helper.dateInRange(date);
1755
+ // numeric month
1756
+ if (month < 0) {
1757
+ for (i = 0; i < numbers.length; i++) {
1758
+ k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
1759
+ j = parseInt(numbers[k]);
1760
+ if (isNaN(j)) {
1761
+ continue;
1762
+ }
1763
+ if (1 <= j && j <= 12) {
1764
+ month = j;
1765
+ numbers.splice(k, 1);
1766
+
1767
+ break;
1768
+ }
1769
+ }
1770
+ }
828
1771
 
829
- var mode = module.get.mode();
830
- var text = module.helper.dateFormat(formatter[settings.type],date);
1772
+ // day
1773
+ for (i = 0; i < numbers.length; i++) {
1774
+ j = parseInt(numbers[i]);
1775
+ if (isNaN(j)) {
1776
+ continue;
1777
+ }
1778
+ if (1 <= j && j <= 31) {
1779
+ day = j;
1780
+ numbers.splice(i, 1);
831
1781
 
832
- if (fireChange && settings.onBeforeChange.call(element, date, text, mode) === false) {
833
- return false;
834
- }
1782
+ break;
1783
+ }
1784
+ }
835
1785
 
836
- module.set.focusDate(date);
1786
+ // year <= settings.centuryBreak
1787
+ if (year < 0) {
1788
+ for (i = numbers.length - 1; i >= 0; i--) {
1789
+ j = parseInt(numbers[i]);
1790
+ if (isNaN(j)) {
1791
+ continue;
1792
+ }
1793
+ if (j <= 99) {
1794
+ j += settings.currentCentury;
1795
+ }
1796
+ year = j;
1797
+ numbers.splice(i, 1);
1798
+
1799
+ break;
1800
+ }
1801
+ }
1802
+ }
837
1803
 
838
- if (settings.isDisabled(date, mode)) {
839
- return false;
840
- }
1804
+ if (!isDateOnly) {
1805
+ // hour
1806
+ if (hour < 0) {
1807
+ for (i = 0; i < numbers.length; i++) {
1808
+ j = parseInt(numbers[i]);
1809
+ if (isNaN(j)) {
1810
+ continue;
1811
+ }
1812
+ if (0 <= j && j <= 23) {
1813
+ hour = j;
1814
+ numbers.splice(i, 1);
1815
+
1816
+ break;
1817
+ }
1818
+ }
1819
+ }
841
1820
 
842
- var endDate = module.get.endDate();
843
- if (!!endDate && !!date && date > endDate) {
844
- //selected date is greater than end date in range, so clear end date
845
- module.set.endDate(undefined);
846
- }
847
- module.set.dataKeyValue(metadata.date, date);
1821
+ // minute
1822
+ if (minute < 0) {
1823
+ for (i = 0; i < numbers.length; i++) {
1824
+ j = parseInt(numbers[i]);
1825
+ if (isNaN(j)) {
1826
+ continue;
1827
+ }
1828
+ if (0 <= j && j <= 59) {
1829
+ minute = j;
1830
+ numbers.splice(i, 1);
1831
+
1832
+ break;
1833
+ }
1834
+ }
1835
+ }
1836
+ }
848
1837
 
849
- if (updateInput && $input.length) {
850
- $input.val(text);
851
- }
1838
+ if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
1839
+ return null;
1840
+ }
852
1841
 
853
- if (fireChange) {
854
- settings.onChange.call(element, date, text, mode);
855
- }
856
- },
857
- startDate: function (date, refreshCalendar) {
858
- date = module.helper.sanitiseDate(date);
859
- var startModule = module.get.calendarModule(settings.startCalendar);
860
- if (startModule) {
861
- startModule.set.date(date);
862
- }
863
- module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
864
- },
865
- endDate: function (date, refreshCalendar) {
866
- date = module.helper.sanitiseDate(date);
867
- var endModule = module.get.calendarModule(settings.endCalendar);
868
- if (endModule) {
869
- endModule.set.date(date);
870
- }
871
- module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
872
- },
873
- focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
874
- date = module.helper.sanitiseDate(date);
875
- date = module.helper.dateInRange(date);
876
- var isDay = module.get.mode() === 'day';
877
- var oldFocusDate = module.get.focusDate();
878
- if (isDay && date && oldFocusDate) {
879
- var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
880
- var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
881
- if (monthDelta) {
882
- var monthOffset = module.get.monthOffset() - monthDelta;
883
- module.set.monthOffset(monthOffset, false);
884
- }
885
- }
886
- var changed = module.set.dataKeyValue(metadata.focusDate, date, !!date && refreshCalendar);
887
- updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
888
- focusDateUsedForRange = updateRange;
889
- if (updateFocus) {
890
- module.update.focus(updateRange);
891
- }
892
- },
893
- minDate: function (date) {
894
- date = module.helper.sanitiseDate(date);
895
- if (settings.maxDate !== null && settings.maxDate <= date) {
896
- module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
897
- } else {
898
- module.setting('minDate', date);
899
- module.set.dataKeyValue(metadata.minDate, date);
900
- }
901
- },
902
- maxDate: function (date) {
903
- date = module.helper.sanitiseDate(date);
904
- if (settings.minDate !== null && settings.minDate >= date) {
905
- module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
906
- } else {
907
- module.setting('maxDate', date);
908
- module.set.dataKeyValue(metadata.maxDate, date);
909
- }
910
- },
911
- monthOffset: function (monthOffset, refreshCalendar) {
912
- var multiMonth = Math.max(settings.multiMonth, 1);
913
- monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
914
- module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
915
- },
916
- mode: function (mode, refreshCalendar) {
917
- module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
918
- },
919
- dataKeyValue: function (key, value, refreshCalendar) {
920
- var oldValue = $module.data(key);
921
- var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
922
- if (value) {
923
- $module.data(key, value);
924
- } else {
925
- $module.removeData(key);
926
- }
927
- refreshCalendar = refreshCalendar !== false && !equal;
928
- if (refreshCalendar) {
929
- module.refresh();
930
- }
931
- return !equal;
932
- }
933
- },
1842
+ if (minute < 0) {
1843
+ minute = 0;
1844
+ }
1845
+ if (hour < 0) {
1846
+ hour = 0;
1847
+ }
1848
+ if (day < 0) {
1849
+ day = 1;
1850
+ }
1851
+ if (month < 0) {
1852
+ month = 1;
1853
+ }
1854
+ if (year < 0) {
1855
+ year = new Date().getFullYear();
1856
+ }
1857
+
1858
+ if (isAm !== undefined) {
1859
+ if (isAm) {
1860
+ if (hour === 12) {
1861
+ hour = 0;
1862
+ }
1863
+ } else if (hour < 12) {
1864
+ hour += 12;
1865
+ }
1866
+ }
934
1867
 
935
- selectDate: function (date, forceSet) {
936
- module.verbose('New date selection', date);
937
- var mode = module.get.mode();
938
- var complete = forceSet || mode === 'minute' ||
939
- (settings.disableMinute && mode === 'hour') ||
940
- (settings.type === 'date' && mode === 'day') ||
941
- (settings.type === 'month' && mode === 'month') ||
942
- (settings.type === 'year' && mode === 'year');
943
- if (complete) {
944
- var canceled = module.set.date(date) === false;
945
- if (!canceled) {
946
- selectionComplete = true;
947
- if(settings.closable) {
948
- module.popup('hide');
949
- //if this is a range calendar, focus the container or input. This will open the popup from its event listeners.
950
- var endModule = module.get.calendarModule(settings.endCalendar);
951
- if (endModule) {
952
- endModule.refresh();
953
- if (endModule.setting('on') !== 'focus') {
954
- endModule.popup('show');
955
- }
956
- endModule.focus();
1868
+ var date = new Date(year, month - 1, day, hour, minute);
1869
+ if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
1870
+ // month or year don't match up, switch to last day of the month
1871
+ date = new Date(year, month, 0, hour, minute);
957
1872
  }
958
- }
959
- }
960
- } else {
961
- var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
962
- mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
963
- module.set.mode(newMode);
964
- if (mode === 'hour' || (mode === 'day' && module.get.date())) {
965
- //the user has chosen enough to consider a valid date/time has been chosen
966
- module.set.date(date, true, false);
967
- } else {
968
- module.set.focusDate(date);
969
- }
970
- }
971
- },
972
1873
 
973
- changeDate: function (date) {
974
- module.set.date(date);
1874
+ return isNaN(date.getTime()) ? null : date;
1875
+ },
975
1876
  },
976
1877
 
977
- clear: function () {
978
- module.set.date(undefined);
1878
+ // callback before date is changed, return false to cancel the change
1879
+ onBeforeChange: function (date, text, mode) {
1880
+ return true;
979
1881
  },
980
1882
 
981
- popup: function () {
982
- return $activator.popup.apply($activator, arguments);
1883
+ // callback when date changes
1884
+ onChange: function (date, text, mode) {
983
1885
  },
984
1886
 
985
- focus: function () {
986
- if ($input.length) {
987
- $input.trigger('focus');
988
- } else {
989
- $container.trigger('focus');
990
- }
991
- },
992
- blur: function () {
993
- if ($input.length) {
994
- $input.trigger('blur');
995
- } else {
996
- $container.trigger('blur');
997
- }
1887
+ // callback before show animation, return false to prevent show
1888
+ onShow: function () {
998
1889
  },
999
1890
 
1000
- helper: {
1001
- dateFormat: function(format,date) {
1002
- if (!(date instanceof Date)) {
1003
- return '';
1004
- }
1005
- if(typeof format === 'function') {
1006
- return format.call(module, date, settings);
1007
- }
1891
+ // callback after show animation
1892
+ onVisible: function () {
1893
+ },
1008
1894
 
1009
- var D = date.getDate(),
1010
- M = date.getMonth(),
1011
- Y = date.getFullYear(),
1012
- d = date.getDay(),
1013
- H = date.getHours(),
1014
- m = date.getMinutes(),
1015
- s = date.getSeconds(),
1016
- w = module.get.weekOfYear(Y,M,D+1-settings.firstDayOfWeek),
1017
- h = H % 12 || 12,
1018
- a = H < 12 ? settings.text.am.toLowerCase() : settings.text.pm.toLowerCase(),
1019
- tokens = {
1020
- D: D,
1021
- DD: ('0'+D).slice(-2),
1022
- M: M + 1,
1023
- MM: ('0'+(M+1)).slice(-2),
1024
- MMM: settings.text.monthsShort[M],
1025
- MMMM: settings.text.months[M],
1026
- Y: Y,
1027
- YY: String(Y).slice(2),
1028
- YYYY: Y,
1029
- d: d,
1030
- dd: settings.text.dayNamesShort[d].slice(0,2),
1031
- ddd: settings.text.dayNamesShort[d],
1032
- dddd: settings.text.dayNames[d],
1033
- h: h,
1034
- hh: ('0'+h).slice(-2),
1035
- H: H,
1036
- HH: ('0'+H).slice(-2),
1037
- m: m,
1038
- mm: ('0'+m).slice(-2),
1039
- s: s,
1040
- ss: ('0'+s).slice(-2),
1041
- a: a,
1042
- A: a.toUpperCase(),
1043
- S: ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D % 100 - D % 10 !== 10) * D % 10],
1044
- w: w,
1045
- ww: ('0'+w).slice(-2)
1046
- }
1047
- ;
1048
- return format.replace(settings.regExp.token, function (match) {
1049
- if (match in tokens) {
1050
- return tokens[match];
1051
- }
1052
- return match.slice(1, match.length - 1);
1053
- });
1054
- },
1055
- isDisabled: function(date, mode) {
1056
- return (mode === 'day' || mode === 'month' || mode === 'year' || mode === 'hour') && (((mode === 'day' && settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
1057
- if(typeof d === 'string') {
1058
- d = module.helper.sanitiseDate(d);
1059
- }
1060
- if (d instanceof Date) {
1061
- return module.helper.dateEqual(date, d, mode);
1062
- }
1063
- if (d !== null && typeof d === 'object') {
1064
- if (d[metadata.year]) {
1065
- if (typeof d[metadata.year] === 'number') {
1066
- return date.getFullYear() == d[metadata.year];
1067
- } else if (Array.isArray(d[metadata.year])) {
1068
- return d[metadata.year].indexOf(date.getFullYear()) > -1;
1069
- }
1070
- } else if (d[metadata.month]) {
1071
- if (typeof d[metadata.month] === 'number') {
1072
- return date.getMonth() == d[metadata.month];
1073
- } else if (Array.isArray(d[metadata.month])) {
1074
- return d[metadata.month].indexOf(date.getMonth()) > -1;
1075
- } else if (d[metadata.month] instanceof Date) {
1076
- var sdate = module.helper.sanitiseDate(d[metadata.month]);
1077
- return (date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())
1078
- }
1079
- } else if (d[metadata.date] && mode === 'day') {
1080
- if (d[metadata.date] instanceof Date) {
1081
- return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
1082
- } else if (Array.isArray(d[metadata.date])) {
1083
- return d[metadata.date].some(function(idate) {
1084
- return module.helper.dateEqual(date, idate, mode);
1085
- });
1086
- }
1087
- }
1088
- }
1089
- })) || (mode === 'hour' && settings.disabledHours.some(function(d){
1090
- if (typeof d === 'string') {
1091
- d = module.helper.sanitiseDate(d);
1092
- }
1093
- if (d instanceof Date) {
1094
- return module.helper.dateEqual(date, d, mode);
1095
- } else if (typeof d === 'number') {
1096
- return date.getHours() === d;
1097
- }
1098
- if (d !== null && typeof d === 'object') {
1099
- var blocked = true;
1100
-
1101
- if (d[metadata.date]) {
1102
- if (d[metadata.date] instanceof Date) {
1103
- blocked = module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]));
1104
- } else if (Array.isArray(d[metadata.date])) {
1105
- return d[metadata.date].some(function(idate) {
1106
- blocked = module.helper.dateEqual(date, idate, mode);
1107
- });
1108
- }
1109
- }
1895
+ // callback before hide animation, return false to prevent hide
1896
+ onHide: function () {
1897
+ },
1110
1898
 
1111
- if (d[metadata.days]) {
1112
- if (typeof d[metadata.days] === 'number') {
1113
- blocked = date.getDay() == d[metadata.days];
1114
- } else if (Array.isArray(d[metadata.days])) {
1115
- blocked = d[metadata.days].indexOf(date.getDay()) > -1;
1116
- }
1117
- }
1899
+ // callback after hide animation
1900
+ onHidden: function () {
1901
+ },
1118
1902
 
1119
- if (d[metadata.hours]) {
1120
- if (typeof d[metadata.hours] === 'number') {
1121
- return blocked && date.getHours() == d[metadata.hours];
1122
- } else if (Array.isArray(d[metadata.hours])) {
1123
- return blocked && d[metadata.hours].indexOf(date.getHours()) > -1;
1124
- }
1125
- }
1126
- }
1127
- })));
1128
- },
1129
- isEnabled: function(date, mode) {
1130
- if (mode === 'day') {
1131
- return settings.enabledDates.length === 0 || settings.enabledDates.some(function(d){
1132
- if(typeof d === 'string') {
1133
- d = module.helper.sanitiseDate(d);
1134
- }
1135
- if (d instanceof Date) {
1136
- return module.helper.dateEqual(date, d, mode);
1137
- }
1138
- if (d !== null && typeof d === 'object' && d[metadata.date]) {
1139
- return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
1140
- }
1141
- });
1142
- } else {
1143
- return true;
1144
- }
1145
- },
1146
- findDayAsObject: function(date, mode, dates) {
1147
- if (mode === 'day' || mode === 'month' || mode === 'year') {
1148
- var d;
1149
- for (var i = 0; i < dates.length; i++) {
1150
- d = dates[i];
1151
- if(typeof d === 'string') {
1152
- d = module.helper.sanitiseDate(d);
1153
- }
1154
- if (d instanceof Date && module.helper.dateEqual(date, d, mode)) {
1155
- var dateObject = {};
1156
- dateObject[metadata.date] = d;
1157
- return dateObject;
1158
- }
1159
- else if (d !== null && typeof d === 'object') {
1160
- if (d[metadata.year]) {
1161
- if (typeof d[metadata.year] === 'number' && date.getFullYear() == d[metadata.year]) {
1162
- return d;
1163
- } else if (Array.isArray(d[metadata.year])) {
1164
- if (d[metadata.year].indexOf(date.getFullYear()) > -1) {
1165
- return d;
1166
- }
1167
- }
1168
- } else if (d[metadata.month]) {
1169
- if (typeof d[metadata.month] === 'number' && date.getMonth() == d[metadata.month]) {
1170
- return d;
1171
- } else if (Array.isArray(d[metadata.month])) {
1172
- if (d[metadata.month].indexOf(date.getMonth()) > -1) {
1173
- return d;
1174
- }
1175
- } else if (d[metadata.month] instanceof Date) {
1176
- var sdate = module.helper.sanitiseDate(d[metadata.month]);
1177
- if ((date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())) {
1178
- return d;
1179
- }
1180
- }
1181
- } else if (d[metadata.date] && mode === 'day') {
1182
- if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode)) {
1183
- return d;
1184
- } else if (Array.isArray(d[metadata.date])) {
1185
- if(d[metadata.date].some(function(idate) { return module.helper.dateEqual(date, idate, mode); })) {
1186
- return d;
1187
- }
1188
- }
1189
- }
1190
- }
1191
- }
1192
- }
1193
- return null;
1194
- },
1195
- findHourAsObject: function(date, mode, hours) {
1196
- if (mode === 'hour') {
1197
- var d;
1198
- var hourCheck = function(date, d) {
1199
- if (d[metadata.hours]) {
1200
- if (typeof d[metadata.hours] === 'number' && date.getHours() == d[metadata.hours]) {
1201
- return d;
1202
- } else if (Array.isArray(d[metadata.hours])) {
1203
- if (d[metadata.hours].indexOf(date.getHours()) > -1) {
1204
- return d;
1205
- }
1206
- }
1207
- }
1208
- }
1209
- for (var i = 0; i < hours.length; i++) {
1210
- d = hours[i];
1211
- if (typeof d === 'number' && date.getHours() == d) {
1212
- return null;
1213
- } else if (d !== null && typeof d === 'object') {
1214
- if (d[metadata.days] && hourCheck(date,d)) {
1215
- if (typeof d[metadata.days] === 'number' && date.getDay() == d[metadata.days]) {
1216
- return d;
1217
- } else if (Array.isArray(d[metadata.days])) {
1218
- if (d[metadata.days].indexOf(date.getDay()) > -1) {
1219
- return d;
1220
- }
1221
- }
1222
- } else if (d[metadata.date] && hourCheck(date,d)) {
1223
- if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]))) {
1224
- return d;
1225
- } else if (Array.isArray(d[metadata.date])) {
1226
- if (d[metadata.date].some(function(idate) { return module.helper.dateEqual(date, idate, mode); })) {
1227
- return d;
1228
- }
1229
- }
1230
- } else if (hourCheck(date,d)) {
1231
- return d;
1232
- }
1233
- }
1234
- }
1235
- }
1236
- return null;
1237
- },
1238
- sanitiseDate: function (date) {
1239
- if (!(date instanceof Date)) {
1240
- date = parser.date('' + date, settings);
1241
- }
1242
- if (!date || isNaN(date.getTime())) {
1243
- return null;
1244
- }
1245
- return date;
1246
- },
1247
- dateDiff: function (date1, date2, mode) {
1248
- mode = mode || 'day';
1249
- var isTimeOnly = settings.type === 'time';
1250
- var isYear = mode === 'year';
1251
- var isYearOrMonth = isYear || mode === 'month';
1252
- var isMinute = mode === 'minute';
1253
- var isHourOrMinute = isMinute || mode === 'hour';
1254
- //only care about a minute accuracy of settings.minTimeGap
1255
- date1 = new Date(
1256
- isTimeOnly ? 2000 : date1.getFullYear(),
1257
- isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
1258
- isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
1259
- !isHourOrMinute ? 0 : date1.getHours(),
1260
- !isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
1261
- date2 = new Date(
1262
- isTimeOnly ? 2000 : date2.getFullYear(),
1263
- isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
1264
- isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
1265
- !isHourOrMinute ? 0 : date2.getHours(),
1266
- !isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
1267
- return date2.getTime() - date1.getTime();
1268
- },
1269
- dateEqual: function (date1, date2, mode) {
1270
- return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
1271
- },
1272
- isDateInRange: function (date, mode, minDate, maxDate) {
1273
- if (!minDate && !maxDate) {
1274
- var startDate = module.get.startDate();
1275
- minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
1276
- maxDate = settings.maxDate;
1277
- }
1278
- minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
1279
- return !(!date ||
1280
- (minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
1281
- (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
1282
- },
1283
- dateInRange: function (date, minDate, maxDate) {
1284
- if (!minDate && !maxDate) {
1285
- var startDate = module.get.startDate();
1286
- minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
1287
- maxDate = settings.maxDate;
1288
- }
1289
- minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
1290
- var isTimeOnly = settings.type === 'time';
1291
- return !date ? date :
1292
- (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
1293
- (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
1294
- (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
1295
- (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
1296
- date;
1297
- },
1298
- mergeDateTime: function (date, time) {
1299
- return (!date || !time) ? time :
1300
- new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
1301
- },
1302
- isTodayButton: function(element) {
1303
- return element.text() === settings.text.today;
1304
- }
1903
+ // callback before item is selected, return false to prevent selection
1904
+ onSelect: function (date, mode) {
1305
1905
  },
1306
1906
 
1307
- setting: function (name, value) {
1308
- module.debug('Changing setting', name, value);
1309
- if ($.isPlainObject(name)) {
1310
- $.extend(true, settings, name);
1311
- }
1312
- else if (value !== undefined) {
1313
- if ($.isPlainObject(settings[name])) {
1314
- $.extend(true, settings[name], value);
1315
- }
1316
- else {
1317
- settings[name] = value;
1318
- }
1319
- }
1320
- else {
1321
- return settings[name];
1322
- }
1907
+ // is the given date disabled?
1908
+ isDisabled: function (date, mode) {
1909
+ return false;
1323
1910
  },
1324
- internal: function (name, value) {
1325
- if( $.isPlainObject(name) ) {
1326
- $.extend(true, module, name);
1327
- }
1328
- else if(value !== undefined) {
1329
- module[name] = value;
1330
- }
1331
- else {
1332
- return module[name];
1333
- }
1911
+
1912
+ selector: {
1913
+ popup: '.ui.popup',
1914
+ input: 'input',
1915
+ activator: 'input',
1916
+ append: '.inline.field,.inline.fields',
1334
1917
  },
1335
- debug: function () {
1336
- if (!settings.silent && settings.debug) {
1337
- if (settings.performance) {
1338
- module.performance.log(arguments);
1339
- }
1340
- else {
1341
- module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
1342
- module.debug.apply(console, arguments);
1343
- }
1344
- }
1918
+
1919
+ regExp: {
1920
+ dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
1921
+ dateNumbers: /[^\d:]+/g,
1922
+ token: /d{1,4}|D{1,2}|M{1,4}|YY(?:YY)?|([Hhmsw])\1?|[SAaY]|"[^"]*"|'[^']*'/g,
1345
1923
  },
1346
- verbose: function () {
1347
- if (!settings.silent && settings.verbose && settings.debug) {
1348
- if (settings.performance) {
1349
- module.performance.log(arguments);
1350
- }
1351
- else {
1352
- module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
1353
- module.verbose.apply(console, arguments);
1354
- }
1355
- }
1924
+
1925
+ error: {
1926
+ popup: 'UI Popup, a required component is not included in this page',
1927
+ method: 'The method you called is not defined.',
1356
1928
  },
1357
- error: function () {
1358
- if (!settings.silent) {
1359
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
1360
- module.error.apply(console, arguments);
1361
- }
1929
+
1930
+ className: {
1931
+ calendar: 'calendar',
1932
+ active: 'active',
1933
+ popup: 'ui popup',
1934
+ grid: 'ui equal width grid',
1935
+ column: 'column',
1936
+ table: 'ui celled center aligned unstackable table',
1937
+ inverted: 'inverted',
1938
+ prev: 'prev link',
1939
+ next: 'next link',
1940
+ prevIcon: 'chevron left icon',
1941
+ nextIcon: 'chevron right icon',
1942
+ link: 'link',
1943
+ cell: 'link',
1944
+ disabledCell: 'disabled',
1945
+ weekCell: 'disabled',
1946
+ adjacentCell: 'adjacent',
1947
+ activeCell: 'active',
1948
+ rangeCell: 'range',
1949
+ focusCell: 'focus',
1950
+ todayCell: 'today',
1951
+ today: 'today link',
1952
+ disabled: 'disabled',
1362
1953
  },
1363
- performance: {
1364
- log: function (message) {
1365
- var
1366
- currentTime,
1367
- executionTime,
1368
- previousTime
1369
- ;
1370
- if (settings.performance) {
1371
- currentTime = new Date().getTime();
1372
- previousTime = time || currentTime;
1373
- executionTime = currentTime - previousTime;
1374
- time = currentTime;
1375
- performance.push({
1376
- 'Name': message[0],
1377
- 'Arguments': [].slice.call(message, 1) || '',
1378
- 'Element': element,
1379
- 'Execution Time': executionTime
1380
- });
1381
- }
1382
- clearTimeout(module.performance.timer);
1383
- module.performance.timer = setTimeout(module.performance.display, 500);
1384
- },
1385
- display: function () {
1386
- var
1387
- title = settings.name + ':',
1388
- totalTime = 0
1389
- ;
1390
- time = false;
1391
- clearTimeout(module.performance.timer);
1392
- $.each(performance, function (index, data) {
1393
- totalTime += data['Execution Time'];
1394
- });
1395
- title += ' ' + totalTime + 'ms';
1396
- if (moduleSelector) {
1397
- title += ' \'' + moduleSelector + '\'';
1398
- }
1399
- if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
1400
- console.groupCollapsed(title);
1401
- if (console.table) {
1402
- console.table(performance);
1403
- }
1404
- else {
1405
- $.each(performance, function (index, data) {
1406
- console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
1407
- });
1408
- }
1409
- console.groupEnd();
1410
- }
1411
- performance = [];
1412
- }
1954
+
1955
+ metadata: {
1956
+ date: 'date',
1957
+ focusDate: 'focusDate',
1958
+ startDate: 'startDate',
1959
+ endDate: 'endDate',
1960
+ minDate: 'minDate',
1961
+ maxDate: 'maxDate',
1962
+ mode: 'mode',
1963
+ type: 'type',
1964
+ monthOffset: 'monthOffset',
1965
+ message: 'message',
1966
+ class: 'class',
1967
+ inverted: 'inverted',
1968
+ variation: 'variation',
1969
+ position: 'position',
1970
+ month: 'month',
1971
+ year: 'year',
1972
+ hours: 'hours',
1973
+ days: 'days',
1413
1974
  },
1414
- invoke: function (query, passedArguments, context) {
1415
- var
1416
- object = instance,
1417
- maxDepth,
1418
- found,
1419
- response
1420
- ;
1421
- passedArguments = passedArguments || queryArguments;
1422
- context = context || element;
1423
- if (typeof query == 'string' && object !== undefined) {
1424
- query = query.split(/[\. ]/);
1425
- maxDepth = query.length - 1;
1426
- $.each(query, function (depth, value) {
1427
- var camelCaseValue = (depth != maxDepth)
1428
- ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1429
- : query
1430
- ;
1431
- if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
1432
- object = object[camelCaseValue];
1433
- }
1434
- else if (object[camelCaseValue] !== undefined) {
1435
- found = object[camelCaseValue];
1436
- return false;
1437
- }
1438
- else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
1439
- object = object[value];
1440
- }
1441
- else if (object[value] !== undefined) {
1442
- found = object[value];
1443
- return false;
1444
- }
1445
- else {
1446
- module.error(error.method, query);
1447
- return false;
1448
- }
1449
- });
1450
- }
1451
- if (isFunction(found)) {
1452
- response = found.apply(context, passedArguments);
1453
- }
1454
- else if (found !== undefined) {
1455
- response = found;
1456
- }
1457
- if (Array.isArray(returnedValue)) {
1458
- returnedValue.push(response);
1459
- }
1460
- else if (returnedValue !== undefined) {
1461
- returnedValue = [returnedValue, response];
1462
- }
1463
- else if (response !== undefined) {
1464
- returnedValue = response;
1465
- }
1466
- return found;
1467
- }
1468
- };
1469
-
1470
- if (methodInvoked) {
1471
- if (instance === undefined) {
1472
- module.initialize();
1473
- }
1474
- module.invoke(query);
1475
- }
1476
- else {
1477
- if (instance !== undefined) {
1478
- instance.invoke('destroy');
1479
- }
1480
- module.initialize();
1481
- }
1482
- })
1483
- ;
1484
- return (returnedValue !== undefined)
1485
- ? returnedValue
1486
- : this
1487
- ;
1488
- };
1489
-
1490
- $.fn.calendar.settings = {
1491
-
1492
- name : 'Calendar',
1493
- namespace : 'calendar',
1494
-
1495
- silent: false,
1496
- debug: false,
1497
- verbose: false,
1498
- performance: true,
1499
-
1500
- context : false,
1501
-
1502
- type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
1503
- firstDayOfWeek : 0, // day for first day column (0 = Sunday)
1504
- constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
1505
- today : false, // show a 'today/now' button at the bottom of the calendar
1506
- closable : true, // close the popup after selecting a date/time
1507
- monthFirst : true, // month before day when parsing date from text
1508
- touchReadonly : true, // set input to readonly on touch devices
1509
- inline : false, // create the calendar inline instead of inside a popup
1510
- on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
1511
- initialDate : null, // date to display initially when no date is selected (null = now)
1512
- startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
1513
- minDate : null, // minimum date/time that can be selected, dates/times before are disabled
1514
- maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
1515
- disableYear : false, // disable year selection mode
1516
- disableMonth : false, // disable month selection mode
1517
- disableMinute : false, // disable minute selection mode
1518
- formatInput : true, // format the input text upon input blur and module creation
1519
- startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
1520
- endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
1521
- multiMonth : 1, // show multiple months when in 'day' mode
1522
- monthOffset : 0, // position current month by offset when multimonth > 1
1523
- minTimeGap : 5,
1524
- showWeekNumbers : false, // show Number of Week at the very first column of a dayView
1525
- disabledHours : [], // specific hour(s) which won't be selectable and contain additional information.
1526
- disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
1527
- disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
1528
- enabledDates : [], // specific day(s) which will be selectable, all other days will be disabled
1529
- eventDates : [], // specific day(s) which will be shown in a different color and using tooltips
1530
- centuryBreak : 60, // starting short year until 99 where it will be assumed to belong to the last century
1531
- currentCentury : 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
1532
- selectAdjacentDays : false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
1533
- // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
1534
- popupOptions: {
1535
- position: 'bottom left',
1536
- lastResort: 'bottom left',
1537
- prefer: 'opposite',
1538
- observeChanges: false,
1539
- hideOnScroll: false
1540
- },
1541
-
1542
- text: {
1543
- days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
1544
- dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
1545
- dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1546
- months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1547
- monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1548
- today: 'Today',
1549
- now: 'Now',
1550
- am: 'AM',
1551
- pm: 'PM',
1552
- weekNo: 'Week'
1553
- },
1554
-
1555
- formatter: {
1556
- yearHeader: function (date, settings) {
1557
- var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
1558
- return (decadeYear - 9) + ' - ' + (decadeYear + 2);
1559
- },
1560
- monthHeader: 'YYYY',
1561
- dayHeader: 'MMMM YYYY',
1562
- hourHeader: 'MMMM D, YYYY',
1563
- minuteHeader: 'MMMM D, YYYY',
1564
- dayColumnHeader: function (day, settings) {
1565
- return settings.text.days[day];
1566
- },
1567
- datetime: 'MMMM D, YYYY h:mm A',
1568
- date: 'MMMM D, YYYY',
1569
- time: 'h:mm A',
1570
- cellTime: 'h:mm A',
1571
- month: 'MMMM YYYY',
1572
- year: 'YYYY',
1573
- today: function (settings) {
1574
- return settings.type === 'date' ? settings.text.today : settings.text.now;
1575
- },
1576
- cell: function (cell, date, cellOptions) {
1577
- }
1578
- },
1579
-
1580
- parser: {
1581
- date: function (text, settings) {
1582
- if (text instanceof Date) {
1583
- return text;
1584
- }
1585
- if (!text) {
1586
- return null;
1587
- }
1588
- text = String(text).trim().replace(/([.:\/\-])\s+/g,'$1').replace(/\s+([.:\/-])/g,'$1').replace(/\s+/g,' ');
1589
- if (text.length === 0) {
1590
- return null;
1591
- }
1592
- if(text.match(/^[0-9]{4}[\/\-\.][0-9]{1,2}[\/\-\.][0-9]{1,2}$/)){
1593
- text = text.replace(/[\/\-\.]/g,'/') + ' 00:00:00';
1594
- }
1595
- // Reverse date and month in some cases
1596
- text = settings.monthFirst || !text.match(/^[0-9]{1,2}[\/\-\.]/) ? text : text.replace(/[\/\-\.]/g,'/').replace(/([0-9]+)\/([0-9]+)/,'$2/$1');
1597
- var textDate = new Date(text);
1598
- var numberOnly = text.match(/^[0-9]+$/) !== null;
1599
- if(!numberOnly && !isNaN(textDate.getDate())) {
1600
- return textDate;
1601
- }
1602
- text = text.toLowerCase();
1603
-
1604
- var i, j, k;
1605
- var minute = -1, hour = -1, day = -1, month = -1, year = -1;
1606
- var isAm = undefined;
1607
-
1608
- var isTimeOnly = settings.type === 'time';
1609
- var isDateOnly = settings.type.indexOf('time') < 0;
1610
-
1611
- var words = text.split(settings.regExp.dateWords), word;
1612
- var numbers = text.split(settings.regExp.dateNumbers), number;
1613
-
1614
- var parts;
1615
- var monthString;
1616
-
1617
- if (!isDateOnly) {
1618
- //am/pm
1619
- isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
1620
- $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
1621
-
1622
- //time with ':'
1623
- for (i = 0; i < numbers.length; i++) {
1624
- number = numbers[i];
1625
- if (number.indexOf(':') >= 0) {
1626
- if (hour < 0 || minute < 0) {
1627
- parts = number.split(':');
1628
- for (k = 0; k < Math.min(2, parts.length); k++) {
1629
- j = parseInt(parts[k]);
1630
- if (isNaN(j)) {
1631
- j = 0;
1632
- }
1633
- if (k === 0) {
1634
- hour = j % 24;
1635
- } else {
1636
- minute = j % 60;
1637
- }
1638
- }
1639
- }
1640
- numbers.splice(i, 1);
1641
- }
1642
- }
1643
- }
1644
-
1645
- if (!isTimeOnly) {
1646
- //textual month
1647
- for (i = 0; i < words.length; i++) {
1648
- word = words[i];
1649
- if (word.length <= 0) {
1650
- continue;
1651
- }
1652
- for (j = 0; j < settings.text.months.length; j++) {
1653
- monthString = settings.text.months[j];
1654
- monthString = monthString.substring(0, word.length).toLowerCase();
1655
- if (monthString === word) {
1656
- month = j + 1;
1657
- break;
1658
- }
1659
- }
1660
- if (month >= 0) {
1661
- break;
1662
- }
1663
- }
1664
-
1665
- //year > settings.centuryBreak
1666
- for (i = 0; i < numbers.length; i++) {
1667
- j = parseInt(numbers[i]);
1668
- if (isNaN(j)) {
1669
- continue;
1670
- }
1671
- if (j >= settings.centuryBreak && i === numbers.length-1) {
1672
- if (j <= 99) {
1673
- j += settings.currentCentury - 100;
1674
- }
1675
- year = j;
1676
- numbers.splice(i, 1);
1677
- break;
1678
- }
1679
- }
1680
-
1681
- //numeric month
1682
- if (month < 0) {
1683
- for (i = 0; i < numbers.length; i++) {
1684
- k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
1685
- j = parseInt(numbers[k]);
1686
- if (isNaN(j)) {
1687
- continue;
1688
- }
1689
- if (1 <= j && j <= 12) {
1690
- month = j;
1691
- numbers.splice(k, 1);
1692
- break;
1693
- }
1694
- }
1695
- }
1696
-
1697
- //day
1698
- for (i = 0; i < numbers.length; i++) {
1699
- j = parseInt(numbers[i]);
1700
- if (isNaN(j)) {
1701
- continue;
1702
- }
1703
- if (1 <= j && j <= 31) {
1704
- day = j;
1705
- numbers.splice(i, 1);
1706
- break;
1707
- }
1708
- }
1709
-
1710
- //year <= settings.centuryBreak
1711
- if (year < 0) {
1712
- for (i = numbers.length - 1; i >= 0; i--) {
1713
- j = parseInt(numbers[i]);
1714
- if (isNaN(j)) {
1715
- continue;
1716
- }
1717
- if (j <= 99) {
1718
- j += settings.currentCentury;
1719
- }
1720
- year = j;
1721
- numbers.splice(i, 1);
1722
- break;
1723
- }
1724
- }
1725
- }
1726
-
1727
- if (!isDateOnly) {
1728
- //hour
1729
- if (hour < 0) {
1730
- for (i = 0; i < numbers.length; i++) {
1731
- j = parseInt(numbers[i]);
1732
- if (isNaN(j)) {
1733
- continue;
1734
- }
1735
- if (0 <= j && j <= 23) {
1736
- hour = j;
1737
- numbers.splice(i, 1);
1738
- break;
1739
- }
1740
- }
1741
- }
1742
-
1743
- //minute
1744
- if (minute < 0) {
1745
- for (i = 0; i < numbers.length; i++) {
1746
- j = parseInt(numbers[i]);
1747
- if (isNaN(j)) {
1748
- continue;
1749
- }
1750
- if (0 <= j && j <= 59) {
1751
- minute = j;
1752
- numbers.splice(i, 1);
1753
- break;
1754
- }
1755
- }
1756
- }
1757
- }
1758
-
1759
- if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
1760
- return null;
1761
- }
1762
-
1763
- if (minute < 0) {
1764
- minute = 0;
1765
- }
1766
- if (hour < 0) {
1767
- hour = 0;
1768
- }
1769
- if (day < 0) {
1770
- day = 1;
1771
- }
1772
- if (month < 0) {
1773
- month = 1;
1774
- }
1775
- if (year < 0) {
1776
- year = new Date().getFullYear();
1777
- }
1778
-
1779
- if (isAm !== undefined) {
1780
- if (isAm) {
1781
- if (hour === 12) {
1782
- hour = 0;
1783
- }
1784
- } else if (hour < 12) {
1785
- hour += 12;
1786
- }
1787
- }
1788
-
1789
- var date = new Date(year, month - 1, day, hour, minute);
1790
- if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
1791
- //month or year don't match up, switch to last day of the month
1792
- date = new Date(year, month, 0, hour, minute);
1793
- }
1794
- return isNaN(date.getTime()) ? null : date;
1795
- }
1796
- },
1797
-
1798
- // callback before date is changed, return false to cancel the change
1799
- onBeforeChange: function (date, text, mode) {
1800
- return true;
1801
- },
1802
-
1803
- // callback when date changes
1804
- onChange: function (date, text, mode) {
1805
- },
1806
-
1807
- // callback before show animation, return false to prevent show
1808
- onShow: function () {
1809
- },
1810
-
1811
- // callback after show animation
1812
- onVisible: function () {
1813
- },
1814
-
1815
- // callback before hide animation, return false to prevent hide
1816
- onHide: function () {
1817
- },
1818
-
1819
- // callback after hide animation
1820
- onHidden: function () {
1821
- },
1822
-
1823
- // callback before item is selected, return false to prevent selection
1824
- onSelect: function (date, mode) {
1825
- },
1826
-
1827
- // is the given date disabled?
1828
- isDisabled: function (date, mode) {
1829
- return false;
1830
- },
1831
-
1832
- selector: {
1833
- popup: '.ui.popup',
1834
- input: 'input',
1835
- activator: 'input',
1836
- append: '.inline.field,.inline.fields'
1837
- },
1838
-
1839
- regExp: {
1840
- dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
1841
- dateNumbers: /[^\d:]+/g,
1842
- token: /d{1,4}|D{1,2}|M{1,4}|YY(?:YY)?|([Hhmsw])\1?|[SAaY]|"[^"]*"|'[^']*'/g
1843
- },
1844
-
1845
- error: {
1846
- popup: 'UI Popup, a required component is not included in this page',
1847
- method: 'The method you called is not defined.'
1848
- },
1849
-
1850
- className: {
1851
- calendar: 'calendar',
1852
- active: 'active',
1853
- popup: 'ui popup',
1854
- grid: 'ui equal width grid',
1855
- column: 'column',
1856
- table: 'ui celled center aligned unstackable table',
1857
- inverted: 'inverted',
1858
- prev: 'prev link',
1859
- next: 'next link',
1860
- prevIcon: 'chevron left icon',
1861
- nextIcon: 'chevron right icon',
1862
- link: 'link',
1863
- cell: 'link',
1864
- disabledCell: 'disabled',
1865
- weekCell: 'disabled',
1866
- adjacentCell: 'adjacent',
1867
- activeCell: 'active',
1868
- rangeCell: 'range',
1869
- focusCell: 'focus',
1870
- todayCell: 'today',
1871
- today: 'today link',
1872
- disabled: 'disabled'
1873
- },
1874
-
1875
- metadata: {
1876
- date: 'date',
1877
- focusDate: 'focusDate',
1878
- startDate: 'startDate',
1879
- endDate: 'endDate',
1880
- minDate: 'minDate',
1881
- maxDate: 'maxDate',
1882
- mode: 'mode',
1883
- type: 'type',
1884
- monthOffset: 'monthOffset',
1885
- message: 'message',
1886
- class: 'class',
1887
- inverted: 'inverted',
1888
- variation: 'variation',
1889
- position: 'position',
1890
- month: 'month',
1891
- year: 'year',
1892
- hours: 'hours',
1893
- days: 'days'
1894
- },
1895
-
1896
- eventClass: 'blue'
1897
- };
1898
1975
 
1976
+ eventClass: 'blue',
1977
+ };
1899
1978
  })(jQuery, window, document);