@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
2,518 lines • 97.4 kB
JavaScript
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
require("./kendo.icons.js");
require("./kendo.dropdownlist.js");
require("./kendo.datepicker.js");
require("./kendo.numerictextbox.js");
require("./kendo.buttongroup.js");
//#region ../src/kendo.scheduler.recurrence.js
const __meta__ = {
id: "scheduler.recurrence",
name: "Recurrence",
category: "web",
depends: [
"dropdownlist",
"datepicker",
"numerictextbox",
"buttongroup",
"icons"
],
hidden: true
};
(function($, undefined) {
var kendo = window.kendo, encode = kendo.htmlEncode, timezone = kendo.timezone, Class = kendo.Class, ui = kendo.ui, Widget = ui.Widget, DropDownList = ui.DropDownList, ButtonGroup = ui.ButtonGroup, kendoDate = kendo.date, setTime = kendoDate.setTime, setDayOfWeek = kendoDate.setDayOfWeek, adjustDST = kendoDate.adjustDST, firstDayOfMonth = kendoDate.firstDayOfMonth, getMilliseconds = kendoDate.getMilliseconds, DAYS_IN_LEAPYEAR = [
0,
31,
60,
91,
121,
152,
182,
213,
244,
274,
305,
335,
366
], DAYS_IN_YEAR = [
0,
31,
59,
90,
120,
151,
181,
212,
243,
273,
304,
334,
365
], MONTHS = [
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
], WEEK_DAYS = {
0: "SU",
1: "MO",
2: "TU",
3: "WE",
4: "TH",
5: "FR",
6: "SA"
}, WEEK_DAYS_IDX = {
"SU": 0,
"MO": 1,
"TU": 2,
"WE": 3,
"TH": 4,
"FR": 5,
"SA": 6
}, DATE_FORMATS = [
"yyyy-MM-ddTHH:mm:ss.fffzzz",
"yyyy-MM-ddTHH:mm:sszzz",
"yyyy-MM-ddTHH:mm:ss",
"yyyy-MM-ddTHH:mm",
"yyyy-MM-ddTHH",
"yyyy-MM-dd",
"yyyyMMddTHHmmssfffzzz",
"yyyyMMddTHHmmsszzz",
"yyyyMMddTHHmmss",
"yyyyMMddTHHmm",
"yyyyMMddTHH",
"yyyyMMdd"
], RULE_NAMES = [
"months",
"weeks",
"yearDays",
"monthDays",
"weekDays",
"hours",
"minutes",
"seconds"
], RULE_NAMES_LENGTH = RULE_NAMES.length, RECURRENCE_DATE_FORMAT = "yyyyMMddTHHmmssZ", limitation = {
months: function(date, end, rule) {
var monthRules = rule.months, months = ruleValues(monthRules, date.getMonth() + 1), changed = false;
if (months !== null) {
if (months.length) date.setMonth(months[0] - 1, 1);
else date.setFullYear(date.getFullYear() + 1, monthRules[0] - 1, 1);
changed = true;
}
return changed;
},
monthDays: function(date, end, rule) {
var monthLength, month, days, changed = false, hours = date.getHours(), normalize = function(monthDay) {
if (monthDay < 0) monthDay = monthLength + monthDay + 1;
return monthDay;
};
while (date <= end) {
month = date.getMonth();
monthLength = getMonthLength(date);
days = ruleValues(rule.monthDays, date.getDate(), normalize);
if (days === null) return changed;
changed = true;
if (days.length) {
date.setMonth(month, days.sort(numberSortPredicate)[0]);
adjustDST(date, hours);
if (month === date.getMonth()) break;
} else date.setMonth(month + 1, 1);
}
return changed;
},
yearDays: function(date, end, rule) {
var year, yearDays, changed = false, hours = date.getHours(), normalize = function(yearDay) {
if (yearDay < 0) yearDay = year + yearDay;
return yearDay;
};
while (date < end) {
year = leapYear(date) ? 366 : 365;
yearDays = ruleValues(rule.yearDays, dayInYear(date), normalize);
if (yearDays === null) return changed;
changed = true;
year = date.getFullYear();
if (yearDays.length) {
date.setFullYear(year, 0, yearDays.sort(numberSortPredicate)[0]);
adjustDST(date, hours);
break;
} else date.setFullYear(year + 1, 0, 1);
}
return changed;
},
weeks: function(date, end, rule) {
var weekStart = rule.weekStart, year, weeks, day, changed = false, hours = date.getHours(), normalize = function(week) {
if (week < 0) week = 53 + week;
return week;
};
while (date < end) {
weeks = ruleValues(rule.weeks, weekInYear(date, weekStart), normalize);
if (weeks === null) return changed;
changed = true;
year = date.getFullYear();
if (weeks.length) {
day = weeks.sort(numberSortPredicate)[0] * 7 - 1;
date.setFullYear(year, 0, day);
setDayOfWeek(date, weekStart, -1);
adjustDST(date, hours);
break;
} else date.setFullYear(year + 1, 0, 1);
}
return changed;
},
weekDays: function(date, end, rule) {
var offsetDate = new Date(date.getTime() + rule.offsets.start);
var normalizeDay = offsetDate.getDay() - date.getDay();
var weekDays = rule.weekDays;
var weekStart = rule.weekStart;
var weekDayRules = ruleWeekValues(weekDays, offsetDate, weekStart);
var hours = date.getHours();
var traverseRuleForNextMont = function(rule) {
var nextMonthFirstDay = new Date(date.getFullYear(), date.getMonth() + 1, 1);
var ruleDay = normalizeDayIndex(rule.day, weekStart);
if (nextMonthFirstDay.getDay() <= ruleDay) {
if (!weekDayRule || normalizeDayIndex(weekDayRule.day, weekStart) > ruleDay) weekDayRule = rule;
}
};
var weekDayRule, day;
if (weekDayRules === null) return false;
weekDayRule = weekDayRules[0];
if (!weekDayRule) {
if (rule.freq === "monthly" && !rule.positions || rule.position > 0) weekDays.forEach(traverseRuleForNextMont);
if (!weekDayRule) weekDayRule = weekDays[0];
setDayOfWeek(date, weekStart);
}
day = weekDayRule.day;
day -= normalizeDay;
if (weekDayRule.offset) while (date <= end && !isInWeek(date, weekDayRule, weekStart)) if (weekInMonth(date, weekStart) === numberOfWeeks(date, weekStart)) {
date.setMonth(date.getMonth() + 1, 1);
adjustDST(date, hours);
} else {
date.setDate(date.getDate() + 7);
adjustDST(date, hours);
setDayOfWeek(date, weekStart, -1);
}
if (date.getDay() !== day) setDayOfWeek(date, day);
return true;
},
hours: function(date, end, rule) {
var hourRules = rule.hours, startTime = rule._startTime, startHours = startTime.getHours(), hours = ruleValues(hourRules, startHours), changed = false;
if (hours !== null) {
changed = true;
date.setHours(startHours);
adjustDST(date, startHours);
if (hours.length) {
hours = hours[0];
date.setHours(hours);
} else {
hours = date.getHours();
date.setDate(date.getDate() + 1);
adjustDST(date, hours);
hours = hourRules[0];
date.setHours(hours);
adjustDST(date, hours);
}
if (rule.minutes) date.setMinutes(0);
startTime.setHours(hours, date.getMinutes());
}
return changed;
},
minutes: function(date, end, rule) {
var minuteRules = rule.minutes, minutes = ruleValues(minuteRules, date.getMinutes()), hours = rule._startTime.getHours(), changed = false;
if (minutes !== null) {
changed = true;
if (minutes.length) minutes = minutes[0];
else {
hours += 1;
minutes = minuteRules[0];
}
if (rule.seconds) date.setSeconds(0);
date.setHours(hours, minutes);
hours = hours % 24;
adjustDST(date, hours);
rule._startTime.setHours(hours, minutes, date.getSeconds());
}
return changed;
},
seconds: function(date, end, rule) {
var secondRules = rule.seconds, hours = rule._startTime.getHours(), seconds = ruleValues(secondRules, date.getSeconds()), minutes = date.getMinutes(), changed = false;
if (seconds !== null) {
changed = true;
if (seconds.length) date.setSeconds(seconds[0]);
else {
minutes += 1;
date.setMinutes(minutes, secondRules[0]);
if (minutes > 59) {
minutes = minutes % 60;
hours = (hours + 1) % 24;
}
}
rule._startTime.setHours(hours, minutes, date.getSeconds());
}
return changed;
}
}, BaseFrequency = Class.extend({
next: function(date, rule) {
var startTime = rule._startTime, day = startTime.getDate(), minutes, seconds;
if (rule.seconds) {
seconds = date.getSeconds() + 1;
date.setSeconds(seconds);
startTime.setSeconds(seconds);
startTime.setDate(day);
} else if (rule.minutes) {
minutes = date.getMinutes() + 1;
date.setMinutes(minutes);
startTime.setMinutes(minutes);
startTime.setDate(day);
} else return false;
return true;
},
normalize: function(options) {
var rule = options.rule;
if (options.idx === 4 && rule.hours) {
rule._startTime.setHours(0);
this._hour(options.date, rule);
}
},
limit: function(date, end, rule) {
var interval = rule.interval, ruleName, firstRule, modified, idx, day;
while (date <= end) {
modified = firstRule = undefined;
day = date.getDate();
for (idx = 0; idx < RULE_NAMES_LENGTH; idx++) {
ruleName = RULE_NAMES[idx];
if (rule[ruleName]) {
modified = limitation[ruleName](date, end, rule);
if (firstRule !== undefined && modified) break;
else firstRule = modified;
}
if (modified) this.normalize({
date,
rule,
day,
idx
});
}
if ((interval === 1 || !this.interval(rule, date)) && idx === RULE_NAMES_LENGTH) break;
}
},
interval: function(rule, current) {
var start = new Date(rule._startPeriod);
var date = new Date(current);
var hours = current.getHours();
var weekStart = rule.weekStart;
var interval = rule.interval;
var frequency = rule.freq;
var modified = false;
var excess = 0;
var month = 0;
var day = 1;
var diff;
var startTimeHours;
if (frequency === "hourly") {
diff = date.getTimezoneOffset() - start.getTimezoneOffset();
startTimeHours = rule._startTime.getHours();
date = date.getTime();
if (hours !== startTimeHours) date += (startTimeHours - hours) * kendoDate.MS_PER_HOUR;
date -= start;
if (diff) date -= diff * kendoDate.MS_PER_MINUTE;
diff = Math.floor(date / kendoDate.MS_PER_HOUR);
excess = intervalExcess(diff, interval);
if (excess !== 0) {
this._hour(current, rule, excess);
modified = true;
}
} else if (frequency === "daily") {
kendoDate.setTime(date, -start, true);
diff = Math.round(date / kendoDate.MS_PER_DAY);
excess = intervalExcess(diff, interval);
if (excess !== 0) {
this._date(current, rule, excess);
modified = true;
}
} else if (frequency === "weekly") {
excess = this._getNumberOfWeeksBetweenDates(start, current);
if (normalizeDayIndex(current.getDay(), weekStart) < normalizeDayIndex(start.getDay(), weekStart)) excess += 1;
excess = intervalExcess(excess, interval);
if (excess !== 0) {
kendoDate.setDayOfWeek(current, rule.weekStart, -1);
current.setDate(current.getDate() + excess * 7);
adjustDST(current, hours);
modified = true;
}
} else if (frequency === "monthly") {
diff = current.getFullYear() - start.getFullYear();
diff = current.getMonth() - start.getMonth() + diff * 12;
excess = intervalExcess(diff, interval);
if (excess !== 0) {
day = rule._hasRuleValue ? 1 : current.getDate();
current.setFullYear(current.getFullYear(), current.getMonth() + excess, day);
adjustDST(current, hours);
modified = true;
}
} else if (frequency === "yearly") {
diff = current.getFullYear() - start.getFullYear();
excess = intervalExcess(diff, interval);
if (!rule.months) month = current.getMonth();
if (!rule.yearDays && !rule.monthDays && !rule.weekDays) day = current.getDate();
if (excess !== 0) {
current.setFullYear(current.getFullYear() + excess, month, day);
adjustDST(current, hours);
modified = true;
}
}
return modified;
},
_getNumberOfWeeksBetweenDates: function(first, second) {
var weeks = (second - first) / 6048e5;
var exactWeeks = Math.floor(weeks);
if (weeks - exactWeeks > .99) exactWeeks = Math.round(weeks);
return exactWeeks;
},
_hour: function(date, rule, interval) {
var startTime = rule._startTime, hours = startTime.getHours();
if (interval) hours += interval;
date.setHours(hours);
hours = hours % 24;
startTime.setHours(hours);
adjustDST(date, hours);
},
_date: function(date, rule, interval) {
var hours = date.getHours();
date.setDate(date.getDate() + interval);
if (!adjustDST(date, hours)) this._hour(date, rule);
}
}), HourlyFrequency = BaseFrequency.extend({
next: function(date, rule) {
if (!BaseFrequency.fn.next(date, rule)) this._hour(date, rule, 1);
},
normalize: function(options) {
var rule = options.rule;
if (options.idx === 4) {
rule._startTime.setHours(0);
this._hour(options.date, rule);
}
}
}), DailyFrequency = BaseFrequency.extend({ next: function(date, rule) {
if (!BaseFrequency.fn.next(date, rule)) this[rule.hours ? "_hour" : "_date"](date, rule, 1);
} }), WeeklyFrequency = DailyFrequency.extend({ setup: function(rule, eventStartDate) {
if (!rule.weekDays) rule.weekDays = [{
day: eventStartDate.getDay(),
offset: 0
}];
} }), MonthlyFrequency = BaseFrequency.extend({
next: function(date, rule) {
var day, hours;
if (!BaseFrequency.fn.next(date, rule)) if (rule.hours) this._hour(date, rule, 1);
else if (rule.monthDays || rule.weekDays || rule.yearDays || rule.weeks) this._date(date, rule, 1);
else {
day = date.getDate();
hours = date.getHours();
date.setMonth(date.getMonth() + 1);
adjustDST(date, hours);
while (date.getDate() !== day) {
date.setDate(day);
adjustDST(date, hours);
}
this._hour(date, rule);
}
},
normalize: function(options) {
var rule = options.rule, date = options.date, hours = date.getHours();
if (options.idx === 0 && !rule.monthDays && !rule.weekDays) {
date.setDate(options.day);
adjustDST(date, hours);
} else BaseFrequency.fn.normalize(options);
},
setup: function(rule, eventStartDate, date) {
if (!rule.monthDays && !rule.weekDays) date.setDate(eventStartDate.getDate());
}
}), YearlyFrequency = MonthlyFrequency.extend({
next: function(date, rule) {
var day, hours = date.getHours();
if (!BaseFrequency.fn.next(date, rule)) if (rule.hours) this._hour(date, rule, 1);
else if (rule.monthDays || rule.weekDays || rule.yearDays || rule.weeks) this._date(date, rule, 1);
else if (rule.months) {
day = date.getDate();
date.setMonth(date.getMonth() + 1);
adjustDST(date, hours);
while (date.getDate() !== day) {
date.setDate(day);
adjustDST(date, hours);
}
this._hour(date, rule);
} else {
date.setFullYear(date.getFullYear() + 1);
adjustDST(date, hours);
this._hour(date, rule);
}
},
setup: function() {}
}), frequencies = {
"hourly": new HourlyFrequency(),
"daily": new DailyFrequency(),
"weekly": new WeeklyFrequency(),
"monthly": new MonthlyFrequency(),
"yearly": new YearlyFrequency()
}, CLICK = "click", CHANGE = "change";
function intervalExcess(diff, interval) {
var excess;
if (diff !== 0 && diff < interval) excess = interval - diff;
else {
excess = diff % interval;
if (excess) excess = interval - excess;
}
return excess;
}
function dayInYear(date) {
var month = date.getMonth();
return (leapYear(date) ? DAYS_IN_LEAPYEAR[month] : DAYS_IN_YEAR[month]) + date.getDate();
}
function weekInYear(date, weekStart) {
var year, days;
date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
adjustDST(date, 0);
year = date.getFullYear();
if (weekStart !== undefined) {
setDayOfWeek(date, weekStart, -1);
date.setDate(date.getDate() + 4);
} else date.setDate(date.getDate() + (4 - (date.getDay() || 7)));
adjustDST(date, 0);
days = Math.floor((date.getTime() - new Date(year, 0, 1, -6)) / 864e5);
return 1 + Math.floor(days / 7);
}
function weekInMonth(date, weekStart) {
var firstWeekLength = 7 - (firstDayOfMonth(date).getDay() + 7 - (weekStart || 7)) || 7;
if (firstWeekLength < 0) firstWeekLength += 7;
return Math.ceil((date.getDate() - firstWeekLength) / 7) + 1;
}
function normalizeDayIndex(weekDay, weekStart) {
return weekDay + (weekDay < weekStart ? 7 : 0);
}
function normalizeOffset(date, rule, weekStart) {
var offset = rule.offset;
if (!offset) return weekInMonth(date, weekStart);
var lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
var weeksInMonth = weekInMonth(lastDate, weekStart);
var day = normalizeDayIndex(rule.day, weekStart);
var skipFirst = day < normalizeDayIndex(new Date(date.getFullYear(), date.getMonth(), 1).getDay(), weekStart);
var skipLast = day > normalizeDayIndex(lastDate.getDay(), weekStart);
if (offset < 0) offset = weeksInMonth + (offset + 1 - (skipLast ? 1 : 0));
else if (skipFirst) offset += 1;
weeksInMonth -= skipLast ? 1 : 0;
if (offset < (skipFirst ? 1 : 0) || offset > weeksInMonth) return null;
return offset;
}
function numberOfWeeks(date, weekStart) {
return weekInMonth(new Date(date.getFullYear(), date.getMonth() + 1, 0), weekStart);
}
function isInWeek(date, rule, weekStart) {
return weekInMonth(date, weekStart) === normalizeOffset(date, rule, weekStart);
}
function ruleWeekValues(weekDays, date, weekStart) {
var currentDay = normalizeDayIndex(date.getDay(), weekStart);
var length = weekDays.length;
var ruleWeekOffset;
var weekDay, day;
var weekNumber;
var result = [];
var idx = 0;
for (; idx < length; idx++) {
weekDay = weekDays[idx];
weekNumber = weekInMonth(date, weekStart);
ruleWeekOffset = normalizeOffset(date, weekDay, weekStart);
if (ruleWeekOffset === null) continue;
if (weekNumber < ruleWeekOffset) result.push(weekDay);
else if (weekNumber === ruleWeekOffset) {
day = normalizeDayIndex(weekDay.day, weekStart);
if (currentDay < day) result.push(weekDay);
else if (currentDay === day) return null;
}
}
return result;
}
function ruleValues(rules, value, normalize) {
var idx = 0, length = rules.length, availableRules = [], ruleValue;
for (; idx < length; idx++) {
ruleValue = rules[idx];
if (normalize) ruleValue = normalize(ruleValue);
if (value === ruleValue) return null;
else if (value < ruleValue) availableRules.push(ruleValue);
}
return availableRules;
}
function parseArray(list, range) {
var idx = 0, length = list.length, value;
for (; idx < length; idx++) {
value = parseInt(list[idx], 10);
if (isNaN(value) || value < range.start || value > range.end || value === 0 && range.start < 0) return null;
list[idx] = value;
}
return list.sort(numberSortPredicate);
}
function parseWeekDayList(list) {
var idx = 0, length = list.length, value, valueLength, day;
for (; idx < length; idx++) {
value = list[idx];
valueLength = value.length;
day = value.substring(valueLength - 2).toUpperCase();
day = WEEK_DAYS_IDX[day];
if (day === undefined) return null;
list[idx] = {
offset: parseInt(value.substring(0, valueLength - 2), 10) || 0,
day
};
}
return list;
}
function serializeWeekDayList(list) {
var idx = 0, length = list.length, value, valueString, result = [];
for (; idx < length; idx++) {
value = list[idx];
if (typeof value === "string") valueString = value;
else {
valueString = "" + WEEK_DAYS[value.day];
if (value.offset) valueString = value.offset + valueString;
}
result.push(valueString);
}
return result.toString();
}
function getMonthLength(date) {
var month = date.getMonth();
if (month === 1) {
if (new Date(date.getFullYear(), 1, 29).getMonth() === 1) return 29;
return 28;
}
return MONTHS[month];
}
function leapYear(year) {
year = year.getFullYear();
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
function numberSortPredicate(a, b) {
return a - b;
}
function parseExceptions(exceptions, zone) {
var idx = 0, length, date, dates = [];
if (exceptions) {
exceptions = exceptions.split(exceptions.indexOf(";") !== -1 ? ";" : ",");
length = exceptions.length;
for (; idx < length; idx++) {
date = parseUTCDate(exceptions[idx], zone);
if (date) dates.push(date);
}
}
return dates;
}
function isException(exceptions, date, zone) {
var dates = Array.isArray(exceptions) ? exceptions : parseExceptions(exceptions, zone), dateTime = date.getTime() - date.getMilliseconds(), idx = 0, length = dates.length;
for (; idx < length; idx++) if (dates[idx].getTime() === dateTime) return true;
return false;
}
function toExceptionString(dates, zone) {
var idx = 0;
var length;
var date;
var result = [].concat(dates);
for (length = result.length; idx < length; idx++) {
date = result[idx];
date = kendo.timezone.convert(date, zone || date.getTimezoneOffset(), "Etc/UTC");
result[idx] = kendo.toString(date, RECURRENCE_DATE_FORMAT);
}
return result.join(",");
}
function startPeriodByFreq(start, rule) {
var date = new Date(start);
switch (rule.freq) {
case "yearly":
date.setFullYear(date.getFullYear(), 0, 1);
break;
case "monthly":
date.setFullYear(date.getFullYear(), date.getMonth(), 1);
break;
case "weekly":
setDayOfWeek(date, rule.weekStart, -1);
break;
default: break;
}
if (rule.hours) date.setHours(0);
if (rule.minutes) date.setMinutes(0);
if (rule.seconds) date.setSeconds(0);
return date;
}
function endPeriodByFreq(start, rule) {
var date = new Date(start);
switch (rule.freq) {
case "yearly":
date.setFullYear(date.getFullYear(), 11, 31);
break;
case "monthly":
date.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
break;
case "weekly":
setDayOfWeek(date, rule.weekStart, -1);
date.setDate(date.getDate() + 6);
break;
default: break;
}
if (rule.hours) date.setHours(23);
if (rule.minutes) date.setMinutes(59);
if (rule.seconds) date.setSeconds(59);
return date;
}
function eventsByPosition(periodEvents, start, positions, until) {
var periodEventsLength = periodEvents.length;
var events = [];
var position;
var event;
var inPeriod;
for (var idx = 0, length = positions.length; idx < length; idx++) {
position = positions[idx];
if (position < 0) position = periodEventsLength + position;
else position -= 1;
event = periodEvents[position];
inPeriod = until ? event.start < until : true;
if (event && event.start >= start && inPeriod) events.push(event);
}
return events;
}
function removeExceptionDates(periodEvents, exceptionDates, zone) {
var events = [];
var event;
for (var idx = 0; idx < periodEvents.length; idx++) {
event = periodEvents[idx];
if (!isException(exceptionDates, event.start, zone)) events.push(event);
}
return events;
}
function expand(event, start, end, zone) {
var rule, startTime, endTime, endDate, hours, minutes, seconds, durationMS, startPeriod, inPeriod, ruleStart, ruleEnd, useEventStart, freqName, exceptionDates, eventStartTime, eventStartMS, eventStart, count, freq, positions, currentIdx, periodEvents, events = [], shiftedStart, shiftedEnd, shiftedStartTime, shifterEndTime;
rule = parseRule(event.recurrenceRule, zone, {
start: (getZoneOffset(event.start, zone) - getZoneOffset(event.start, event.startTimezone || zone)) * kendo.date.MS_PER_MINUTE,
end: (getZoneOffset(event.end, zone) - getZoneOffset(event.end, event.endTimezone || zone)) * kendo.date.MS_PER_MINUTE
});
if (!rule) return [event];
positions = rule.positions;
currentIdx = positions ? 0 : 1;
ruleStart = rule.start;
ruleEnd = rule.end;
if (ruleStart || ruleEnd) event = event.clone({
start: ruleStart ? new Date(ruleStart.value[0]) : undefined,
end: ruleEnd ? new Date(ruleEnd.value[0]) : undefined
});
eventStart = event.start;
eventStartMS = eventStart.getTime();
eventStartTime = getMilliseconds(eventStart);
exceptionDates = parseExceptions(event.recurrenceException, zone);
if (!exceptionDates[0] && rule.exdates) {
exceptionDates = rule.exdates.value;
event.set("recurrenceException", toExceptionString(exceptionDates, zone));
}
startPeriod = start = new Date(start);
end = new Date(end);
freqName = rule.freq;
freq = frequencies[freqName];
count = rule.count;
if (rule.until && rule.until < end) end = new Date(rule.until);
useEventStart = freqName === "yearly" || freqName === "monthly" || freqName === "weekly";
if (start < eventStartMS || count || rule.interval > 1 || useEventStart || (freqName === "daily" || freqName === "hourly") && !rule.seconds) start = new Date(eventStartMS);
else {
hours = start.getHours();
minutes = start.getMinutes();
seconds = start.getSeconds();
if (!rule.hours) hours = eventStart.getHours();
if (!rule.minutes) minutes = eventStart.getMinutes();
if (!rule.seconds) seconds = eventStart.getSeconds();
start.setHours(hours, minutes, seconds, eventStart.getMilliseconds());
}
rule._startPeriod = new Date(start);
if (positions) {
start = startPeriodByFreq(start, rule);
end = endPeriodByFreq(end, rule);
if (getMilliseconds(end) - getMilliseconds(start) < 0) {
hours = start.getHours();
end.setHours(hours, start.getMinutes(), start.getSeconds(), start.getMilliseconds());
kendoDate.adjustDST(end, hours);
}
rule._startPeriod = new Date(start);
rule._endPeriod = endPeriodByFreq(start, rule);
}
durationMS = event.duration();
var allDayCompensation = event.isAllDay ? 864e5 : 0;
rule._startTime = startTime = kendoDate.toInvariantTime(start);
if (freq.setup) freq.setup(rule, eventStart, start);
freq.limit(start, end, rule);
while (start <= end) {
endDate = new Date(start);
setTime(endDate, durationMS);
var inPeriodCheckEndDate = new Date(start);
setTime(inPeriodCheckEndDate, durationMS + allDayCompensation);
inPeriod = start >= startPeriod || inPeriodCheckEndDate > startPeriod;
if (inPeriod && !isException(exceptionDates, start, zone) || positions) {
startTime = kendoDate.toUtcTime(kendoDate.getDate(start)) + getMilliseconds(rule._startTime);
endTime = startTime + durationMS;
if (eventStartMS !== start.getTime() || eventStartTime !== getMilliseconds(rule._startTime)) {
var startZone = event.startTimezone || event.endTimezone;
var endZone = event.endTimezone || event.startTimezone;
if (!event.isAllDay) {
if (zone && startZone || !zone && !startZone) {
var startOffsetDiff = getZoneOffset(start, zone) - getZoneOffset(event.start, zone);
var endOffsetDiff = getZoneOffset(endDate, zone) - getZoneOffset(event.end, zone);
var startTZOffsetDiff = getZoneOffset(start, startZone) - getZoneOffset(event.start, startZone);
var endTZOffsetDiff = getZoneOffset(endDate, endZone) - getZoneOffset(event.end, endZone);
if (startOffsetDiff !== startTZOffsetDiff) {
var offsetTicksStart = (startOffsetDiff - startTZOffsetDiff) * 6e4;
shiftedStart = new Date(start.getTime() - offsetTicksStart);
shiftedStartTime = startTime - offsetTicksStart;
}
if (endOffsetDiff !== endTZOffsetDiff) {
var offsetTicksEnd = (endOffsetDiff - endTZOffsetDiff) * 6e4;
shiftedEnd = new Date(endDate.getTime() - offsetTicksEnd);
shifterEndTime = endTime - offsetTicksEnd;
}
}
}
events.push(event.toOccurrence({
start: shiftedStart || new Date(start),
end: shiftedEnd || endDate,
_startTime: shiftedStartTime || startTime,
_endTime: shifterEndTime || endTime
}));
shiftedStart = shiftedEnd = shiftedStartTime = shifterEndTime = null;
} else {
event._startTime = startTime;
event._endTime = endTime;
events.push(event);
}
}
if (positions) {
freq.next(start, rule);
freq.limit(start, end, rule);
if (start > rule._endPeriod) {
periodEvents = eventsByPosition(events.slice(currentIdx), eventStart, positions, rule.until);
periodEvents = removeExceptionDates(periodEvents, exceptionDates, zone);
events = events.slice(0, currentIdx).concat(periodEvents);
rule._endPeriod = endPeriodByFreq(start, rule);
currentIdx = events.length;
}
if (count && count === currentIdx) break;
} else {
if (count && count === currentIdx) break;
currentIdx += 1;
var isMissingDSTHour = isDSTMissingHour(start);
freq.next(start, rule);
if (isMissingDSTHour && rule.freq !== "hourly" && kendoDate.toInvariantTime(event.start).getTime() !== kendoDate.toInvariantTime(start).getTime()) rule._startTime = startTime = /* @__PURE__ */ new Date(start.getTime() - 36e5);
freq.limit(start, end, rule);
}
}
return events;
}
function isDSTMissingHour(date) {
return date.getTimezoneOffset() < (/* @__PURE__ */ new Date(date.getTime() - 36e5)).getTimezoneOffset();
}
function getZoneOffset(date, zone) {
return zone ? kendo.timezone.offset(date, zone) : date.getTimezoneOffset();
}
function parseUTCDate(value, zone) {
value = kendo.parseDate(value, DATE_FORMATS);
if (value && zone) value = timezone.apply(value, zone);
return value;
}
function parseDateRule(dateRule, zone) {
var pairs = dateRule.split(";");
var pair;
var property;
var value;
var tzid;
var valueIdx, valueLength;
for (var idx = 0, length = pairs.length; idx < length; idx++) {
pair = pairs[idx].split(":");
property = pair[0];
value = pair[1];
if (property.indexOf("TZID") !== -1) tzid = property.substring(property.indexOf("TZID")).split("=")[1];
if (value) {
value = value.split(",");
for (valueIdx = 0, valueLength = value.length; valueIdx < valueLength; valueIdx++) value[valueIdx] = parseUTCDate(value[valueIdx], tzid || zone);
}
}
if (value) return {
value,
tzid
};
}
function parseRule(recur, zone, offsets) {
var instance = {};
var splits, value;
var idx = 0, length;
var ruleValue = false;
var rule, part, parts;
var property, weekStart, weekDays;
var predicate = function(a, b) {
var day1 = a.day, day2 = b.day;
if (day1 < weekStart) day1 += 7;
if (day2 < weekStart) day2 += 7;
return day1 - day2;
};
if (!recur) return null;
parts = recur.split("\n");
if (!parts[1] && (recur.indexOf("DTSTART") !== -1 || recur.indexOf("DTEND") !== -1 || recur.indexOf("EXDATE") !== -1)) parts = recur.split(" ");
for (idx = 0, length = parts.length; idx < length; idx++) {
part = kendo.trim(parts[idx]);
if (part.indexOf("DTSTART") !== -1) instance.start = parseDateRule(part, zone);
else if (part.indexOf("DTEND") !== -1) instance.end = parseDateRule(part, zone);
else if (part.indexOf("EXDATE") !== -1) instance.exdates = parseDateRule(part, zone);
else if (part.indexOf("RRULE") !== -1) rule = part.substring(6);
else if (kendo.trim(part)) rule = part;
}
rule = (rule || "").split(";");
for (idx = 0, length = rule.length; idx < length; idx++) {
property = rule[idx];
splits = property.split("=");
value = kendo.trim(splits[1]).split(",");
switch (kendo.trim(splits[0]).toUpperCase()) {
case "FREQ":
instance.freq = value[0].toLowerCase();
break;
case "UNTIL":
instance.until = parseUTCDate(value[0], zone);
break;
case "COUNT":
instance.count = parseInt(value[0], 10);
break;
case "INTERVAL":
instance.interval = parseInt(value[0], 10);
break;
case "BYSECOND":
instance.seconds = parseArray(value, {
start: 0,
end: 60
});
ruleValue = true;
break;
case "BYMINUTE":
instance.minutes = parseArray(value, {
start: 0,
end: 59
});
ruleValue = true;
break;
case "BYHOUR":
instance.hours = parseArray(value, {
start: 0,
end: 23
});
ruleValue = true;
break;
case "BYMONTHDAY":
instance.monthDays = parseArray(value, {
start: -31,
end: 31
});
ruleValue = true;
break;
case "BYYEARDAY":
instance.yearDays = parseArray(value, {
start: -366,
end: 366
});
ruleValue = true;
break;
case "BYMONTH":
instance.months = parseArray(value, {
start: 1,
end: 12
});
ruleValue = true;
break;
case "BYDAY":
instance.weekDays = weekDays = parseWeekDayList(value);
ruleValue = true;
break;
case "BYWEEKNO":
instance.weeks = parseArray(value, {
start: -53,
end: 53
});
ruleValue = true;
break;
case "BYSETPOS":
instance.positions = parseArray(value, {
start: -366,
end: 366
});
break;
case "WKST":
instance.weekStart = weekStart = WEEK_DAYS_IDX[value[0]];
break;
}
}
if (instance.freq === undefined || instance.count !== undefined && instance.until) return null;
if (!instance.interval) instance.interval = 1;
if (weekStart === undefined) instance.weekStart = weekStart = kendo.culture().calendar.firstDay;
if (weekDays) instance.weekDays = weekDays.sort(predicate);
if (instance.positions && !ruleValue) instance.positions = null;
instance._hasRuleValue = ruleValue;
instance.offsets = offsets;
return instance;
}
function serializeDateRule(dateRule, zone) {
var value = dateRule.value;
var tzid = dateRule.tzid || "";
var length = value.length;
var idx = 0;
var val;
for (; idx < length; idx++) {
val = value[idx];
val = timezone.convert(val, tzid || zone || val.getTimezoneOffset(), "Etc/UTC");
value[idx] = kendo.toString(val, "yyyyMMddTHHmmssZ");
}
if (tzid) tzid = ";TZID=" + tzid;
return tzid + ":" + value.join(",") + " ";
}
function serialize(rule, zone) {
var weekStart = rule.weekStart;
var ruleString = "FREQ=" + rule.freq.toUpperCase();
var exdates = rule.exdates || "";
var start = rule.start || "";
var end = rule.end || "";
var until = rule.until;
if (weekStart === undefined) weekStart = kendo.culture().calendar.firstDay;
if (rule.interval > 1) ruleString += ";INTERVAL=" + rule.interval;
if (rule.count) ruleString += ";COUNT=" + rule.count;
if (until) {
until = timezone.convert(until, zone || until.getTimezoneOffset(), "Etc/UTC");
ruleString += ";UNTIL=" + kendo.toString(until, "yyyyMMddTHHmmssZ");
}
if (rule.months) ruleString += ";BYMONTH=" + rule.months;
if (rule.weeks) ruleString += ";BYWEEKNO=" + rule.weeks;
if (rule.yearDays) ruleString += ";BYYEARDAY=" + rule.yearDays;
if (rule.monthDays) ruleString += ";BYMONTHDAY=" + rule.monthDays;
if (rule.weekDays) ruleString += ";BYDAY=" + serializeWeekDayList(rule.weekDays);
if (rule.hours) ruleString += ";BYHOUR=" + rule.hours;
if (rule.minutes) ruleString += ";BYMINUTE=" + rule.minutes;
if (rule.seconds) ruleString += ";BYSECOND=" + rule.seconds;
if (rule.positions) ruleString += ";BYSETPOS=" + rule.positions;
if (weekStart !== undefined) ruleString += ";WKST=" + WEEK_DAYS[weekStart];
if (start) start = "DTSTART" + serializeDateRule(start, zone);
if (end) end = "DTEND" + serializeDateRule(end, zone);
if (exdates) exdates = "EXDATE" + serializeDateRule(exdates, zone);
if (start || end || exdates) ruleString = start + end + exdates + "RRULE:" + ruleString;
return ruleString;
}
kendo.recurrence = {
rule: {
parse: parseRule,
serialize
},
expand,
dayInYear,
weekInYear,
weekInMonth,
numberOfWeeks,
isException,
toExceptionString
};
kendo.template(({ frequency, messages, end }) => (frequency !== "never" ? `<div class="k-form-field"><label id="recur_interval_label" class="k-label k-form-label" for="recur_interval">${encode(messages.repeatEvery)}</label><div class="k-form-field-wrap"><input id="recur_interval" ref-recur-interval title="${encode(messages.repeatEvery)} ${encode(messages.interval)}" aria-labelledby="recur_interval_label">${encode(messages.interval)}</div></div>` : "") + (frequency === "weekly" ? `<div class="k-form-field"><label class="k-label k-form-label">${encode(messages.repeatOn)}</label><div class="k-form-field-wrap"><div class="k-button-group-stretched k-recur-weekday-buttons" title="${encode(messages.repeatOn)}"></div></div></div></div>` : "") + (frequency === "monthly" ? `<div class="k-form-field"><label class="k-label k-form-label">${encode(messages.repeatOn)}</label></div><div class="k-form-field-wrap"><ul class="k-radio-list"><li class="k-radio-item"><label class="k-radio-label"><input class="k-recur-month-radio k-radio" type="radio" name="month" value="monthday" title="${encode(messages.repeatOn)}" />${encode(messages.date)}:</label><input ref-recur-monthday aria-label="${encode(messages.date)}" title="${encode(messages.date)}" /></li><li class="k-radio-item"><input class="k-recur-month-radio k-radio" type="radio" name="month" value="weekday" aria-label="${encode(messages.repeatOn)} ${encode(messages.day)}" title="${encode(messages.repeatOn)} ${encode(messages.day)}" /><input class="k-recur-weekday-offset" title="${encode(messages.repeatOn)}" ${kendo.attr("style-width")}="8em" /><input class="k-recur-weekday" title="${encode(messages.day)}" ${kendo.attr("style-width")}="8em" /></li></ul></div></div>` : "") + (frequency === "yearly" ? `<div class="k-form-field"><label class="k-label k-form-label">${encode(messages.repeatOn)}</label><div class="k-form-field-wrap"><ul class="k-radio-list"><li class="k-radio-item"><input class="k-recur-year-radio k-radio" type="radio" name="year" value="monthday" title="${encode(messages.repeatOn)} ${encode(messages.month)}" /><input class="k-recur-month" aria-label="${encode(messages.month)}" title="${encode(messages.month)}" ${kendo.attr("style-width")}="8em" /><input ref-recur-monthday aria-label="${encode(messages.date)}" title="${encode(messages.date)}" /></li><li class="k-radio-item"><input class="k-recur-year-radio k-radio" type="radio" name="year" value="weekday" title="${encode(messages.repeatOn)} ${encode(messages.day)}" /><input class="k-recur-weekday-offset" title="${encode(messages.repeatOn)}" ${kendo.attr("style-width")}="8em"/><input class="k-recur-weekday" title="${encode(messages.day)}" ${kendo.attr("style-width")}="8em"/>${encode(messages.of)}<input class="k-recur-month" title="${encode(messages.of + messages.month)}" ${kendo.attr("style-width")}="8em"/></li></ul></div></div>` : "") + (frequency !== "never" ? `<div class="k-form-field"><label class="k-label k-form-label">${encode(end.label)}</label><div class="k-form-field-wrap"><ul class="k-radio-list"><li class="k-radio-item"><label class="k-radio-label"><input class="k-recur-end-never k-radio" type="radio" name="end" value="never" title="${encode(end.label)}" />${encode(end.never)}</label></li><li class="k-radio-item"><label class="k-radio-label"><input class="k-recur-end-count k-radio" type="radio" name="end" value="count" title="${encode(end.label)}" />${encode(end.after)}</label><input ref-recur-count aria-label="${encode(end.occurrence)}" title="${encode(end.occurrence)}" />${encode(end.occurrence)}</li><li class="k-radio-item"><label class="k-radio-label"><input class="k-recur-end-until k-radio" type="radio" name="end" value="until" title="${encode(end.label)}" />${encode(end.on)}</label><input title="${encode(end.on)}" aria-label="${encode(end.on)}" ref-recur-until /></li></ul></div></div>` : ""));
var DAY_RULE = [
{
day: 0,
offset: 0
},
{
day: 1,
offset: 0
},
{
day: 2,
offset: 0
},
{
day: 3,
offset: 0
},
{
day: 4,
offset: 0
},
{
day: 5,
offset: 0
},
{
day: 6,
offset: 0
}
];
var WEEKDAY_RULE = [
{
day: 1,
offset: 0
},
{
day: 2,
offset: 0
},
{
day: 3,
offset: 0
},
{
day: 4,
offset: 0
},
{
day: 5,
offset: 0
}
];
var WEEKEND_RULE = [{
day: 0,
offset: 0
}, {
day: 6,
offset: 0
}];
var BaseRecurrenceEditor = Widget.extend({
init: function(element, options) {
var start;
var that = this;
var frequencies = options && options.frequencies;
Widget.fn.init.call(that, element, options);
that.wrapper = that.element;
options = that.options;
options.start = start = options.start || kendoDate.today();
if (frequencies) options.frequencies = frequencies;
if (typeof start === "string") options.start = kendo.parseDate(start, "yyyyMMddTHHmmss");
if (options.firstWeekDay === null) options.firstWeekDay = kendo.culture().calendar.firstDay;
that._namespace = "." + options.name;
Widget.fn.endInit.call(that);
},
options: {
value: "",
start: "",
timezone: "",
spinners: true,
firstWeekDay: null,
frequencies: [
"never",
"daily",
"weekly",
"monthly",
"yearly"
],
mobile: false,
messages: {
repeat: "Repeat",
recurrenceEditorTitle: "Recurrence editor",
frequencies: {
never: "Never",
hourly: "Hour",
daily: "Day",
weekly: "Week",
monthly: "Month",
yearly: "Year"
},
hourly: {
repeatEvery: "Repeat every: ",
interval: " hour(s)"
},
daily: {
repeatEvery: "Repeat every: ",
interval: " day(s)"
},
weekly: {
interval: " week(s)",
repeatEvery: "Repeat every: ",
repeatOn: "Repeat on: "
},
monthly: {
repeatEvery: "Repeat every: ",
repeatOn: "Repeat on: ",
interval: " month(s)",
day: "Day ",
date: "Date"
},
yearly: {
repeatEvery: "Repeat every: ",
repeatOn: "Repeat on: ",
interval: " year(s)",
of: " of ",
month: "month",
day: "day",
date: "Date"
},
end: {
label: "End:",
mobileLabel: "Ends",
never: "Never",
after: "After ",
occurrence: " occurrence(s)",
on: "On "
},
offsetPositions: {
first: "first",
second: "second",
third: "third",
fourth: "fourth",
last: "last"
},
weekdays: {
day: "day",
weekday: "weekday",
weekend: "weekend day"
},
makeRecurring: "Make recurring",
summary: {
on: "on",
onThe: "on the",
onDay: "on day",
until: "until"
}
}
},
events: ["change"],
_initInterval: function() {
var that = this, input = that._container.find("[ref-recur-interval]"), rule = that._value;
that._interval = input.kendoNumericTextBox({
spinners: that.options.spinners,
value: rule.interval || 1,
decimals: 0,
format: "#",
min: 1,
change: function() {
that._value.interval = this.value();
that._trigger();
}
}).data("kendoNumericTextBox");
that._interval.wrapper.addClass("k-recur-interval");
},
_weekDayButtons: function(firstDay) {
var that = this, names = kendo.culture().calendar.days.names, abbreviated = kendo.culture().calendar.days.namesAbbr, repeatOn = that.options.messages.weekly.repeatOn, length = names.length, idx = 0, values = [], items = [];
for (; idx < length; idx++) values.push(idx);
names = names.slice(firstDay).concat(names.slice(0, firstDay));
abbreviated = abbreviated.slice(firstDay).concat(abbreviated.slice(0, firstDay));
values = values.slice(firstDay).concat(values.slice(0, firstDay));
for (idx = 0; idx < length; idx++) items.push({
text: abbreviated[idx].substring(0, 1),
attributes: {
"data-value": values[idx],
"aria-label": repeatOn + " " + names[idx]
}
});
if (that._container.find(".k-recur-weekday-buttons").length > 0) {
that._weekDayButtonGroup = new ButtonGroup(that._container.find(".k-recur-weekday-buttons"), {
items,
fillMode: "flat",
rounded: "full",
selection: "multiple",
select: function(e) {
var rule = that._value, buttons = that._weekDayButtonGroup.element.children();
rule.weekDays = e.indices.map(function(index) {
return {
day: Number(buttons.eq(index).attr("data-value")),
offset: 0
};
});
if (!that._isMobile()) {
that._trigger();
that._updateHintText();
}
}
});
that._weekDayButtonGroup.wrapper.removeClass("k-button-group").removeClass("k-button-group-flat").removeClass("k-button-group-stretched");
}
},
_weekDayRule: function(clear) {
var that = this;
var weekday = (that._weekDay.element || that._weekDay).val();
var offset = Number((that._weekDayOffset.element || that._weekDayOffset).val());
var weekDays = null;
var positions = null;
if (!clear) if (weekday === "day") {
weekDays = DAY_RULE;
positions = offset;
} else if (weekday === "weekday") {
weekDays = WEEKDAY_RULE;
positions = offset;
} else if (weekday === "weekend") {
weekDays = WEEKEND_RULE;
positions = offset;
} else weekDays = [{
offset,
day: Number(weekday)
}];
that._value.weekDays = weekDays;
that._value.positions = positions;
},
_weekDayView: function() {
var that = this;
var weekDays = that._value.weekDays;
var positions = that._value.positions;
var weekDayOffsetWidget = that._weekDayOffset;
var weekDayOffset;
var weekDayValue;
var length;
var method;
if (weekDays) {
length = weekDays.length;
if (positions) {
if (length === 7) {
weekDayValue = "day";
weekDayOffset = positions;
} else if (length === 5) {
weekDayValue = "weekday";
weekDayOffset = positions;
} else if (length === 2) {
weekDayValue = "weekend";
weekDayOffset = positions;
}
}
if (!weekDayValue) {
weekDays = weekDays[0];
weekDayValue = weekDays.day;
weekDayOffset = weekDays.offset || "";
}
method = weekDayOffsetWidget.value ? "value" : "val";
weekDayOffsetWidget[method](weekDayOffset);
that._weekDay[method](weekDayValue);
}
},
_initWeekDay: function() {
var that = this, data;
var weekdayMessage = that.options.messages.weekdays;
var offsetMessage = that.options.messages.offsetPositions;
var weekDayInput = that._container.find(".k-recur-weekday");
var change = function() {
that._weekDayRule();
that._trigger();
if (!that._isMobile() && typeof that._updateHintText === "function") that._updateHintText();
};
if (weekDayInput[0]) {
that._weekDayOffset = new DropDownList(that._container.find(".k-recur-weekday-offset"), {
autoWidth: true,
change,
dataTextField: "text",
dataValueField: "value",
dataSource: [
{
text: offsetMessage.first,
value: "1"
},
{
text: offsetMessage.second,
value: "2"
},
{
text: offsetMessage.third,
value: "3"
},
{
text: offsetMessage.fourth,
value: "4"
},
{
text: offsetMessage.last,
value: "-1"
}
]
});
data = [
{
text: weekdayMessage.day,
value: "day"
},
{
text: weekdayMessage.weekday,
value: "weekday"
},
{
text: weekdayMessage.weekend,
value: "weekend"
}
];
that._weekDay = new DropDownList(weekDayInput, {
autoWidth: true,
value: that.options.start.getDay(),
change,
dataTextField: "text",
dataValueField: "value",
dataSource: data.concat($.map(kendo.culture().calendar.days.names, function(dayName, idx) {
return {
text: dayName,
value: idx
};
}))
});
that._weekDayView();
}
},
_initWeekDays: function() {
var that = this;
var rule = that._value;
var weekDayButtonGroup = that._weekDayButtonGroup;
if (weekDayButtonGroup && rule.weekDays && rule.weekDays.length) {
var ruleDays = rule.weekDays, ruleDaysLength = ruleDays.length, selectors = [], i = 0, selectedWeekDayButtons;
for (; i < ruleDaysLength; i++) selectors.push("[data-value='" + ruleDays[i].day + "']");
selectedWeekDayButtons = weekDayButtonGroup.element.find(selectors.join(","));
weekDayButtonGroup.select(selectedWeekDayButtons);
}
},
_initMonthDay: function() {
var that = this;
var rule = that._value;
var monthDayInput = that._container.find("[ref-recur-monthday]");
if (monthDayInput[0]) {
that._monthDay = new kendo.ui.NumericTextBox(monthDayInput, {
spinners: that.options.spinners,
min: 1,
max: 31,
decimals: 0,
format: "#",
value: rule.monthDays ? rule.monthDays[0] : that.options.start.getDate(),
change: function() {
var value = this.value();
rule.monthDays = value ? [value] : value;
that._trigger();
if (!that._isMobile() && typeof that._updateHintText === "function") that._updateHintText();
}
});
that._monthDay.wrapper.addClass("k-recur-monthday");
}
},
_initCount: function() {
var that = this, input = that._container.find("[ref-recur-count]"), rule = that._value, endMessages = that.options.messages.end || {};
that._count = input.kendoNumericTextBox({
spinners: that.options.spinners,
value: rule.count || 1,
decimals: 0,
format: `# ${encode(endMessages.occurrence || "occurrence(s)")}`,
min: 1,
change: function() {
that._value.count = this.value();
that._trigger();
}
}).data("kendoNumericTextBox");
that._count.wrapper.addClass("k-recur-count");
},
_initUntil: function() {
var that = this, input = that._container.find("[ref-recur-until]"), start = that.options.start, until = that._value.until, min = until && until < start ? until : start, startInput = that.wrapper.closest(".k-scheduler-edit-form").find("[name=start]:visible"), validDateValidationMessage = kendo.format(kendo.ui.Validator.prototype.options.messages.date, that.options.messages.end.on), dateCompareValidationMessage = kendo.ui.Validator.prototype.options.messages.dateCompare, initialValue = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 23, 59, 59);
input.attr("data-validDate-msg", validDateValidationMessage);
input.attr("data-untilDateCompare-msg", dateCompareValidationMessage);
if (startInput.length === 0) startInput = that.wrapper.closest(".k-scheduler-edit-form").find("[name=start]");
if (startInput.length > 0 && startInput.val()) {
min = kendo.parseDate(startInput.val());
if (initialValue < min) initialValue = min;
}
that._until = input.kendoDatePicker({
min,
value: until || initialValue,
change: function() {
var date = this.value();
if (date) that._value.until = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
that._trigger();
}
}).data("kendoDatePicker");
that._until.wrapper.addClass("k-recur-until");
if (startInput) startInput.on("change", function() {
var untilEl = that._until.element, readonly = Boolean(untilEl.attr("readonly")), enable = !Boolean(untilEl.is("[disabled]") || untilEl.parents("fieldset").is(":disabled"));
that._until.setOptions({
min: startInput.val(),
readonly,
enable
});
});
},
_isMobile: function() {
return this.options.mobile;
},
_trigger: function() {
if (!this._isMobile()) this.trigger("change");
}
});
var DIALOG_FREQ_ITEMS = [
"daily",
"weekly",
"monthly",
"yearly"
];
var DIALOG_FREQ_LABELS = {
daily: "Day",
weekly: "Week",
monthly: "Month",
yearly: "Year"
};
var RecurrenceEditor = BaseRecurrenceEditor.extend({
init: function(element, options) {
var that = this;
BaseRecurrenceEditor.fn.init.call(that, element, options);
that._value = parseRule(that.options.value, that.options.timezone) || {};
that._initButton();
},
options: {
name: "RecurrenceEditor",
recurrenceRuleLabelTemplate: null
},
events: ["change"],
destroy: function() {
var that = this;
if (that._dialogWrapper) {
kendo.destroy(that._dialogWrapper);
that._dialogWrapper.remove();
that._dialogWrapper = null;
that._dialog = null;
}
that.element.off(CLICK + that._namespace);
that.element.empty();
BaseRecurrenceEditor.fn.destroy.call(that);
},
value: function(value) {
var that = this;
var timezone = that.options.timezone;
if (value === undefined) {
if (!that._value || !that._value.freq) return "";
return serialize(that._value, timezone);
}
that._value = parseRule(value, timezone) || {};
that._updateButton();
},
_trigger: function() {
if (!this._inDialog) this.trigger(CHANGE);
else this._updateHintText();
},
_initButton: function() {
var that = this;
that.element.empty();
that.element.append(that._renderTriggerButton());
that.element.on(CLICK + that._namespace, ".k-recur-trigger", function(e) {
e.preventDefault();
that._openDialog();
});
},
_renderTriggerButton: function() {
var that = this;
var text = !!(that._value && that._value.freq) ? that._summaryText() : that.options.messages.makeRecurring || "Make recurring";
return $("<a href=\"#\" class=\"k-button k-button-flat k-button-primary k-recur-trigger k-scheduler-recurrence-button\">").css("max-width", "100%").append($(kendo.ui.icon("arrow-rotate-cw")).addClass("k-button-icon")).append($("<span class=\"k-button-text\">").text(text));
},
_updateButton: function() {
var that = this;
var text = !!(that._value && that._value.freq) ? that._summaryText() : that.options.messages.makeRecurring || "Make recurring";
that.element.find(".k-recur-trigger .k-button-text").text(text);
},
_summaryText: function() {
var that = this;
var rule = that._value;
var messages = that.options.messages;
var s = messages.summary || {};
var endMessages = messages.end || {};
var freqMessages = messages[rule.freq] || {};
if (!rule || !rule.freq) return "";
if (that.options.recurrenceRuleLabelTemplate) return (kendo.isFunction(that.options.recurrenceRuleLabelTemplate) ? that.options.recurrenceRuleLabelTemplate : kendo.template(that.options.recurrenceRuleLabelTemplate))({
rule,
recurrenceRule: serialize(rule, that.options.timezone)
});
var freqLabel = messages.frequencies && messages.frequencies[rule.freq] || rule.freq;
var interval = rule.interval || 1;
var text = (freqMessages.repeatEvery || "Repeat every: ").replace(/[:\s]+$/, "") + " " + (interval > 1 ? interval + " " : "") + freqLabel.toLowerCase();
if (rule.freq === "weekly") text += that._summaryTextWeekly(rule, messages);
else if (rule.freq === "monthly") text += that._summaryTextMonthly(rule, messages);
else if (rule.freq === "yearly") text += that._summaryTextYearly(rule, messages);
if (rule.count) {
var after = (endMessages.after || "After ").replace(/\s+$/, "").toLowerCase();
var occurrence = endMessages.occurrence || " occurrence(s)";
text += ", " + after + " " + rule.count + occurrence;
} else if (rule.until) {
var until = s.until || "until";
text += " " + until + " " + kendo.toString(rule.until, "d");
}
return text + ".";
},
_summaryTextWeekly: function(rule, messages) {
if (!rule.weekDays || !rule.weekDays.length) return "";
var on = (messages && messages.summary || {}).on || "on";
var dayNames = kendo.culture().calendar.days.names;
var days = rule.weekDays.map(function(d) {
return dayNames[Number.isInteger(d) ? d : d.day];
});
return " " + on + " " + Array.from(days).join(", ");
},
_summaryTextMonthly: function(rule, messages) {
var offsetKeyMap = {
"1": "first",
"2": "second",
"3": "third",
"4": "fourth",
"-1": "last"
};
var s = messages && messages.summary || {};
var onThe = s.onThe || "on the";
var onDay = s.onDay || "on day";
var offsetPositions = messages && messages.offsetPositions || {};
var weekdayMessages = messages && messages.weekdays || {};
if (rule.weekDays && rule.weekDays.length) {
var weekDayCount = rule.weekDays.length;
var monthOffset, monthDayLabel;
if (weekDayCount >= 2) {
monthOffset = rule.positions;
if (weekDayCount === 7) monthDayLabel = weekdayMessages.day || "day";
else if (weekDayCount === 5) monthDayLabel = weekdayMessages.weekday || "weekday";
else monthDayLabel = weekdayMessages.weekend || "weekend day";
} else {
monthOffset = rule.weekDays[0].offset;
monthDayLabel = kendo.culture().calendar.days.names[rule.weekDays[0].day];
}
var monthOffsetLabel = offsetPositions[offsetKeyMap[String(monthOffset)]] || String(monthOffset);
return " " + onThe + " " + monthOffsetLabel + " " + monthDayLabel;
} else if (rule.monthDays && rule.monthDays.length) return " " + onDay + " " + rule.monthDays[0];
return "";
},
_summaryTextYearly: function(rule, messages) {
var monthNames = kendo.culture().calendar.months.names;
var offsetKeyMap = {
"1": "first",
"2": "second",
"3": "third",
"4": "fourth",
"-1": "last"
};
var s = messages && messages.summary || {};
var onThe = s.onThe || "on the";
var onDay = s.onDay || "on day";
var on = s.on || "on";
var offsetPositions = messages && messages.offsetPositions || {};
var weekdayMessages = messages && messages.weekdays || {};
var of = (messages && messages.yearly || {}).of || " of ";
var monthName = rule.months && rule.months.length ? monthNames[rule.months[0] - 1] : "";
if (rule.weekDays && rule.weekDays.length) {
var weekDayCount = rule.weekDays.length;
var yearOffset, yearDayLabel;
if (weekDayCount >= 2) {
yearOffset = rule.positions;
if (weekDayCount === 7) yearDayLabel = weekdayMessages.day || "day";
else if (weekDayCount === 5) yearDayLabel = weekdayMessages.weekday || "weekday";
else yearDayLabel = weekdayMessages.weekend || "weekend day";
} else {
yearOffset = rule.weekDays[0].offset;
yearDayLabel = kendo.culture().calendar.days.names[rule.weekDays[0].day];
}
var yearOffsetLabel = offsetPositions[offsetKeyMap[String(yearOffset)]] || String(yearOffset);
return " " + onThe + " " + yearOffsetLabel + " " + yearDayLabel + (monthName ? of + monthName : "");
} else if (rule.monthDays && rule.monthDays.length) return (monthName ? " " + on + " " + monthName + " " : " " + onDay + " ") + rule.monthDays[0];
return "";
},
_openDialog: function() {
var that = this;
that._savedValue = $.extend(true, {}, that._value);
if (that._value.weekDays) that._savedValue.weekDays = that._value.weekDays.map(function(d) {
return $.extend({}, d);
});
if (that._dialog) {
kendo.destroy(that._dialogWrapper);
that._dialogWrapper.remove();
that._dialog = null;
that._dialogWrapper = null;
}
that._createDialog();
},
_createDialog: function() {
var that = this;
var messages = that.options.messages;
var hasRecurrence = !!(that._value && that._value.freq);
var appendTarget = that.element.closest(".k-scheduler").length ? that.element.closest(".k-scheduler") : $("body");
that._dialogWrapper = $("<div>").appendTo(appendTarget);
var actions = [];
if (hasRecurrence) actions.push({
text: "Remove recurrence",
cssClass: "k-button-flat",
action: function() {
that._value = {};
that._updateButton();
that.trigger(CHANGE);
return true;
}
});
actions.push({
text: messages.cancel || "Cancel",
action: function() {
that._value = that._savedValue;
return true;
}
});
actions.push({
text: messages.update || "Save",
primary: true,
action: function() {
that._collectFromDialog();
that._updateButton();
that.trigger(CHANGE);
return true;
}
});
that._inDialog = false;
var formHtml = that._buildFormHtml();
that._dialog = that._dialogWrapper.kendoDialog({
title: "Recurrence",
content: formHtml,
modal: true,
width: 540,
resizable: false,
closable: true,
buttonLayout: "normal",
visible: false,
actions,
open: function() {
that._inDialog = true;
that._container = $(this.element).find(".k-recur-dialog-form");
that._initDialogWidgets();
},
close: function() {
that._freqDdl = null;
that._endTypeDdl = null;
that._weekDayButtonGroup = null;
that._interval = null;
that._count = null;
that._until = null;
that._weekDay = null;
that._weekDayOffset = null;
that._monthDay = null;
that._month1 = null;
that._month2 = null;
that._container = null;
},
hide: function() {
that.element.find(".k-recur-trigger").trigger("focus");
}
}).data("kendoDialog");
that._dialog.open();
},
_buildFormHtml: function() {
var that = this;
var messages = that.options.messages;
var endMessages = messages.end || {};
var rule = that._value;
var freq = rule.freq || "daily";
var endType = rule.count ? "count" : rule.until ? "until" : "";
var repeatEveryLabel = messages.daily && messages.daily.repeatEvery || "Repeat every";
var frequencyLabel = messages.repeat || "Repeat";
var endLabel = endMessages.label || "Ends";
var freqOptions = DIALOG_FREQ_ITEMS.map(function(f) {
return `<option value="${f}"${f === freq ? " selected" : ""}>${encode(messages.frequencies && messages.frequencies[f] || DIALOG_FREQ_LABELS[f] || f)}</option>`;
}).join("");
var endTypeOptions = [
{
value: "",
text: endMessages.never || "Never"
},
{
value: "count",
text: endMessages.after || "After"
},
{
value: "until",
text: endMessages.on || "On"
}
].map(function(o) {
var sel = endType === o.value ? " selected" : "";
return `<option value="${o.value}"${sel}>${encode(o.text)}</option>`;
}).join("");
return `<div class="k-form k-form-horizontal k-recur-dialog-form">
<div class="k-form-field">
<label class="k-form-label k-label">${encode(repeatEveryLabel)}</label>
<div class="k-form-field-wrap">
<div class="k-scheduler-recurrence-fields">
<input ref-recur-interval type="text" aria-label="${encode(repeatEveryLabel)}" />
<select ref-recur-freq aria-label="${encode(frequencyLabel)}">${freqOptions}</select>
</div>
</div>
</div>
<div class="k-recur-repeat-on"></div>
<div class="k-form-field">
<label class="k-form-label k-label">${encode(endLabel)}</label>
<div class="k-form-field-wrap">
<div class="k-scheduler-recurrence-fields k-recur-end-fields">
<select ref-recur-end-type aria-label="${encode(endLabel)}">${endTypeOptions}</select>
${that._buildEndInputsHtml(endType)}
</div>
</div>
</div>
<div class="k-form-field">
<div class="k-form-field-wrap">
<div class="k-form-hint k-recur-dialog-hint"></div>
</div>
</div>
</div>`;
},
_buildEndInputsHtml: function(endType) {
var endMessages = this.options.messages.end || {};
return `<input ref-recur-count type="text" aria-label="${encode(endMessages.occurrence || "occurrence(s)")}"${endType !== "count" ? " style=\"display:none\"" : ""} /><input ref-recur-until type="text" aria-label="${encode(endMessages.on || "On")}"${endType !== "until" ? " style=\"display:none\"" : ""} />`;
},
_initDialogWidgets: function() {
var that = this;
var rule = that._value;
var freq = rule.freq || "daily";
if (!rule.freq) {
rule.freq = freq;
if (!rule.interval) rule.interval = 1;
}
that._initInterval();
that._freqDdl = that._container.find("[ref-recur-freq]").kendoDropDownList({ change: function() {
var newFreq = this.value();
var interval = that._interval ? that._interval.value() || 1 : 1;
var prevCount = that._count ? that._count.value() : null;
var prevUntil = that._until ? that._until.value() || null : null;
that._value = {
freq: newFreq,
interval
};
if (prevCount) that._value.count = prevCount;
if (prevUntil) that._value.until = prevUntil;
if (newFreq === "weekly") that._value.weekDays = [{
day: that.options.start.getDay(),
offset: 0
}];
that._renderRepeatOn(newFreq);
that._updateHintText();
} }).data("kendoDropDownList");
that._renderRepeatOn(freq);
that._endTypeDdl = that._container.find("[ref-recur-end-type]").kendoDropDownList({ change: function() {
var endType = this.value();
that._applyEndType(endType);
var countWrapper = that._count ? that._count.wrapper : that._container.find("[ref-recur-count]");
var untilWrapper = that._until ? that._until.wrapper : that._container.find("[ref-recur-until]");
if (that._count) {
that._count.destroy();
that._count = null;
}
if (that._until) {
that._until.destroy();
that._until = null;
}
countWrapper.remove();
untilWrapper.remove();
that._container.find(".k-recur-end-fields").append(that._buildEndInputsHtml(endType));
if (endType === "count") that._initCount();
else if (endType === "until") that._initUntil();
that._updateHintText();
} }).data("kendoDropDownList");
var endType = rule.count ? "count" : rule.until ? "until" : "";
if (endType === "count") that._initCount();
else if (endType === "until") that._initUntil();
that._updateHintText();
},
_renderRepeatOn: function(freq) {
var that = this;
var container = that._container;
var messages = that.options.messages;
var repeatOnWrap = container.find(".k-recur-repeat-on");
that._value;
if (that._weekDayButtonGroup) {
that._weekDayButtonGroup.destroy();
that._weekDayButtonGroup = null;
}
kendo.destroy(repeatOnWrap);
repeatOnWrap.empty();
if (freq === "daily") return;
var repeatOnLabel = encode(messages[freq] && messages[freq].repeatOn || "Repeat on");
if (freq === "weekly") {
repeatOnWrap.html(`<div class="k-form-field">
<label class="k-form-label k-label">${repeatOnLabel}</label>
<div class="k-form-field-wrap">
<div class="k-scheduler-weekday-picker k-button-group-stretched k-recur-weekday-buttons" role="group" aria-label="${repeatOnLabel}"></div>
</div>
</div>`);
that._weekDayButtons(that.options.firstWeekDay);
that._initWeekDays();
} else if (freq === "monthly") {
var m = messages.monthly || {};
repeatOnWrap.html(`<div class="k-form-field">
<label class="k-form-label k-label">${repeatOnLabel}</label>
<div class="k-form-field-wrap">
<ul class="k-radio-list k-list-vertical" role="radiogroup" aria-label="${repeatOnLabel}">
<li class="k-radio-list-item">
<span class="k-radio-wrap"><input class="k-radio k-recur-month-radio" type="radio" name="recur-month" value="weekday" aria-label="${encode((m.repeatOn || "Repeat on") + " " + (m.day || "Day"))}" /></span>
<div class="k-scheduler-recurrence-fields">
<select class="k-recur-weekday-offset" title="${encode(m.repeatOn || "")}" aria-label="${encode(m.repeatOn || "Repeat on")}"></select>
<select class="k-recur-weekday" title="${encode(m.day || "")}" aria-label="${encode(m.day || "Day")}"></select>
</div>
</li>
<li class="k-radio-list-item">
<span class="k-radio-wrap"><input class="k-recur-month-radio k-radio" type="radio" name="recur-month" value="monthday" aria-label="${encode((m.repeatOn || "Repeat on") + " " + (m.date || "Date"))}" /></span>
<div class="k-scheduler-recurrence-fields">
<input ref-recur-monthday type="number" aria-label="${encode(m.date || "Date")}" pattern="\d*" />
</div>
</li>
</ul>
</div>
</div>`);
that._initMonthDay();
that._initWeekDay();
that._period();
} else if (freq === "yearly") {
var y = messages.yearly || {};
repeatOnWrap.html(`<div class="k-form-field">
<label class="k-form-label k-label">${repeatOnLabel}</label>
<div class="k-form-field-wrap">
<ul class="k-radio-list k-list-vertical" role="radiogroup" aria-label="${repeatOnLabel}">
<li class="k-radio-list-item">
<span class="k-radio-wrap"><input class="k-radio k-recur-year-radio" type="radio" name="recur-year" value="monthday" aria-label="${encode((y.repeatOn || "Repeat on") + " " + (y.date || "Date"))}" /></span>
<div class="k-scheduler-recurrence-fields">
<select class="k-recur-month k-recur-month1" title="${encode(y.month || "")}" aria-label="${encode(y.month || "Month")}"></select>
<input ref-recur-monthday type="number" aria-label="${encode(y.date || "Date")}" pattern="\d*" />
</div>
</li>
<li class="k-radio-list-item">
<span class="k-radio-wrap"><input class="k-radio k-recur-year-radio" type="radio" name="recur-year" value="weekday" aria-label="${encode((y.repeatOn || "Repeat on") + " " + (y.day || "Day"))}" /></span>
<div class="k-scheduler-recurrence-fields">
<select class="k-recur-weekday-offset" title="${encode(y.repeatOn || "")}" aria-label="${encode(y.repeatOn || "Repeat on")}"></select>
<select class="k-recur-weekday" title="${encode(y.day || "")}" aria-label="${encode(y.day || "Day")}"></select>
<span class="k-recur-editor-text">${encode(y.of || "of")}</span>
<select class="k-recur-month k-recur-month2" title="${encode(y.month || "")}" aria-label="${encode(y.month || "Month")}"></select>
</div>
</li>
</ul>
</div>
</div>`);
that._initMonthDay();
that._initWeekDay();
that._initMonth();
that._period();
}
},
_applyEndType: function(endType) {
var rule = this._value;
if (endType === "") {
rule.count = null;
rule.until = null;
} else if (endType === "count") {
rule.until = null;
if (!rule.count) rule.count = 1;
} else if (endType === "until") {
rule.count = null;
if (!rule.until) rule.until = this.options.start;
}
},
_updateHintText: function() {
var that = this;
var container = that._container;
if (!container) return;
container.find(".k-recur-dialog-hint").text(that._summaryText());
},
_collectFromDialog: function() {
var that = this;
if (that._interval) that._value.interval = that._interval.value() || 1;
if (that._count && that._value.count) that._value.count = that._count.value() || 1;
if (that._until && that._value.until) {
var until = that._until.value();
if (until) that._value.until = new Date(until.getFullYear(), until.getMonth(), until.getDate(), 23, 59, 59);
}
},
_initContainer: function() {},
_initFrequency: function() {},
_initView: function() {},
_end: function() {},
_toggleEnd: function(endRule) {
var that = this;
var count = null;
var until = null;
if (endRule === "count") count = that._count ? that._count.value() || 1 : 1;
else if (endRule === "until") until = that._until ? that._until.value() || that.options.start : that.options.start;
if (that._count) that._count.enable(endRule === "count");
if (that._until) that._until.enable(endRule === "until");
that._value.count = count;
that._value.until = until;
},
_period: function() {
var that = this;
var rule = that._value;
var monthly = rule.freq === "monthly";
var toggleRule = monthly ? that._toggleMonthDay : that._toggleYear;
var selector = ".k-recur-" + (monthly ? "month" : "year") + "-radio";
var radioButtons = that._container.find(selector);
if (!monthly && rule.freq !== "yearly") return;
radioButtons.on(CLICK + that._namespace, function(e) {
toggleRule.call(that, e.currentTarget.value);
if (!that._isMobile() && typeof that._updateHintText === "function") that._updateHintText();
});
that._buttonMonthDay = radioButtons.filter("[value=\"monthday\"]");
that._buttonWeekDay = radioButtons.filter("[value=\"weekday\"]");
toggleRule.call(that, rule.weekDays ? "weekday" : "monthday");
},
_toggleMonthDay: function(monthRule) {
var that = this;
var enableMonthDay = false;
var enableWeekDay = true;
var clear = false;
var monthDays;
if (monthRule === "monthday") {
that._buttonMonthDay.prop("checked", true);
monthDays = [that._monthDay.value()];
enableMonthDay = true;
enableWeekDay = false;
clear = true;
} else {
that._buttonWeekDay.prop("checked", true);
monthDays = null;
}
that._weekDay.enable(enableWeekDay);
that._weekDayOffset.enable(enableWeekDay);
that._monthDay.enable(enableMonthDay);
that._value.monthDays = monthDays;
that._weekDayRule(clear);
},
_toggleYear: function(yearRule) {
var that = this;
var enableMonth1 = false;
var enableMonth2 = true;
var month;
if (yearRule === "monthday") {
enableMonth1 = true;
enableMonth2 = false;
month = that._month1.value();
} else month = that._month2.value();
that._month1.enable(enableMonth1);
that._month2.enable(enableMonth2);
that._value.months = [month];
that._toggleMonthDay(yearRule);
},
_initMonth: function() {
var that = this;
var rule = that._value;
var month = rule.months || [that.options.start.getMonth() + 1];
var monthInputs = that._container.find(".k-recur-month");
var options;
if (monthInputs[0]) {
options = {
autoWidth: true,
change: function() {
rule.months = [Number(this.value())];
var other = this === (that._month1 && that._month1.element[0] ? that._month1 : null) ? that._month2 : that._month1;
if (other) other.value(this.value());
that._trigger();
that._updateHintText();
},
dataTextField: "text",
dataValueField: "value",
dataSource: $.map(kendo.culture().calendar.months.names, function(monthName, idx) {
return {
text: monthName,
value: idx + 1
};
})
};
that._month1 = new DropDownList(monthInputs[0], options);
if (monthInputs[1]) that._month2 = new DropDownList(monthInputs[1], $.extend({}, options));
if (month && month[0]) {
that._month1.value(month[0]);
if (that._month2) that._month2.value(month[0]);
}
}
}
});
ui.plugin(RecurrenceEditor);
var RECURRENCE_HEADER_TEMPLATE = kendo.template(({ headerTitle }) => `<div data-role="content"><ul class="k-listgroup k-listgroup-flush"><li class="k-item k-listgroup-item"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${headerTitle}</span><div class="k-recur-pattern k-listgroup-form-field-wrapper"></div></label></li><li class="k-item k-listgroup-item k-recur-view"></li></ul></div>`);
var RECURRENCE_REPEAT_PATTERN_TEMPLATE = kendo.template(({ frequency, messages }) => (frequency !== "never" ? `<label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.repeatEvery)}</span><div class="k-recur-editor-wrap k-listgroup-form-field-wrapper"><input ref-recur-interval type="number" pattern="\\d*"/>` + (messages.interval.length ? `<span class="k-recur-editor-text">${encode(messages.interval)}</span>` : "") + "</div></label>" : "") + (frequency === "weekly" ? `<ul class="k-recur-items-wrap k-listgroup k-listgroup-flush"><li class="k-item k-listgroup-item k-no-click"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.repeatOn)}</span></label></li><div class="k-button-group-stretched k-recur-weekday-buttons" title="${encode(messages.repeatOn)}"></ul>` : "") + (frequency === "monthly" ? `<ul class="k-recur-items-wrap k-listgroup k-listgroup-flush"><li class="k-item k-listgroup-item"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.repeatBy)}</span><div class="k-repeat-rule k-listgroup-form-field-wrapper"></div></label></li><li class="k-monthday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.day)}</span><div class="k-listgroup-form-field-wrapper"><input ref-recur-monthday type="number" aria-label="${encode(messages.date)}" title="${encode(messages.day)}" pattern="\\d*"/></div></label></li><li class="k-weekday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.every)}</span><div class="k-listgroup-form-field-wrapper"><select class="k-recur-weekday-offset" title="${encode(messages.every)}"></select></div></label></li><li class="k-weekday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.day)}</span><div class="k-listgroup-form-field-wrapper"><select class="k-recur-weekday" title="${encode(messages.day)}"></select></div></label></li></ul>` : "") + (frequency === "yearly" ? `<ul class="k-recur-items-wrap k-listgroup k-listgroup-flush"><li class="k-item k-listgroup-item"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.repeatBy)}</span><div class="k-repeat-rule k-listgroup-form-field-wrapper"></div></label></li><li class="k-monthday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.day)}</span><div class="k-listgroup-form-field-wrapper"><input ref-recur-monthday type="number" aria-label="${encode(messages.date)}" title="${encode(messages.day)}" pattern="\\d*"/></div></label></li><li class="k-weekday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.every)}</span><div class="k-listgroup-form-field-wrapper"><select class="k-recur-weekday-offset" title="${encode(messages.every)}"></select></div></label></li><li class="k-weekday-view k-item k-listgroup-item" ${kendo.attr("style-display")}="none"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.day)}</span><div class="k-listgroup-form-field-wrapper"><select class="k-recur-weekday" title="${encode(messages.day)}"></select></div></label></li><li class="k-item k-item k-listgroup-item"><label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.month)}</span><div class="k-listgroup-form-field-wrapper"><select class="k-recur-month" title="${encode(messages.month)}"></select></div></label></li></ul>` : ""));
var RECURRENCE_END_PATTERN_TEMPLATE = kendo.template(({ endPattern, messages }) => {
if (endPattern === "count") return `<label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.after)}</span><div class="k-listgroup-form-field-wrapper"><input ref-recur-count aria-label="${encode(messages.occurrence)}" type="number" pattern="\\d*" /></div></label>`;
else if (endPattern === "until") return `<label class="k-label k-listgroup-form-row"><span class="k-item-title k-listgroup-form-field-label">${encode(messages.on)}</span><div class="k-listgroup-form-field-wrapper"><input type="date" aria-label="${encode(messages.on)}" ref-recur-until /></div></label>`;
});
var RECURRENCE_GROUP_BUTTON_TEMPLATE = kendo.template(({ dataSource, value }) => "<select class=\"k-scheduler-select\">" + dataSource.map((item) => `<option value="${item.value}" ${value === item.value ? "selected" : ""}>${encode(item.text)}</option>`).join("") + "</select>");
var MobileRecurrenceEditor = BaseRecurrenceEditor.extend({
init: function(element, options) {
var that = this;
BaseRecurrenceEditor.fn.init.call(that, element, options);
options = that.options;
that._optionTemplate = kendo.template(({ value, text }) => `<option value="${encode(value)}">${encode(text)}</option>`);
that.value(options.value);
that._pane = options.pane || that.wrapper.closest("[data-role=pane]").data("kendoPane");
that._initRepeatButton();
that._initParentRepeatEnd();
that._defaultValue = that._value;
Widget.fn.endInit.call(that);
},
options: {
name: "MobileRecurrenceEditor",
animations: {
left: "slide",
right: "slide:right"
},
mobile: true,
messages: {
cancel: "Cancel",
update: "Save",
endTitle: "Repeat ends",
repeatTitle: "Repeat pattern",
headerTitle: "Repeat event",
end: {
patterns: {
never: "Never",
after: "After...",
on: "On..."
},
never: "Never",
after: "End repeat after",
on: "End repeat on"
},
daily: { interval: "" },
hourly: { interval: "" },
weekly: { interval: "" },
monthly: {
interval: "",
repeatBy: "Repeat by: ",
dayOfMonth: "Day of the month",
dayOfWeek: "Day of the week",
repeatEvery: "Repeat every",
every: "Every",
day: "Day "
},
yearly: {
interval: "",
repeatBy: "Repeat by: ",
dayOfMonth: "Day of the month",
dayOfWeek: "Day of the week",
repeatEvery: "Repeat every: ",
every: "Every",
month: "Month",
day: "Day"
}
}
},
events: ["change"],
value: function(value) {
var that = this;
var timezone = that.options.timezone;
if (value === undefined) {
if (!that._value.freq) return "";
return serialize(that._value, timezone);
}
that._value = parseRule(value, timezone) || {};
},
destroy: function() {
this._destroyView();
kendo.destroy(this._endFields);
this.element.off(CLICK + this._namespace);
BaseRecurrenceEditor.fn.destroy.call(this);
},
_initInterval: function() {
var that = this;
var rule = that._value;
that._container.find("[ref-recur-interval]").val(that._value.interval || 1).on(CHANGE + that._namespace, function(e) {
rule.interval = e.target.value;
that._trigger();
});
},
_initRepeatButton: function() {
var that = this;
var freq = that.options.messages.frequencies[this._value.freq || "never"];
that._chevronButton = $(kendo.ui.icon("chevron-right"));
that._repeatValue = $("<span class=\"\">" + freq + "</span>");
that.element.append(that._repeatValue).append(that._chevronButton);
that.element.parents("li.k-item").on(CLICK + that._namespace, function(e) {
e.preventDefault();
that._createView("repeat");
that._pane.navigate(that._view, that.options.animations.left);
});
},
_endLiItem: function() {
return "<li class=\"k-item k-listgroup-item\"><label class=\"k-label k-listgroup-form-row\"><span class=\"k-item-title k-listgroup-form-field-label\">" + this.options.messages.end.mobileLabel + "</span></label></li>";
},
_initParentRepeatEnd: function() {
var that = this;
var endLabelField = $(that._endLiItem()).insertAfter(that.element.parents("li.k-item"));
var endEditField = $("<div class=\"k-scheduler-recur-end-wrap k-listgroup-form-field-wrapper\"><span class=\"k-scheduler-recur-end\"></span></div>").appendTo(endLabelField.find(".k-label"));
endLabelField.on(CLICK + that._namespace, function(e) {
e.preventDefault();
that._navigateToView("repeat");
});
that._endParentLabelField = endLabelField.toggle(!!that._value.freq);
that._endParentEndButton = endEditField.find(".k-scheduler-recur-end").text(that._endText());
},
_initRepeatEnd: function() {
var that = this;
var endLabelField = $(that._endLiItem()).insertAfter(that._container);
var endEditField = $(`<div class="k-scheduler-recur-end-wrap k-listgroup-form-field-wrapper"><span class="k-scheduler-recur-end"></span>${kendo.ui.icon("chevron-right")}</div>`).appendTo(endLabelField.find(".k-label"));
endLabelField.on(CLICK + that._namespace, function(e) {
e.preventDefault();
that._navigateToView("end");
});
that._endLabelField = endLabelField.toggleClass("k-disabled", !that._value.freq);
that._endButton = endEditField.find(".k-scheduler-recur-end").text(that._endText());
},
_navigateToView: function(viewName) {
var that = this;
that._createView(viewName);
that._pane.navigate(that._view, that.options.animations.left);
},
_endText: function() {
var rule = this._value;
var messages = this.options.messages.end;
var text = messages.never;
if (rule.count) text = kendo.format("{0} {1}", messages.after, rule.count);
else if (rule.until) text = kendo.format("{0} {1:d}", messages.on, rule.until);
return text;
},
_initFrequency: function() {
var that = this;
var frequencyMessages = that.options.messages.frequencies;
var html = RECURRENCE_GROUP_BUTTON_TEMPLATE({
dataSource: $.map(this.options.frequencies, function(frequency) {
return {
text: frequencyMessages[frequency],
value: frequency !== "never" ? frequency : ""
};
}),
value: that._value.freq || "",
ns: kendo.ns
});
that._view.element.find(".k-recur-pattern").append(html);
that._view.element.find(".k-scheduler-select").on(CHANGE + that._namespace, function(e) {
that._value = { freq: e.target.value };
that._defaultValue = $.extend({}, that._value);
that._initRepeatView();
that._endButton.text(that._endText());
that._endParentEndButton.text(that._endText());
});
},
_initEndNavigation: function() {
var that = this;
var endMessages = that.options.messages.end.patterns;
var rule = that._value;
var value = "";
if (rule.count) value = "count";
else if (rule.until) value = "until";
var html = RECURRENCE_GROUP_BUTTON_TEMPLATE({
dataSource: [
{
text: endMessages.never,
value: ""
},
{
text: endMessages.after,
value: "count"
},
{
text: endMessages.on,
value: "until"
}
],
value,
ns: kendo.ns
});
that._view.element.find(".k-recur-pattern").append(html);
that._view.element.find(".k-scheduler-select").on(CHANGE + that._namespace, function(e) {
var value = e.target.value;
var count = null;
var until = null;
that._initEndView(value);
if (that._count.length) {
count = that._count.val();
until = null;
} else if (that._until.length) {
count = null;
until = that._until.val ? kendo.parseDate(that._until.val(), "yyyy-MM-dd") : that._until.value();
}
rule.count = count;
rule.until = until;
});
},
_createView: function(viewType) {
var that = this;
var messages = that.options.messages;
var headerTitle = messages[viewType === "repeat" ? "repeatTitle" : "endTitle"];
var html = "<div data-role=\"view\" class=\"k-popup-edit-form k-scheduler-edit-form\" id=\"recurrence\"><div data-role=\"header\" class=\"k-appbar k-appbar-primary\">" + kendo.html.renderButton(`<button class="k-header-cancel k-scheduler-cancel" title="${messages.cancel}" aria-label="${messages.cancel}"></button>`, {
fillMode: "flat",
icon: "chevron-left"
}) + `<span class="k-spacer"></span><span>${encode(messages.headerTitle)}</span><span class="k-spacer"></span>` + kendo.html.renderButton(`<button class="k-header-done k-scheduler-update" title="${messages.update}" aria-label="${messages.update}"></button>`, {
fillMode: "flat",
icon: "check"
}) + "</div>";
var returnViewId = that._pane.view().id;
that._view = that._pane.append(html + RECURRENCE_HEADER_TEMPLATE({ headerTitle }));
that._view.element.on(CLICK + that._namespace, ".k-scheduler-cancel, .k-scheduler-update", function(e) {
e.preventDefault();
e.stopPropagation();
if ($(this).hasClass("k-scheduler-update")) {
that.trigger("change");
that._defaultValue = $.extend({}, that._value);
} else that._value = that._defaultValue;
var frequency = that._value.freq;
that._endParentEndButton.text(that._endText());
that._endParentLabelField.toggle(!!frequency && frequency !== "never");
that._endButton.text(that._endText());
that._repeatValue.text(messages.frequencies[frequency || "never"]);
that._pane.one("viewShow", function() {
that._destroyView();
});
that._pane.navigate(returnViewId, that.options.animations.right);
});
that._container = that._view.element.find(".k-recur-view");
if (viewType === "repeat") {
that._initFrequency();
that._initRepeatView();
that._initRepeatEnd();
} else {
that._initEndNavigation();
that._initEndView();
}
},
_destroyView: function() {
if (this._view) {
this._view.destroy();
this._view.element.remove();
this._container = null;
}
this._view = null;
},
_initRepeatView: function() {
var that = this;
var frequency = that._value.freq || "never";
var html = RECURRENCE_REPEAT_PATTERN_TEMPLATE({
frequency,
firstWeekDay: that.options.firstWeekDay,
messages: that.options.messages[frequency]
});
var $html = $(html);
kendo.applyStylesFromKendoAttributes($html, ["display"]);
var container = that._container = that._container || this._pane.view().content.find("li.k-recur-view");
var rule = that._value;
if (that._endLabelField) that._endLabelField.toggleClass("k-disabled", frequency === "never");
kendo.destroy(container);
container.html($html);
if (!html) {
that._value = {};
container.hide();
return;
} else container.show();
if (frequency === "weekly" && !rule.weekDays) rule.weekDays = [{
day: that.options.start.getDay(),
offset: 0
}];
that._weekDayButtons(that.options.firstWeekDay);
that._initInterval();
that._initMonthDay();
that._initWeekDays();
that._initWeekDay();
that._initMonth();
that._period();
},
_initMonthDay: function() {
var that = this;
var rule = that._value;
(that._monthDay = that._container.find("[ref-recur-monthday]")).attr({
min: 1,
max: 31
}).val(rule.monthDays ? rule.monthDays[0] : that.options.start.getDate()).on(CHANGE + that._namespace, function(e) {
rule.monthDays = e.target.value ? [e.target.value] : null;
that._trigger();
});
},
_initCount: function() {
var that = this, input = that._count = that._container.find("[ref-recur-count]"), rule = that._value;
input.val(rule.count || 1).on(CHANGE + that._namespace, function(ev) {
rule.count = ev.target.value;
that._trigger();
});
input.parent().addClass("k-recur-count");
},
_initEndView: function(endPattern) {
var that = this;
var rule = that._value;
if (endPattern === undefined) {
if (rule.count) endPattern = "count";
else if (rule.until) endPattern = "until";
}
var data = {
endPattern,
messages: that.options.messages.end
};
kendo.destroy(that._container);
that._container.html(RECURRENCE_END_PATTERN_TEMPLATE(data));
that._initCount();
that._initUntil();
},
_initWeekDay: function() {
var that = this, data;
var weekdayMessage = that.options.messages.weekdays;
var offsetMessage = that.options.messages.offsetPositions;
var weekDaySelect = that._container.find(".k-recur-weekday");
var change = function() {
that._weekDayRule();
that.trigger("change");
};
if (weekDaySelect[0]) {
that._weekDayOffset = that._container.find(".k-recur-weekday-offset").html(that._options([
{
text: offsetMessage.first,
value: "1"
},
{
text: offsetMessage.second,
value: "2"
},
{
text: offsetMessage.third,
value: "3"
},
{
text: offsetMessage.fourth,
value: "4"
},
{
text: offsetMessage.last,
value: "-1"
}
])).on("change", change);
data = [
{
text: weekdayMessage.day,
value: "day"
},
{
text: weekdayMessage.weekday,
value: "weekday"
},
{
text: weekdayMessage.weekend,
value: "weekend"
}
];
data = data.concat($.map(kendo.culture().calendar.days.names, function(dayName, idx) {
return {
text: dayName,
value: idx
};
}));
that._weekDay = weekDaySelect.html(that._options(data)).on("change", change).val(that.options.start.getDay());
that._weekDayView();
}
},
_initMonth: function() {
var that = this;
var rule = that._value;
var start = that.options.start;
var month = rule.months || [start.getMonth() + 1];
var monthSelect = that._container.find(".k-recur-month");
var monthNames = kendo.culture().calendar.months.names;
if (monthSelect[0]) {
var data = $.map(monthNames, function(monthName, idx) {
return {
text: monthName,
value: idx + 1
};
});
monthSelect.html(that._options(data)).on("change", function() {
rule.months = [Number(this.value)];
});
that._monthSelect = monthSelect;
if (month) monthSelect.val(month[0]);
}
},
_period: function() {
var that = this;
var rule = that._value;
var container = that._container;
var messages = that.options.messages[rule.freq];
var repeatRuleGroupButton = container.find(".k-repeat-rule");
var weekDayView = container.find(".k-weekday-view");
var monthDayView = container.find(".k-monthday-view");
if (repeatRuleGroupButton[0]) {
var currentValue = rule.weekDays ? "weekday" : "monthday";
var html = RECURRENCE_GROUP_BUTTON_TEMPLATE({
value: currentValue,
dataSource: [{
text: messages.dayOfMonth,
value: "monthday"
}, {
text: messages.dayOfWeek,
value: "weekday"
}],
ns: kendo.ns
});
var init = function(val) {
var weekDayName = that._weekDay.val();
var weekDayOffset = that._weekDayOffset.val();
var monthDay = that._monthDay.val();
var month = that._monthSelect ? that._monthSelect.val() : null;
if (val === "monthday") {
rule.weekDays = null;
rule.monthDays = monthDay ? [monthDay] : monthDay;
rule.months = month ? [Number(month)] : month;
weekDayView.hide();
monthDayView.show();
} else {
rule.monthDays = null;
rule.months = month ? [Number(month)] : month;
rule.weekDays = [{
offset: Number(weekDayOffset),
day: Number(weekDayName)
}];
weekDayView.show();
monthDayView.hide();
}
};
repeatRuleGroupButton.append(html);
repeatRuleGroupButton.find(".k-scheduler-select").on(CHANGE + that._namespace, function(e) {
init(e.target.value);
});
init(currentValue);
}
},
_initUntil: function() {
var that = this;
var input = that._container.find("[ref-recur-until]");
var start = that.options.start;
var rule = that._value;
var until = rule.until;
var min = until && until < start ? until : start;
var validDateValidationMessage = kendo.format(kendo.ui.Validator.prototype.options.messages.date, that.options.messages.end.on);
var dateCompareValidationMessage = kendo.ui.Validator.prototype.options.messages.dateCompare;
input.attr("data-validDate-msg", validDateValidationMessage);
input.attr("data-untilDateCompare-msg", dateCompareValidationMessage);
if (kendo.support.input.date) {
that._until = input.attr("min", kendo.toString(min, "yyyy-MM-dd")).val(kendo.toString(until || start, "yyyy-MM-dd")).on("change", function() {
var date = kendo.parseDate(this.value, "yyyy-MM-dd");
if (date) rule.until = date;
that._trigger();
});
that._until.parent().addClass("k-recur-until");
} else {
that._until = input.kendoDatePicker({
min,
value: until || start,
change: function() {
var date = this.value();
if (date) rule.until = date;
that._trigger();
}
}).data("kendoDatePicker");
that._until.wrapper.addClass("k-recur-until");
}
},
_options: function(data, optionLabel) {
var idx = 0;
var html = "";
var length = data.length;
var template = this._optionTemplate;
if (optionLabel) html += template({
value: "",
text: optionLabel
});
for (; idx < length; idx++) html += template(data[idx]);
return html;
}
});
ui.plugin(MobileRecurrenceEditor);
})(window.kendo.jQuery);
var kendo_scheduler_recurrence_default = kendo;
//#endregion
exports.__meta__ = __meta__;
exports.default = kendo_scheduler_recurrence_default;