import { Modal, Popover } from "bootstrap";
export class MdsPersianDateTimePicker {
constructor(element: Element, setting: MdsPersianDateTimePickerSetting) {
setting = MdsPersianDateTimePicker.extend(new MdsPersianDateTimePickerSetting(), setting);
if (!element) throw new Error(`MdsPersianDateTimePicker => element is null!`);
if (setting.rangeSelector && (setting.toDate || setting.fromDate)) throw new Error(`MdsPersianDateTimePicker => You can not set true 'toDate' or 'fromDate' and 'rangeSelector' together`);
if (setting.toDate && setting.fromDate) throw new Error(`MdsPersianDateTimePicker => You can not set true 'toDate' and 'fromDate' together`);
if (!setting.groupId && (setting.toDate || setting.fromDate)) throw new Error(`MdsPersianDateTimePicker => When you set 'toDate' or 'fromDate' true, you have to set 'groupId'`);
if (!setting.textFormat) {
setting.textFormat = 'yyyy/MM/dd';
if (setting.enableTimePicker)
setting.textFormat += ' HH:mm';
}
if (!setting.dateFormat) {
setting.dateFormat = 'yyyy/MM/dd';
if (setting.enableTimePicker)
setting.dateFormat += ' HH:mm';
}
if (setting.yearOffset > 15)
setting.yearOffset = 15;
this.setting = setting;
this.setting.selectedDate = setting.selectedDate ? MdsPersianDateTimePicker.getClonedDate(setting.selectedDate) : null;
this.setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow) ?? new Date();
this.guid = MdsPersianDateTimePicker.newGuid();
this.element = element;
this.element.setAttribute("data-mds-dtp-guid", this.guid);
MdsPersianDateTimePickerData.set(this.guid, this);
this.initializeBsPopover(setting);
}
// #region jalali calendar
private static toJalali(gy: number, gm: number, gd: number): JalaliJsonModel {
return this.d2j(this.g2d(gy, gm, gd));
}
private static toGregorian(jy: number, jm: number, jd: number): GregorianJsonModel {
return this.d2g(this.j2d(jy, jm, jd));
}
// private static isValidJalaliDate(jy: number, jm: number, jd: number): boolean {
// return jy >= -61 && jy <= 3177 &&
// jm >= 1 && jm <= 12 &&
// jd >= 1 && jd <= this.jalaliMonthLength(jy, jm);
// }
private static isLeapJalaliYear(jy: number): boolean {
return this.jalCal(jy).leap === 0;
}
// private static jalaliMonthLength(jy: number, jm: number): number {
// if (jm <= 6) return 31;
// if (jm <= 11) return 30;
// if (this.isLeapJalaliYear(jy)) return 30;
// return 29;
// }
private static jalCal(jy: number): JalCalModel {
// Jalali years starting the 33-year rule.
let breaks = [-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178],
bl = breaks.length,
gy = jy + 621,
leapJ = -14,
jp = breaks[0],
jm,
jump = 1,
leap,
n,
i;
if (jy < jp || jy >= breaks[bl - 1])
throw new Error('Invalid Jalali year ' + jy);
// Find the limiting years for the Jalali year jy.
for (i = 1; i < bl; i += 1) {
jm = breaks[i];
jump = jm - jp;
if (jy < jm)
break;
leapJ = leapJ + this.div(jump, 33) * 8 + this.div(this.mod(jump, 33), 4);
jp = jm;
}
n = jy - jp;
// Find the number of leap years from AD 621 to the beginning
// of the current Jalali year in the Persian calendar.
leapJ = leapJ + this.div(n, 33) * 8 + this.div(this.mod(n, 33) + 3, 4);
if (this.mod(jump, 33) === 4 && jump - n === 4)
leapJ += 1;
// And the same in the Gregorian calendar (until the year gy).
let leapG = this.div(gy, 4) - this.div((this.div(gy, 100) + 1) * 3, 4) - 150;
// Determine the Gregorian date of Farvardin the 1st.
let march = 20 + leapJ - leapG;
// Find how many years have passed since the last leap year.
if (jump - n < 6)
n = n - jump + this.div(jump + 4, 33) * 33;
leap = this.mod(this.mod(n + 1, 33) - 1, 4);
if (leap === -1) leap = 4;
return {
leap: leap,
gy: gy,
march: march
};
}
private static j2d(jy: number, jm: number, jd: number): number {
let r = this.jalCal(jy);
return this.g2d(r.gy, 3, r.march) + (jm - 1) * 31 - this.div(jm, 7) * (jm - 7) + jd - 1;
}
private static d2j(jdn: number): JalaliJsonModel {
let gy = this.d2g(jdn).gy, // Calculate Gregorian year (gy).
jy = gy - 621,
r = this.jalCal(jy),
jdn1F = this.g2d(gy, 3, r.march),
jd,
jm,
k;
// Find number of days that passed since 1 Farvardin.
k = jdn - jdn1F;
if (k >= 0) {
if (k <= 185) {
// The first 6 months.
jm = 1 + this.div(k, 31);
jd = this.mod(k, 31) + 1;
return {
jy: jy,
jm: jm,
jd: jd
};
} else {
// The remaining months.
k -= 186;
}
} else {
// Previous Jalali year.
jy -= 1;
k += 179;
if (r.leap === 1)
k += 1;
}
jm = 7 + this.div(k, 30);
jd = this.mod(k, 30) + 1;
return {
jy: jy,
jm: jm,
jd: jd
};
}
private static g2d(gy: number, gm: number, gd: number): number {
let d = this.div((gy + this.div(gm - 8, 6) + 100100) * 1461, 4) +
this.div(153 * this.mod(gm + 9, 12) + 2, 5) +
gd - 34840408;
d = d - this.div(this.div(gy + 100100 + this.div(gm - 8, 6), 100) * 3, 4) + 752;
return d;
}
private static d2g(jdn: number): GregorianJsonModel {
let j;
j = 4 * jdn + 139361631;
j = j + this.div(this.div(4 * jdn + 183187720, 146097) * 3, 4) * 4 - 3908;
let i = this.div(this.mod(j, 1461), 4) * 5 + 308;
let gd = this.div(this.mod(i, 153), 5) + 1;
let gm = this.mod(this.div(i, 153), 12) + 1;
let gy = this.div(j, 1461) - 100100 + this.div(8 - gm, 6);
return {
gy: gy,
gm: gm,
gd: gd
};
}
private static div(a: number, b: number): number {
return ~~(a / b);
}
private static mod(a: number, b: number): number {
return a - ~~(a / b) * b;
}
//#endregion jalali calendar
// #region Template
private static modalHtmlTemplate =
`
`;
private static popoverHtmlTemplate = ``;
private static popoverHeaderSelectYearHtmlTemplate = ``;
private static dateTimePickerYearsToSelectHtmlTemplate = `
{{yearsBoxHtml}}
|
|
`;
private static dateTimePickerHtmlTemplate = ``;
private static dateTimePickerMonthTableHtmlTemplate = `
|
|
|
|
|
|
|
|
|
|
| {{weekDayShortName1}} |
{{weekDayShortName2}} |
{{weekDayShortName3}} |
{{weekDayShortName4}} |
{{weekDayShortName5}} |
{{weekDayShortName6}} |
{{weekDayShortName7}} |
{{daysHtml}}
| `;
private static previousYearTextPersian = 'سال قبل';
private static previousMonthTextPersian = 'ماه قبل';
private static previousTextPersian = 'قبلی';
private static nextYearTextPersian = 'سال بعد';
private static nextMonthTextPersian = 'ماه بعد';
private static nextTextPersian = 'بعدی';
private static todayTextPersian = 'امروز';
private static goTodayTextPersian = 'برو به امروز';
private static cancelTextPersian = 'انصراف';
private static currentYearTextPersian = 'سال جاری';
private static previousText = 'Previous';
private static previousYearText = 'Previous Year';
private static previousMonthText = 'Previous Month';
private static nextText = 'Next';
private static nextYearText = 'Next Year';
private static nextMonthText = 'Next Month';
private static todayText = 'Today';
private static goTodayText = 'Go Today';
private static cancelText = 'Cancel';
private static currentYearText = 'Current Year';
private static shortDayNamesPersian = [
'ش',
'ی',
'د',
'س',
'چ',
'پ',
'ج',
];
private static shortDayNames = [
'Su',
'Mo',
'Tu',
'We',
'Th',
'Fr',
'Sa',
];
private static monthNamesPersian = [
'فروردین',
'اردیبهشت',
'خرداد',
'تیر',
'مرداد',
'شهریور',
'مهر',
'آبان',
'آذر',
'دی',
'بهمن',
'اسفند'
];
private static monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
private static weekDayNames = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
private static weekDayNamesPersian = [
'یک شنبه',
'دوشنبه',
'سه شنبه',
'چهارشنبه',
'پنج شنبه',
'جمعه',
'شنبه'
];
// #endregion
// #region Properties
readonly guid: string = '';
readonly setting: MdsPersianDateTimePickerSetting;
private readonly element: Element;
private bsPopover: Popover | null = null;
private bsModal: Modal | null = null;
private tempTitleString = '';
// #endregion
// #region Methods
private initializeBsPopover(setting: MdsPersianDateTimePickerSetting): void {
// Validation
if (setting.rangeSelector && (setting.toDate || setting.fromDate))
throw new Error(`MdsPersianDateTimePicker => You can not set true 'toDate' or 'fromDate' and 'rangeSelector' together`);
if (setting.toDate && setting.fromDate)
throw new Error(`MdsPersianDateTimePicker => You can not set true 'toDate' and 'fromDate' together`);
if (!setting.groupId && (setting.toDate || setting.fromDate))
throw new Error(`MdsPersianDateTimePicker => When you set 'toDate' or 'fromDate' true, you have to set 'groupId'`);
// ---------------------
// آپشن هایی که باید همان لحظه تغییر اعمال شوند
if (setting.disabled) {
this.element.setAttribute("disabled", '');
} else {
this.element.removeAttribute("disabled");
}
if (setting.toDate || setting.fromDate) {
setting.rangeSelector = false;
this.element.setAttribute("data-mds-dtp-group", setting.groupId);
if (setting.toDate)
this.element.setAttribute("data-to-date", 'true');
else if (setting.fromDate)
this.element.setAttribute("data-from-date", 'true');
}
if (!setting.rangeSelector) {
setting.rangeSelectorMonthsToShow = [0, 0];
}
// ---------------------
setTimeout(() => {
this.dispose();
const title = this.getPopoverHeaderTitle(setting);
let datePickerBodyHtml = this.getDateTimePickerBodyHtml(setting);
let tempDiv = document.createElement('div');
tempDiv.innerHTML = datePickerBodyHtml;
const dropDowns = tempDiv.querySelectorAll('.dropdown>button');
dropDowns.forEach(e => {
if (setting.disabled) {
e.setAttribute('disabled', '');
e.classList.add('disabled');
}
else {
e.removeAttribute('disabled');
e.classList.remove('disabled');
}
});
datePickerBodyHtml = tempDiv.innerHTML;
if (setting.modalMode == true) {
this.setModalHtml(title, datePickerBodyHtml, setting);
this.bsPopover = null;
setTimeout(() => {
const el = this.getModal();
if (el != null) {
this.bsModal = new Modal(el);
this.enableMainEvents();
}
}, 200);
} else if (setting.inLine == true) {
this.bsPopover = null;
this.element.innerHTML = datePickerBodyHtml;
this.enableInLineEvents();
} else {
this.bsPopover = new Popover(this.element, {
container: 'body',
content: datePickerBodyHtml,
title: title,
html: true,
placement: setting.placement,
trigger: 'manual',
template: MdsPersianDateTimePicker.popoverHtmlTemplate,
sanitize: false,
});
this.enableMainEvents();
}
MdsPersianDateTimePicker.setSelectedData(setting);
this.tempTitleString = title;
}, setting.inLine ? 10 : 100);
}
private static newGuid(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
private static extend(...args: any[]): any {
for (let i = 1; i < args.length; i++)
for (let key in args[i])
if (args[i].hasOwnProperty(key))
args[0][key] = args[i][key];
return args[0];
}
private static getClonedDate(dateTime: Date): Date {
return new Date(dateTime.getTime());
}
private static getDateTimeJson1(dateTime: Date): GetDateTimeJson1 {
return {
year: dateTime.getFullYear(),
month: dateTime.getMonth() + 1,
day: dateTime.getDate(),
hour: dateTime.getHours(),
minute: dateTime.getMinutes(),
second: dateTime.getSeconds(),
millisecond: dateTime.getMilliseconds(),
dayOfWeek: dateTime.getDay()
};
}
private static getDateTimeJson2(dateNumber: number): GetDateTimeJson1 {
return {
year: Math.floor(dateNumber / 10000),
month: Math.floor(dateNumber / 100) % 100,
day: dateNumber % 100,
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
dayOfWeek: -1
};
}
private static getDateTimeJsonPersian1(dateTime: Date): GetDateTimeJson1 {
let persianDate = this.toJalali(dateTime.getFullYear(), dateTime.getMonth() + 1, dateTime.getDate());
return {
year: persianDate.jy,
month: persianDate.jm,
day: persianDate.jd,
hour: dateTime.getHours(),
minute: dateTime.getMinutes(),
second: dateTime.getSeconds(),
millisecond: dateTime.getMilliseconds(),
dayOfWeek: dateTime.getDay(),
};
}
private static getDateTimeJsonPersian2(yearPersian: number, monthPersian: number, dayPersian: number, hour: number, minute: number, second: number): GetDateTimeJson1 {
if (!this.isNumber(hour)) hour = 0;
if (!this.isNumber(minute)) minute = 0;
if (!this.isNumber(second)) second = 0;
let gregorian = this.toGregorian(yearPersian, monthPersian, dayPersian);
return MdsPersianDateTimePicker.getDateTimeJsonPersian1(new Date(gregorian.gy, gregorian.gm - 1, gregorian.gd, hour, minute, second));
}
private static getWeekDayName(englishWeekDayIndex: number, isGregorian: boolean): string {
if (!isGregorian) return this.weekDayNamesPersian[englishWeekDayIndex];
return this.weekDayNames[englishWeekDayIndex];
}
private static getMonthName(monthIndex: number, isGregorian: boolean): string {
if (monthIndex < 0)
monthIndex = 11;
else if (monthIndex > 11)
monthIndex = 0;
if (!isGregorian) return this.monthNamesPersian[monthIndex];
return this.monthNames[monthIndex];
}
private static getWeekDayShortName(englishWeekDayIndex: number, isGregorian: boolean): string {
if (!isGregorian)
return this.shortDayNamesPersian[englishWeekDayIndex];
return this.shortDayNames[englishWeekDayIndex];
}
private static isLeapYear(persianYear: number): boolean {
return this.isLeapJalaliYear(persianYear);
}
private static getDaysInMonthPersian(year: number, month: number): number {
let numberOfDaysInMonth = 31;
if (month > 6 && month < 12)
numberOfDaysInMonth = 30;
else if (month == 12)
numberOfDaysInMonth = this.isLeapYear(year) ? 30 : 29;
return numberOfDaysInMonth;
}
private static getDaysInMonth(year: number, month: number): number {
return new Date(year, month + 1, 0).getDate();
}
private static getLastDayDateOfPreviousMonth(dateTime: Date, isGregorian: boolean): Date {
let dateTimeLocal = MdsPersianDateTimePicker.getClonedDate(dateTime);
if (isGregorian) {
let previousMonth = new Date(dateTimeLocal.getFullYear(), dateTimeLocal.getMonth() - 1, 1),
daysInMonth = MdsPersianDateTimePicker.getDaysInMonth(previousMonth.getFullYear(), previousMonth.getMonth());
return new Date(previousMonth.getFullYear(), previousMonth.getMonth(), daysInMonth);
}
let dateTimeJsonPersian = MdsPersianDateTimePicker.getDateTimeJsonPersian1(dateTimeLocal);
dateTimeJsonPersian.month += -1;
if (dateTimeJsonPersian.month <= 0) {
dateTimeJsonPersian.month = 12;
dateTimeJsonPersian.year--;
} else if (dateTimeJsonPersian.month > 12) {
dateTimeJsonPersian.year++;
dateTimeJsonPersian.month = 1;
}
return MdsPersianDateTimePicker.getDateTime1(dateTimeJsonPersian.year, dateTimeJsonPersian.month, MdsPersianDateTimePicker.getDaysInMonthPersian(dateTimeJsonPersian.year, dateTimeJsonPersian.month));
}
private static getFirstDayDateOfNextMonth(dateTime: Date, isGregorian: boolean): Date {
let dateTimeLocal = MdsPersianDateTimePicker.getClonedDate(dateTime);
if (isGregorian) {
let nextMonth = new Date(dateTimeLocal.getFullYear(), dateTimeLocal.getMonth() + 1, 1);
return new Date(nextMonth.getFullYear(), nextMonth.getMonth(), 1);
}
let dateTimeJsonPersian = MdsPersianDateTimePicker.getDateTimeJsonPersian1(dateTimeLocal);
dateTimeJsonPersian.month += 1;
if (dateTimeJsonPersian.month <= 0) {
dateTimeJsonPersian.month = 12;
dateTimeJsonPersian.year--;
}
if (dateTimeJsonPersian.month > 12) {
dateTimeJsonPersian.year++;
dateTimeJsonPersian.month = 1;
}
return MdsPersianDateTimePicker.getDateTime1(dateTimeJsonPersian.year, dateTimeJsonPersian.month, 1);
}
private static getDateTime1(yearPersian: number, monthPersian: number, dayPersian: number, hour?: number, minute?: number, second?: number): Date {
if (!this.isNumber(hour)) hour = 0;
if (!this.isNumber(minute)) minute = 0;
if (!this.isNumber(second)) second = 0;
let gregorian = this.toGregorian(yearPersian, monthPersian, dayPersian);
return new Date(gregorian.gy, gregorian.gm - 1, gregorian.gd, hour, minute, second);
}
private static getDateTime2(dateTimeJsonPersian: GetDateTimeJson1): Date {
if (!dateTimeJsonPersian.hour) dateTimeJsonPersian.hour = 0;
if (!dateTimeJsonPersian.minute) dateTimeJsonPersian.minute = 0;
if (!dateTimeJsonPersian.second) dateTimeJsonPersian.second = 0;
let gregorian = this.toGregorian(dateTimeJsonPersian.year, dateTimeJsonPersian.month, dateTimeJsonPersian.day);
return new Date(gregorian.gy, gregorian.gm - 1, gregorian.gd, dateTimeJsonPersian.hour, dateTimeJsonPersian.minute, dateTimeJsonPersian.second);
}
private static getDateTime3(dateTimeJson: GetDateTimeJson1): Date {
return new Date(dateTimeJson.year, dateTimeJson.month - 1, dateTimeJson.day, dateTimeJson.hour, dateTimeJson.minute, dateTimeJson.second);
}
private static getDateTime4(dateNumber: number, dateTime: Date, isGregorian: boolean): Date {
let dateTimeJson = MdsPersianDateTimePicker.getDateTimeJson2(dateNumber);
if (!isGregorian) {
let dateTimeJsonPersian = MdsPersianDateTimePicker.getDateTimeJsonPersian1(dateTime);
dateTimeJsonPersian.year = dateTimeJson.year;
dateTimeJsonPersian.month = dateTimeJson.month;
dateTimeJsonPersian.day = dateTimeJson.day;
dateTime = this.getDateTime2(dateTimeJsonPersian);
} else
dateTime = new Date(dateTimeJson.year, dateTimeJson.month - 1, dateTimeJson.day,
dateTime.getHours(), dateTime.getMinutes(), dateTime.getSeconds());
return dateTime;
}
private static getLesserDisableBeforeDate(setting: MdsPersianDateTimePickerSetting): GetDateTimeJson1 | null {
// دریافت تاریخ کوچکتر
// از بین تاریخ های غیر فعال شده در گذشته
let resultDate: Date | null = null;
const dateNow = new Date();
if (setting.disableBeforeToday && setting.disableBeforeDate) {
if (setting.disableBeforeDate.getTime() <= dateNow.getTime())
resultDate = MdsPersianDateTimePicker.getClonedDate(setting.disableBeforeDate);
else
resultDate = dateNow;
} else if (setting.disableBeforeDate)
resultDate = MdsPersianDateTimePicker.getClonedDate(setting.disableBeforeDate);
else if (setting.disableBeforeToday)
resultDate = dateNow;
if (resultDate == null)
return null;
if (setting.isGregorian)
return MdsPersianDateTimePicker.getDateTimeJson1(resultDate);
return MdsPersianDateTimePicker.getDateTimeJsonPersian1(resultDate);
}
private static getBiggerDisableAfterDate(setting: MdsPersianDateTimePickerSetting): GetDateTimeJson1 | null {
// دریافت تاریخ بزرگتر
// از بین تاریخ های غیر فعال شده در آینده
let resultDate: Date | null = null;
const dateNow = new Date();
if (setting.disableAfterDate && setting.disableAfterToday) {
if (setting.disableAfterDate.getTime() >= dateNow.getTime())
resultDate = MdsPersianDateTimePicker.getClonedDate(setting.disableAfterDate);
else
resultDate = dateNow;
} else if (setting.disableAfterDate)
resultDate = MdsPersianDateTimePicker.getClonedDate(setting.disableAfterDate);
else if (setting.disableAfterToday)
resultDate = dateNow;
if (resultDate == null)
return null;
if (setting.isGregorian)
return MdsPersianDateTimePicker.getDateTimeJson1(resultDate);
return MdsPersianDateTimePicker.getDateTimeJsonPersian1(resultDate);
}
private static addMonthToDateTimeJson(dateTimeJson: GetDateTimeJson1, addedMonth: number, isGregorian: boolean): GetDateTimeJson1 {
// وقتی نیاز هست تا ماه یا روز به تاریخی اضافه کنم
// پس از اضافه کردن ماه یا روز این متد را استفاده میکنم تا سال و ماه
// با مقادیر جدید تصحیح و برگشت داده شوند
const dateTimeJson1 = Object.assign({}, dateTimeJson);
dateTimeJson1.day = 1;
dateTimeJson1.month += addedMonth;
if (!isGregorian) {
if (dateTimeJson1.month <= 0) {
dateTimeJson1.month = 12;
dateTimeJson1.year--;
}
if (dateTimeJson1.month > 12) {
dateTimeJson1.year++;
dateTimeJson1.month = 1;
}
return dateTimeJson1;
}
return MdsPersianDateTimePicker.getDateTimeJson1(this.getDateTime3(dateTimeJson1));
}
private static convertToNumber1(dateTimeJson: GetDateTimeJson1): number {
return Number(MdsPersianDateTimePicker.zeroPad(dateTimeJson.year) + MdsPersianDateTimePicker.zeroPad(dateTimeJson.month) + MdsPersianDateTimePicker.zeroPad(dateTimeJson.day));
}
private static convertToNumber2(year: number, month: number, day: number): number {
return Number(MdsPersianDateTimePicker.zeroPad(year) + MdsPersianDateTimePicker.zeroPad(month) + MdsPersianDateTimePicker.zeroPad(day));
}
private static convertToNumber3(dateTime: Date): number {
return MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(dateTime));
}
private static correctOptionValue(optionName: string, value: any): any {
const setting = new MdsPersianDateTimePickerSetting();
Object.keys(setting).filter(key => key === optionName).forEach(key => {
switch (typeof (setting)[key]) {
case 'number':
value = +value;
break;
case 'string':
value = value.toString();
break;
case 'boolean':
value = !!value;
break;
case 'object':
if ((setting)[key] instanceof Date) {
value = new Date(value);
} else if (Array.isArray((setting)[key])) {
switch (optionName) {
case 'holidays':
case 'disabledDates':
case 'specialDates':
case 'selectedRangeDate':
value.forEach((item: any, i: number) => {
value[i] = new Date(item);
});
break;
case 'disabledDays':
case 'rangeSelectorMonthsToShow':
value.forEach((item: any, i: number) => {
value[i] = +item;
});
break;
}
}
break;
}
});
return value;
}
private static getShortHour(hour: number): number {
let shortHour;
if (hour > 12)
shortHour = hour - 12;
else
shortHour = hour;
return shortHour;
}
private static getAmPm(hour: number, isGregorian: boolean): string {
let amPm;
if (hour > 12) {
if (isGregorian)
amPm = 'PM';
else
amPm = 'ب.ظ';
} else
if (isGregorian)
amPm = 'AM';
else
amPm = 'ق.ظ';
return amPm;
}
private static addMonthToDateTime(dateTime: Date, addedMonth: number, isGregorian: boolean): Date {
let dateTimeJson: GetDateTimeJson1;
if (!isGregorian) {
dateTimeJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(dateTime);
dateTimeJson = MdsPersianDateTimePicker.addMonthToDateTimeJson(dateTimeJson, addedMonth, isGregorian);
return this.getDateTime2(dateTimeJson);
}
dateTimeJson = MdsPersianDateTimePicker.getDateTimeJson1(dateTime);
dateTimeJson = MdsPersianDateTimePicker.addMonthToDateTimeJson(dateTimeJson, addedMonth, isGregorian);
return this.getDateTime3(dateTimeJson);
}
private static isNumber(n: any): boolean {
return !isNaN(parseFloat(n)) && isFinite(n);
}
private static toPersianNumber(inputNumber1: number | string): string {
/* ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ */
if (!inputNumber1) return '';
let str1 = inputNumber1.toString().trim();
if (!str1) return '';
str1 = str1.replace(/0/img, '۰');
str1 = str1.replace(/1/img, '۱');
str1 = str1.replace(/2/img, '۲');
str1 = str1.replace(/3/img, '۳');
str1 = str1.replace(/4/img, '۴');
str1 = str1.replace(/5/img, '۵');
str1 = str1.replace(/6/img, '۶');
str1 = str1.replace(/7/img, '۷');
str1 = str1.replace(/8/img, '۸');
str1 = str1.replace(/9/img, '۹');
return str1;
}
private static toEnglishNumber(inputNumber1: number | string): string {
/* ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ */
if (!inputNumber1) return '';
let str1 = inputNumber1.toString().trim();
if (!str1) return '';
str1 = str1.replace(/۰/img, '0');
str1 = str1.replace(/۱/img, '1');
str1 = str1.replace(/۲/img, '2');
str1 = str1.replace(/۳/img, '3');
str1 = str1.replace(/۴/img, '4');
str1 = str1.replace(/۵/img, '5');
str1 = str1.replace(/۶/img, '6');
str1 = str1.replace(/۷/img, '7');
str1 = str1.replace(/۸/img, '8');
str1 = str1.replace(/۹/img, '9');
return str1;
}
private static zeroPad(nr: any, base?: string): string {
if (nr == undefined || nr == '') return '00';
if (base == undefined || base == '') base = '00';
let len = (String(base).length - String(nr).length) + 1;
return len > 0 ? new Array(len).join('0') + nr : nr;
}
private static getDateTimeString(dateTimeJson: GetDateTimeJson1, format: string, isGregorian: boolean, persianNumber: boolean): string {
/// فرمت های که پشتیبانی می شوند
///
/// yyyy: سال چهار رقمی
///
/// yy: سال دو رقمی
///
/// MMMM: نام ماه
///
/// MM: عدد دو رقمی ماه
///
/// M: عدد یک رقمی ماه
///
/// dddd: نام روز هفته
///
/// dd: عدد دو رقمی روز ماه
///
/// d: عدد یک رقمی روز ماه
///
/// HH: ساعت دو رقمی با فرمت 00 تا 24
///
/// H: ساعت یک رقمی با فرمت 0 تا 24
///
/// hh: ساعت دو رقمی با فرمت 00 تا 12
///
/// h: ساعت یک رقمی با فرمت 0 تا 12
///
/// mm: عدد دو رقمی دقیقه
///
/// m: عدد یک رقمی دقیقه
///
/// ss: ثانیه دو رقمی
///
/// s: ثانیه یک رقمی
///
/// fff: میلی ثانیه 3 رقمی
///
/// ff: میلی ثانیه 2 رقمی
///
/// f: میلی ثانیه یک رقمی
///
/// tt: ب.ظ یا ق.ظ
///
/// t: حرف اول از ب.ظ یا ق.ظ
format = format.replace(/yyyy/mg, dateTimeJson.year.toString());
format = format.replace(/yy/mg, (dateTimeJson.year % 100).toString());
format = format.replace(/MMMM/mg, MdsPersianDateTimePicker.getMonthName(dateTimeJson.month - 1, isGregorian));
format = format.replace(/MM/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.month));
format = format.replace(/M/mg, dateTimeJson.month.toString());
format = format.replace(/dddd/mg, MdsPersianDateTimePicker.getWeekDayName(dateTimeJson.dayOfWeek, isGregorian));
format = format.replace(/dd/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.day));
format = format.replace(/d/mg, dateTimeJson.day.toString());
format = format.replace(/HH/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.hour));
format = format.replace(/H/mg, dateTimeJson.hour.toString());
format = format.replace(/hh/mg, MdsPersianDateTimePicker.zeroPad(this.getShortHour(dateTimeJson.hour).toString()));
format = format.replace(/h/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.hour));
format = format.replace(/mm/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.minute));
format = format.replace(/m/mg, dateTimeJson.minute.toString());
format = format.replace(/ss/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.second));
format = format.replace(/s/mg, dateTimeJson.second.toString());
format = format.replace(/fff/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.millisecond, '000'));
format = format.replace(/ff/mg, MdsPersianDateTimePicker.zeroPad(dateTimeJson.millisecond / 10));
format = format.replace(/f/mg, (dateTimeJson.millisecond / 100).toString());
format = format.replace(/tt/mg, this.getAmPm(dateTimeJson.hour, isGregorian));
format = format.replace(/t/mg, this.getAmPm(dateTimeJson.hour, isGregorian)[0]);
if (persianNumber)
format = MdsPersianDateTimePicker.toPersianNumber(format);
return format;
}
private static getSelectedDateTimeTextFormatted(setting: MdsPersianDateTimePickerSetting): string {
if (setting.selectedDate == undefined) return '';
if (!setting.enableTimePicker) {
setting.selectedDate.setHours(0);
setting.selectedDate.setMinutes(0);
setting.selectedDate.setSeconds(0);
}
if (setting.rangeSelector && setting.rangeSelectorStartDate != undefined && setting.rangeSelectorEndDate != undefined)
return MdsPersianDateTimePicker.getDateTimeString(!setting.isGregorian ? MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.rangeSelectorStartDate) : MdsPersianDateTimePicker.getDateTimeJson1(setting.rangeSelectorStartDate), setting.textFormat, setting.isGregorian, setting.persianNumber) + ' - ' +
MdsPersianDateTimePicker.getDateTimeString(!setting.isGregorian ? MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.rangeSelectorEndDate) : MdsPersianDateTimePicker.getDateTimeJson1(setting.rangeSelectorEndDate), setting.textFormat, setting.isGregorian, setting.persianNumber);
return MdsPersianDateTimePicker.getDateTimeString(!setting.isGregorian ? MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.selectedDate) : MdsPersianDateTimePicker.getDateTimeJson1(setting.selectedDate), setting.textFormat, setting.isGregorian, setting.persianNumber);
}
private static getSelectedDateFormatted(setting: MdsPersianDateTimePickerSetting): string {
// دریافت رشته تاریخ انتخاب شده
if ((!setting.rangeSelector && !setting.selectedDate) ||
(setting.rangeSelector && !setting.rangeSelectorStartDate && !setting.rangeSelectorEndDate))
return '';
if (setting.rangeSelector)
return MdsPersianDateTimePicker.getDateTimeString(MdsPersianDateTimePicker.getDateTimeJson1(setting.rangeSelectorStartDate!), setting.dateFormat, true, setting.persianNumber) + ' - ' +
MdsPersianDateTimePicker.getDateTimeString(MdsPersianDateTimePicker.getDateTimeJson1(setting.rangeSelectorEndDate!), setting.dateFormat, true, setting.persianNumber);
return MdsPersianDateTimePicker.getDateTimeString(MdsPersianDateTimePicker.getDateTimeJson1(setting.selectedDate!), setting.dateFormat, true, setting.persianNumber);
}
private static getDisabledDateObject(setting: MdsPersianDateTimePickerSetting): [GetDateTimeJson1 | null, GetDateTimeJson1 | null] {
let disableBeforeDateTimeJson = this.getLesserDisableBeforeDate(setting);
let disableAfterDateTimeJson = this.getBiggerDisableAfterDate(setting);
// بررسی پراپرتی های از تاریخ، تا تاریخ
if ((setting.fromDate || setting.toDate) && setting.groupId) {
const toDateElement = document.querySelector(`[data-mds-dtp-group="${setting.groupId}"][data-to-date]`);
const fromDateElement = document.querySelector(`[data-mds-dtp-group="${setting.groupId}"][data-from-date]`);
if (toDateElement != null && setting.fromDate) {
const toDateSetting = MdsPersianDateTimePicker.getInstance(toDateElement)?.setting;
const toDateSelectedDate = !toDateSetting ? null : toDateSetting.selectedDate;
disableAfterDateTimeJson = !toDateSelectedDate ? null : setting.isGregorian ? MdsPersianDateTimePicker.getDateTimeJson1(toDateSelectedDate) : MdsPersianDateTimePicker.getDateTimeJsonPersian1(toDateSelectedDate);
} else if (fromDateElement != null && setting.toDate) {
const fromDateSetting = MdsPersianDateTimePicker.getInstance(fromDateElement)?.setting;
const fromDateSelectedDate = !fromDateSetting ? null : fromDateSetting.selectedDate;
disableBeforeDateTimeJson = !fromDateSelectedDate ? null : setting.isGregorian ? MdsPersianDateTimePicker.getDateTimeJson1(fromDateSelectedDate) : MdsPersianDateTimePicker.getDateTimeJsonPersian1(fromDateSelectedDate);
}
}
return [disableBeforeDateTimeJson, disableAfterDateTimeJson];
}
private static setSelectedData(setting: MdsPersianDateTimePickerSetting): void {
const targetTextElement = setting.targetTextSelector ? document.querySelector(setting.targetTextSelector) : undefined;
const targetDateElement = setting.targetDateSelector ? document.querySelector(setting.targetDateSelector) : undefined;
const changeEvent = new Event('change');
if (targetTextElement != undefined) {
const dateTimeTextFormat = this.getSelectedDateTimeTextFormatted(setting);
switch (targetTextElement.tagName.toLowerCase()) {
case 'input':
(targetTextElement).value = dateTimeTextFormat;
break;
default:
targetTextElement.innerHTML = dateTimeTextFormat;
break;
}
targetTextElement.dispatchEvent(changeEvent);
}
if (targetDateElement != undefined) {
const dateTimeFormat = this.toEnglishNumber(this.getSelectedDateFormatted(setting));
switch (targetDateElement.tagName.toLowerCase()) {
case 'input':
(targetDateElement).value = dateTimeFormat;
break;
default:
targetDateElement.innerHTML = dateTimeFormat;
break;
}
targetDateElement.dispatchEvent(changeEvent);
}
}
private getPopover(element: Element): Element | null {
let popoverId = element.getAttribute('aria-describedby');
if (popoverId == undefined || popoverId == '')
return element.closest('[data-mds-dtp]');
return document.getElementById(popoverId.toString());
}
private getModal(): Element | null {
return document.querySelector(`.modal[data-mds-dtp-guid="${this.guid}"]`);
}
private setModalHtml(title: string, datePickerBodyHtml: string, setting: MdsPersianDateTimePickerSetting): void {
const prevModalElement = this.getModal();
if (prevModalElement == null) {
let modalHtml = MdsPersianDateTimePicker.modalHtmlTemplate;
modalHtml = modalHtml.replace(/\{\{guid\}\}/img, this.guid);
const tempDiv = document.createElement('div');
tempDiv.innerHTML = modalHtml;
tempDiv.querySelector('[data-mds-dtp-title] .modal-title')!.innerHTML = title;
tempDiv.querySelector('[data-name="mds-dtp-body"]')!.innerHTML = datePickerBodyHtml;
document.querySelector('body')!.appendChild(tempDiv);
} else {
prevModalElement.querySelector('[data-mds-dtp-title] .modal-title')!.innerHTML = title;
prevModalElement.querySelector('[data-name="mds-dtp-body"]')!.innerHTML = datePickerBodyHtml;
}
const modalDialogElement = document.querySelector(`[data-mds-dtp-guid="${this.guid}"] .modal-dialog`);
if (modalDialogElement != null) {
if (setting.rangeSelector) {
if (setting.rangeSelectorMonthsToShow[0] > 0 || setting.rangeSelectorMonthsToShow[1] > 0)
modalDialogElement.classList.add('modal-xl');
else
modalDialogElement.classList.remove('modal-xl');
} else {
modalDialogElement.classList.remove('modal-xl');
}
} else {
console.warn("mds.bs.datetimepicker: element with `data-mds-dtp-guid` selector not found !")
}
}
private getYearsBoxBodyHtml(setting: MdsPersianDateTimePickerSetting, yearToStart: number): MdsPersianDateTimePickerYearToSelect {
// بدست آوردن اچ تی ام ال انتخاب سال
// yearToStart سال شروع
setting.yearOffset = Number(setting.yearOffset);
const selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow);
const disabledDateObj = MdsPersianDateTimePicker.getDisabledDateObject(setting);
const disableBeforeDateTimeJson = disabledDateObj[0];
const disableAfterDateTimeJson = disabledDateObj[1];
let html = MdsPersianDateTimePicker.dateTimePickerYearsToSelectHtmlTemplate;
let yearsBoxHtml = '';
let todayDateTimeJson: GetDateTimeJson1;
let selectedDateTimeToShowJson: GetDateTimeJson1;
let counter = 1;
if (setting.isGregorian) {
selectedDateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJson1(selectedDateToShow);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJson1(new Date());
} else {
selectedDateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(selectedDateToShow);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(new Date());
}
counter = 1;
const yearStart = yearToStart ? yearToStart : todayDateTimeJson.year - setting.yearOffset;
const yearEnd = yearToStart ? yearToStart + setting.yearOffset * 2 : todayDateTimeJson.year + setting.yearOffset;
for (let i = yearStart; i < yearEnd; i++) {
let disabledAttr = '';
if (disableBeforeDateTimeJson != null) {
disabledAttr = i < disableBeforeDateTimeJson.year ? 'disabled' : '';
}
if (!disabledAttr && disableAfterDateTimeJson != null) {
disabledAttr = i > disableAfterDateTimeJson.year ? 'disabled' : '';
}
let currentYearDateTimeJson = MdsPersianDateTimePicker.getDateTimeJson2(MdsPersianDateTimePicker.convertToNumber2(i, selectedDateTimeToShowJson.month, MdsPersianDateTimePicker.getDaysInMonthPersian(i, selectedDateTimeToShowJson.month)));
let currentYearDisabledAttr = '';
let yearText = setting.isGregorian ? i.toString() : MdsPersianDateTimePicker.toPersianNumber(i);
let yearDateNumber = MdsPersianDateTimePicker.convertToNumber2(i, selectedDateTimeToShowJson.month, 1);
let todayAttr = todayDateTimeJson.year == i ? 'data-current-year="true"' : ''
let selectedYearAttr = selectedDateTimeToShowJson.year == i ? 'data-selected-year' : ''
let selectedYearTitle = '';
if (todayAttr)
selectedYearTitle = setting.isGregorian ? MdsPersianDateTimePicker.currentYearText : MdsPersianDateTimePicker.currentYearTextPersian;
if (disableBeforeDateTimeJson != undefined && disableBeforeDateTimeJson.year != undefined && currentYearDateTimeJson.year < disableBeforeDateTimeJson.year)
currentYearDisabledAttr = 'disabled';
if (disableAfterDateTimeJson != undefined && disableAfterDateTimeJson.year != undefined && currentYearDateTimeJson.year > disableAfterDateTimeJson.year)
currentYearDisabledAttr = 'disabled';
if (setting.disableBeforeToday && currentYearDateTimeJson.year < todayDateTimeJson.year)
currentYearDisabledAttr = 'disabled';
if (setting.disableAfterToday && currentYearDateTimeJson.year > todayDateTimeJson.year)
currentYearDisabledAttr = 'disabled';
if (counter == 1) yearsBoxHtml += '';
yearsBoxHtml += `
|
|
`;
if (counter == 5) yearsBoxHtml += '
';
counter++;
if (counter > 5) counter = 1;
}
html = html.replace(/\{\{yearsBoxHtml\}\}/img, yearsBoxHtml);
html = html.replace(/\{\{cancelText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.cancelText : MdsPersianDateTimePicker.cancelTextPersian);
if (setting.inLine && setting.yearOffset > 15)
html += '';
return {
yearStart,
yearEnd,
html
};
}
private getYearsBoxHeaderHtml(setting: MdsPersianDateTimePickerSetting, yearStart: number, yearEnd: number): string {
const yearsRangeText = ` ${yearStart} - ${yearEnd - 1} `;
const disabledDateObj = MdsPersianDateTimePicker.getDisabledDateObject(setting);
let html = MdsPersianDateTimePicker.popoverHeaderSelectYearHtmlTemplate;
html = html.replace(/\{{rtlCssClass\}\}/img, setting.isGregorian ? '' : 'rtl');
html = html.replace(/\{{dirAttrValue\}\}/img, setting.isGregorian ? 'ltr' : 'rtl');
html = html.replace(/\{\{yearsRangeText\}\}/img, setting.isGregorian ? yearsRangeText : MdsPersianDateTimePicker.toPersianNumber(yearsRangeText));
html = html.replace(/\{\{previousText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.previousText : MdsPersianDateTimePicker.previousTextPersian);
html = html.replace(/\{\{nextText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.nextText : MdsPersianDateTimePicker.nextTextPersian);
html = html.replace(/\{\{latestPreviousYear\}\}/img, yearStart > yearEnd ? yearEnd.toString() : yearStart.toString());
html = html.replace(/\{\{latestNextYear\}\}/img, yearStart > yearEnd ? yearStart.toString() : yearEnd.toString());
html = html.replace(/\{\{prevYearButtonAttr\}\}/img, disabledDateObj[0] != null && yearStart - 1 < disabledDateObj[0].year ? 'disabled' : '');
html = html.replace(/\{\{nextYearButtonAttr\}\}/img, disabledDateObj[1] != null && yearEnd + 1 > disabledDateObj[1].year ? 'disabled' : '');
return html;
}
private getDateTimePickerMonthHtml(setting: MdsPersianDateTimePickerSetting, isNextMonth: boolean, isPrevMonth: boolean): string {
let selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow);
let selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
let selectedDateTime = setting.selectedDate != undefined ? MdsPersianDateTimePicker.getClonedDate(setting.selectedDate) : undefined;
let isNextOrPrevMonth = isNextMonth || isPrevMonth;
let html = MdsPersianDateTimePicker.dateTimePickerMonthTableHtmlTemplate;
html = html.replace(/\{\{guid\}\}/img, this.guid);
html = html.replace(/\{\{monthTdAttribute\}\}/img, isNextMonth ? 'data-next-month' : isPrevMonth ? 'data-prev-month' : '');
html = html.replace(/\{\{monthNameAttribute\}\}/img, !isNextOrPrevMonth ? 'hidden' : '');
html = html.replace(/\{\{theadSelectDateButtonTrAttribute\}\}/img, !isNextOrPrevMonth ? '' : 'hidden');
html = html.replace(/\{\{weekDayShortName1CssClass\}\}/img, setting.isGregorian ? 'text-danger' : '');
html = html.replace(/\{\{weekDayShortName7CssClass\}\}/img, !setting.isGregorian ? 'text-danger' : '');
html = html.replace(/\{\{previousYearText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.previousYearText : MdsPersianDateTimePicker.previousYearTextPersian);
html = html.replace(/\{\{previousMonthText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.previousMonthText : MdsPersianDateTimePicker.previousMonthTextPersian);
html = html.replace(/\{\{nextMonthText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.nextMonthText : MdsPersianDateTimePicker.nextMonthTextPersian);
html = html.replace(/\{\{nextYearText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.nextYearText : MdsPersianDateTimePicker.nextYearTextPersian);
html = html.replace(/\{\{monthName1\}\}/img, MdsPersianDateTimePicker.getMonthName(0, setting.isGregorian));
html = html.replace(/\{\{monthName2\}\}/img, MdsPersianDateTimePicker.getMonthName(1, setting.isGregorian));
html = html.replace(/\{\{monthName3\}\}/img, MdsPersianDateTimePicker.getMonthName(2, setting.isGregorian));
html = html.replace(/\{\{monthName4\}\}/img, MdsPersianDateTimePicker.getMonthName(3, setting.isGregorian));
html = html.replace(/\{\{monthName5\}\}/img, MdsPersianDateTimePicker.getMonthName(4, setting.isGregorian));
html = html.replace(/\{\{monthName6\}\}/img, MdsPersianDateTimePicker.getMonthName(5, setting.isGregorian));
html = html.replace(/\{\{monthName7\}\}/img, MdsPersianDateTimePicker.getMonthName(6, setting.isGregorian));
html = html.replace(/\{\{monthName8\}\}/img, MdsPersianDateTimePicker.getMonthName(7, setting.isGregorian));
html = html.replace(/\{\{monthName9\}\}/img, MdsPersianDateTimePicker.getMonthName(8, setting.isGregorian));
html = html.replace(/\{\{monthName10\}\}/img, MdsPersianDateTimePicker.getMonthName(9, setting.isGregorian));
html = html.replace(/\{\{monthName11\}\}/img, MdsPersianDateTimePicker.getMonthName(10, setting.isGregorian));
html = html.replace(/\{\{monthName12\}\}/img, MdsPersianDateTimePicker.getMonthName(11, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName1\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(0, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName2\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(1, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName3\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(2, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName4\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(3, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName5\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(4, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName6\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(5, setting.isGregorian));
html = html.replace(/\{\{weekDayShortName7\}\}/img, MdsPersianDateTimePicker.getWeekDayShortName(6, setting.isGregorian));
const disabledDateObj = MdsPersianDateTimePicker.getDisabledDateObject(setting);
let i = 0,
j = 0,
firstWeekDayNumber,
cellNumber = 0,
tdNumber = 0,
selectedDateNumber = 0,
selectedMonthName = '',
todayDateTimeJson: GetDateTimeJson1, // year, month, day, hour, minute, second
dateTimeToShowJson: GetDateTimeJson1, // year, month, day, hour, minute, second
numberOfDaysInCurrentMonth = 0,
numberOfDaysInPreviousMonth = 0,
tr = document.createElement('TR'),
td = document.createElement("TD"),
daysHtml = '',
currentDateNumber = 0,
previousMonthDateNumber = 0,
nextMonthDateNumber = 0,
previousYearDateNumber = 0,
nextYearDateNumber = 0,
rangeSelectorStartDate = !setting.rangeSelector || setting.rangeSelectorStartDate == undefined ? undefined : MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorStartDate),
rangeSelectorEndDate = !setting.rangeSelector || setting.rangeSelectorEndDate == undefined ? undefined : MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorEndDate),
rangeSelectorStartDateNumber = 0,
rangeSelectorEndDateNumber = 0,
dayNumberInString = '0',
dayOfWeek = '', // نام روز هفته
monthsDateNumberAndAttr: any = {
month1DateNumber: 0,
month2DateNumber: 0,
month3DateNumber: 0,
month4DateNumber: 0,
month5DateNumber: 0,
month6DateNumber: 0,
month7DateNumber: 0,
month8DateNumber: 0,
month9DateNumber: 0,
month10DateNumber: 0,
month11DateNumber: 0,
month12DateNumber: 0,
selectMonth1ButtonCssClass: '',
selectMonth2ButtonCssClass: '',
selectMonth3ButtonCssClass: '',
selectMonth4ButtonCssClass: '',
selectMonth5ButtonCssClass: '',
selectMonth6ButtonCssClass: '',
selectMonth7ButtonCssClass: '',
selectMonth8ButtonCssClass: '',
selectMonth9ButtonCssClass: '',
selectMonth10ButtonCssClass: '',
selectMonth11ButtonCssClass: '',
selectMonth12ButtonCssClass: '',
},
holidaysDateNumbers: number[] = [],
disabledDatesNumber: number[] = [],
specialDatesNumber: number[] = [],
disableBeforeDateTimeJson = disabledDateObj[0],
disableAfterDateTimeJson = disabledDateObj[1],
previousYearButtonDisabledAttribute = '',
previousMonthButtonDisabledAttribute = '',
selectYearButtonDisabledAttribute = '',
nextMonthButtonDisabledAttribute = '',
nextYearButtonDisabledAttribute = '',
isTrAppended = false;
if (setting.isGregorian) {
dateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJson1(selectedDateToShowTemp);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJson1(new Date());
firstWeekDayNumber = new Date(dateTimeToShowJson.year, dateTimeToShowJson.month - 1, 1).getDay();
selectedDateNumber = !selectedDateTime ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(selectedDateTime));
numberOfDaysInCurrentMonth = MdsPersianDateTimePicker.getDaysInMonth(dateTimeToShowJson.year, dateTimeToShowJson.month - 1);
numberOfDaysInPreviousMonth = MdsPersianDateTimePicker.getDaysInMonth(dateTimeToShowJson.year, dateTimeToShowJson.month - 2);
previousMonthDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(MdsPersianDateTimePicker.getLastDayDateOfPreviousMonth(selectedDateToShowTemp, true)));
nextMonthDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(MdsPersianDateTimePicker.getFirstDayDateOfNextMonth(selectedDateToShowTemp, true)));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
previousYearDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(new Date(selectedDateToShowTemp.setFullYear(selectedDateToShowTemp.getFullYear() - 1))));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
nextYearDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(new Date(selectedDateToShowTemp.setFullYear(selectedDateToShowTemp.getFullYear() + 1))));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
rangeSelectorStartDateNumber = !setting.rangeSelector || !rangeSelectorStartDate ? 0 : MdsPersianDateTimePicker.convertToNumber3(rangeSelectorStartDate);
rangeSelectorEndDateNumber = !setting.rangeSelector || !rangeSelectorEndDate ? 0 : MdsPersianDateTimePicker.convertToNumber3(rangeSelectorEndDate);
for (i = 1; i <= 12; i++) {
monthsDateNumberAndAttr['month' + i.toString() + 'DateNumber'] = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(new Date(selectedDateToShowTemp.setMonth(i - 1))));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
}
for (i = 0; i < setting.holidays.length; i++) {
holidaysDateNumbers.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(setting.holidays[i])));
}
for (i = 0; i < setting.disabledDates.length; i++) {
disabledDatesNumber.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(setting.disabledDates[i])));
}
for (i = 0; i < setting.specialDates.length; i++) {
specialDatesNumber.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJson1(setting.specialDates[i])));
}
} else {
dateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(selectedDateToShowTemp);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(new Date());
firstWeekDayNumber = MdsPersianDateTimePicker.getDateTimeJsonPersian2(dateTimeToShowJson.year, dateTimeToShowJson.month, 1, 0, 0, 0).dayOfWeek;
selectedDateNumber = !selectedDateTime ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(selectedDateTime));
numberOfDaysInCurrentMonth = MdsPersianDateTimePicker.getDaysInMonthPersian(dateTimeToShowJson.year, dateTimeToShowJson.month);
numberOfDaysInPreviousMonth = MdsPersianDateTimePicker.getDaysInMonthPersian(dateTimeToShowJson.year - 1, dateTimeToShowJson.month - 1);
previousMonthDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(MdsPersianDateTimePicker.getLastDayDateOfPreviousMonth(selectedDateToShowTemp, false)));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
nextMonthDateNumber = MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(MdsPersianDateTimePicker.getFirstDayDateOfNextMonth(selectedDateToShowTemp, false)));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
previousYearDateNumber = MdsPersianDateTimePicker.convertToNumber2(dateTimeToShowJson.year - 1, dateTimeToShowJson.month, dateTimeToShowJson.day);
nextYearDateNumber = MdsPersianDateTimePicker.convertToNumber2(dateTimeToShowJson.year + 1, dateTimeToShowJson.month, dateTimeToShowJson.day);
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
rangeSelectorStartDateNumber = !setting.rangeSelector || !rangeSelectorStartDate ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(rangeSelectorStartDate));
rangeSelectorEndDateNumber = !setting.rangeSelector || !rangeSelectorEndDate ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(rangeSelectorEndDate));
for (i = 1; i <= 12; i++) {
monthsDateNumberAndAttr['month' + i.toString() + 'DateNumber'] = MdsPersianDateTimePicker.convertToNumber2(dateTimeToShowJson.year, i, MdsPersianDateTimePicker.getDaysInMonthPersian(dateTimeToShowJson.year, i));
selectedDateToShowTemp = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
}
for (i = 0; i < setting.holidays.length; i++) {
holidaysDateNumbers.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.holidays[i])));
}
for (i = 0; i < setting.disabledDates.length; i++) {
disabledDatesNumber.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.disabledDates[i])));
}
for (i = 0; i < setting.specialDates.length; i++) {
specialDatesNumber.push(MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.specialDates[i])));
}
}
let todayDateNumber = MdsPersianDateTimePicker.convertToNumber1(todayDateTimeJson);
let selectedYear = setting.isGregorian ? dateTimeToShowJson.year.toString() : MdsPersianDateTimePicker.toPersianNumber(dateTimeToShowJson.year);
let disableBeforeDateTimeNumber = !disableBeforeDateTimeJson ? undefined : MdsPersianDateTimePicker.convertToNumber1(disableBeforeDateTimeJson);
let disableAfterDateTimeNumber = !disableAfterDateTimeJson ? undefined : MdsPersianDateTimePicker.convertToNumber1(disableAfterDateTimeJson);
let currentMonthInfo = MdsPersianDateTimePicker.getMonthName(dateTimeToShowJson.month - 1, setting.isGregorian) + ' ' + dateTimeToShowJson.year.toString();
if (!setting.isGregorian)
currentMonthInfo = MdsPersianDateTimePicker.toPersianNumber(currentMonthInfo);
selectedMonthName = MdsPersianDateTimePicker.getMonthName(dateTimeToShowJson.month - 1, setting.isGregorian);
if (setting.yearOffset <= 0) {
previousYearButtonDisabledAttribute = 'disabled';
nextYearButtonDisabledAttribute = 'disabled';
selectYearButtonDisabledAttribute = 'disabled';
}
// روز های ماه قبل
if (!setting.isGregorian && firstWeekDayNumber != 6 || setting.isGregorian && firstWeekDayNumber != 0) {
if (setting.isGregorian)
firstWeekDayNumber--;
let previousMonthDateTimeJson = MdsPersianDateTimePicker.addMonthToDateTimeJson(dateTimeToShowJson, -1, setting.isGregorian);
for (i = numberOfDaysInPreviousMonth - firstWeekDayNumber; i <= numberOfDaysInPreviousMonth; i++) {
currentDateNumber = MdsPersianDateTimePicker.convertToNumber2(previousMonthDateTimeJson.year, previousMonthDateTimeJson.month, i);
dayNumberInString = setting.isGregorian ? MdsPersianDateTimePicker.zeroPad(i) : MdsPersianDateTimePicker.toPersianNumber(MdsPersianDateTimePicker.zeroPad(i));
td = document.createElement('TD');
td.setAttribute('data-nm', '');
td.setAttribute('data-number', currentDateNumber.toString());
td.innerHTML = dayNumberInString;
if (setting.rangeSelector) {
if (currentDateNumber == rangeSelectorStartDateNumber || currentDateNumber == rangeSelectorEndDateNumber)
td.classList.add('selected-range-days-start-end');
else if (rangeSelectorStartDateNumber > 0 && rangeSelectorEndDateNumber > 0 && currentDateNumber > rangeSelectorStartDateNumber && currentDateNumber < rangeSelectorEndDateNumber)
td.classList.add('selected-range-days-nm');
}
// روز جمعه
if (!setting.isGregorian && tdNumber == 6)
td.classList.add('text-danger');
// روز یکشنبه
else if (setting.isGregorian && tdNumber == 0)
td.classList.add('text-danger');
tr.appendChild(td);
cellNumber++;
tdNumber++;
if (tdNumber >= 7) {
tdNumber = 0;
daysHtml += tr.outerHTML;
isTrAppended = true;
tr = document.createElement('TR');
}
}
}
// روزهای ماه جاری
for (i = 1; i <= numberOfDaysInCurrentMonth; i++) {
if (tdNumber >= 7) {
tdNumber = 0;
daysHtml += tr.outerHTML;
isTrAppended = true;
tr = document.createElement('TR');
}
// عدد روز
currentDateNumber = MdsPersianDateTimePicker.convertToNumber2(dateTimeToShowJson.year, dateTimeToShowJson.month, i);
dayNumberInString = setting.isGregorian ? MdsPersianDateTimePicker.zeroPad(i) : MdsPersianDateTimePicker.toPersianNumber(MdsPersianDateTimePicker.zeroPad(i));
td = document.createElement('TD');
td.setAttribute('data-day', '');
td.setAttribute('data-number', currentDateNumber.toString());
td.innerHTML = dayNumberInString;
// امروز
if (currentDateNumber == todayDateNumber) {
td.setAttribute('data-today', '');
td.setAttribute('title', setting.isGregorian ? MdsPersianDateTimePicker.todayText : MdsPersianDateTimePicker.todayTextPersian);
// اگر نام روز هفته انتخاب شده در تکس باکس قبل از تاریخ امروز باشد
// نباید دیگر نام روز هفته تغییر کند
if (!dayOfWeek)
dayOfWeek = MdsPersianDateTimePicker.getWeekDayName(tdNumber - 1 < 0 ? 0 : tdNumber - 1, setting.isGregorian);
}
// روز از قبل انتخاب شده
if (!setting.rangeSelector && selectedDateNumber == currentDateNumber) {
td.setAttribute('data-mds-dtp-selected-day', '');
dayOfWeek = MdsPersianDateTimePicker.getWeekDayName(tdNumber - 1 < 0 ? 0 : tdNumber - 1, setting.isGregorian);
}
// روزهای تعطیل
for (j = 0; j < holidaysDateNumbers.length; j++) {
if (holidaysDateNumbers[j] != currentDateNumber) continue;
td.classList.add('text-danger');
break;
}
// روز جمعه شمسی
if (!setting.isGregorian && tdNumber == 6) {
td.classList.add('text-danger');
}
// روز یکشنبه میلادی
else if (setting.isGregorian && tdNumber == 0) {
td.classList.add('text-danger');
}
// روزهای غیر فعال شده
if (setting.disableBeforeToday) {
if (currentDateNumber < todayDateNumber) td.setAttribute('disabled', '');
if (nextMonthDateNumber < todayDateNumber)
nextMonthButtonDisabledAttribute = 'disabled';
if (nextYearDateNumber < todayDateNumber)
nextYearButtonDisabledAttribute = 'disabled';
if (previousMonthDateNumber < todayDateNumber)
previousMonthButtonDisabledAttribute = 'disabled';
if (previousYearDateNumber < todayDateNumber)
previousYearButtonDisabledAttribute = 'disabled';
for (j = 1; j <= 12; j++) {
if (monthsDateNumberAndAttr['month' + j.toString() + 'DateNumber'] < todayDateNumber)
monthsDateNumberAndAttr['selectMonth' + j.toString() + 'ButtonCssClass'] = 'disabled';
}
}
if (setting.disableAfterToday) {
if (currentDateNumber > todayDateNumber) td.setAttribute('disabled', '');
if (nextMonthDateNumber > todayDateNumber)
nextMonthButtonDisabledAttribute = 'disabled';
if (nextYearDateNumber > todayDateNumber)
nextYearButtonDisabledAttribute = 'disabled';
if (previousMonthDateNumber > todayDateNumber)
previousMonthButtonDisabledAttribute = 'disabled';
if (previousYearDateNumber > todayDateNumber)
previousYearButtonDisabledAttribute = 'disabled';
for (j = 1; j <= 12; j++) {
if (monthsDateNumberAndAttr['month' + j.toString() + 'DateNumber'] > todayDateNumber)
monthsDateNumberAndAttr['selectMonth' + j.toString() + 'ButtonCssClass'] = 'disabled';
}
}
if (disableAfterDateTimeNumber) {
if (currentDateNumber > disableAfterDateTimeNumber) td.setAttribute('disabled', '');
if (nextMonthDateNumber > disableAfterDateTimeNumber)
nextMonthButtonDisabledAttribute = 'disabled';
if (nextYearDateNumber > disableAfterDateTimeNumber)
nextYearButtonDisabledAttribute = 'disabled';
if (previousMonthDateNumber > disableAfterDateTimeNumber)
previousMonthButtonDisabledAttribute = 'disabled';
if (previousYearDateNumber > disableAfterDateTimeNumber)
previousYearButtonDisabledAttribute = 'disabled';
for (j = 1; j <= 12; j++) {
if (monthsDateNumberAndAttr['month' + j.toString() + 'DateNumber'] > disableAfterDateTimeNumber)
monthsDateNumberAndAttr['selectMonth' + j.toString() + 'ButtonCssClass'] = 'disabled';
}
}
if (disableBeforeDateTimeNumber) {
if (currentDateNumber < disableBeforeDateTimeNumber) td.setAttribute('disabled', '');
if (nextMonthDateNumber < disableBeforeDateTimeNumber)
nextMonthButtonDisabledAttribute = 'disabled';
if (nextYearDateNumber < disableBeforeDateTimeNumber)
nextYearButtonDisabledAttribute = 'disabled';
if (previousMonthDateNumber < disableBeforeDateTimeNumber)
previousMonthButtonDisabledAttribute = 'disabled';
if (previousYearDateNumber < disableBeforeDateTimeNumber)
previousYearButtonDisabledAttribute = 'disabled';
for (j = 1; j <= 12; j++) {
if (monthsDateNumberAndAttr['month' + j.toString() + 'DateNumber'] < disableBeforeDateTimeNumber)
monthsDateNumberAndAttr['selectMonth' + j.toString() + 'ButtonCssClass'] = 'disabled';
}
}
for (j = 0; j < disabledDatesNumber.length; j++) {
if (currentDateNumber == disabledDatesNumber[j])
td.setAttribute('disabled', '');
}
for (j = 0; j < specialDatesNumber.length; j++) {
if (currentDateNumber == specialDatesNumber[j])
td.setAttribute('data-special-date', '');
}
if (setting.disabledDays != null && setting.disabledDays.length > 0 && setting.disabledDays.indexOf(tdNumber) >= 0) {
td.setAttribute('disabled', '');
}
// \\
if (setting.rangeSelector) {
if (currentDateNumber == rangeSelectorStartDateNumber || currentDateNumber == rangeSelectorEndDateNumber)
td.classList.add('selected-range-days-start-end');
else if (rangeSelectorStartDateNumber > 0 && rangeSelectorEndDateNumber > 0 && currentDateNumber > rangeSelectorStartDateNumber && currentDateNumber < rangeSelectorEndDateNumber)
td.classList.add('selected-range-days');
}
tr.appendChild(td);
isTrAppended = false;
tdNumber++;
cellNumber++;
}
if (tdNumber >= 7) {
tdNumber = 0;
daysHtml += tr.outerHTML;
isTrAppended = true;
tr = document.createElement('TR');
}
// روزهای ماه بعد
let nextMonthDateTimeJson = MdsPersianDateTimePicker.addMonthToDateTimeJson(dateTimeToShowJson, 1, setting.isGregorian);
for (i = 1; i <= 42 - cellNumber; i++) {
dayNumberInString = setting.isGregorian ? MdsPersianDateTimePicker.zeroPad(i) : MdsPersianDateTimePicker.toPersianNumber(MdsPersianDateTimePicker.zeroPad(i));
currentDateNumber = MdsPersianDateTimePicker.convertToNumber2(nextMonthDateTimeJson.year, nextMonthDateTimeJson.month, i);
td = document.createElement('TD');
td.setAttribute('data-nm', '');
td.setAttribute('data-number', currentDateNumber.toString());
td.innerHTML = dayNumberInString;
if (setting.rangeSelector) {
if (currentDateNumber == rangeSelectorStartDateNumber || currentDateNumber == rangeSelectorEndDateNumber)
td.classList.add('selected-range-days-start-end');
else if (rangeSelectorStartDateNumber > 0 && rangeSelectorEndDateNumber > 0 && currentDateNumber > rangeSelectorStartDateNumber && currentDateNumber < rangeSelectorEndDateNumber)
td.classList.add('selected-range-days-nm');
}
// روز جمعه
if (!setting.isGregorian && tdNumber == 6)
td.classList.add('text-danger');
// روز یکشنبه
else if (setting.isGregorian && tdNumber == 0)
td.classList.add('text-danger');
tr.appendChild(td);
tdNumber++;
if (tdNumber >= 7) {
tdNumber = 0;
daysHtml += tr.outerHTML;
isTrAppended = true;
tr = document.createElement('TR');
}
}
if (!isTrAppended) {
daysHtml += tr.outerHTML;
isTrAppended = true;
}
html = html.replace(/\{\{currentMonthInfo\}\}/img, currentMonthInfo);
html = html.replace(/\{\{selectedYear\}\}/img, selectedYear);
html = html.replace(/\{\{selectedMonthName\}\}/img, selectedMonthName);
html = html.replace(/\{\{daysHtml\}\}/img, daysHtml);
html = html.replace(/\{\{previousYearButtonDisabledAttribute\}\}/img, previousYearButtonDisabledAttribute);
html = html.replace(/\{\{previousYearButtonDateNumber\}\}/img, previousYearDateNumber.toString());
html = html.replace(/\{\{previousMonthButtonDisabledAttribute\}\}/img, previousMonthButtonDisabledAttribute);
html = html.replace(/\{\{previousMonthButtonDateNumber\}\}/img, previousMonthDateNumber.toString());
html = html.replace(/\{\{selectYearButtonDisabledAttribute\}\}/img, selectYearButtonDisabledAttribute);
html = html.replace(/\{\{nextMonthButtonDisabledAttribute\}\}/img, nextMonthButtonDisabledAttribute);
html = html.replace(/\{\{nextMonthButtonDateNumber\}\}/img, nextMonthDateNumber.toString());
html = html.replace(/\{\{nextYearButtonDisabledAttribute\}\}/img, nextYearButtonDisabledAttribute);
html = html.replace(/\{\{nextYearButtonDateNumber\}\}/img, nextYearDateNumber.toString());
html = html.replace(/\{\{dropDownMenuMonth1DateNumber\}\}/img, monthsDateNumberAndAttr.month1DateNumber);
html = html.replace(/\{\{dropDownMenuMonth2DateNumber\}\}/img, monthsDateNumberAndAttr.month2DateNumber);
html = html.replace(/\{\{dropDownMenuMonth3DateNumber\}\}/img, monthsDateNumberAndAttr.month3DateNumber);
html = html.replace(/\{\{dropDownMenuMonth4DateNumber\}\}/img, monthsDateNumberAndAttr.month4DateNumber);
html = html.replace(/\{\{dropDownMenuMonth5DateNumber\}\}/img, monthsDateNumberAndAttr.month5DateNumber);
html = html.replace(/\{\{dropDownMenuMonth6DateNumber\}\}/img, monthsDateNumberAndAttr.month6DateNumber);
html = html.replace(/\{\{dropDownMenuMonth7DateNumber\}\}/img, monthsDateNumberAndAttr.month7DateNumber);
html = html.replace(/\{\{dropDownMenuMonth8DateNumber\}\}/img, monthsDateNumberAndAttr.month8DateNumber);
html = html.replace(/\{\{dropDownMenuMonth9DateNumber\}\}/img, monthsDateNumberAndAttr.month9DateNumber);
html = html.replace(/\{\{dropDownMenuMonth10DateNumber\}\}/img, monthsDateNumberAndAttr.month10DateNumber);
html = html.replace(/\{\{dropDownMenuMonth11DateNumber\}\}/img, monthsDateNumberAndAttr.month11DateNumber);
html = html.replace(/\{\{dropDownMenuMonth12DateNumber\}\}/img, monthsDateNumberAndAttr.month12DateNumber);
html = html.replace(/\{\{selectMonth1ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth1ButtonCssClass);
html = html.replace(/\{\{selectMonth2ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth2ButtonCssClass);
html = html.replace(/\{\{selectMonth3ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth3ButtonCssClass);
html = html.replace(/\{\{selectMonth4ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth4ButtonCssClass);
html = html.replace(/\{\{selectMonth5ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth5ButtonCssClass);
html = html.replace(/\{\{selectMonth6ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth6ButtonCssClass);
html = html.replace(/\{\{selectMonth7ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth7ButtonCssClass);
html = html.replace(/\{\{selectMonth8ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth8ButtonCssClass);
html = html.replace(/\{\{selectMonth9ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth9ButtonCssClass);
html = html.replace(/\{\{selectMonth10ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth10ButtonCssClass);
html = html.replace(/\{\{selectMonth11ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth11ButtonCssClass);
html = html.replace(/\{\{selectMonth12ButtonCssClass\}\}/img, monthsDateNumberAndAttr.selectMonth12ButtonCssClass);
return html;
}
private hideYearsBox = (element: Element, setting: MdsPersianDateTimePickerSetting): void => {
if (setting.inLine) {
const dtpInLine = element.closest('[data-mds-dtp-guid]');
if (dtpInLine == null) return;
const dtpInlineHeaderElement = dtpInLine.querySelector('[mds-dtp-inline-header]');
if (this.tempTitleString && dtpInlineHeaderElement != null)
dtpInlineHeaderElement.innerHTML = this.tempTitleString;
const yearListBoxElement = dtpInLine.querySelector('[data-mds-dtp-year-list-box]');
if (yearListBoxElement != null) {
yearListBoxElement.classList.add('w-0');
yearListBoxElement.innerHTML = '';
}
const inlineYearsContainerElement = dtpInLine.querySelector('[data-name="dtp-years-container"]');
if (inlineYearsContainerElement != null) {
inlineYearsContainerElement.classList.add('w-0');
inlineYearsContainerElement.innerHTML = '';
}
dtpInLine.classList.remove('overflow-hidden');
} else {
const popoverOrModalElement = setting.modalMode ? this.getModal() : this.getPopover(element);
if (popoverOrModalElement == null) return;
if (this.tempTitleString) {
if (setting.modalMode)
popoverOrModalElement.querySelector('[data-mds-dtp-title] .modal-title')!.innerHTML = this.tempTitleString;
else {
popoverOrModalElement.querySelector('[data-mds-dtp-title]')!.innerHTML = this.tempTitleString;
}
popoverOrModalElement.querySelector('[data-name="mds-dtp-body"]')!.removeAttribute('hidden');
}
const yearListBox = popoverOrModalElement.querySelector('[data-mds-dtp-year-list-box]');
yearListBox!.classList.add('w-0');
yearListBox!.innerHTML = '';
}
}
private showYearsBox = (element: Element): void => {
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) {
return;
}
const setting = instance.setting;
const mdDatePickerContainer = setting.inLine ? element.closest('[data-mds-dtp-guid]') : element.closest('[data-mds-dtp]');
if (mdDatePickerContainer == null) return;
this.tempTitleString = setting.inLine
? mdDatePickerContainer.querySelector('[mds-dtp-inline-header]')!.textContent!.trim()
: mdDatePickerContainer.querySelector('[data-mds-dtp-title]')!.textContent!.trim();
const yearsToSelectObject = this.getYearsBoxBodyHtml(setting, 0);
const dateTimePickerYearsToSelectHtml = yearsToSelectObject.html;
const dateTimePickerYearsToSelectContainer = mdDatePickerContainer.querySelector('[data-mds-dtp-year-list-box]');
this.setPopoverHeaderHtml(element, setting, this.getYearsBoxHeaderHtml(setting, yearsToSelectObject.yearStart, yearsToSelectObject.yearEnd));
dateTimePickerYearsToSelectContainer!.innerHTML = dateTimePickerYearsToSelectHtml;
dateTimePickerYearsToSelectContainer!.classList.remove('w-0');
if (setting.inLine) {
mdDatePickerContainer.classList.add('overflow-hidden')
dateTimePickerYearsToSelectContainer!.classList.add('inline');
} else if (setting.modalMode) {
mdDatePickerContainer.querySelector('[data-name="mds-dtp-body"]')!.setAttribute('hidden', '');
} else {
dateTimePickerYearsToSelectContainer!.classList.remove('inline');
}
}
private changeYearList = (element: Element): void => {
// کلیک روی دکمه های عوض کردن رنج سال انتخابی
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) {
return;
}
const setting = instance.setting;
const isNext = element.getAttribute('data-year-range-button-change') == '1';
const yearStart = Number(element.getAttribute('data-year'));
const yearsToSelectObject = this.getYearsBoxBodyHtml(setting, isNext ? yearStart : yearStart - setting.yearOffset * 2);
if (setting.inLine)
element.closest('[data-mds-dtp-guid]')!.querySelector('[data-mds-dtp-year-list-box]')!.innerHTML = yearsToSelectObject.html;
else
element.closest('[data-mds-dtp]')!.querySelector('[data-mds-dtp-year-list-box]')!.innerHTML = yearsToSelectObject.html;
this.setPopoverHeaderHtml(element, setting, this.getYearsBoxHeaderHtml(setting, yearsToSelectObject.yearStart, yearsToSelectObject.yearEnd));
}
private getPopoverHeaderTitle(setting: MdsPersianDateTimePickerSetting): string {
let selectedDateToShowJson: GetDateTimeJson1;
let title = '';
if (setting.isGregorian) {
selectedDateToShowJson = MdsPersianDateTimePicker.getDateTimeJson1(setting.selectedDateToShow);
} else {
selectedDateToShowJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(setting.selectedDateToShow);
}
if (setting.rangeSelector) {
const startDate = MdsPersianDateTimePicker.addMonthToDateTime(setting.selectedDateToShow, -setting.rangeSelectorMonthsToShow[0], setting.isGregorian);
const endDate = MdsPersianDateTimePicker.addMonthToDateTime(setting.selectedDateToShow, setting.rangeSelectorMonthsToShow[1], setting.isGregorian);
let statDateJson: GetDateTimeJson1;
let endDateJson: GetDateTimeJson1;
if (setting.isGregorian) {
statDateJson = MdsPersianDateTimePicker.getDateTimeJson1(startDate);
endDateJson = MdsPersianDateTimePicker.getDateTimeJson1(endDate);
} else {
statDateJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(startDate);
endDateJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(endDate);
}
const startMonthName = MdsPersianDateTimePicker.getMonthName(statDateJson.month - 1, setting.isGregorian);
const endMonthName = MdsPersianDateTimePicker.getMonthName(endDateJson.month - 1, setting.isGregorian);
title = `${startMonthName} ${statDateJson.year} - ${endMonthName} ${endDateJson.year}`;
}
else
title = `${MdsPersianDateTimePicker.getMonthName(selectedDateToShowJson.month - 1, setting.isGregorian)} ${selectedDateToShowJson.year}`;
if (!setting.isGregorian)
title = MdsPersianDateTimePicker.toPersianNumber(title);
return title;
}
private setPopoverHeaderHtml = (element: Element, setting: MdsPersianDateTimePickerSetting, htmlString: string): void => {
// element = المانی که روی آن فعالیتی انجام شده و باید عنوان تقویم آن عوض شود
if (this.bsPopover != null) {
const popoverElement = this.getPopover(element);
if (popoverElement == null) return;
popoverElement.querySelector('[data-mds-dtp-title]')!.innerHTML = htmlString;
} else if (setting.inLine) {
let inlineTitleBox = element.closest('[data-mds-dtp-guid]')!.querySelector('[data-name="dtp-years-container"]')!;
inlineTitleBox.innerHTML = htmlString;
inlineTitleBox.classList.remove('w-0');
}
else if (setting.modalMode) {
let inlineTitleBox = element.closest('[data-mds-dtp-guid]')!.querySelector('[data-mds-dtp-title] .modal-title')!;
inlineTitleBox.innerHTML = htmlString;
}
}
private getDateTimePickerBodyHtml(setting: MdsPersianDateTimePickerSetting): string {
let selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow);
let html = MdsPersianDateTimePicker.dateTimePickerHtmlTemplate;
html = html.replace(/\{\{inlineAttr\}\}/img, setting.inLine ? 'data-inline' : '');
html = html.replace(/\{\{rtlCssClass\}\}/img, setting.isGregorian ? '' : 'rtl');
html = html.replace(/\{\{selectedDateStringAttribute\}\}/img, setting.inLine ? '' : 'hidden');
html = html.replace(/\{\{goTodayText\}\}/img, setting.isGregorian ? MdsPersianDateTimePicker.goTodayText : MdsPersianDateTimePicker.goTodayTextPersian);
html = html.replace(/\{\{timePickerAttribute\}\}/img, setting.enableTimePicker ? '' : 'hidden');
const disabledDays = MdsPersianDateTimePicker.getDisabledDateObject(setting);
let title = '';
let todayDateString = '';
let todayDateTimeJson: GetDateTimeJson1;
let selectedDateTimeToShowJson: GetDateTimeJson1;
let disableBeforeDateTimeJson: GetDateTimeJson1 | null = disabledDays[0];
let disableAfterDateTimeJson: GetDateTimeJson1 | null = disabledDays[1];
if (setting.isGregorian) {
selectedDateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJson1(selectedDateToShow);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJson1(new Date());
} else {
selectedDateTimeToShowJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(selectedDateToShow);
todayDateTimeJson = MdsPersianDateTimePicker.getDateTimeJsonPersian1(new Date());
}
title = this.getPopoverHeaderTitle(setting);
todayDateString = `${setting.isGregorian ? 'Today,' : 'امروز،'} ${todayDateTimeJson.day} ${MdsPersianDateTimePicker.getMonthName(todayDateTimeJson.month - 1, setting.isGregorian)} ${todayDateTimeJson.year}`;
if (!setting.isGregorian) {
todayDateString = MdsPersianDateTimePicker.toPersianNumber(todayDateString);
}
if (disableAfterDateTimeJson != undefined && disableAfterDateTimeJson.year <= selectedDateTimeToShowJson.year && disableAfterDateTimeJson.month < selectedDateTimeToShowJson.month)
selectedDateToShow = setting.isGregorian ? new Date(disableAfterDateTimeJson.year, disableAfterDateTimeJson.month - 1, 1) : MdsPersianDateTimePicker.getDateTime1(disableAfterDateTimeJson.year, disableAfterDateTimeJson.month, disableAfterDateTimeJson.day);
if (disableBeforeDateTimeJson != undefined && disableBeforeDateTimeJson.year >= selectedDateTimeToShowJson.year && disableBeforeDateTimeJson.month > selectedDateTimeToShowJson.month)
selectedDateToShow = setting.isGregorian ? new Date(disableBeforeDateTimeJson.year, disableBeforeDateTimeJson.month - 1, 1) : MdsPersianDateTimePicker.getDateTime1(disableBeforeDateTimeJson.year, disableBeforeDateTimeJson.month, disableBeforeDateTimeJson.day);
let monthsTdHtml = '';
// let tempSelectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
let numberOfNextMonths = setting.rangeSelectorMonthsToShow[1] <= 0 ? 0 : setting.rangeSelectorMonthsToShow[1];
let numberOfPrevMonths = setting.rangeSelectorMonthsToShow[0] <= 0 ? 0 : setting.rangeSelectorMonthsToShow[0];
numberOfPrevMonths *= -1;
for (let i1 = numberOfPrevMonths; i1 < 0; i1++) {
setting.selectedDateToShow = MdsPersianDateTimePicker.addMonthToDateTime(MdsPersianDateTimePicker.getClonedDate(selectedDateToShow), i1, setting.isGregorian);
monthsTdHtml += this.getDateTimePickerMonthHtml(setting, false, true);
}
setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
monthsTdHtml += this.getDateTimePickerMonthHtml(setting, false, false);
for (let i2 = 1; i2 <= numberOfNextMonths; i2++) {
setting.selectedDateToShow = MdsPersianDateTimePicker.addMonthToDateTime(MdsPersianDateTimePicker.getClonedDate(selectedDateToShow), i2, setting.isGregorian);
monthsTdHtml += this.getDateTimePickerMonthHtml(setting, true, false);
}
// setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
let totalMonthNumberToShow = Math.abs(numberOfPrevMonths) + 1 + numberOfNextMonths;
let monthTdStyle = totalMonthNumberToShow > 1 ? 'width: ' + (100 / totalMonthNumberToShow).toString() + '%;' : '';
monthsTdHtml = monthsTdHtml.replace(/\{\{monthTdStyle\}\}/img, monthTdStyle);
html = html.replace(/\{\{dtpInlineHeader\}\}/img, title);
html = html.replace(/\{\{todayDateString\}\}/img, todayDateString);
html = html.replace(/\{\{time\}\}/img, `${MdsPersianDateTimePicker.zeroPad(selectedDateTimeToShowJson.hour)}:${MdsPersianDateTimePicker.zeroPad(selectedDateTimeToShowJson.minute)}`);
html = html.replace(/\{\{monthsTdHtml\}\}/img, monthsTdHtml);
return html;
}
private updateCalendarBodyHtml = (element: Element, setting: MdsPersianDateTimePickerSetting, updatePopoverContent = false): void => {
const calendarHtml = this.getDateTimePickerBodyHtml(setting);
const dtpInlineHeader = calendarHtml.match(/]*>(.*?)<\/th>/img)![0];
this.tempTitleString = dtpInlineHeader;
if (!setting.inLine && updatePopoverContent && !setting.modalMode) {
const popover = this.getBsPopoverInstance();
if (!popover) {
console.error("mds.bs.datetimepicker: `BsPopoverInstance` is null!");
return;
}
setTimeout(() => {
popover.setContent({
'.popover-header': dtpInlineHeader,
'.popover-body': calendarHtml
});
}, 100);
return;
}
let containerElement = element.closest('[data-name="mds-dtp-body"]');
if (containerElement == null) {
containerElement = element.closest('[data-mds-dtp-guid]');
if (containerElement == null) {
console.error("mds.bs.datetimepicker: `data-mds-dtp-guid` element not found !")
return;
}
if (setting.modalMode)
containerElement = containerElement.querySelector('[data-name="mds-dtp-body"]');
}
if (!containerElement) {
console.error("mds.bs.datetimepicker: `data-mds-dtp-guid` element not found!")
return;
}
this.setPopoverHeaderHtml(element, setting, dtpInlineHeader.trim());
containerElement.innerHTML = calendarHtml;
this.hideYearsBox(element, setting);
this.enableEvents();
this.enableInLineEvents();
}
private changeMonth = (element: Element): void => {
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance || instance.setting.disabled)
return;
const dateNumber = Number(element.getAttribute('data-number'));
const setting = instance.setting;
let selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow);
selectedDateToShow = MdsPersianDateTimePicker.getDateTime4(dateNumber, selectedDateToShow, setting.isGregorian);
setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
MdsPersianDateTimePickerData.set(instance.guid, instance);
this.updateCalendarBodyHtml(element, setting);
if (setting.calendarViewOnChange != undefined)
setting.calendarViewOnChange(selectedDateToShow);
}
private selectDay = (element: Element): void => {
// کلیک روی روزها
// انتخاب روز
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) return;
if (instance.setting.disabled || element.getAttribute('disabled') != undefined)
return;
let dateNumber = Number(element.getAttribute('data-number'));
const setting = instance.setting;
const disabled = element.getAttribute('disabled') != undefined;
if (setting.selectedDate != undefined && !setting.enableTimePicker) {
setting.selectedDate.setHours(0);
setting.selectedDate.setMinutes(0);
setting.selectedDate.setSeconds(0);
}
let selectedDateJson = !setting.selectedDate ? null : MdsPersianDateTimePicker.getDateTimeJson1(setting.selectedDate);
let selectedDateToShow = !setting.selectedDateToShow ? new Date() : MdsPersianDateTimePicker.getClonedDate(setting.selectedDateToShow);
let selectedDateToShowJson = MdsPersianDateTimePicker.getDateTimeJson1(selectedDateToShow);
if (disabled) {
if (setting.onDayClick != undefined) setting.onDayClick(setting);
return;
}
selectedDateToShow = MdsPersianDateTimePicker.getDateTime4(dateNumber, selectedDateToShow, setting.isGregorian);
if (setting.rangeSelector) { // اگر رنج سلکتور فعال بود
if (setting.rangeSelectorStartDate != null && setting.rangeSelectorEndDate != null) {
setting.selectedRangeDate = [];
setting.rangeSelectorStartDate = null;
setting.rangeSelectorEndDate = null;
let closestSelector = '[data-mds-dtp]';
if (setting.inLine)
closestSelector = '[data-mds-dtp-guid]';
element.closest(closestSelector)?.querySelectorAll('td.selected-range-days-start-end,td.selected-range-days')
.forEach(e => {
e.classList.remove('selected-range-days');
e.classList.remove('selected-range-days-start-end');
});
}
if (setting.rangeSelectorStartDate == undefined) {
element.classList.add('selected-range-days-start-end');
setting.rangeSelectorStartDate = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
setting.selectedDate = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
} else if (setting.rangeSelectorStartDate != undefined && setting.rangeSelectorEndDate == undefined) {
if (setting.rangeSelectorStartDate.getTime() >= selectedDateToShow.getTime())
return;
element.classList.add('selected-range-days-start-end');
setting.rangeSelectorEndDate = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
MdsPersianDateTimePicker.setSelectedData(setting);
}
MdsPersianDateTimePickerData.set(instance.guid, instance);
if (setting.rangeSelectorStartDate != undefined && setting.rangeSelectorEndDate != undefined) {
setting.selectedRangeDate = [MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorStartDate), MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorEndDate)];
if (!setting.inLine)
instance.hide();
else
this.updateCalendarBodyHtml(element, setting);
}
return;
}
setting.selectedDate = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
if (setting.selectedDate != undefined && !setting.enableTimePicker) {
setting.selectedDate.setHours(0);
setting.selectedDate.setMinutes(0);
setting.selectedDate.setSeconds(0);
}
setting.selectedDateToShow = MdsPersianDateTimePicker.getClonedDate(selectedDateToShow);
if (selectedDateJson != undefined) {
if (setting.enableTimePicker) {
selectedDateJson.hour = selectedDateToShowJson.hour;
selectedDateJson.minute = selectedDateToShowJson.minute;
selectedDateJson.second = selectedDateToShowJson.second;
} else {
selectedDateJson.hour = 0;
selectedDateJson.minute = 0;
selectedDateJson.second = 0;
}
setting.selectedDate.setHours(selectedDateJson.hour);
setting.selectedDate.setMinutes(selectedDateJson.minute);
setting.selectedDate.setSeconds(selectedDateJson.second);
}
MdsPersianDateTimePickerData.set(instance.guid, instance);
MdsPersianDateTimePicker.setSelectedData(setting);
element.setAttribute('data-mds-dtp-selected-day', '');
if (setting.toDate || setting.fromDate) {
// وقتی روی روز یکی از تقویم ها کلیک می شود
// باید تقویم دیگر نیز تغییر کند و روزهایی از آن غیر فعال شود
const toDateElement = document.querySelector(`[data-mds-dtp-group="${setting.groupId}"][data-to-date]`);
const fromDateElement = document.querySelector(`[data-mds-dtp-group="${setting.groupId}"][data-from-date]`);
if (setting.fromDate && toDateElement != undefined) {
const toDateInstance = MdsPersianDateTimePicker.getInstance(toDateElement);
if (toDateInstance != null) {
if (setting.inLine)
this.updateCalendarBodyHtml(toDateElement, toDateInstance.setting);
else
toDateInstance.initializeBsPopover(toDateInstance.setting);
}
} else if (setting.toDate && fromDateElement != undefined) {
const fromDateInstance = MdsPersianDateTimePicker.getInstance(fromDateElement);
if (fromDateInstance != null) {
if (setting.inLine)
this.updateCalendarBodyHtml(fromDateElement, fromDateInstance.setting);
else
fromDateInstance.initializeBsPopover(fromDateInstance.setting);
}
} else
this.updateCalendarBodyHtml(element, setting);
} else
this.updateCalendarBodyHtml(element, setting, true);
if (setting.onDayClick != undefined)
setting.onDayClick(setting);
if (!setting.inLine) {
instance.hide();
} else {
// حذف روزهای انتخاب شده در تقویم این لاین
let dtp = element.closest(`[data-mds-dtp-guid="${this.guid}"]`);
if (!dtp)
dtp = document.querySelector(`[data-mds-dtp-guid="${this.guid}"]`);
dtp!.querySelectorAll(`[data-day]:not([data-number="${element.getAttribute('data-number')}"])`)
.forEach(e => e.removeAttribute('data-mds-dtp-selected-day'));
}
}
private hoverOnDays = (e: Event): void => {
// هاور روی روزها
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) return;
const setting = instance.setting;
if (element.getAttribute('disabled') != undefined || !setting.rangeSelector ||
(setting.rangeSelectorStartDate != undefined && setting.rangeSelectorEndDate != undefined)) return;
const dateNumber = Number(element.getAttribute('data-number'));
const allDayElements: Element[] = [].slice.call(document.querySelectorAll('td[data-day]'));
allDayElements.forEach(e => {
e.classList.remove('selected-range-days');
e.classList.remove('selected-range-days-nm');
});
const allNextOrPrevMonthDayElements: Element[] = [].slice.call(document.querySelectorAll('td[data-nm]'));
allNextOrPrevMonthDayElements.forEach(e => {
e.classList.remove('selected-range-days');
e.classList.remove('selected-range-days-nm');
});
const rangeSelectorStartDate = !setting.rangeSelectorStartDate ? undefined : MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorStartDate);
const rangeSelectorEndDate = !setting.rangeSelectorEndDate ? undefined : MdsPersianDateTimePicker.getClonedDate(setting.rangeSelectorEndDate);
let rangeSelectorStartDateNumber = 0;
let rangeSelectorEndDateNumber = 0;
if (setting.isGregorian) {
rangeSelectorStartDateNumber = !rangeSelectorStartDate ? 0 : MdsPersianDateTimePicker.convertToNumber3(rangeSelectorStartDate);
rangeSelectorEndDateNumber = !rangeSelectorEndDate ? 0 : MdsPersianDateTimePicker.convertToNumber3(rangeSelectorEndDate);
} else {
rangeSelectorStartDateNumber = !rangeSelectorStartDate ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(rangeSelectorStartDate));
rangeSelectorEndDateNumber = !rangeSelectorEndDate ? 0 : MdsPersianDateTimePicker.convertToNumber1(MdsPersianDateTimePicker.getDateTimeJsonPersian1(rangeSelectorEndDate));
}
if (rangeSelectorStartDateNumber > 0 && dateNumber > rangeSelectorStartDateNumber) {
for (var i1 = rangeSelectorStartDateNumber; i1 <= dateNumber; i1++) {
allDayElements.filter(e => e.getAttribute('data-number') == i1.toString() && e.classList.value.indexOf('selected-range-days-start-end') <= -1)
.forEach(e => e.classList.add('selected-range-days'));
allNextOrPrevMonthDayElements.filter(e => e.getAttribute('data-number') == i1.toString() && e.classList.value.indexOf('selected-range-days-start-end') <= -1)
.forEach(e => e.classList.add('selected-range-days-nm'));
}
} else if (rangeSelectorEndDateNumber > 0 && dateNumber < rangeSelectorEndDateNumber) {
for (var i2 = dateNumber; i2 <= rangeSelectorEndDateNumber; i2++) {
allDayElements.filter(e => e.getAttribute('data-number') == i2.toString() && e.classList.value.indexOf('selected-range-days-start-end') <= -1)
.forEach(e => e.classList.add('selected-range-days'));
allNextOrPrevMonthDayElements.filter(e => e.getAttribute('data-number') == i2.toString() && e.classList.value.indexOf('selected-range-days-start-end') <= -1)
.forEach(e => e.classList.add('selected-range-days-nm'));
}
}
}
private goToday = (e: Event): void => {
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance)
return;
const setting = instance.setting;
setting.selectedDateToShow = new Date();
MdsPersianDateTimePickerData.set(instance.guid, instance);
this.updateCalendarBodyHtml(element, setting);
}
private timeChanged = (e: Event): void => {
// عوض کردن ساعت
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) return;
const setting = instance.setting;
const value: string = (element).value;
if (!setting.enableTimePicker) return;
if (setting.selectedDateToShow == undefined)
setting.selectedDateToShow = new Date();
let hour = Number(value.substr(0, 2));
let minute = Number(value.substr(3, 2));
setting.selectedDateToShow = new Date(setting.selectedDateToShow.setHours(hour));
setting.selectedDateToShow = new Date(setting.selectedDateToShow.setMinutes(minute));
if (setting.selectedDate == undefined)
setting.selectedDate = new Date();
setting.selectedDate = new Date(setting.selectedDate.setHours(hour));
setting.selectedDate = new Date(setting.selectedDate.setMinutes(minute));
MdsPersianDateTimePickerData.set(instance.guid, instance);
MdsPersianDateTimePicker.setSelectedData(setting);
}
private enableMainEvents(): void {
if (this.setting.inLine) return;
if (this.bsPopover != null) {
this.element.addEventListener('shown.bs.popover', this.popoverOrModalShownEvent);
this.element.addEventListener('hidden.bs.popover', this.popoverOrModalHiddenEvent);
this.element.addEventListener('inserted.bs.popover', this.popoverInsertedEvent);
this.element.addEventListener('click', this.showPopoverEvent, true);
} else if (this.bsModal != null) {
const modalElement = this.getModal();
if (modalElement == null) {
console.error("mds.bs.datetimepicker: `modalElement` not found!");
return;
}
modalElement.addEventListener('shown.bs.modal', this.popoverOrModalShownEvent);
modalElement.addEventListener('hidden.bs.modal', this.popoverOrModalHiddenEvent);
}
}
private popoverInsertedEvent = (e: Event): void => {
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) return;
const setting = instance.setting;
this.hideYearsBox(element, setting);
}
private popoverOrModalShownEvent = (): void => {
this.enableEvents();
}
private popoverOrModalHiddenEvent = (): void => {
this.disableEvents();
}
private enableInLineEvents(): void {
if (!this.setting.inLine) return;
setTimeout(() => {
const dtp = document.querySelector(`[data-mds-dtp-guid="${this.guid}"]`);
if (dtp != null) {
dtp.querySelector('[data-mds-dtp-time]')?.addEventListener('change', this.timeChanged, false);
dtp.addEventListener('click', this.selectCorrectClickEvent);
dtp.querySelectorAll('[data-day]').forEach(e => e.addEventListener('mouseenter', this.hoverOnDays, true));
}
}, 100);
}
private enableEvents(): void {
if (this.setting.inLine) return;
setTimeout(() => {
document.addEventListener('click', this.selectCorrectClickEvent, false);
document.querySelector('html')!.addEventListener('click', this.hidePopoverEvent, true);
document.querySelectorAll('[data-mds-dtp-time]').forEach(e => e.addEventListener('change', this.timeChanged, false));
document.querySelectorAll('[data-mds-dtp] [data-day]').forEach(e => e.addEventListener('mouseenter', this.hoverOnDays, true));
}, 500);
}
private disableEvents(): void {
document.removeEventListener('click', this.selectCorrectClickEvent);
document.querySelector('html')!.removeEventListener('click', this.hidePopoverEvent);
document.querySelectorAll('[data-mds-dtp-time]')?.forEach(e => e.removeEventListener('change', this.timeChanged));
document.querySelectorAll('[data-mds-dtp] [data-day]').forEach(e => e.removeEventListener('mouseenter', this.hoverOnDays));
const dtp = document.querySelector(`[data-mds-dtp-guid="${this.guid}"]`);
if (dtp != null) {
dtp.removeEventListener('click', this.selectCorrectClickEvent, false);
dtp.querySelectorAll('[data-day]')?.forEach(e => e.removeEventListener('mouseenter', this.hoverOnDays, true));
}
}
private selectCorrectClickEvent = (e: Event): void => {
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance) return;
if (instance != null && (instance.setting.disabled || instance.element.getAttribute('disabled') != undefined))
return;
if (element.getAttribute('mds-pdtp-select-year-button') != null) {
instance.showYearsBox(element);
} else if (element.getAttribute('data-mds-dtp-go-today') != null) {
this.goToday(e);
} else if (element.getAttribute('data-day') != null) {
this.selectDay(element);
} else if (element.getAttribute('data-mds-hide-year-list-box')) {
this.hideYearsBox(element, instance.setting);
} else if (element.getAttribute('data-change-date-button')) {
this.changeMonth(element);
} else if (element.getAttribute('data-year-range-button-change') != null && element.getAttribute('disabled') == null) {
this.changeYearList(element);
}
}
private showPopoverEvent = (e: Event): void => {
MdsPersianDateTimePickerData.getAll().forEach(i => i.hide());
const element = e.target;
const instance = MdsPersianDateTimePicker.getInstance(element);
if (!instance || instance.setting.disabled)
return;
instance.show();
}
private hidePopoverEvent = (e: Event): void => {
const element = e.target;
if (element.tagName == 'HTML') {
MdsPersianDateTimePickerData.getAll().forEach(i => !i.setting.modalMode ? i.hide() : () => { });
return;
}
const isWithinDatePicker = element.closest('[data-mds-dtp]') != null || element.getAttribute('data-mds-dtp-guid') != null || element.getAttribute('data-mds-dtp-go-today') != null;
if (!isWithinDatePicker) {
MdsPersianDateTimePickerData.getAll().forEach(i => i.hide());
}
}
/**
* نمایش تقویم
*/
show(): void {
this.bsModal?.show();
this.bsPopover?.show();
}
/**
* مخفی کردن تقویم
*/
hide(): void {
this.bsModal?.hide();
this.bsPopover?.hide();
}
/**
* مخفی یا نمایش تقویم
*/
toggle(): void {
if (this.bsPopover == null) return;
this.bsPopover.toggle();
}
/**
* فعال کردن تقویم
*/
enable(): void {
this.setting.disabled = false;
this.element.removeAttribute("disabled");
MdsPersianDateTimePickerData.set(this.guid, this);
if (this.bsPopover != null)
this.bsPopover.enable();
}
/**
* غیر فعال کردن تقویم
*/
disable(): void {
this.setting.disabled = true;
this.element.setAttribute("disabled", '');
MdsPersianDateTimePickerData.set(this.guid, this);
if (this.bsPopover != null)
this.bsPopover.disable();
}
/**
* بروز کردن محل قرار گرفتن تقویم
*/
updatePosition(): void {
this.bsPopover?.update();
this.bsModal?.handleUpdate();
}
/**
* به روز کردن متن نمایش تاریخ روز انتخاب شده
*/
updateSelectedDateText(): void {
MdsPersianDateTimePicker.setSelectedData(this.setting);
}
/**
* از بین بردن تقویم
*/
dispose(): void {
if (this.bsPopover != null)
this.bsPopover.dispose();
if (this.bsModal != null)
this.bsModal.dispose();
this.element.removeEventListener('click', this.showPopoverEvent);
this.bsPopover = null;
this.bsModal = null;
}
/**
* دریافت اینستنس پاپ آور بوت استرپ
*/
getBsPopoverInstance(): Popover | null {
return this.bsPopover;
}
/**
* دریافت اینستنس مدال بوت استرپ
* در صورتی که آپشن modalMode را صحیح کرده باشید
*/
getBsModalInstance(): Modal | null {
return this.bsModal;
}
/**
* دریافت متن تاریخ انتخاب شده
*/
getText(): string {
return MdsPersianDateTimePicker.getSelectedDateFormatted(this.setting);
}
/**
* دریافت آبجکت تاریخ انتخاب شده
*/
getSelectedDate(): Date | null {
return this.setting.selectedDate;
}
/**
* دریافت آبجکت های تاریخ های انتخاب شده در مد رنج سلکتور
*/
getSelectedDateRange(): Date[] {
return this.setting.selectedRangeDate;
}
/**
* بروز کردن تاریخ انتخاب شده
*/
setDate(date: Date): void {
this.updateOptions({
selectedDate: date,
selectedDateToShow: date
});
}
/**
* بروز کردن تاریخ انتخاب شده با استفاده از تاریخ شمسی
*/
setDatePersian(yearPersian: number, monthPersian: number, dayPersian: number): void {
const gregorianDateJson = MdsPersianDateTimePicker.toGregorian(yearPersian, monthPersian, dayPersian);
console.log(gregorianDateJson);
const date = new Date(gregorianDateJson.gy, gregorianDateJson.gm - 1, gregorianDateJson.gd);
this.updateOptions({
selectedDate: date,
selectedDateToShow: date
});
}
/**
* بروز کردن رنج تاریخی انتخاب شده
*/
setDateRange(startDate: Date, endDate: Date): void {
this.updateOptions({
selectedDate: startDate,
selectedDateToShow: startDate,
selectedRangeDate: [startDate, endDate]
});
}
/**
* حذف تاریخ انتخاب شده
*/
clearDate(): void {
this.updateOptions({
selectedDate: null,
selectedDateToShow: new Date(),
});
}
/**
* بروز کردن تنظیمات تقویم
* @param optionName نام آپشن مورد نظر
* @param value مقدار
*/
updateOption(optionName: string, value: any): void {
if (!optionName) return;
value = MdsPersianDateTimePicker.correctOptionValue(optionName, value);
(this.setting)[optionName] = value;
MdsPersianDateTimePickerData.set(this.guid, this);
this.initializeBsPopover(this.setting);
}
/**
* بروز کردن تنظیمات تقویم
* @param options تنظیمات مورد نظر
*/
updateOptions(options: any): void {
Object.keys(options).forEach((key) => {
(this.setting)[key] = MdsPersianDateTimePicker.correctOptionValue(key, (options)[key]);
});
MdsPersianDateTimePickerData.set(this.guid, this);
this.initializeBsPopover(this.setting);
}
/**
* تبدیل آبجکت تاریخ به رشته
* @param date آبجکت تاریخ
* @param isGregorian آیا تاریخ میلادی مد نظر است یا تبدیل به شمسی شود
* @param format فرمت مورد نظر برای تبدیل تاریخ به رشته
*/
static convertDateToString = (date: Date, isGregorian: boolean, format: string): string => {
return MdsPersianDateTimePicker.getDateTimeString(!isGregorian ? MdsPersianDateTimePicker.getDateTimeJsonPersian1(date) : MdsPersianDateTimePicker.getDateTimeJson1(date), format, isGregorian, !isGregorian);
};
/**
* تبدیل آبجکت تاریخ به شمسی
* @param date آبجکت تاریخ
*/
static convertDateToJalali = (date: Date): MdsPersianDateTimePickerConvertedDateModel => {
const dateTimeJson1 = MdsPersianDateTimePicker.getDateTimeJson1(date);
const jalaliJsonModel = MdsPersianDateTimePicker.toJalali(dateTimeJson1.year, dateTimeJson1.month, dateTimeJson1.day);
return {
year: jalaliJsonModel.jy,
month: jalaliJsonModel.jm,
day: jalaliJsonModel.jd,
}
};
/**
* دریافت اینستنس تقویم از روی المانی که تقویم روی آن فعال شده است
* @param element المانی که تقویم روی آن فعال شده
* @returns اینستنس تقویم
*/
static getInstance(element: Element): MdsPersianDateTimePicker | null {
let elementGuid = element.getAttribute('data-mds-dtp-guid');
if (!elementGuid) {
elementGuid = element.closest('[data-mds-dtp-guid]')?.getAttribute('data-mds-dtp-guid') ?? null;
if (!elementGuid) {
const id = element.closest('[data-mds-dtp]')?.getAttribute('id');
if (!id)
return null;
elementGuid = document.querySelector('[aria-describedby="' + id + '"]')?.getAttribute('data-mds-dtp-guid') ?? null;
if (!elementGuid)
return null;
}
};
return MdsPersianDateTimePickerData.get(elementGuid);
}
// #endregion
}
interface GetDateTimeJson1 {
year: number,
month: number,
day: number,
hour: number,
minute: number,
second: number,
millisecond: number,
dayOfWeek: number
}
interface JalaliJsonModel {
jy: number,
jm: number,
jd: number
}
interface GregorianJsonModel {
gy: number,
gm: number,
gd: number
}
interface JalCalModel {
leap: number,
gy: number,
march: number
}
interface MdsPersianDateTimePickerYearToSelect {
yearStart: number,
yearEnd: number,
html: string
}
type PopoverPlacement = 'auto' | 'top' | 'bottom' | 'left' | 'right';
export class MdsPersianDateTimePickerSetting {
/**
* محل قرار گرفتن تقویم
*/
placement: PopoverPlacement | (() => PopoverPlacement) | undefined = 'bottom';
/**
* فعال بودن تایم پیکر
*/
enableTimePicker = false;
/**
* سلکتور نمایش روز انتخاب شده
*/
targetTextSelector = '';
/**
* سلکتور ذخیره تاریخ میلادی، برای روز انتخاب شده
*/
targetDateSelector = '';
/**
* آیا تقویم برای کنترل روز پایانی تاریخ است
*/
toDate = false;
/**
* آیا تقویم برای کنترل روز شروع تاریخ است
*/
fromDate = false;
/**
* شناسه گروه در حالتی که از
* toDate
* و
* fromDate
* استفاده شده است
*/
groupId = '';
/**
* آیا تقویم غیر فعال است؟
*/
disabled = false;
/**
* فرمت نمایش روز انتخاب شده تقویم
*/
textFormat = '';
/**
* فرمت ذخیره تاریخ میلادی انتخاب شده
*/
dateFormat = '';
/**
* آیا تقویم میلادی استفاده شود؟
*/
isGregorian = false;
/**
* آیا تقویم به صورت این لاین نمایش داده شود؟
*/
inLine = false;
/**
* تاریخ انتخاب شده
*/
selectedDate: Date | null = null;
/**
* تاریخی که نمایش تقویم از آن شروع می شود
*/
selectedDateToShow = new Date();
/**
* تعداد سال های قابل نمایش در لیست سال های قابل انتخاب
*/
yearOffset = 15;
/**
* تاریخ میلادی روزهای تعطیل
*/
holidays: Date[] = [];
/**
* تاریخ میلادی روزهای غیر فعال
*/
disabledDates: Date[] = [];
/**
* عدد روزهایی از هفته که غیر فعال هستند
*/
disabledDays: number[] = [];
/**
* تاریخ میلادی روزهای خاص
*/
specialDates: Date[] = [];
/**
* آیا روزهای قبل از امروز غیر فعال شوند؟
*/
disableBeforeToday = false;
/**
* آیا روزهای بعد از امروز غیر فعال شوند؟
*/
disableAfterToday = false;
/**
* روزهای قبل از این تاریخ غیر فعال شود
*/
disableBeforeDate: Date | null = null;
/**
* روزهای بعد از این تاریخ غیر فعال شود
*/
disableAfterDate: Date | null = null;
/**
* آیا تقویم به صورت انتخاب بازه نمایش داده شود؟
*/
rangeSelector = false;
/**
* تاریخ شروع تقویم در مد انتخاب بازه تاریخی برای نمایش
*/
rangeSelectorStartDate: Date | null = null;
/**
* تاریخ پایان تقویم در مد انتخاب بازه تاریخی برای نمایش
*/
rangeSelectorEndDate: Date | null = null;
/**
* تعداد ماه های قابل نمایش در قابلیت انتخاب بازه تاریخی
*/
rangeSelectorMonthsToShow: number[] = [0, 0];
/**
* تاریخ های انتخاب شده در مد بازه انتخابی
*/
selectedRangeDate: Date[] = [];
/**
* آیا تقویم به صورت مدال نمایش داده شود
*/
modalMode = false;
/**
* تبدیل اعداد به فارسی
*/
persianNumber = false;
/**
* رویداد عوض شدن ماه و تاریخ در دیت پیکر
* @param _ تاریخ ماه انتخابی
*/
calendarViewOnChange = (_: Date) => { };
/**
* رویداد انتخاب روز در دیت پیکر
* @param _ تمامی تنظیمات دیت پیکر
*/
onDayClick = (_: MdsPersianDateTimePickerSetting) => { }
}
export interface MdsPersianDateTimePickerConvertedDateModel {
year: number,
month: number,
day: number,
}
const MdsPersianDateTimePickerElementMap = new Map();
var MdsPersianDateTimePickerData = {
set(key: string, instance: MdsPersianDateTimePicker): void {
if (!MdsPersianDateTimePickerElementMap.has(key)) {
MdsPersianDateTimePickerElementMap.set(key, instance);
return;
}
MdsPersianDateTimePickerElementMap.set(key, instance);
},
get(key: string): MdsPersianDateTimePicker {
return MdsPersianDateTimePickerElementMap.get(key) || null;
},
getAll(): MdsPersianDateTimePicker[] {
return Array.from(MdsPersianDateTimePickerElementMap, ([_name, value]) => value);
},
remove(key: string): void {
if (!MdsPersianDateTimePickerElementMap.has(key)) {
return;
}
MdsPersianDateTimePickerElementMap.delete(key);
}
};
|