迷你日历(日期选择器)
迷你日历(日期选择器)是一个实用的扩展,可以让你在页面的 HTML 容器中显示一个紧凑的月份视图。
Mini calendar without the scheduler
要在你的应用中使用迷你日历,请确保在页面上添加 minical 扩展。
在头部添加
要将迷你日历(日期选择器)添加到调度器的头部(如下图所示),请按照以下步骤操作:

- 在页面上引入扩展文件:
scheduler.plugins({
minical: true
});
- 定义迷你日历的容器,并将其添加到调度器的标记中:
<div className="dhx_cal_navline">
...
<div className="dhx_cal_date"></div>
<div className="dhx_minical_icon" id="dhx_minical_icon"
onclick="show_minical()"> </div>
</div>
- 实现初始化(使用 renderCalendar 方法)和销毁(使用 destroyCalendar 方法)迷你日历的逻辑:
function show_minical(){
if (scheduler.isCalendarVisible()){
scheduler.destroyCalendar();
} else {
scheduler.renderCalendar({
position:"dhx_minical_icon",
date:scheduler._date,
navigation:true,
handler:function(date,calendar){
scheduler.setCurrentView(date);
scheduler.destroyCalendar()
}
});
}
}
Mini calendar in the scheduler header
在头部集成第三方日期选择器
本节展示如何将第三方迷你日历(日期选择器)集成到调度器的头部。

Related sample 3rd party Mini Calendar in the header
我们的示例使用 jQuery 和 Bootstrap Datepicker 来添加迷你日历。如果你使用其他库,需要相应调整代码,但整体思路类似:
- 点击日历头部时显示日期选择器
首先,在调度器头部内定义一个用于迷你日历(或其他控件)的 DIV 容器。采用 标记初始化方式 时,类似如下:
<div id="scheduler_here" className="dhx_cal_container">
<div className="dhx_cal_navline">
<div className="dhx_cal_prev_button"> </div>
<div className="dhx_cal_next_button"> </div>
<div className="dhx_cal_today_button"></div>
<div className="dhx_cal_date"></div>
{/*- HERE */}
<div className="input-group date">
<input type="text" className="form-control"/>
<div className="dhx_minical_icon input-group-addon" id="dhx_minical_icon"> </div>
</div>
{/*- end HERE */}
如果你使用 header config,可以像这样添加 自定义元素:
scheduler.config.header = [
"day",
"week",
"month",
{html:'<div className="input-group date">'+
'<input type="text" className="form-control"/>'+
'<div className="dhx_minical_icon input-group-addon" id="dhx_minical_icon"> </div>'+
'</div>'},
"date",
"prev",
"today",
"next"
];
scheduler.init("scheduler_here");
接下来,在调度器准备好后,设置点击调度器导航面板中的日期时显示日期选择器的事件:
scheduler.attachEvent("onSchedulerReady", function(){
const $node = $('#scheduler_here .input-group.date').datepicker({
autoclose: true,
todayHighlight: true,
todayBtn: "linked",
});
$("#scheduler_here").delegate(".dhx_cal_date", "click", function () {
$node.datepicker("show");
});
$node.datepicker().on("show", function () {
$node.datepicker("update", scheduler.getState().date);
// 将弹出层居中显示在日期标签下方
centerDatepicker($(".dhx_cal_date"));
});
...
});
centerDatepicker 函数用于正确定位下拉日期选择器:
...
function centerDatepicker(referenceElement) {
if (!$('.datepicker-dropdown').is(':visible')) {
return;
}
// 将弹出层居中显示在日期标签下方
var offset = $(".dhx_cal_date").offset();
var width = $(".dhx_cal_date").width();
var popupWidth = $(".datepicker-dropdown").width();
$(".datepicker-dropdown").css({
top: offset.bottom + "px",
left: (width - popupWidth) / 2 + "px"
});
}
- 用户选择日期时更新调度器当前日期
显示日期选择器后,当选 择某天时更新调度器的日期:
$node.datepicker().on("changeDate", function () {
scheduler.setCurrentView($node.datepicker("getDate"));
});
- 在日期选择器中高亮显示当前日期
为了突出显示调度器当前显示的日期,可以应用一个简单的 CSS 类:
.datepicker table .scheduler-date{
background-color: #fff3e4;
}
调度器中可见的所有日期单元格都会添加此类:
function fillDatepicker(scheduler) {
// 重置高亮事件和活动日期
...
$(".datepicker-dropdown").find("[data-date]").removeClass("scheduler-date");
// 高亮调度器日期
var visibleDates = getVisibleDates(scheduler);
visibleDates.forEach(function (date) {
$(".datepicker-dropdown").find(
"[data-date='" + date + "']"
).addClass("scheduler-date");
});
...
}
要获取当前可见日期,可使用 scheduler.getState:
function getVisibleDates(scheduler) {
var minVisible = scheduler.getState().min_date;
var maxVisible = scheduler.getState().max_date;
var current = minVisible;
var result = [];
while (current.valueOf() < maxVisible.valueOf()) {
var currentUTC = Date.UTC(
current.getFullYear(),current.getMonth(),current.getDate()
);
result.push(currentUTC.valueOf());
current = scheduler.date.add(current, 1, "day");
}
return result;
}
- 在日期选择器中标记有事件的日期
为了高亮显示调度器中有事件的日期,可以添加另一个 CSS 类:
.datepicker table .has-event::after {
content: " ";
width: 6px;
height: 6px;
position: absolute;
background-color: #6b96f7;
border-radius: 4px;
}
这将高亮显示迷你日历中有事件的日期。
要在鼠标悬停日期时显示事件数量的提示,可以获取当前日期选择器所显示月份的事件:
function getVisibleEvents(calendarDate, scheduler) {
var min = scheduler.date.month_start(new Date(calendarDate));
var max = scheduler.date.add(calendarDate, 1, "month");
min = scheduler.date.week_start(min);
if(scheduler.date.week_start(new Date(max)) < max){
max = scheduler.date.week_start(new Date(max));
max = scheduler.date.add(max, 1, "week");
}
var events = scheduler.getEvents(min, max);
var days = {};
events.forEach(function (event) {
var eventDate = event.start_date;
while(eventDate < event.end_date){
var day = Date.UTC(
eventDate.getFullYear(),
eventDate.getMonth(),
eventDate.getDate()
);
if (!days[day.valueOf()]) {
days[day.valueOf()] = 0;
}
days[day.valueOf()]++;
eventDate = scheduler.date.add(eventDate, 1, "day");
eventDate = scheduler.date.day_start(eventDate);
}
});
var result = [];
for (var i in days) {
result.push({ timestamp: i, count: days[i] });
}
return result;
}
该方法从调度器中获取事件数据,因此只会高亮当前已加载的事件。如果你的应用使用动态加载,可能无法覆盖所有事件,因为只加载了一部分。
另一种方式是从服务器请求事件数据。
获得事件时间戳和数量后,可以如下更新日期选择器:
function fillDatepicker(scheduler) {
// 重置高亮事件和活动日期
$(".datepicker-dropdown").find("[data-date]").removeClass("has-event");
$(".datepicker-dropdown").find("[data-date]").removeAttr("title");
...
// 高亮事件
const eventCells = getVisibleEvents($node.datepicker("getDate"), scheduler);
eventCells.forEach(function (cellEvents) {
$(".datepicker-dropdown").find(
"[data-date='" + cellEvents.timestamp + "']"
).addClass("has-event");
$(".datepicker-dropdown").find(
"[data-date='" + cellEvents.timestamp + "']"
).attr("title", cellEvents.count + " events");
});
}
- 保持显示的日期标签与调度器当前日期同步
最后,在窗口尺寸变化时重新居中日期选择器,并在用户更改日期时更新高亮:
$(window).on('resize', function () {
setTimeout(function(){
centerDatepicker($(".dhx_cal_date"));
}, 10);
});
$node.datepicker().on("changeDate", function () {
scheduler.setCurrentView($node.datepicker("getDate"));
});
$node.datepicker().on("changeMonth", function () {
refreshDatepicker(scheduler);
});
$node.datepicker().on("changeYear", function () {
refreshDatepicker(scheduler);
});
$node.datepicker().on("changeDecade", function () {
refreshDatepicker(scheduler);
});
$node.datepicker().on("changeCentury", function () {
refreshDatepicker(scheduler);
});
function refreshDatepicker(scheduler) {
// 使用 timeout 以确保在日期选择器弹窗更新后执行
setTimeout(function () {
fillDatepicker(scheduler);
});
}
如果你使用独立元素显示调度器当前日期,可以监听 onViewChange 事件并在其中更新标签:
scheduler.attachEvent("onViewChange", function (newMode , newDate){
const state = scheduler.getState();
const minDate = state.min_date;
const maxDate = state.max_date;
const dateToStr = scheduler.date.str_to_date("%d-%m-%Y");
$(dateHeader).html(dateToStr(minDate) + " - " + dateToStr(minDate));
});
请注意,该处理器在示例代码中未使用,因为内置日期头会自动更新。只有在你 隐藏默认日期头 或需要在多个地方显示当前日期时,才需要这样做。
在弹窗(lightbox)中使用
迷你日历(日期选择器)也可以在弹窗中用于选择"开始"和"结束"日期。

要在弹窗中添加迷你日历,请按照以下步骤操作:
- 在页面上启用扩展:
scheduler.plugins({
minical: true
});
- 将 time 区块的 type 属性从 time 修改为 calendar_time:
// 默认弹窗配置
scheduler.config.lightbox.sections="["
{name:"description", height:200, map_to:"text", type:"textarea", focus:true},
{name:"time", height:72, type:"time", map_to:"auto"}
];
// 修改 type:"time" -> type:"calendar_time"
scheduler.config.lightbox.sections = [
{name:"description", height:200, map_to:"text", type:"textarea", focus:true},
{name:"time", height:72, type:"calendar_time", map_to:"auto" }
];