Mini calendar (date picker) is a special extension that provides an ability to render a small month view in an HTML container on a page.
Related sample: Mini calendar without the scheduler
To use the mini calendar in an app, include the minical extension on the page.
To place the mini calendar (date picker) into the header of the scheduler (as shown in the image below), follow these steps:
scheduler.plugins({
minical: true
});
<div class="dhx_cal_navline">
...
<div class="dhx_cal_date"></div>
<div class="dhx_minical_icon" id="dhx_minical_icon"
onclick="show_minical()"> </div>
</div>
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()
}
});
}
}
Related sample: Mini calendar in the scheduler header
In this section we'll demonstrate you how to add a third party mini calendar (date picker) into the header of the scheduler.
Related sample: 3rd party Mini Calendar in the header
In our sample, we will add a mini calendar on the base of jQuery and Bootstrap Datepicker. If you use other libraries, you'll need to modify the code but the main approach should stay the same:
1. Show the date picker when clicking the calendar header
Firstly, you need to define the DIV container for the mini calendar (or any other control) in the scheduler header. If you use the markup approach for initialization, you can do this, as in:
<div id="scheduler_here" class="dhx_cal_container" style="width:100%; height:100%;">
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button"> </div>
<div class="dhx_cal_next_button"> </div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<!--- HERE -->
<div class="input-group date" style="display: none;">
<input type="text" class="form-control">
<div class="dhx_minical_icon input-group-addon" id="dhx_minical_icon"> </div>
</div>
<!--- end HERE -->
If you use the header config, you'll need to add a custom element there:
scheduler.config.header = [
"day",
"week",
"month",
{html:'<div class="input-group date" style="display: none;">'+
'<input type="text" class="form-control">'+
'<div class="dhx_minical_icon input-group-addon" id="dhx_minical_icon"> </div>'+
'</div>'},
"date",
"prev",
"today",
"next"
];
scheduler.init("scheduler_here");
To display the date picker on clicking the date in the navigation panel of the scheduler, we initialize the click event as soon as the scheduler is ready:
scheduler.attachEvent("onSchedulerReady", function(){
var $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);
// center popup below date label
centerDatepicker($(".dhx_cal_date"));
});
...
});
centerDatepicker
is an auxiliary function that we implement to render the dropdown date picker in the necessary place:
...
function centerDatepicker(referenceElement) {
if (!$('.datepicker-dropdown').is(':visible')) {
return;
}
// center popup below date label
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"
});
}
2. Switch the scheduler to the selected date when the user clicks the date in the date picker
Once we display the datepicker on demand, we need to change the scheduler date when selecting a day in the calendar:
$node.datepicker().on("changeDate", function () {
scheduler.setCurrentView($node.datepicker("getDate"));
});
3. Highlight current dates in the datepicker
To highlight the dates of the date picker that are currently displayed in the scheduler we use a simple css class:
.datepicker table .scheduler-date{
background-color: #fff3e4;
}
All cells of the date picker, that are currently visible in the scheduler, will receive this class:
function fillDatepicker(scheduler) {
// reset highlighted events and active dates
...
$(".datepicker-dropdown").find("[data-date]").removeClass("scheduler-date");
// highlight scheduler date
var visibleDates = getVisibleDates(scheduler);
visibleDates.forEach(function (date) {
$(".datepicker-dropdown").find(
"[data-date='" + date + "']"
).addClass("scheduler-date");
});
...
}
In order to get the dates that are currently visible, you can use 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;
}
4. Highlight days with events in the date picker
Next, we want the date picker to highlight the dates of the events specified in the scheduler. For that, we use the same approach as in the previous step and add a css class:
.datepicker table .has-event::after {
content: " ";
width: 6px;
height: 6px;
position: absolute;
background-color: #6b96f7;
border-radius: 4px;
}
As you can see from the above example, we highlight the dates of the mini calendar that contain events.
To show the tooltip with the amount of events for the date that the user hovers over with the cursor, we need to get the events of the months currently displayed in the date picker:
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 = {};
debugger;
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;
}
In the example above, we get information of the events from the scheduler. It means, that we'll only be able to highlight the events that are already loaded into the scheduler. This approach won't work particularly well if you use dynamic loading, since only a small part of all events will be loaded into the scheduler at the time.
The alternative approach would be to request data on the events from the server.
When we have data on the timestamps of the cells that contain events and the amount of events per cell, we can populate the date picker with this information, as in:
function fillDatepicker(scheduler) {
// reset highlighted events and active dates
$(".datepicker-dropdown").find("[data-date]").removeClass("has-event");
$(".datepicker-dropdown").find("[data-date]").removeAttr("title");
...
// highlight events
var 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");
});
}
5. Synchronize the displayed label of the date with the active date in the scheduler
Finally, we need to recenter the date picker if the size of the window changes, and apply the highlighting when the user changes the current date in the date picker:
$(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) {
// call from timeout so code fires after the datepicker popup is updated
setTimeout(function () {
fillDatepicker(scheduler);
});
}
If you use a separate element to display the active date of the scheduler, you'll need to capture the onViewChange event of the scheduler and update the date label from there:
scheduler.attachEvent("onViewChange", function (newMode , newDate){
var state = scheduler.getState();
var minDate = state.min_date;
var maxDate = state.max_date;
var dateToStr = scheduler.date.str_to_date("%d-%m-%Y");
$(dateHeader).html(dateToStr(minDate) + " - " + dateToStr(minDate));
});
Note, that we don't use this handler in our code sample, since we rely on the built-in date header of the scheduler which is updated automatically. You need to use such code only if you hide the default date header, or if you need to display the active date in multiple places.
The mini calendar (date picker) can be used in the lightbox for "start" and "end" dates selection.
To place the mini calendar in the lightbox, follow these steps:
scheduler.plugins({
minical: true
});
//default lightbox definition
scheduler.config.lightbox.sections=[
{name:"description", height:200, map_to:"text", type:"textarea", focus:true},
{name:"time", height:72, type:"time", map_to:"auto"}
];
//change 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" }
];
Related sample: Mini calendar in the lightbox
The mini calendar (date picker) can reside at any place on the page.
To place the mini calendar in some HTML container outside the scheduler, follow these steps:
scheduler.plugins({
minical: true
});
<div id="scheduler_here" class="dhx_cal_container" ...>
...
</div>
<div style='float: left; padding:10px;'>
<div id="cal_here" style='width:250px;'></div>
</div>
var calendar = scheduler.renderCalendar({
container:"cal_here",
navigation:true,
handler:function(date){
scheduler.setCurrentView(date, scheduler._mode);
}
});
Related sample: Mini calendar outside the scheduler
To customize the format of dates presented in the mini calendar (date picker), you can use a number of templates listed in the article Mini Calendar Templates.
scheduler.templates.calendar_month = scheduler.date.date_to_str("%M, %Y");
scheduler.init('scheduler_here',new Date(2019,2,1),"day");
...
var calendar = scheduler.renderCalendar({..});
To customize the look of days in the mini calendar (date picker), you can redefine the following CSS classes:
CSS class | Applied to |
---|---|
.dhx_cal_container.dhx_mini_calendar .dhx_month_head | a day's cell |
.dhx_cal_container.dhx_mini_calendar .dhx_month_head.dhx_year_event | a day's cell with the assigned event(s) |
.dhx_cal_container.dhx_mini_calendar .dhx_now .dhx_month_head | a day's cell with the current date |
.dhx_cal_container.dhx_mini_calendar .dhx_calendar_click | a day's cell with the currently active date |
<style>
.dhx_cal_container.dhx_mini_calendar .dhx_calendar_click{
color:red;
}
</style>
<script>
var calendar = scheduler.renderCalendar({...});
</script>
To assign a custom CSS class to a day, you can use the markCalendar method:
<style>
.my_style{
background: red !important;
}
</style>
<script>
var calendar = scheduler.renderCalendar({...});
...
scheduler.markCalendar(calendar, new Date(2019,3,1), "my_style");
</script>
destroyCalendar | destroys the previously created mini-calendar |
isCalendarVisible | checks whether the calendar is currently opened in the scheduler |
linkCalendar | 'says' to change the active date in the mini calendar each time the active date in the scheduler is changed |
markCalendar | applies a CSS class to the specified date |
renderCalendar | creates a mini calendar |
unmarkCalendar | removes a CSS class from the specified date |
updateCalendar | displays the specified date in the mini calendar |