Как сделать недоступными к выбору даты меньше текущей в стандартном календаре битрикса?
Стандартный встроенный календарь 1C Битрикс (BX.Calendar) не предоставляет возможности ограничения выбора даты.
Предположим, нам надо ограничить выбор даты таким образом, чтобы невозможно было выбрать дату, меньше текущей. То есть, чтобы мы могли выбрать сегодняшнюю дату и все последующие, но не могли выбрать все предыдущие дни (вчера, позавчера и т.д.)
Так как код вывода календаря формируется в скриптах ядра bitrix, мы не можем его менять буквально.
Пишем функцию изменения блока показа календаря, после того как он сформирован ядром Битрикс.
function changeCalendar() – устанавливает элементам, отображающим дни в окне показа календаря класс disabled, если они соответствуют дате меньшей чем текущая.
function changeCalendar() {
var el = $('[id ^= "calendar_popup_"]'); //найдем div с календарем
var links = el.find(".bx-calendar-cell"); //найдем элементы отображающие дни
$('.bx-calendar-left-arrow').attr({'onclick': 'changeCalendar();',}); //вешаем функцию изменения календаря на кнопку смещения календаря на месяц назад
$('.bx-calendar-right-arrow').attr({'onclick': 'changeCalendar();',}); //вешаем функцию изменения календаря на кнопку смещения календаря на месяц вперед
$('.bx-calendar-top-month').attr({'onclick': 'changeMonth();',}); //вешаем функцию изменения календаря на кнопку выбора месяца
$('.bx-calendar-top-year').attr({'onclick': 'changeYear();',}); //вешаем функцию изменения календаря на кнопку выбора года
var date = new Date();
for (var i =0; i < links.length; i++)
{
var atrDate = links[i].attributes['data-date'].value;
var d = date.valueOf();
var g = links[i].innerHTML;
if (date - atrDate > 24*60*60*1000) {
$('[data-date="' + atrDate +'"]').addClass("bx-calendar-date-hidden disabled"); //меняем класс у элемента отображающего день, который меньше по дате чем текущий день
}
}
}
Для того, чтобы доступность выбора дат изменялась при смене месяца или года пишем две дополнительные функции, которые вешают вызов функции changeCalendar() на событие клика на месяц и год
Функция changeMonth() – функция устанавливает запуск функции изменения календаря по клику на месяц при выборе месяца.
function changeMonth() {
var el = $('[id ^= "calendar_popup_month_"]'); //найдем div с календарем
var links = el.find(".bx-calendar-month");
for (var i =0; i < links.length; i++) {
var func = links[i].attributes['onclick'].value;
$('[onclick="' + func +'"]').attr({'onclick': func + '; changeCalendar();',}); //повесим событие на выбор месяца
}
}
Функция changeYear() - функция устанавливает запуск функции изменения календаря по клику на год при выборе года.
function changeYear() {
var el = $('[id ^= "calendar_popup_year_"]'); //найдем div с календарем
var link = el.find(".bx-calendar-year-input");
var func2 = link[0].attributes['onkeyup'].value;
$('[onkeyup="' + func2 +'"]').attr({'onkeyup': func2 + '; changeCalendar();',}); //повесим событие на ввод года
var links = el.find(".bx-calendar-year-number");
for (var i =0; i < links.length; i++) {
var func = links[i].attributes['onclick'].value;
$('[onclick="' + func +'"]').attr({'onclick': func + '; changeCalendar();',}); //повесим событие на выбор года
}
}
В файле стилей добавляем класс .bx-calendar-range .disabled и устанавливаем для него запрет на нажатие по элементам данного класса:
.bx-calendar-range .disabled{
pointer-events: none;
}
Теперь подключаем написанную нами функцию в том же событии, что и вызов календаря.
Перечисляем функции в событии через «;» в следующем порядке: 1. Вызов календаря. 2. Функция изменения календаря changeCalendar();
Например:
input onclick="BX.calendar({node: this, value: new Date(), field: this, bTime: false}); changeCalendar();"
Теперь все даты, меньше текущей недоступны к выводу:
Дополнение от 12.04.2022:
Описанный метод может не работать в актуальной версии Битрикс. Далее предлагаем альтернативное решение которое прислал нам читатель блога.
function changeCalendarBlock(){
var el = $('[id ^= "calendar_popup_"]'); // найдем div с календарем
var links = el.find(".bx-calendar-cell"); // найдем элементы отображающие дни
var date = new Date();
for (var i = 0; i < links.length; i++)
{
var atrDate = link[i].attributes['data-date'].value;
var d = date.valueOf();
var g = links[i].innerHTML;
if(date - atrDate > 24*60*60*1000){
// меняем класс у элемента отображающего день, который меньше по дате чем текущий день
$('[data-date="'+atrDate+'"]').addClass("bx-calendar-date-hidden disables");
}
}
}
function changeCalendar(){
changeCalendarBlock();
// следит за изменением календаря
var BXcalendars = BX.findChildrenByClassName(document,'bx-calendar-cell-block', true);
// создаем экземпляр наблюдателя с указанной функцией колбэка
const callback = function (mutationList, observer){
changeCalendarBlock();
};
const observer = new MutationObserver(callback);
BXcalendars.forEach(function(item,i,arr) {
observer.observe(item, {attributes: true, childList: true, subtree:false});
}
);
}