//http://t1m0n.name/air-datepicker/docs/index-ru.html - описаны все возможности declare var moment: any; $(document).ready(InitAirDateTimePickers); class LocalizedAirStrings { private _locale: 'ru' | 'en' = 'ru' private _strings = { placeholder: { times: { 'ru': 'дд.мм.гггг чч:мм', 'en': 'dd.mm.yyyy HH:MM' }, days: { 'ru': 'дд.мм.гггг', 'en': 'dd.mm.yyyy' }, month: { 'ru': 'мм.гггг', 'en': 'mm.yyyy' }, years: { 'ru': 'гггг', 'en': 'yyyy' } }, locale: { 'ru': { days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'], daysShort: ['Вос','Пон','Вто','Сре','Чет','Пят','Суб'], daysMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'], months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], today: 'Сегодня', clear: 'Очистить', }, 'en': { days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], months: ['January','February','March','April','May','June', 'July','August','September','October','November','December'], monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], today: 'Today', clear: 'Clear', } } } constructor() { this._locale = $('.page-wrapper').data('lang') || 'ru' } public get getTimes(): string { return this._strings.placeholder.times[this._locale] } public get getDays(): string { return this._strings.placeholder.days[this._locale] } public get getMonth(): string { return this._strings.placeholder.month[this._locale] } public get getYears(): string { return this._strings.placeholder.years[this._locale] } public get getLocaleStrings() { return this._strings.locale[this._locale] } } function InitAirDateTimePickers() { AirDateTimePickerInitializer.init(); } class AirDateTimePickerInitializer { private static dateMinAbsolute: Date = new Date(1920, 0, 1); private static dateMaxAbsolute: Date = new Date(2100, 0, 1); private static minHoursAbsolute: number; private static maxHoursAbsolute: number; private static view: string; private static defaultDateMask: string = 'DD.MM.YYYY'; private static defaultConvertedDateMask: string = 'YYYY-MM-DD'; private static localizedAirStrings public static init() { this.localizedAirStrings = new LocalizedAirStrings() $('.custom-air-date-time input').each((i, item) => { let attr = $(item).data(); let datepicker = ($(item) as any).datepicker().data('datepicker'); AirDateTimePickerInitializer.initElement(item, attr, datepicker); AirDateTimePickerInitializer.initInputMask(item); AirDateTimePickerInitializer.validateItem(item, attr, datepicker); }); new LocalizedAirStrings() } public static initItem(selector) { let item = $(selector)[0]; let attr = $(item).data(); let datepicker = ($(item) as any).datepicker().data('datepicker'); AirDateTimePickerInitializer.initElement(item, attr, datepicker); AirDateTimePickerInitializer.initInputMask(item); AirDateTimePickerInitializer.validateItem(item, attr, datepicker); } public static initInputMask(input: HTMLElement) { let isTime: boolean = this.stringToBooleanFormat($(input).attr('data-timepicker')); let mask: string; let placeholder: string; if (this.view == 'days') { if (isTime) { mask = '99.99.9999 99:99'; placeholder = this.localizedAirStrings.getTimes; } else { mask = '99.99.9999'; placeholder = this.localizedAirStrings.getDays; } } if (this.view == 'months') { mask = '99.9999'; placeholder = this.localizedAirStrings.getMonth; } if (this.view == 'years') { mask = '9999'; placeholder = this.localizedAirStrings.getYears; } ($(input) as any).inputmask({ "alias": "date", "mask": mask, "placeholder": placeholder, "autoGroup": "true" }); } public static initElement(dateTimeElement: any, attr: any, datepicker: any) { let { dateMask, toFormatDateMask } = AirDateTimePickerInitializer.GetAttrDateMask(attr); let {dateMin, dateMax} = AirDateTimePickerInitializer.GetAttrDateMinAndMax(attr, dateMask, toFormatDateMask); this.minHoursAbsolute = parseInt(attr.minHours) || 0; this.maxHoursAbsolute = parseInt(attr.maxHours) || 23; this.view = attr.view; let date; let dVal = dateTimeElement.defaultValue; if (dVal && dVal != '') { date = new Date(dVal); } datepicker.selectDate(date); let todayButtonDate: any = false; if (attr.todayButton != undefined) { let formatDate = moment(attr.todayButton, dateMask).format(toFormatDateMask); todayButtonDate = new Date(formatDate); } ($(dateTimeElement) as any).datepicker({ startDate: date, minDate: dateMin, maxDate: dateMax, minHours: this.minHoursAbsolute, maxHours: this.maxHoursAbsolute, todayButton: todayButtonDate, language: this.localizedAirStrings.getLocaleStrings, onSelect: function (formattedDate, date, inst) { if (date) { if (inst.timepicker) { date.setHours(inst.timepicker.hours); date.setMinutes(inst.timepicker.minutes); } let validDateTime: Date = AirDateTimePickerInitializer.ValidatePairedInputs(date, dateMask, toFormatDateMask, attr, dateTimeElement); inst.date = validDateTime; inst.selectedDates = [validDateTime]; inst.update({ startDate: validDateTime }); } $(dateTimeElement).trigger('updated', [formattedDate, date, inst]); } }) } public static setDateBoundaries(element: HTMLElement, minDate: Date, maxDate: Date) { //@ts-ignore $(element).datepicker({ minDate: minDate, maxDate: maxDate }); } public static validateItem(item: HTMLElement, attr: any, datepicker: any) { $(item).on("change", (event) => { let { dateMask, toFormatDateMask } = AirDateTimePickerInitializer.GetAttrDateMask(attr); let { dateMin, dateMax } = AirDateTimePickerInitializer.GetAttrDateMinAndMax(attr, dateMask, toFormatDateMask); let date: any; if (dateMask) { date = moment($(item).val(), dateMask); } else { date = moment($(item).val()); } if (!date.isValid()) { MessageShower.showError("Указана некорректная дата"); return; } let validDateTime: Date = date.toDate(); if (date < dateMin && dateMin) { let dateStr = moment(dateMin).format(dateMask); MessageShower.showError("Нельзя установить дату, раньше чем " + dateStr + " !"); } if (date > dateMax && dateMax) { let dateStr = moment(dateMax).format(dateMask); MessageShower.showError("Нельзя установить дату, позже чем " + dateStr + " !"); } if (attr.startPairedInputId || attr.endPairedInputId) { validDateTime = AirDateTimePickerInitializer.ValidatePairedInputs(validDateTime, dateMask, toFormatDateMask, attr, item); } datepicker.selectDate(validDateTime); }); } private static ValidatePairedInputs(date: Date, dateMask: string, toFormatDateMask: string, attr: any, item: any): Date { let startDateStr: string = $(document.getElementById(attr.startPairedInputId)).val() as string; let endDateStr: string = $(document.getElementById(attr.endPairedInputId)).val() as string; let startDate: Date; let endDate: Date; const isStartDateInput = $(item).attr("id") == attr.startPairedInputId; const isEndDateInput = $(item).attr("id") == attr.endPairedInputId; if (!startDateStr || !endDateStr) { return date; } let startDateMoment = moment(startDateStr, dateMask); if (startDateMoment.isValid()) { startDate = new Date(startDateMoment.format(toFormatDateMask)); } else { startDate = date; } let endDateMoment = moment(endDateStr, dateMask); if (endDateMoment.isValid()) { endDate = new Date(endDateMoment.format(toFormatDateMask)); } else { endDate = date } if (moment(endDate).isSame(startDate)) { return date; } if (isStartDateInput && moment(startDate).isAfter(endDate)) { $(item).val(endDateStr); MessageShower.showError("Нельзя установить дату, позже чем " + endDateStr + " !"); return endDate; } if (isEndDateInput && moment(endDate).isBefore(startDate)) { $(item).val(startDateStr); MessageShower.showError("Нельзя установить дату, раньше чем " + startDateStr + " !"); return startDate; } return date; } public static GetAttrDateMask(attr: any) { let isTime: boolean = this.stringToBooleanFormat(attr.timepicker); let dateMask: string = AirDateTimePickerInitializer.defaultDateMask; let toFormatDateMask: string = AirDateTimePickerInitializer.defaultConvertedDateMask; if (attr.view === 'days') { if (isTime) { dateMask = 'DD.MM.YYYY HH:mm'; toFormatDateMask = 'YYYY-MM-DD HH:mm'; } } if (attr.view === 'years') { dateMask = 'YYYY'; toFormatDateMask = AirDateTimePickerInitializer.defaultConvertedDateMask; } return { dateMask: dateMask, toFormatDateMask: toFormatDateMask } } public static GetAttrDateMinAndMax(attr: any, dateMask: string, toFormatDateMask: string) { let dateMin: Date = AirDateTimePickerInitializer.dateMinAbsolute; let dateMax: Date = AirDateTimePickerInitializer.dateMaxAbsolute; if (attr.view === 'days') { if (attr.dateMin) { let formatDate = moment(new Date(attr.dateMin)).format(toFormatDateMask); dateMin = new Date(formatDate); } if (attr.dateMax) { let formatDate = moment(new Date(attr.dateMax)).format(toFormatDateMask); dateMax = new Date(formatDate); } } if (attr.view === 'years') { if (attr.dateMin) { let year = moment(attr.dateMin, AirDateTimePickerInitializer.defaultDateMask).toDate().getFullYear(); dateMin = new Date(year, 0, 1); } if (attr.dateMax) { let year = moment(attr.dateMax, AirDateTimePickerInitializer.defaultDateMask).toDate().getFullYear(); dateMax = new Date(year, 0, 1); } } return { dateMin: dateMin, dateMax: dateMax } } private static dateToStringFormat(date: Date): string { return (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + "." + ((date.getMonth() + 1) < 10 ? "0" + (date.getMonth() + 1) : (date.getMonth() + 1)) + "." + date.getFullYear(); } private static stringToBooleanFormat(str: string): boolean { if (!str) { return false; } return str.toLowerCase() === 'true'; } } class AirDateTimePickerValidator { public static validate(item: HTMLElement): boolean { let dateValue = $(item).val(); if (!dateValue) { return true; } let elParent = $(item).parents(".experience-item")[0] let isTillNowChecked = $(elParent).find('#TillNow').prop('checked') let attr = $(item).data(); let { dateMask, toFormatDateMask } = AirDateTimePickerInitializer.GetAttrDateMask(attr); let { dateMin, dateMax } = AirDateTimePickerInitializer.GetAttrDateMinAndMax(attr, dateMask, toFormatDateMask); let date = moment($(item).val(), dateMask, true); if (!date.isValid()) { return false; } let validDateTime: Date = date.toDate(); if (date < dateMin && dateMin) { return false; } if (date > dateMax && dateMax) { return false; } if (!isTillNowChecked && (attr.startPairedInputId || attr.endPairedInputId)) { return AirDateTimePickerValidator.validatePairedInputs(validDateTime, dateMask, toFormatDateMask, attr, item); } return true; } private static validatePairedInputs(date: Date, dateMask: string, toFormatDateMask: string, attr: any, item: any): boolean { let startDateStr: string = $(document.getElementById(attr.startPairedInputId)).val() as string; let endDateStr: string = $(document.getElementById(attr.endPairedInputId)).val() as string; let startDate: Date; let endDate: Date; if (!startDateStr || !endDateStr) { return true; } let startDateMoment = moment(startDateStr, dateMask); if (startDateMoment.isValid()) { startDate = new Date(startDateMoment.format(toFormatDateMask)); } else { startDate = date; } let endDateMoment = moment(endDateStr, dateMask); if (endDateMoment.isValid()) { endDate = new Date(endDateMoment.format(toFormatDateMask)); } else { endDate = date } if (moment(endDate).isSame(startDate)) { return true; } if (moment(endDate).isBefore(startDate) && startDateStr) { return false; } if (moment(startDate).isAfter(endDate) && endDateStr) { return false; } return true; } }