2022-03-15 09:43:53 +00:00
|
|
|
/*!
|
2022-09-30 13:48:25 +00:00
|
|
|
* # Fomantic-UI 2.9.0-beta.323+b4c18ce - Calendar
|
2022-03-15 09:43:53 +00:00
|
|
|
* http://github.com/fomantic/Fomantic-UI/
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Released under the MIT license
|
|
|
|
* http://opensource.org/licenses/MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
;(function ($, window, document, undefined) {
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
$.isFunction = $.isFunction || function(obj) {
|
|
|
|
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
|
|
|
};
|
|
|
|
|
|
|
|
window = (typeof window != 'undefined' && window.Math == Math)
|
|
|
|
? window
|
|
|
|
: (typeof self != 'undefined' && self.Math == Math)
|
|
|
|
? self
|
|
|
|
: Function('return this')()
|
|
|
|
;
|
|
|
|
|
|
|
|
$.fn.calendar = function(parameters) {
|
|
|
|
var
|
|
|
|
$allModules = $(this),
|
|
|
|
|
|
|
|
moduleSelector = $allModules.selector || '',
|
|
|
|
|
|
|
|
time = new Date().getTime(),
|
|
|
|
performance = [],
|
|
|
|
|
|
|
|
query = arguments[0],
|
|
|
|
methodInvoked = (typeof query == 'string'),
|
|
|
|
queryArguments = [].slice.call(arguments, 1),
|
|
|
|
returnedValue,
|
|
|
|
timeGapTable = {
|
|
|
|
'5': {'row': 4, 'column': 3 },
|
|
|
|
'10': {'row': 3, 'column': 2 },
|
|
|
|
'15': {'row': 2, 'column': 2 },
|
|
|
|
'20': {'row': 3, 'column': 1 },
|
|
|
|
'30': {'row': 2, 'column': 1 }
|
|
|
|
},
|
|
|
|
numberText = ['','one','two','three','four','five','six','seven','eight']
|
|
|
|
;
|
|
|
|
|
|
|
|
$allModules
|
|
|
|
.each(function () {
|
|
|
|
var
|
|
|
|
settings = ( $.isPlainObject(parameters) )
|
|
|
|
? $.extend(true, {}, $.fn.calendar.settings, parameters)
|
|
|
|
: $.extend({}, $.fn.calendar.settings),
|
|
|
|
|
|
|
|
className = settings.className,
|
|
|
|
namespace = settings.namespace,
|
|
|
|
selector = settings.selector,
|
|
|
|
formatter = settings.formatter,
|
|
|
|
parser = settings.parser,
|
|
|
|
metadata = settings.metadata,
|
|
|
|
timeGap = timeGapTable[settings.minTimeGap],
|
|
|
|
error = settings.error,
|
|
|
|
|
|
|
|
eventNamespace = '.' + namespace,
|
|
|
|
moduleNamespace = 'module-' + namespace,
|
|
|
|
|
|
|
|
$module = $(this),
|
|
|
|
$input = $module.find(selector.input),
|
|
|
|
$container = $module.find(selector.popup),
|
|
|
|
$activator = $module.find(selector.activator),
|
|
|
|
|
|
|
|
element = this,
|
|
|
|
instance = $module.data(moduleNamespace),
|
|
|
|
|
|
|
|
isTouch,
|
|
|
|
isTouchDown = false,
|
|
|
|
isInverted = $module.hasClass(className.inverted),
|
|
|
|
focusDateUsedForRange = false,
|
|
|
|
selectionComplete = false,
|
|
|
|
classObserver,
|
|
|
|
module
|
|
|
|
;
|
|
|
|
|
|
|
|
module = {
|
|
|
|
|
|
|
|
initialize: function () {
|
|
|
|
module.debug('Initializing calendar for', element, $module);
|
|
|
|
|
|
|
|
isTouch = module.get.isTouch();
|
|
|
|
module.setup.config();
|
|
|
|
module.setup.popup();
|
|
|
|
module.setup.inline();
|
|
|
|
module.setup.input();
|
|
|
|
module.setup.date();
|
|
|
|
module.create.calendar();
|
|
|
|
|
|
|
|
module.bind.events();
|
|
|
|
module.observeChanges();
|
|
|
|
module.instantiate();
|
|
|
|
},
|
|
|
|
|
|
|
|
instantiate: function () {
|
|
|
|
module.verbose('Storing instance of calendar');
|
|
|
|
instance = module;
|
|
|
|
$module.data(moduleNamespace, instance);
|
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function () {
|
|
|
|
module.verbose('Destroying previous calendar for', element);
|
|
|
|
$module.removeData(moduleNamespace);
|
|
|
|
module.unbind.events();
|
|
|
|
module.disconnect.classObserver();
|
|
|
|
},
|
|
|
|
|
|
|
|
setup: {
|
|
|
|
config: function () {
|
|
|
|
if (module.get.minDate() !== null) {
|
|
|
|
module.set.minDate($module.data(metadata.minDate));
|
|
|
|
}
|
|
|
|
if (module.get.maxDate() !== null) {
|
|
|
|
module.set.maxDate($module.data(metadata.maxDate));
|
|
|
|
}
|
|
|
|
module.setting('type', module.get.type());
|
2022-08-05 09:25:53 +00:00
|
|
|
module.setting('on', settings.on || 'click');
|
2022-03-15 09:43:53 +00:00
|
|
|
},
|
|
|
|
popup: function () {
|
|
|
|
if (settings.inline) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!$activator.length) {
|
|
|
|
$activator = $module.children().first();
|
|
|
|
if (!$activator.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($.fn.popup === undefined) {
|
|
|
|
module.error(error.popup);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!$container.length) {
|
|
|
|
//prepend the popup element to the activator's parent so that it has less chance of messing with
|
|
|
|
//the styling (eg input action button needs to be the last child to have correct border radius)
|
|
|
|
var $activatorParent = $activator.parent(),
|
|
|
|
domPositionFunction = $activatorParent.closest(selector.append).length !== 0 ? 'appendTo' : 'prependTo';
|
|
|
|
$container = $('<div/>').addClass(className.popup)[domPositionFunction]($activatorParent);
|
|
|
|
}
|
|
|
|
$container.addClass(className.calendar);
|
|
|
|
if(isInverted){
|
|
|
|
$container.addClass(className.inverted);
|
|
|
|
}
|
|
|
|
var onVisible = function () {
|
|
|
|
module.refreshTooltips();
|
|
|
|
return settings.onVisible.apply($container, arguments);
|
|
|
|
};
|
2022-08-05 09:25:53 +00:00
|
|
|
var onHidden = function () {
|
|
|
|
module.blur();
|
|
|
|
return settings.onHidden.apply($container, arguments)
|
|
|
|
}
|
2022-03-15 09:43:53 +00:00
|
|
|
if (!$input.length) {
|
|
|
|
//no input, $container has to handle focus/blur
|
|
|
|
$container.attr('tabindex', '0');
|
|
|
|
onVisible = function () {
|
|
|
|
module.refreshTooltips();
|
|
|
|
module.focus();
|
|
|
|
return settings.onVisible.apply($container, arguments);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
var onShow = function () {
|
|
|
|
//reset the focus date onShow
|
|
|
|
module.set.focusDate(module.get.date());
|
|
|
|
module.set.mode(module.get.validatedMode(settings.startMode));
|
|
|
|
return settings.onShow.apply($container, arguments);
|
|
|
|
};
|
|
|
|
var on = module.setting('on');
|
|
|
|
var options = $.extend({}, settings.popupOptions, {
|
|
|
|
popup: $container,
|
|
|
|
on: on,
|
|
|
|
hoverable: on === 'hover',
|
|
|
|
closable: on === 'click',
|
|
|
|
onShow: onShow,
|
|
|
|
onVisible: onVisible,
|
|
|
|
onHide: settings.onHide,
|
|
|
|
onHidden: onHidden
|
|
|
|
});
|
|
|
|
module.popup(options);
|
|
|
|
},
|
|
|
|
inline: function () {
|
|
|
|
if ($activator.length && !settings.inline) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
settings.inline = true;
|
|
|
|
$container = $('<div/>').addClass(className.calendar).appendTo($module);
|
|
|
|
if (!$input.length) {
|
|
|
|
$container.attr('tabindex', '0');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
input: function () {
|
|
|
|
if (settings.touchReadonly && $input.length && isTouch) {
|
|
|
|
$input.prop('readonly', true);
|
|
|
|
}
|
|
|
|
module.check.disabled();
|
|
|
|
},
|
|
|
|
date: function () {
|
|
|
|
var date;
|
|
|
|
if (settings.initialDate) {
|
|
|
|
date = parser.date(settings.initialDate, settings);
|
|
|
|
} else if ($module.data(metadata.date) !== undefined) {
|
|
|
|
date = parser.date($module.data(metadata.date), settings);
|
|
|
|
} else if ($input.length) {
|
|
|
|
date = parser.date($input.val(), settings);
|
|
|
|
}
|
|
|
|
module.set.date(date, settings.formatInput, false);
|
|
|
|
module.set.mode(module.get.mode(), false);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
trigger: {
|
|
|
|
change: function() {
|
|
|
|
var
|
|
|
|
inputElement = $input[0]
|
|
|
|
;
|
|
|
|
if(inputElement) {
|
|
|
|
var events = document.createEvent('HTMLEvents');
|
|
|
|
module.verbose('Triggering native change event');
|
|
|
|
events.initEvent('change', true, false);
|
|
|
|
inputElement.dispatchEvent(events);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
create: {
|
|
|
|
calendar: function () {
|
|
|
|
var i, r, c, p, row, cell, pageGrid;
|
|
|
|
|
|
|
|
var
|
|
|
|
mode = module.get.mode(),
|
|
|
|
today = new Date(),
|
|
|
|
date = module.get.date(),
|
|
|
|
focusDate = module.get.focusDate(),
|
|
|
|
display = module.helper.dateInRange(focusDate || date || settings.initialDate || today)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (!focusDate) {
|
|
|
|
focusDate = display;
|
|
|
|
module.set.focusDate(focusDate, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
var
|
|
|
|
isYear = mode === 'year',
|
|
|
|
isMonth = mode === 'month',
|
|
|
|
isDay = mode === 'day',
|
|
|
|
isHour = mode === 'hour',
|
|
|
|
isMinute = mode === 'minute',
|
|
|
|
isTimeOnly = settings.type === 'time'
|
|
|
|
;
|
|
|
|
|
|
|
|
var multiMonth = Math.max(settings.multiMonth, 1);
|
|
|
|
var monthOffset = !isDay ? 0 : module.get.monthOffset();
|
|
|
|
|
|
|
|
var
|
|
|
|
minute = display.getMinutes(),
|
|
|
|
hour = display.getHours(),
|
|
|
|
day = display.getDate(),
|
|
|
|
startMonth = display.getMonth() + monthOffset,
|
|
|
|
year = display.getFullYear()
|
|
|
|
;
|
|
|
|
|
|
|
|
var columns = isDay ? settings.showWeekNumbers ? 8 : 7 : isHour ? 4 : timeGap['column'];
|
|
|
|
var rows = isDay || isHour ? 6 : timeGap['row'];
|
|
|
|
var pages = isDay ? multiMonth : 1;
|
|
|
|
|
|
|
|
var container = $container;
|
|
|
|
var tooltipPosition = container.hasClass("left") ? "right center" : "left center";
|
|
|
|
container.empty();
|
|
|
|
if (pages > 1) {
|
|
|
|
pageGrid = $('<div/>').addClass(className.grid).appendTo(container);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (p = 0; p < pages; p++) {
|
|
|
|
if (pages > 1) {
|
|
|
|
var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid);
|
|
|
|
container = pageColumn;
|
|
|
|
}
|
|
|
|
|
|
|
|
var month = startMonth + p;
|
|
|
|
var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7;
|
|
|
|
if (!settings.constantHeight && isDay) {
|
|
|
|
var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn;
|
|
|
|
rows = Math.ceil(requiredCells / 7);
|
|
|
|
}
|
|
|
|
|
|
|
|
var
|
|
|
|
yearChange = isYear ? 10 : isMonth ? 1 : 0,
|
|
|
|
monthChange = isDay ? 1 : 0,
|
|
|
|
dayChange = isHour || isMinute ? 1 : 0,
|
|
|
|
prevNextDay = isHour || isMinute ? day : 1,
|
|
|
|
prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour),
|
|
|
|
nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour),
|
|
|
|
prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) :
|
|
|
|
isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1),
|
|
|
|
nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) :
|
|
|
|
isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1)
|
|
|
|
;
|
|
|
|
|
|
|
|
var tempMode = mode;
|
|
|
|
if (isDay && settings.showWeekNumbers){
|
|
|
|
tempMode += ' andweek';
|
|
|
|
}
|
|
|
|
var table = $('<table/>').addClass(className.table).addClass(tempMode).addClass(numberText[columns] + ' column').appendTo(container);
|
|
|
|
if(isInverted){
|
|
|
|
table.addClass(className.inverted);
|
|
|
|
}
|
|
|
|
var textColumns = columns;
|
|
|
|
//no header for time-only mode
|
|
|
|
if (!isTimeOnly) {
|
|
|
|
var thead = $('<thead/>').appendTo(table);
|
|
|
|
|
|
|
|
row = $('<tr/>').appendTo(thead);
|
|
|
|
cell = $('<th/>').attr('colspan', '' + columns).appendTo(row);
|
|
|
|
|
|
|
|
var headerDate = isYear || isMonth ? new Date(year, 0, 1) :
|
|
|
|
isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute);
|
|
|
|
var headerText = $('<span/>').addClass(className.link).appendTo(cell);
|
2022-08-05 09:25:53 +00:00
|
|
|
headerText.text(module.helper.dateFormat(formatter[mode+'Header'], headerDate));
|
2022-03-15 09:43:53 +00:00
|
|
|
var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') :
|
|
|
|
isDay ? (settings.disableMonth ? 'year' : 'month') : 'day';
|
|
|
|
headerText.data(metadata.mode, newMode);
|
|
|
|
|
|
|
|
if (p === 0) {
|
|
|
|
var prev = $('<span/>').addClass(className.prev).appendTo(cell);
|
|
|
|
prev.data(metadata.focusDate, prevDate);
|
|
|
|
prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode));
|
|
|
|
$('<i/>').addClass(className.prevIcon).appendTo(prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p === pages - 1) {
|
|
|
|
var next = $('<span/>').addClass(className.next).appendTo(cell);
|
|
|
|
next.data(metadata.focusDate, nextDate);
|
|
|
|
next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode));
|
|
|
|
$('<i/>').addClass(className.nextIcon).appendTo(next);
|
|
|
|
}
|
|
|
|
if (isDay) {
|
|
|
|
row = $('<tr/>').appendTo(thead);
|
|
|
|
if(settings.showWeekNumbers) {
|
|
|
|
cell = $('<th/>').appendTo(row);
|
|
|
|
cell.text(settings.text.weekNo);
|
|
|
|
cell.addClass(className.weekCell);
|
|
|
|
textColumns--;
|
|
|
|
}
|
|
|
|
for (i = 0; i < textColumns; i++) {
|
|
|
|
cell = $('<th/>').appendTo(row);
|
|
|
|
cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var tbody = $('<tbody/>').appendTo(table);
|
|
|
|
i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0;
|
|
|
|
for (r = 0; r < rows; r++) {
|
|
|
|
row = $('<tr/>').appendTo(tbody);
|
|
|
|
if(isDay && settings.showWeekNumbers){
|
|
|
|
cell = $('<th/>').appendTo(row);
|
|
|
|
cell.text(module.get.weekOfYear(year,month,i+1-settings.firstDayOfWeek));
|
|
|
|
cell.addClass(className.weekCell);
|
|
|
|
}
|
|
|
|
for (c = 0; c < textColumns; c++, i++) {
|
|
|
|
var cellDate = isYear ? new Date(i, month, 1, hour, minute) :
|
|
|
|
isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) :
|
|
|
|
isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * settings.minTimeGap);
|
|
|
|
var cellText = isYear ? i :
|
|
|
|
isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() :
|
2022-08-05 09:25:53 +00:00
|
|
|
module.helper.dateFormat(formatter.cellTime,cellDate);
|
2022-03-15 09:43:53 +00:00
|
|
|
cell = $('<td/>').addClass(className.cell).appendTo(row);
|
|
|
|
cell.text(cellText);
|
|
|
|
cell.data(metadata.date, cellDate);
|
|
|
|
var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12);
|
|
|
|
var disabled = (!settings.selectAdjacentDays && adjacent) || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode) || module.helper.isDisabled(cellDate, mode) || !module.helper.isEnabled(cellDate, mode);
|
|
|
|
var eventDate;
|
|
|
|
if (disabled) {
|
|
|
|
var disabledDate = module.helper.findDayAsObject(cellDate, mode, settings.disabledDates);
|
|
|
|
if (disabledDate !== null && disabledDate[metadata.message]) {
|
|
|
|
cell.attr("data-tooltip", disabledDate[metadata.message]);
|
|
|
|
cell.attr("data-position", disabledDate[metadata.position] || tooltipPosition);
|
|
|
|
if(disabledDate[metadata.inverted] || (isInverted && disabledDate[metadata.inverted] === undefined)) {
|
|
|
|
cell.attr("data-inverted", '');
|
|
|
|
}
|
|
|
|
if(disabledDate[metadata.variation]) {
|
|
|
|
cell.attr("data-variation", disabledDate[metadata.variation]);
|
|
|
|
}
|
|
|
|
}
|
2022-08-05 09:25:53 +00:00
|
|
|
if (mode === 'hour') {
|
|
|
|
var disabledHour = module.helper.findHourAsObject(cellDate, mode, settings.disabledHours);
|
|
|
|
if (disabledHour !== null && disabledHour[metadata.message]) {
|
|
|
|
cell.attr("data-tooltip", disabledHour[metadata.message]);
|
|
|
|
cell.attr("data-position", disabledHour[metadata.position] || tooltipPosition);
|
|
|
|
if(disabledHour[metadata.inverted] || (isInverted && disabledHour[metadata.inverted] === undefined)) {
|
|
|
|
cell.attr("data-inverted", '');
|
|
|
|
}
|
|
|
|
if(disabledHour[metadata.variation]) {
|
|
|
|
cell.attr("data-variation", disabledHour[metadata.variation]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-15 09:43:53 +00:00
|
|
|
} else {
|
|
|
|
eventDate = module.helper.findDayAsObject(cellDate, mode, settings.eventDates);
|
|
|
|
if (eventDate !== null) {
|
|
|
|
cell.addClass(eventDate[metadata.class] || settings.eventClass);
|
|
|
|
if (eventDate[metadata.message]) {
|
|
|
|
cell.attr("data-tooltip", eventDate[metadata.message]);
|
|
|
|
cell.attr("data-position", eventDate[metadata.position] || tooltipPosition);
|
|
|
|
if(eventDate[metadata.inverted] || (isInverted && eventDate[metadata.inverted] === undefined)) {
|
|
|
|
cell.attr("data-inverted", '');
|
|
|
|
}
|
|
|
|
if(eventDate[metadata.variation]) {
|
|
|
|
cell.attr("data-variation", eventDate[metadata.variation]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var active = module.helper.dateEqual(cellDate, date, mode);
|
|
|
|
var isToday = module.helper.dateEqual(cellDate, today, mode);
|
|
|
|
cell.toggleClass(className.adjacentCell, adjacent && !eventDate);
|
|
|
|
cell.toggleClass(className.disabledCell, disabled);
|
|
|
|
cell.toggleClass(className.activeCell, active && !(adjacent && disabled));
|
|
|
|
if (!isHour && !isMinute) {
|
|
|
|
cell.toggleClass(className.todayCell, !adjacent && isToday);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow for external modifications of each cell
|
|
|
|
var cellOptions = {
|
|
|
|
mode: mode,
|
|
|
|
adjacent: adjacent,
|
|
|
|
disabled: disabled,
|
|
|
|
active: active,
|
|
|
|
today: isToday
|
|
|
|
};
|
|
|
|
formatter.cell(cell, cellDate, cellOptions);
|
|
|
|
|
|
|
|
if (module.helper.dateEqual(cellDate, focusDate, mode)) {
|
|
|
|
//ensure that the focus date is exactly equal to the cell date
|
|
|
|
//so that, if selected, the correct value is set
|
|
|
|
module.set.focusDate(cellDate, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (settings.today) {
|
|
|
|
var todayRow = $('<tr/>').appendTo(tbody);
|
|
|
|
var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow);
|
|
|
|
todayButton.text(formatter.today(settings));
|
|
|
|
todayButton.data(metadata.date, today);
|
|
|
|
}
|
|
|
|
|
|
|
|
module.update.focus(false, table);
|
|
|
|
|
|
|
|
if(settings.inline){
|
|
|
|
module.refreshTooltips();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
update: {
|
|
|
|
focus: function (updateRange, container) {
|
|
|
|
container = container || $container;
|
|
|
|
var mode = module.get.mode();
|
|
|
|
var date = module.get.date();
|
|
|
|
var focusDate = module.get.focusDate();
|
|
|
|
var startDate = module.get.startDate();
|
|
|
|
var endDate = module.get.endDate();
|
|
|
|
var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null);
|
|
|
|
|
|
|
|
container.find('td').each(function () {
|
|
|
|
var cell = $(this);
|
|
|
|
var cellDate = cell.data(metadata.date);
|
|
|
|
if (!cellDate) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var disabled = cell.hasClass(className.disabledCell);
|
|
|
|
var active = cell.hasClass(className.activeCell);
|
|
|
|
var adjacent = cell.hasClass(className.adjacentCell);
|
|
|
|
var focused = module.helper.dateEqual(cellDate, focusDate, mode);
|
|
|
|
var inRange = !rangeDate ? false :
|
|
|
|
((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) ||
|
|
|
|
(!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate)));
|
|
|
|
cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && (!adjacent || (settings.selectAdjacentDays && adjacent)) && !disabled);
|
|
|
|
|
|
|
|
if (module.helper.isTodayButton(cell)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cell.toggleClass(className.rangeCell, inRange && !active && !disabled);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
refresh: function () {
|
|
|
|
module.create.calendar();
|
|
|
|
},
|
|
|
|
|
|
|
|
refreshTooltips: function() {
|
|
|
|
var winWidth = $(window).width();
|
|
|
|
$container.find('td[data-position]').each(function () {
|
|
|
|
var cell = $(this);
|
2022-08-05 09:25:53 +00:00
|
|
|
var tooltipWidth = window.getComputedStyle(cell[0], '::after').width.replace(/[^0-9\.]/g,'');
|
2022-03-15 09:43:53 +00:00
|
|
|
var tooltipPosition = cell.attr('data-position');
|
|
|
|
// use a fallback width of 250 (calendar width) for IE/Edge (which return "auto")
|
|
|
|
var calcPosition = (winWidth - cell.width() - (parseInt(tooltipWidth,10) || 250)) > cell.offset().left ? 'right' : 'left';
|
|
|
|
if(tooltipPosition.indexOf(calcPosition) === -1) {
|
|
|
|
cell.attr('data-position',tooltipPosition.replace(/(left|right)/,calcPosition));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
bind: {
|
|
|
|
events: function () {
|
|
|
|
module.debug('Binding events');
|
|
|
|
$container.on('mousedown' + eventNamespace, module.event.mousedown);
|
|
|
|
$container.on('touchstart' + eventNamespace, module.event.mousedown);
|
|
|
|
$container.on('mouseup' + eventNamespace, module.event.mouseup);
|
|
|
|
$container.on('touchend' + eventNamespace, module.event.mouseup);
|
|
|
|
$container.on('mouseover' + eventNamespace, module.event.mouseover);
|
|
|
|
if ($input.length) {
|
|
|
|
$input.on('input' + eventNamespace, module.event.inputChange);
|
|
|
|
$input.on('focus' + eventNamespace, module.event.inputFocus);
|
|
|
|
$input.on('blur' + eventNamespace, module.event.inputBlur);
|
|
|
|
$input.on('keydown' + eventNamespace, module.event.keydown);
|
|
|
|
} else {
|
|
|
|
$container.on('keydown' + eventNamespace, module.event.keydown);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
unbind: {
|
|
|
|
events: function () {
|
|
|
|
module.debug('Unbinding events');
|
|
|
|
$container.off(eventNamespace);
|
|
|
|
if ($input.length) {
|
|
|
|
$input.off(eventNamespace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
event: {
|
|
|
|
mouseover: function (event) {
|
|
|
|
var target = $(event.target);
|
|
|
|
var date = target.data(metadata.date);
|
|
|
|
var mousedown = event.buttons === 1;
|
|
|
|
if (date) {
|
|
|
|
module.set.focusDate(date, false, true, mousedown);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mousedown: function (event) {
|
|
|
|
if ($input.length) {
|
|
|
|
//prevent the mousedown on the calendar causing the input to lose focus
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
isTouchDown = event.type.indexOf('touch') >= 0;
|
|
|
|
var target = $(event.target);
|
|
|
|
var date = target.data(metadata.date);
|
|
|
|
if (date) {
|
|
|
|
module.set.focusDate(date, false, true, true);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mouseup: function (event) {
|
|
|
|
//ensure input has focus so that it receives keydown events for calendar navigation
|
|
|
|
module.focus();
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
isTouchDown = false;
|
|
|
|
var target = $(event.target);
|
|
|
|
if (target.hasClass("disabled")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var parent = target.parent();
|
|
|
|
if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) {
|
|
|
|
//clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element)
|
|
|
|
target = parent;
|
|
|
|
}
|
|
|
|
var date = target.data(metadata.date);
|
|
|
|
var focusDate = target.data(metadata.focusDate);
|
|
|
|
var mode = target.data(metadata.mode);
|
|
|
|
if (date && settings.onSelect.call(element, date, module.get.mode()) !== false) {
|
|
|
|
var forceSet = target.hasClass(className.today);
|
|
|
|
module.selectDate(date, forceSet);
|
|
|
|
}
|
|
|
|
else if (focusDate) {
|
|
|
|
module.set.focusDate(focusDate);
|
|
|
|
}
|
|
|
|
else if (mode) {
|
|
|
|
module.set.mode(mode);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
keydown: function (event) {
|
|
|
|
var keyCode = event.which;
|
2022-08-31 14:40:59 +00:00
|
|
|
if (keyCode === 9) {
|
|
|
|
//tab
|
2022-03-15 09:43:53 +00:00
|
|
|
module.popup('hide');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (module.popup('is visible')) {
|
2022-09-15 12:58:37 +00:00
|
|
|
var mode = module.get.mode();
|
2022-03-15 09:43:53 +00:00
|
|
|
if (keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
|
|
|
|
//arrow keys
|
|
|
|
var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : mode === 'minute' ? timeGap['column'] : 3;
|
|
|
|
var increment = keyCode === 37 ? -1 : keyCode === 38 ? -bigIncrement : keyCode == 39 ? 1 : bigIncrement;
|
|
|
|
increment *= mode === 'minute' ? settings.minTimeGap : 1;
|
|
|
|
var focusDate = module.get.focusDate() || module.get.date() || new Date();
|
|
|
|
var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0);
|
|
|
|
var month = focusDate.getMonth() + (mode === 'month' ? increment : 0);
|
|
|
|
var day = focusDate.getDate() + (mode === 'day' ? increment : 0);
|
|
|
|
var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0);
|
|
|
|
var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0);
|
|
|
|
var newFocusDate = new Date(year, month, day, hour, minute);
|
|
|
|
if (settings.type === 'time') {
|
|
|
|
newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate);
|
|
|
|
}
|
|
|
|
if (module.helper.isDateInRange(newFocusDate, mode)) {
|
|
|
|
module.set.focusDate(newFocusDate);
|
|
|
|
}
|
|
|
|
} else if (keyCode === 13) {
|
|
|
|
//enter
|
|
|
|
var date = module.get.focusDate();
|
|
|
|
if (date && !settings.isDisabled(date, mode) && !module.helper.isDisabled(date, mode) && module.helper.isEnabled(date, mode)) {
|
2022-08-05 09:25:53 +00:00
|
|
|
if (settings.onSelect.call(element, date, module.get.mode()) !== false) {
|
|
|
|
module.selectDate(date);
|
|
|
|
}
|
2022-03-15 09:43:53 +00:00
|
|
|
}
|
|
|
|
//disable form submission:
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
2022-08-31 14:40:59 +00:00
|
|
|
} else if (keyCode === 27) {
|
|
|
|
module.popup('hide');
|
|
|
|
event.stopPropagation();
|
2022-03-15 09:43:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyCode === 38 || keyCode === 40) {
|
|
|
|
//arrow-up || arrow-down
|
|
|
|
event.preventDefault(); //don't scroll
|
|
|
|
module.popup('show');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
inputChange: function () {
|
|
|
|
var val = $input.val();
|
|
|
|
var date = parser.date(val, settings);
|
|
|
|
module.set.date(date, false);
|
|
|
|
},
|
|
|
|
inputFocus: function () {
|
|
|
|
$container.addClass(className.active);
|
|
|
|
},
|
|
|
|
inputBlur: function () {
|
|
|
|
$container.removeClass(className.active);
|
|
|
|
if (settings.formatInput) {
|
|
|
|
var date = module.get.date();
|
2022-08-05 09:25:53 +00:00
|
|
|
var text = module.helper.dateFormat(formatter[settings.type], date);
|
2022-03-15 09:43:53 +00:00
|
|
|
$input.val(text);
|
|
|
|
}
|
|
|
|
if(selectionComplete){
|
|
|
|
module.trigger.change();
|
|
|
|
selectionComplete = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
class: {
|
|
|
|
mutation: function(mutations) {
|
|
|
|
mutations.forEach(function(mutation) {
|
|
|
|
if(mutation.attributeName === "class") {
|
|
|
|
module.check.disabled();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
observeChanges: function() {
|
|
|
|
if('MutationObserver' in window) {
|
|
|
|
classObserver = new MutationObserver(module.event.class.mutation);
|
|
|
|
module.debug('Setting up mutation observer', classObserver);
|
|
|
|
module.observe.class();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
disconnect: {
|
|
|
|
classObserver: function() {
|
|
|
|
if($input.length && classObserver) {
|
|
|
|
classObserver.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
observe: {
|
|
|
|
class: function() {
|
|
|
|
if($input.length && classObserver) {
|
|
|
|
classObserver.observe($module[0], {
|
|
|
|
attributes : true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
is: {
|
|
|
|
disabled: function() {
|
|
|
|
return $module.hasClass(className.disabled);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
check: {
|
|
|
|
disabled: function(){
|
|
|
|
$input.attr('tabindex',module.is.disabled() ? -1 : 0);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
get: {
|
|
|
|
weekOfYear: function(weekYear,weekMonth,weekDay) {
|
|
|
|
// adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
|
|
|
|
var ms1d = 864e5, // milliseconds in a day
|
|
|
|
ms7d = 7 * ms1d; // milliseconds in a week
|
|
|
|
|
|
|
|
return function() { // return a closure so constants get calculated only once
|
|
|
|
var DC3 = Date.UTC(weekYear, weekMonth, weekDay + 3) / ms1d, // an Absolute Day Number
|
|
|
|
AWN = Math.floor(DC3 / 7), // an Absolute Week Number
|
|
|
|
Wyr = new Date(AWN * ms7d).getUTCFullYear();
|
|
|
|
|
|
|
|
return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
|
|
|
|
}();
|
|
|
|
},
|
2022-08-05 09:25:53 +00:00
|
|
|
formattedDate: function(format, date) {
|
|
|
|
return module.helper.dateFormat(format || formatter[settings.type], date || module.get.date());
|
|
|
|
},
|
2022-03-15 09:43:53 +00:00
|
|
|
date: function () {
|
|
|
|
return module.helper.sanitiseDate($module.data(metadata.date)) || null;
|
|
|
|
},
|
|
|
|
inputDate: function() {
|
|
|
|
return $input.val();
|
|
|
|
},
|
|
|
|
focusDate: function () {
|
|
|
|
return $module.data(metadata.focusDate) || null;
|
|
|
|
},
|
|
|
|
startDate: function () {
|
|
|
|
var startModule = module.get.calendarModule(settings.startCalendar);
|
|
|
|
return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null;
|
|
|
|
},
|
|
|
|
endDate: function () {
|
|
|
|
var endModule = module.get.calendarModule(settings.endCalendar);
|
|
|
|
return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null;
|
|
|
|
},
|
|
|
|
minDate: function() {
|
|
|
|
return $module.data(metadata.minDate) || null;
|
|
|
|
},
|
|
|
|
maxDate: function() {
|
|
|
|
return $module.data(metadata.maxDate) || null;
|
|
|
|
},
|
|
|
|
monthOffset: function () {
|
2022-08-05 09:25:53 +00:00
|
|
|
return $module.data(metadata.monthOffset) || settings.monthOffset || 0;
|
2022-03-15 09:43:53 +00:00
|
|
|
},
|
|
|
|
mode: function () {
|
|
|
|
//only returns valid modes for the current settings
|
|
|
|
var mode = $module.data(metadata.mode) || settings.startMode;
|
|
|
|
return module.get.validatedMode(mode);
|
|
|
|
},
|
|
|
|
validatedMode: function(mode){
|
|
|
|
var validModes = module.get.validModes();
|
|
|
|
if ($.inArray(mode, validModes) >= 0) {
|
|
|
|
return mode;
|
|
|
|
}
|
|
|
|
return settings.type === 'time' ? 'hour' :
|
|
|
|
settings.type === 'month' ? 'month' :
|
|
|
|
settings.type === 'year' ? 'year' : 'day';
|
|
|
|
},
|
|
|
|
type: function() {
|
|
|
|
return $module.data(metadata.type) || settings.type;
|
|
|
|
},
|
|
|
|
validModes: function () {
|
|
|
|
var validModes = [];
|
|
|
|
if (settings.type !== 'time') {
|
|
|
|
if (!settings.disableYear || settings.type === 'year') {
|
|
|
|
validModes.push('year');
|
|
|
|
}
|
|
|
|
if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') {
|
|
|
|
validModes.push('month');
|
|
|
|
}
|
|
|
|
if (settings.type.indexOf('date') >= 0) {
|
|
|
|
validModes.push('day');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (settings.type.indexOf('time') >= 0) {
|
|
|
|
validModes.push('hour');
|
|
|
|
if (!settings.disableMinute) {
|
|
|
|
validModes.push('minute');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return validModes;
|
|
|
|
},
|
|
|
|
isTouch: function () {
|
|
|
|
try {
|
|
|
|
document.createEvent('TouchEvent');
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
calendarModule: function (selector) {
|
|
|
|
if (!selector) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (!(selector instanceof $)) {
|
2022-08-05 09:25:53 +00:00
|
|
|
selector = $(document).find(selector).first();
|
2022-03-15 09:43:53 +00:00
|
|
|
}
|
|
|
|
//assume range related calendars are using the same namespace
|
|
|
|
return selector.data(moduleNamespace);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
set: {
|
|
|
|
date: function (date, updateInput, fireChange) {
|
|
|
|
updateInput = updateInput !== false;
|
|
|
|
fireChange = fireChange !== false;
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
date = module.helper.dateInRange(date);
|
|
|
|
|
|
|
|
var mode = module.get.mode();
|
2022-08-05 09:25:53 +00:00
|
|
|
var text = module.helper.dateFormat(formatter[settings.type],date);
|
2022-03-15 09:43:53 +00:00
|
|
|
|
|
|
|
if (fireChange && settings.onBeforeChange.call(element, date, text, mode) === false) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
module.set.focusDate(date);
|
|
|
|
|
|
|
|
if (settings.isDisabled(date, mode)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var endDate = module.get.endDate();
|
|
|
|
if (!!endDate && !!date && date > endDate) {
|
|
|
|
//selected date is greater than end date in range, so clear end date
|
|
|
|
module.set.endDate(undefined);
|
|
|
|
}
|
|
|
|
module.set.dataKeyValue(metadata.date, date);
|
|
|
|
|
|
|
|
if (updateInput && $input.length) {
|
|
|
|
$input.val(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fireChange) {
|
|
|
|
settings.onChange.call(element, date, text, mode);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
startDate: function (date, refreshCalendar) {
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
var startModule = module.get.calendarModule(settings.startCalendar);
|
|
|
|
if (startModule) {
|
|
|
|
startModule.set.date(date);
|
|
|
|
}
|
|
|
|
module.set.dataKeyValue(metadata.startDate, date, refreshCalendar);
|
|
|
|
},
|
|
|
|
endDate: function (date, refreshCalendar) {
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
var endModule = module.get.calendarModule(settings.endCalendar);
|
|
|
|
if (endModule) {
|
|
|
|
endModule.set.date(date);
|
|
|
|
}
|
|
|
|
module.set.dataKeyValue(metadata.endDate, date, refreshCalendar);
|
|
|
|
},
|
|
|
|
focusDate: function (date, refreshCalendar, updateFocus, updateRange) {
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
date = module.helper.dateInRange(date);
|
|
|
|
var isDay = module.get.mode() === 'day';
|
|
|
|
var oldFocusDate = module.get.focusDate();
|
|
|
|
if (isDay && date && oldFocusDate) {
|
|
|
|
var yearDelta = date.getFullYear() - oldFocusDate.getFullYear();
|
|
|
|
var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth();
|
|
|
|
if (monthDelta) {
|
|
|
|
var monthOffset = module.get.monthOffset() - monthDelta;
|
|
|
|
module.set.monthOffset(monthOffset, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var changed = module.set.dataKeyValue(metadata.focusDate, date, !!date && refreshCalendar);
|
|
|
|
updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange;
|
|
|
|
focusDateUsedForRange = updateRange;
|
|
|
|
if (updateFocus) {
|
|
|
|
module.update.focus(updateRange);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
minDate: function (date) {
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
if (settings.maxDate !== null && settings.maxDate <= date) {
|
|
|
|
module.verbose('Unable to set minDate variable bigger that maxDate variable', date, settings.maxDate);
|
|
|
|
} else {
|
|
|
|
module.setting('minDate', date);
|
|
|
|
module.set.dataKeyValue(metadata.minDate, date);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
maxDate: function (date) {
|
|
|
|
date = module.helper.sanitiseDate(date);
|
|
|
|
if (settings.minDate !== null && settings.minDate >= date) {
|
|
|
|
module.verbose('Unable to set maxDate variable lower that minDate variable', date, settings.minDate);
|
|
|
|
} else {
|
|
|
|
module.setting('maxDate', date);
|
|
|
|
module.set.dataKeyValue(metadata.maxDate, date);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
monthOffset: function (monthOffset, refreshCalendar) {
|
|
|
|
var multiMonth = Math.max(settings.multiMonth, 1);
|
|
|
|
monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset));
|
|
|
|
module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar);
|
|
|
|
},
|
|
|
|
mode: function (mode, refreshCalendar) {
|
|
|
|
module.set.dataKeyValue(metadata.mode, mode, refreshCalendar);
|
|
|
|
},
|
|
|
|
dataKeyValue: function (key, value, refreshCalendar) {
|
|
|
|
var oldValue = $module.data(key);
|
|
|
|
var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects
|
|
|
|
if (value) {
|
|
|
|
$module.data(key, value);
|
|
|
|
} else {
|
|
|
|
$module.removeData(key);
|
|
|
|
}
|
|
|
|
refreshCalendar = refreshCalendar !== false && !equal;
|
|
|
|
if (refreshCalendar) {
|
|
|
|
module.refresh();
|
|
|
|
}
|
|
|
|
return !equal;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
selectDate: function (date, forceSet) {
|
|
|
|
module.verbose('New date selection', date);
|
|
|
|
var mode = module.get.mode();
|
|
|
|
var complete = forceSet || mode === 'minute' ||
|
|
|
|
(settings.disableMinute && mode === 'hour') ||
|
|
|
|
(settings.type === 'date' && mode === 'day') ||
|
|
|
|
(settings.type === 'month' && mode === 'month') ||
|
|
|
|
(settings.type === 'year' && mode === 'year');
|
|
|
|
if (complete) {
|
|
|
|
var canceled = module.set.date(date) === false;
|
|
|
|
if (!canceled) {
|
|
|
|
selectionComplete = true;
|
|
|
|
if(settings.closable) {
|
|
|
|
module.popup('hide');
|
|
|
|
//if this is a range calendar, focus the container or input. This will open the popup from its event listeners.
|
|
|
|
var endModule = module.get.calendarModule(settings.endCalendar);
|
|
|
|
if (endModule) {
|
2022-08-05 09:25:53 +00:00
|
|
|
endModule.refresh();
|
2022-03-15 09:43:53 +00:00
|
|
|
if (endModule.setting('on') !== 'focus') {
|
|
|
|
endModule.popup('show');
|
|
|
|
}
|
|
|
|
endModule.focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') :
|
|
|
|
mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute';
|
|
|
|
module.set.mode(newMode);
|
|
|
|
if (mode === 'hour' || (mode === 'day' && module.get.date())) {
|
|
|
|
//the user has chosen enough to consider a valid date/time has been chosen
|
|
|
|
module.set.date(date, true, false);
|
|
|
|
} else {
|
|
|
|
module.set.focusDate(date);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
changeDate: function (date) {
|
|
|
|
module.set.date(date);
|
|
|
|
},
|
|
|
|
|
|
|
|
clear: function () {
|
|
|
|
module.set.date(undefined);
|
|
|
|
},
|
|
|
|
|
|
|
|
popup: function () {
|
|
|
|
return $activator.popup.apply($activator, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
focus: function () {
|
|
|
|
if ($input.length) {
|
|
|
|
$input.focus();
|
|
|
|
} else {
|
|
|
|
$container.focus();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
blur: function () {
|
|
|
|
if ($input.length) {
|
|
|
|
$input.blur();
|
|
|
|
} else {
|
|
|
|
$container.blur();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
helper: {
|
2022-08-05 09:25:53 +00:00
|
|
|
dateFormat: function(format,date) {
|
|
|
|
if (!(date instanceof Date)) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
if(typeof format === 'function') {
|
|
|
|
return format.call(module, date, settings);
|
|
|
|
}
|
|
|
|
|
|
|
|
var D = date.getDate(),
|
|
|
|
M = date.getMonth(),
|
|
|
|
Y = date.getFullYear(),
|
|
|
|
d = date.getDay(),
|
|
|
|
H = date.getHours(),
|
|
|
|
m = date.getMinutes(),
|
|
|
|
s = date.getSeconds(),
|
|
|
|
w = module.get.weekOfYear(Y,M,D+1-settings.firstDayOfWeek),
|
|
|
|
h = H % 12 || 12,
|
|
|
|
a = H < 12 ? settings.text.am.toLowerCase() : settings.text.pm.toLowerCase(),
|
|
|
|
tokens = {
|
|
|
|
D: D,
|
|
|
|
DD: ('0'+D).slice(-2),
|
|
|
|
M: M + 1,
|
|
|
|
MM: ('0'+(M+1)).slice(-2),
|
|
|
|
MMM: settings.text.monthsShort[M],
|
|
|
|
MMMM: settings.text.months[M],
|
|
|
|
Y: Y,
|
|
|
|
YY: String(Y).slice(2),
|
|
|
|
YYYY: Y,
|
|
|
|
d: d,
|
|
|
|
dd: settings.text.dayNamesShort[d].slice(0,2),
|
|
|
|
ddd: settings.text.dayNamesShort[d],
|
|
|
|
dddd: settings.text.dayNames[d],
|
|
|
|
h: h,
|
|
|
|
hh: ('0'+h).slice(-2),
|
|
|
|
H: H,
|
|
|
|
HH: ('0'+H).slice(-2),
|
|
|
|
m: m,
|
|
|
|
mm: ('0'+m).slice(-2),
|
|
|
|
s: s,
|
|
|
|
ss: ('0'+s).slice(-2),
|
|
|
|
a: a,
|
|
|
|
A: a.toUpperCase(),
|
|
|
|
S: ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D % 100 - D % 10 !== 10) * D % 10],
|
|
|
|
w: w,
|
|
|
|
ww: ('0'+w).slice(-2)
|
|
|
|
}
|
|
|
|
;
|
|
|
|
return format.replace(settings.regExp.token, function (match) {
|
|
|
|
if (match in tokens) {
|
|
|
|
return tokens[match];
|
|
|
|
}
|
|
|
|
return match.slice(1, match.length - 1);
|
|
|
|
});
|
|
|
|
},
|
2022-03-15 09:43:53 +00:00
|
|
|
isDisabled: function(date, mode) {
|
2022-08-05 09:25:53 +00:00
|
|
|
return (mode === 'day' || mode === 'month' || mode === 'year' || mode === 'hour') && (((mode === 'day' && settings.disabledDaysOfWeek.indexOf(date.getDay()) !== -1) || settings.disabledDates.some(function(d){
|
2022-03-15 09:43:53 +00:00
|
|
|
if(typeof d === 'string') {
|
|
|
|
d = module.helper.sanitiseDate(d);
|
|
|
|
}
|
|
|
|
if (d instanceof Date) {
|
|
|
|
return module.helper.dateEqual(date, d, mode);
|
|
|
|
}
|
|
|
|
if (d !== null && typeof d === 'object') {
|
|
|
|
if (d[metadata.year]) {
|
|
|
|
if (typeof d[metadata.year] === 'number') {
|
|
|
|
return date.getFullYear() == d[metadata.year];
|
|
|
|
} else if (Array.isArray(d[metadata.year])) {
|
|
|
|
return d[metadata.year].indexOf(date.getFullYear()) > -1;
|
|
|
|
}
|
|
|
|
} else if (d[metadata.month]) {
|
|
|
|
if (typeof d[metadata.month] === 'number') {
|
|
|
|
return date.getMonth() == d[metadata.month];
|
|
|
|
} else if (Array.isArray(d[metadata.month])) {
|
|
|
|
return d[metadata.month].indexOf(date.getMonth()) > -1;
|
|
|
|
} else if (d[metadata.month] instanceof Date) {
|
|
|
|
var sdate = module.helper.sanitiseDate(d[metadata.month]);
|
|
|
|
return (date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())
|
|
|
|
}
|
|
|
|
} else if (d[metadata.date] && mode === 'day') {
|
|
|
|
if (d[metadata.date] instanceof Date) {
|
|
|
|
return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
|
|
|
|
} else if (Array.isArray(d[metadata.date])) {
|
|
|
|
return d[metadata.date].some(function(idate) {
|
|
|
|
return module.helper.dateEqual(date, idate, mode);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-05 09:25:53 +00:00
|
|
|
})) || (mode === 'hour' && settings.disabledHours.some(function(d){
|
|
|
|
if (typeof d === 'string') {
|
|
|
|
d = module.helper.sanitiseDate(d);
|
|
|
|
}
|
|
|
|
if (d instanceof Date) {
|
|
|
|
return module.helper.dateEqual(date, d, mode);
|
|
|
|
} else if (typeof d === 'number') {
|
|
|
|
return date.getHours() === d;
|
|
|
|
}
|
|
|
|
if (d !== null && typeof d === 'object') {
|
|
|
|
var blocked = true;
|
|
|
|
|
|
|
|
if (d[metadata.date]) {
|
|
|
|
if (d[metadata.date] instanceof Date) {
|
|
|
|
blocked = module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]));
|
|
|
|
} else if (Array.isArray(d[metadata.date])) {
|
|
|
|
return d[metadata.date].some(function(idate) {
|
|
|
|
blocked = module.helper.dateEqual(date, idate, mode);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d[metadata.days]) {
|
|
|
|
if (typeof d[metadata.days] === 'number') {
|
|
|
|
blocked = date.getDay() == d[metadata.days];
|
|
|
|
} else if (Array.isArray(d[metadata.days])) {
|
|
|
|
blocked = d[metadata.days].indexOf(date.getDay()) > -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d[metadata.hours]) {
|
|
|
|
if (typeof d[metadata.hours] === 'number') {
|
|
|
|
return blocked && date.getHours() == d[metadata.hours];
|
|
|
|
} else if (Array.isArray(d[metadata.hours])) {
|
|
|
|
return blocked && d[metadata.hours].indexOf(date.getHours()) > -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})));
|
2022-03-15 09:43:53 +00:00
|
|
|
},
|
|
|
|
isEnabled: function(date, mode) {
|
|
|
|
if (mode === 'day') {
|
|
|
|
return settings.enabledDates.length === 0 || settings.enabledDates.some(function(d){
|
|
|
|
if(typeof d === 'string') {
|
|
|
|
d = module.helper.sanitiseDate(d);
|
|
|
|
}
|
|
|
|
if (d instanceof Date) {
|
|
|
|
return module.helper.dateEqual(date, d, mode);
|
|
|
|
}
|
|
|
|
if (d !== null && typeof d === 'object' && d[metadata.date]) {
|
|
|
|
return module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
findDayAsObject: function(date, mode, dates) {
|
|
|
|
if (mode === 'day' || mode === 'month' || mode === 'year') {
|
|
|
|
var d;
|
|
|
|
for (var i = 0; i < dates.length; i++) {
|
|
|
|
d = dates[i];
|
|
|
|
if(typeof d === 'string') {
|
|
|
|
d = module.helper.sanitiseDate(d);
|
|
|
|
}
|
|
|
|
if (d instanceof Date && module.helper.dateEqual(date, d, mode)) {
|
|
|
|
var dateObject = {};
|
|
|
|
dateObject[metadata.date] = d;
|
|
|
|
return dateObject;
|
|
|
|
}
|
|
|
|
else if (d !== null && typeof d === 'object') {
|
|
|
|
if (d[metadata.year]) {
|
|
|
|
if (typeof d[metadata.year] === 'number' && date.getFullYear() == d[metadata.year]) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.year])) {
|
|
|
|
if (d[metadata.year].indexOf(date.getFullYear()) > -1) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (d[metadata.month]) {
|
|
|
|
if (typeof d[metadata.month] === 'number' && date.getMonth() == d[metadata.month]) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.month])) {
|
|
|
|
if (d[metadata.month].indexOf(date.getMonth()) > -1) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
} else if (d[metadata.month] instanceof Date) {
|
|
|
|
var sdate = module.helper.sanitiseDate(d[metadata.month]);
|
|
|
|
if ((date.getMonth() == sdate.getMonth()) && (date.getFullYear() == sdate.getFullYear())) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (d[metadata.date] && mode === 'day') {
|
|
|
|
if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]), mode)) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.date])) {
|
|
|
|
if(d[metadata.date].some(function(idate) { return module.helper.dateEqual(date, idate, mode); })) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
2022-08-05 09:25:53 +00:00
|
|
|
findHourAsObject: function(date, mode, hours) {
|
|
|
|
if (mode === 'hour') {
|
|
|
|
var d;
|
|
|
|
var hourCheck = function(date, d) {
|
|
|
|
if (d[metadata.hours]) {
|
|
|
|
if (typeof d[metadata.hours] === 'number' && date.getHours() == d[metadata.hours]) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.hours])) {
|
|
|
|
if (d[metadata.hours].indexOf(date.getHours()) > -1) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (var i = 0; i < hours.length; i++) {
|
|
|
|
d = hours[i];
|
|
|
|
if (typeof d === 'number' && date.getHours() == d) {
|
|
|
|
return null;
|
|
|
|
} else if (d !== null && typeof d === 'object') {
|
|
|
|
if (d[metadata.days] && hourCheck(date,d)) {
|
|
|
|
if (typeof d[metadata.days] === 'number' && date.getDay() == d[metadata.days]) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.days])) {
|
|
|
|
if (d[metadata.days].indexOf(date.getDay()) > -1) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (d[metadata.date] && hourCheck(date,d)) {
|
|
|
|
if (d[metadata.date] instanceof Date && module.helper.dateEqual(date, module.helper.sanitiseDate(d[metadata.date]))) {
|
|
|
|
return d;
|
|
|
|
} else if (Array.isArray(d[metadata.date])) {
|
|
|
|
if (d[metadata.date].some(function(idate) { return module.helper.dateEqual(date, idate, mode); })) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (hourCheck(date,d)) {
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
2022-03-15 09:43:53 +00:00
|
|
|
sanitiseDate: function (date) {
|
|
|
|
if (!(date instanceof Date)) {
|
|
|
|
date = parser.date('' + date, settings);
|
|
|
|
}
|
|
|
|
if (!date || isNaN(date.getTime())) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return date;
|
|
|
|
},
|
|
|
|
dateDiff: function (date1, date2, mode) {
|
|
|
|
mode = mode || 'day';
|
|
|
|
var isTimeOnly = settings.type === 'time';
|
|
|
|
var isYear = mode === 'year';
|
|
|
|
var isYearOrMonth = isYear || mode === 'month';
|
|
|
|
var isMinute = mode === 'minute';
|
|
|
|
var isHourOrMinute = isMinute || mode === 'hour';
|
|
|
|
//only care about a minute accuracy of settings.minTimeGap
|
|
|
|
date1 = new Date(
|
|
|
|
isTimeOnly ? 2000 : date1.getFullYear(),
|
|
|
|
isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(),
|
|
|
|
isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(),
|
|
|
|
!isHourOrMinute ? 0 : date1.getHours(),
|
|
|
|
!isMinute ? 0 : settings.minTimeGap * Math.floor(date1.getMinutes() / settings.minTimeGap));
|
|
|
|
date2 = new Date(
|
|
|
|
isTimeOnly ? 2000 : date2.getFullYear(),
|
|
|
|
isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(),
|
|
|
|
isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(),
|
|
|
|
!isHourOrMinute ? 0 : date2.getHours(),
|
|
|
|
!isMinute ? 0 : settings.minTimeGap * Math.floor(date2.getMinutes() / settings.minTimeGap));
|
|
|
|
return date2.getTime() - date1.getTime();
|
|
|
|
},
|
|
|
|
dateEqual: function (date1, date2, mode) {
|
|
|
|
return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0;
|
|
|
|
},
|
|
|
|
isDateInRange: function (date, mode, minDate, maxDate) {
|
|
|
|
if (!minDate && !maxDate) {
|
|
|
|
var startDate = module.get.startDate();
|
|
|
|
minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
|
|
|
|
maxDate = settings.maxDate;
|
|
|
|
}
|
|
|
|
minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
|
|
|
|
return !(!date ||
|
|
|
|
(minDate && module.helper.dateDiff(date, minDate, mode) > 0) ||
|
|
|
|
(maxDate && module.helper.dateDiff(maxDate, date, mode) > 0));
|
|
|
|
},
|
|
|
|
dateInRange: function (date, minDate, maxDate) {
|
|
|
|
if (!minDate && !maxDate) {
|
|
|
|
var startDate = module.get.startDate();
|
|
|
|
minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate;
|
|
|
|
maxDate = settings.maxDate;
|
|
|
|
}
|
|
|
|
minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), settings.minTimeGap * Math.ceil(minDate.getMinutes() / settings.minTimeGap));
|
|
|
|
var isTimeOnly = settings.type === 'time';
|
|
|
|
return !date ? date :
|
|
|
|
(minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ?
|
|
|
|
(isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) :
|
|
|
|
(maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ?
|
|
|
|
(isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) :
|
|
|
|
date;
|
|
|
|
},
|
|
|
|
mergeDateTime: function (date, time) {
|
|
|
|
return (!date || !time) ? time :
|
|
|
|
new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes());
|
|
|
|
},
|
|
|
|
isTodayButton: function(element) {
|
|
|
|
return element.text() === settings.text.today;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
setting: function (name, value) {
|
|
|
|
module.debug('Changing setting', name, value);
|
|
|
|
if ($.isPlainObject(name)) {
|
|
|
|
$.extend(true, settings, name);
|
|
|
|
}
|
|
|
|
else if (value !== undefined) {
|
|
|
|
if ($.isPlainObject(settings[name])) {
|
|
|
|
$.extend(true, settings[name], value);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
settings[name] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return settings[name];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
internal: function (name, value) {
|
|
|
|
if( $.isPlainObject(name) ) {
|
|
|
|
$.extend(true, module, name);
|
|
|
|
}
|
|
|
|
else if(value !== undefined) {
|
|
|
|
module[name] = value;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return module[name];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
debug: function () {
|
|
|
|
if (!settings.silent && settings.debug) {
|
|
|
|
if (settings.performance) {
|
|
|
|
module.performance.log(arguments);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
|
|
module.debug.apply(console, arguments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
verbose: function () {
|
|
|
|
if (!settings.silent && settings.verbose && settings.debug) {
|
|
|
|
if (settings.performance) {
|
|
|
|
module.performance.log(arguments);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
|
|
module.verbose.apply(console, arguments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error: function () {
|
|
|
|
if (!settings.silent) {
|
|
|
|
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
|
|
|
module.error.apply(console, arguments);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
performance: {
|
|
|
|
log: function (message) {
|
|
|
|
var
|
|
|
|
currentTime,
|
|
|
|
executionTime,
|
|
|
|
previousTime
|
|
|
|
;
|
|
|
|
if (settings.performance) {
|
|
|
|
currentTime = new Date().getTime();
|
|
|
|
previousTime = time || currentTime;
|
|
|
|
executionTime = currentTime - previousTime;
|
|
|
|
time = currentTime;
|
|
|
|
performance.push({
|
|
|
|
'Name': message[0],
|
|
|
|
'Arguments': [].slice.call(message, 1) || '',
|
|
|
|
'Element': element,
|
|
|
|
'Execution Time': executionTime
|
|
|
|
});
|
|
|
|
}
|
|
|
|
clearTimeout(module.performance.timer);
|
|
|
|
module.performance.timer = setTimeout(module.performance.display, 500);
|
|
|
|
},
|
|
|
|
display: function () {
|
|
|
|
var
|
|
|
|
title = settings.name + ':',
|
|
|
|
totalTime = 0
|
|
|
|
;
|
|
|
|
time = false;
|
|
|
|
clearTimeout(module.performance.timer);
|
|
|
|
$.each(performance, function (index, data) {
|
|
|
|
totalTime += data['Execution Time'];
|
|
|
|
});
|
|
|
|
title += ' ' + totalTime + 'ms';
|
|
|
|
if (moduleSelector) {
|
|
|
|
title += ' \'' + moduleSelector + '\'';
|
|
|
|
}
|
|
|
|
if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) {
|
|
|
|
console.groupCollapsed(title);
|
|
|
|
if (console.table) {
|
|
|
|
console.table(performance);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$.each(performance, function (index, data) {
|
|
|
|
console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
console.groupEnd();
|
|
|
|
}
|
|
|
|
performance = [];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
invoke: function (query, passedArguments, context) {
|
|
|
|
var
|
|
|
|
object = instance,
|
|
|
|
maxDepth,
|
|
|
|
found,
|
|
|
|
response
|
|
|
|
;
|
|
|
|
passedArguments = passedArguments || queryArguments;
|
2022-09-15 12:58:37 +00:00
|
|
|
context = context || element;
|
2022-03-15 09:43:53 +00:00
|
|
|
if (typeof query == 'string' && object !== undefined) {
|
|
|
|
query = query.split(/[\. ]/);
|
|
|
|
maxDepth = query.length - 1;
|
|
|
|
$.each(query, function (depth, value) {
|
|
|
|
var camelCaseValue = (depth != maxDepth)
|
|
|
|
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
|
|
|
: query
|
|
|
|
;
|
|
|
|
if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) {
|
|
|
|
object = object[camelCaseValue];
|
|
|
|
}
|
|
|
|
else if (object[camelCaseValue] !== undefined) {
|
|
|
|
found = object[camelCaseValue];
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ($.isPlainObject(object[value]) && (depth != maxDepth)) {
|
|
|
|
object = object[value];
|
|
|
|
}
|
|
|
|
else if (object[value] !== undefined) {
|
|
|
|
found = object[value];
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
module.error(error.method, query);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if ($.isFunction(found)) {
|
|
|
|
response = found.apply(context, passedArguments);
|
|
|
|
}
|
|
|
|
else if (found !== undefined) {
|
|
|
|
response = found;
|
|
|
|
}
|
|
|
|
if (Array.isArray(returnedValue)) {
|
|
|
|
returnedValue.push(response);
|
|
|
|
}
|
|
|
|
else if (returnedValue !== undefined) {
|
|
|
|
returnedValue = [returnedValue, response];
|
|
|
|
}
|
|
|
|
else if (response !== undefined) {
|
|
|
|
returnedValue = response;
|
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (methodInvoked) {
|
|
|
|
if (instance === undefined) {
|
|
|
|
module.initialize();
|
|
|
|
}
|
|
|
|
module.invoke(query);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (instance !== undefined) {
|
|
|
|
instance.invoke('destroy');
|
|
|
|
}
|
|
|
|
module.initialize();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
;
|
|
|
|
return (returnedValue !== undefined)
|
|
|
|
? returnedValue
|
|
|
|
: this
|
|
|
|
;
|
|
|
|
};
|
|
|
|
|
|
|
|
$.fn.calendar.settings = {
|
|
|
|
|
|
|
|
name : 'Calendar',
|
|
|
|
namespace : 'calendar',
|
|
|
|
|
|
|
|
silent: false,
|
|
|
|
debug: false,
|
|
|
|
verbose: false,
|
2022-08-31 14:40:59 +00:00
|
|
|
performance: true,
|
2022-03-15 09:43:53 +00:00
|
|
|
|
|
|
|
type : 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year'
|
|
|
|
firstDayOfWeek : 0, // day for first day column (0 = Sunday)
|
|
|
|
constantHeight : true, // add rows to shorter months to keep day calendar height consistent (6 rows)
|
|
|
|
today : false, // show a 'today/now' button at the bottom of the calendar
|
|
|
|
closable : true, // close the popup after selecting a date/time
|
2022-08-05 09:25:53 +00:00
|
|
|
monthFirst : true, // month before day when parsing date from text
|
2022-03-15 09:43:53 +00:00
|
|
|
touchReadonly : true, // set input to readonly on touch devices
|
|
|
|
inline : false, // create the calendar inline instead of inside a popup
|
|
|
|
on : null, // when to show the popup (defaults to 'focus' for input, 'click' for others)
|
|
|
|
initialDate : null, // date to display initially when no date is selected (null = now)
|
|
|
|
startMode : false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day')
|
|
|
|
minDate : null, // minimum date/time that can be selected, dates/times before are disabled
|
|
|
|
maxDate : null, // maximum date/time that can be selected, dates/times after are disabled
|
|
|
|
disableYear : false, // disable year selection mode
|
|
|
|
disableMonth : false, // disable month selection mode
|
|
|
|
disableMinute : false, // disable minute selection mode
|
|
|
|
formatInput : true, // format the input text upon input blur and module creation
|
|
|
|
startCalendar : null, // jquery object or selector for another calendar that represents the start date of a date range
|
|
|
|
endCalendar : null, // jquery object or selector for another calendar that represents the end date of a date range
|
|
|
|
multiMonth : 1, // show multiple months when in 'day' mode
|
2022-08-05 09:25:53 +00:00
|
|
|
monthOffset : 0, // position current month by offset when multimonth > 1
|
2022-03-15 09:43:53 +00:00
|
|
|
minTimeGap : 5,
|
2022-08-05 09:25:53 +00:00
|
|
|
showWeekNumbers : false, // show Number of Week at the very first column of a dayView
|
|
|
|
disabledHours : [], // specific hour(s) which won't be selectable and contain additional information.
|
2022-03-15 09:43:53 +00:00
|
|
|
disabledDates : [], // specific day(s) which won't be selectable and contain additional information.
|
|
|
|
disabledDaysOfWeek : [], // day(s) which won't be selectable(s) (0 = Sunday)
|
|
|
|
enabledDates : [], // specific day(s) which will be selectable, all other days will be disabled
|
|
|
|
eventDates : [], // specific day(s) which will be shown in a different color and using tooltips
|
|
|
|
centuryBreak : 60, // starting short year until 99 where it will be assumed to belong to the last century
|
|
|
|
currentCentury : 2000, // century to be added to 2-digit years (00 to {centuryBreak}-1)
|
|
|
|
selectAdjacentDays : false, // The calendar can show dates from adjacent month. These adjacent month dates can also be made selectable.
|
|
|
|
// popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden)
|
|
|
|
popupOptions: {
|
|
|
|
position: 'bottom left',
|
|
|
|
lastResort: 'bottom left',
|
|
|
|
prefer: 'opposite',
|
2022-08-05 09:25:53 +00:00
|
|
|
observeChanges: false,
|
2022-03-15 09:43:53 +00:00
|
|
|
hideOnScroll: false
|
|
|
|
},
|
|
|
|
|
|
|
|
text: {
|
|
|
|
days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
|
2022-08-05 09:25:53 +00:00
|
|
|
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
|
|
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
2022-03-15 09:43:53 +00:00
|
|
|
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
|
|
monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
|
|
today: 'Today',
|
|
|
|
now: 'Now',
|
|
|
|
am: 'AM',
|
|
|
|
pm: 'PM',
|
|
|
|
weekNo: 'Week'
|
|
|
|
},
|
|
|
|
|
|
|
|
formatter: {
|
|
|
|
yearHeader: function (date, settings) {
|
|
|
|
var decadeYear = Math.ceil(date.getFullYear() / 10) * 10;
|
|
|
|
return (decadeYear - 9) + ' - ' + (decadeYear + 2);
|
|
|
|
},
|
2022-08-05 09:25:53 +00:00
|
|
|
monthHeader: 'YYYY',
|
|
|
|
dayHeader: 'MMMM YYYY',
|
|
|
|
hourHeader: 'MMMM D, YYYY',
|
|
|
|
minuteHeader: 'MMMM D, YYYY',
|
2022-03-15 09:43:53 +00:00
|
|
|
dayColumnHeader: function (day, settings) {
|
|
|
|
return settings.text.days[day];
|
|
|
|
},
|
2022-08-05 09:25:53 +00:00
|
|
|
datetime: 'MMMM D, YYYY h:mm A',
|
|
|
|
date: 'MMMM D, YYYY',
|
|
|
|
time: 'h:mm A',
|
|
|
|
cellTime: 'h:mm A',
|
|
|
|
month: 'MMMM YYYY',
|
|
|
|
year: 'YYYY',
|
2022-03-15 09:43:53 +00:00
|
|
|
today: function (settings) {
|
|
|
|
return settings.type === 'date' ? settings.text.today : settings.text.now;
|
|
|
|
},
|
|
|
|
cell: function (cell, date, cellOptions) {
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
parser: {
|
|
|
|
date: function (text, settings) {
|
|
|
|
if (text instanceof Date) {
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
if (!text) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-08-05 09:25:53 +00:00
|
|
|
text = String(text).trim().replace(/([.:\/\-])\s+/g,'$1').replace(/\s+([.:\/-])/g,'$1').replace(/\s+/g,' ');
|
2022-03-15 09:43:53 +00:00
|
|
|
if (text.length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if(text.match(/^[0-9]{4}[\/\-\.][0-9]{1,2}[\/\-\.][0-9]{1,2}$/)){
|
|
|
|
text = text.replace(/[\/\-\.]/g,'/') + ' 00:00:00';
|
|
|
|
}
|
|
|
|
// Reverse date and month in some cases
|
|
|
|
text = settings.monthFirst || !text.match(/^[0-9]{1,2}[\/\-\.]/) ? text : text.replace(/[\/\-\.]/g,'/').replace(/([0-9]+)\/([0-9]+)/,'$2/$1');
|
|
|
|
var textDate = new Date(text);
|
|
|
|
var numberOnly = text.match(/^[0-9]+$/) !== null;
|
|
|
|
if(!numberOnly && !isNaN(textDate.getDate())) {
|
|
|
|
return textDate;
|
|
|
|
}
|
|
|
|
text = text.toLowerCase();
|
|
|
|
|
|
|
|
var i, j, k;
|
|
|
|
var minute = -1, hour = -1, day = -1, month = -1, year = -1;
|
|
|
|
var isAm = undefined;
|
|
|
|
|
|
|
|
var isTimeOnly = settings.type === 'time';
|
|
|
|
var isDateOnly = settings.type.indexOf('time') < 0;
|
|
|
|
|
|
|
|
var words = text.split(settings.regExp.dateWords), word;
|
|
|
|
var numbers = text.split(settings.regExp.dateNumbers), number;
|
|
|
|
|
|
|
|
var parts;
|
|
|
|
var monthString;
|
|
|
|
|
|
|
|
if (!isDateOnly) {
|
|
|
|
//am/pm
|
|
|
|
isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true :
|
|
|
|
$.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined;
|
|
|
|
|
|
|
|
//time with ':'
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
number = numbers[i];
|
|
|
|
if (number.indexOf(':') >= 0) {
|
|
|
|
if (hour < 0 || minute < 0) {
|
|
|
|
parts = number.split(':');
|
|
|
|
for (k = 0; k < Math.min(2, parts.length); k++) {
|
|
|
|
j = parseInt(parts[k]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
j = 0;
|
|
|
|
}
|
|
|
|
if (k === 0) {
|
|
|
|
hour = j % 24;
|
|
|
|
} else {
|
|
|
|
minute = j % 60;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isTimeOnly) {
|
|
|
|
//textual month
|
|
|
|
for (i = 0; i < words.length; i++) {
|
|
|
|
word = words[i];
|
|
|
|
if (word.length <= 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (j = 0; j < settings.text.months.length; j++) {
|
|
|
|
monthString = settings.text.months[j];
|
|
|
|
monthString = monthString.substring(0, word.length).toLowerCase();
|
|
|
|
if (monthString === word) {
|
|
|
|
month = j + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (month >= 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//year > settings.centuryBreak
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
j = parseInt(numbers[i]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (j >= settings.centuryBreak && i === numbers.length-1) {
|
|
|
|
if (j <= 99) {
|
|
|
|
j += settings.currentCentury - 100;
|
|
|
|
}
|
|
|
|
year = j;
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//numeric month
|
|
|
|
if (month < 0) {
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1;
|
|
|
|
j = parseInt(numbers[k]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (1 <= j && j <= 12) {
|
|
|
|
month = j;
|
|
|
|
numbers.splice(k, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//day
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
j = parseInt(numbers[i]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (1 <= j && j <= 31) {
|
|
|
|
day = j;
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//year <= settings.centuryBreak
|
|
|
|
if (year < 0) {
|
|
|
|
for (i = numbers.length - 1; i >= 0; i--) {
|
|
|
|
j = parseInt(numbers[i]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (j <= 99) {
|
|
|
|
j += settings.currentCentury;
|
|
|
|
}
|
|
|
|
year = j;
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isDateOnly) {
|
|
|
|
//hour
|
|
|
|
if (hour < 0) {
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
j = parseInt(numbers[i]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (0 <= j && j <= 23) {
|
|
|
|
hour = j;
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//minute
|
|
|
|
if (minute < 0) {
|
|
|
|
for (i = 0; i < numbers.length; i++) {
|
|
|
|
j = parseInt(numbers[i]);
|
|
|
|
if (isNaN(j)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (0 <= j && j <= 59) {
|
|
|
|
minute = j;
|
|
|
|
numbers.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (minute < 0) {
|
|
|
|
minute = 0;
|
|
|
|
}
|
|
|
|
if (hour < 0) {
|
|
|
|
hour = 0;
|
|
|
|
}
|
|
|
|
if (day < 0) {
|
|
|
|
day = 1;
|
|
|
|
}
|
|
|
|
if (month < 0) {
|
|
|
|
month = 1;
|
|
|
|
}
|
|
|
|
if (year < 0) {
|
|
|
|
year = new Date().getFullYear();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isAm !== undefined) {
|
|
|
|
if (isAm) {
|
|
|
|
if (hour === 12) {
|
|
|
|
hour = 0;
|
|
|
|
}
|
|
|
|
} else if (hour < 12) {
|
|
|
|
hour += 12;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var date = new Date(year, month - 1, day, hour, minute);
|
|
|
|
if (date.getMonth() !== month - 1 || date.getFullYear() !== year) {
|
|
|
|
//month or year don't match up, switch to last day of the month
|
|
|
|
date = new Date(year, month, 0, hour, minute);
|
|
|
|
}
|
|
|
|
return isNaN(date.getTime()) ? null : date;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback before date is changed, return false to cancel the change
|
|
|
|
onBeforeChange: function (date, text, mode) {
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback when date changes
|
|
|
|
onChange: function (date, text, mode) {
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback before show animation, return false to prevent show
|
|
|
|
onShow: function () {
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback after show animation
|
|
|
|
onVisible: function () {
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback before hide animation, return false to prevent hide
|
|
|
|
onHide: function () {
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback after hide animation
|
|
|
|
onHidden: function () {
|
|
|
|
},
|
|
|
|
|
|
|
|
// callback before item is selected, return false to prevent selection
|
|
|
|
onSelect: function (date, mode) {
|
|
|
|
},
|
|
|
|
|
|
|
|
// is the given date disabled?
|
|
|
|
isDisabled: function (date, mode) {
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
selector: {
|
|
|
|
popup: '.ui.popup',
|
|
|
|
input: 'input',
|
|
|
|
activator: 'input',
|
|
|
|
append: '.inline.field,.inline.fields'
|
|
|
|
},
|
|
|
|
|
|
|
|
regExp: {
|
|
|
|
dateWords: /[^A-Za-z\u00C0-\u024F]+/g,
|
2022-08-05 09:25:53 +00:00
|
|
|
dateNumbers: /[^\d:]+/g,
|
|
|
|
token: /d{1,4}|D{1,2}|M{1,4}|YY(?:YY)?|([Hhmsw])\1?|[SAaY]|"[^"]*"|'[^']*'/g
|
2022-03-15 09:43:53 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
error: {
|
|
|
|
popup: 'UI Popup, a required component is not included in this page',
|
|
|
|
method: 'The method you called is not defined.'
|
|
|
|
},
|
|
|
|
|
|
|
|
className: {
|
|
|
|
calendar: 'calendar',
|
|
|
|
active: 'active',
|
|
|
|
popup: 'ui popup',
|
|
|
|
grid: 'ui equal width grid',
|
|
|
|
column: 'column',
|
|
|
|
table: 'ui celled center aligned unstackable table',
|
|
|
|
inverted: 'inverted',
|
|
|
|
prev: 'prev link',
|
|
|
|
next: 'next link',
|
|
|
|
prevIcon: 'chevron left icon',
|
|
|
|
nextIcon: 'chevron right icon',
|
|
|
|
link: 'link',
|
|
|
|
cell: 'link',
|
|
|
|
disabledCell: 'disabled',
|
|
|
|
weekCell: 'disabled',
|
|
|
|
adjacentCell: 'adjacent',
|
|
|
|
activeCell: 'active',
|
|
|
|
rangeCell: 'range',
|
|
|
|
focusCell: 'focus',
|
|
|
|
todayCell: 'today',
|
|
|
|
today: 'today link',
|
|
|
|
disabled: 'disabled'
|
|
|
|
},
|
|
|
|
|
|
|
|
metadata: {
|
|
|
|
date: 'date',
|
|
|
|
focusDate: 'focusDate',
|
|
|
|
startDate: 'startDate',
|
|
|
|
endDate: 'endDate',
|
|
|
|
minDate: 'minDate',
|
|
|
|
maxDate: 'maxDate',
|
|
|
|
mode: 'mode',
|
|
|
|
type: 'type',
|
|
|
|
monthOffset: 'monthOffset',
|
|
|
|
message: 'message',
|
|
|
|
class: 'class',
|
|
|
|
inverted: 'inverted',
|
|
|
|
variation: 'variation',
|
|
|
|
position: 'position',
|
|
|
|
month: 'month',
|
2022-08-05 09:25:53 +00:00
|
|
|
year: 'year',
|
|
|
|
hours: 'hours',
|
|
|
|
days: 'days'
|
2022-03-15 09:43:53 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
eventClass: 'blue'
|
|
|
|
};
|
|
|
|
|
|
|
|
})(jQuery, window, document);
|