Mini Calendar (Date Picker)

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.

In the header

To place the mini calendar (date picker) into the header of the scheduler (as shown in the image below), follow these steps:

  1. Include the extension file on the page:
    scheduler.plugins({
        minical: true
    });
  2. Specify the container for the mini calendar and add it to the scheduler markup:
    <div class="dhx_cal_navline">
        ...
        <div class="dhx_cal_date"></div>
        <div class="dhx_minical_icon" id="dhx_minical_icon" 
        onclick="show_minical()">&nbsp;</div>
    </div>
  3. Provide the logic that will initialize (the renderCalendar method) and destroy (the destroyCalendar method) the mini calendar:
    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 the header (Third-party Date Picker)

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">&nbsp;</div>
    <div class="dhx_cal_next_button">&nbsp;</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">&nbsp;</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">&nbsp;</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(){
 
    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);
 
        // 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 = {};
 
        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
        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");
        });
    }

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){
    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));
});

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.

In the lightbox

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:

  1. Enable the extension on the page:
    scheduler.plugins({
        minical: true
    });
  2. Set the type of the time section to calendar_time (instead of time):
    //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

Outside the scheduler

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:

  1. Enable the extension on the page:
    scheduler.plugins({
        minical: true
    });
  2. Specify the container for the mini calendar on the page:
    <div id="scheduler_here" class="dhx_cal_container" ...>
    ...
    </div>
     
    <div style='float: left; padding:10px;'>
            <div id="cal_here" style='width:250px;'></div>
    </div>
  3. Call the renderCalendar method to render the mini calendar on the page:
    const calendar = scheduler.renderCalendar({
        container:"cal_here", 
        navigation:true,
        handler:function(date){
            scheduler.setCurrentView(date, scheduler._mode);
        }
    });

Related sample:  Mini calendar outside the scheduler

Templates and styles

Templates

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");
...
const calendar = scheduler.renderCalendar({..});

CSS classes

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>
    const calendar = scheduler.renderCalendar({...});
</script>

Marking days with the markCalendar() method

To assign a custom CSS class to a day, you can use the markCalendar method:

<style>
.my_style{
    background: red !important;
}
</style>
<script>
    const calendar = scheduler.renderCalendar({...});
    ...
    scheduler.markCalendar(calendar, new Date(2019,3,1), "my_style");
</script>

API

Event handling

The mini calendar provides callbacks for common user actions, such as changing the visible month, hovering over a date, and clicking on dates. These callbacks can be specified in the events property of the configuration object:

const dateToStr = (date) => date ? scheduler.templates.format_date(date) : null;
const calendar = scheduler.renderCalendar({
    container: "cal_here",
    navigation: true,
    events: {
        onBeforeMonthChange: function(oldDate, newDate) {
            scheduler.message(`Before change from ${dateToStr(oldDate)} 
                to ${dateToStr(newDate)}`);
            return true;
        },
        onMonthChange: function(oldDate, newDate) {
            scheduler.message(`Changed from ${dateToStr(oldDate)} 
                to ${dateToStr(newDate)}`);
        },
        onDateClick: function(date, e) {
            scheduler.setCurrentView(date);
            scheduler.message(`Selected date ${dateToStr(date)}`);
        },
        onDateMouseOver: function(date, e){
            scheduler.message(`Mouse over ${dateToStr(date)}`)
 
        }
    }
});
Back to top