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