rails-active-ui 0.3.0 → 0.3.2

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