• Zoom using HTML5 slider control
  • Zoom using buttons: [+] and [-]
  • Custom zoom levels with defined properties (scale, visible days, time headers...)
  • Includes a trial version of DayPilot Pro for JavaScript (see License below)


Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

Live Demo

Scheduler Zoom Levels


The first steps is to define the zoom levels for the JavaScript Scheduler component that we want to make available in our application. The users will be able to change the Scheduler zoom level using an HTML5 slider control and (+)/(-) buttons that we add later.

It's an array of objects that specify the zoom level properties:

  • name (custom zoom level name displayed to the user)
  • scale (Scheduler scale unit)
  • cellWidth (cell width in pixels)
  • cellDuration (cell duration which is used for custom scale)
  • timeHeaders (time header rows)
  • startDate (calculated start date)
  • days (calculated number of visible days)
var levels = [
    name: "Year",
    scale: "Day",
    cellWidth: 40,
    timeHeaders: [{groupBy: "Year"}, {groupBy: "Month", format: "MMMM"}, {groupBy: "Day", format: "d"}],
    start: function(d) { return d.firstDayOfYear(); },
    days: function() { return dp.startDate.daysInYear();},
    name: "Month",
    scale: "CellDuration",
    cellDuration: 720,
    cellWidth: 40,
    timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "ddd d"}, {groupBy: "Cell", format: "tt"}],
    start: function(d) { return d.firstDayOfMonth(); },
    days: function() { return dp.startDate.daysInMonth();},
    name: "Week",
    scale: "Hour",
    cellWidth: 40,
    timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "dddd d"}, {groupBy: "Hour"}],
    start: function(d) { return d.firstDayOfWeek(); },
    days: function() { return 7; },
    name: "Hour",
    scale: "CellDuration",
    cellDuration: 15,
    cellWidth: 40,
    timeHeaders: [{groupBy: "Day", format: "dddd MMMM d, yyyy"}, {groupBy: "Hour"}, {groupBy: "Cell"}],
    start: function(d) { return d.getDatePart(); },
    days: function() { return 1; },

Applying Zoom Level

The applyLevel() function applies the selected zoom level (specified using index parameter) to the JavaScript Scheduler component. 

It calculates the startDate and days values using startDate() and days() functions of the zoom level, and applies the additional properties (scale, timeHeaders, cellDuration, cellWidth).

When the Scheduler is updated to display the new zoom level it scrolls to the target date/time. If the target date is not specified it uses the center of the previous zoom level viewport as a reference point.

It also displays the current zoom level name using the <span> label element.

function applyLevel(index, date) {
  var level = levels[index];
  if (!level) {
    console.log("Level not found: ", index);

  if (elements.range.value != index) {
    elements.range.value = index;

  if (!date) {
    date = dp.getViewPort().start.addTime((dp.getViewPort().end.getTime() - dp.getViewPort().start.getTime())/2);

  dp.startDate = level.start(date);
  dp.scale = level.scale;
  dp.days = level.days();
  dp.timeHeaders = level.timeHeaders;
  dp.cellDuration = level.cellDuration;
  dp.cellWidth = level.cellWidth;
  dp.scrollTo(date, null, "middle");

  elements.label.innerText = "Current zoom level: " + level.name;


Slider Control for Changing Scheduler Zoom Level


HTML5 slider control:

<input type="range" min="0" max="3" step="1" id="zoom-level" />

Event handler:

var elements = {
  range: document.getElementById("zoom-level"),
  // ...

elements.range.addEventListener("input", function(ev) {
  var val = elements.range.value;

Zoom Buttons



<div class="controls">
  <button id="minus">-</button>
  <button id="plus">+</button>

CSS Styling:

.controls button {
  width: 25px;
  height: 25px;

  background-color: #3c78d8;
  color: white;
  border: 0;
  cursor: pointer;
.controls button:focus {
  outline: none;

Event handlers:

var elements = {
  plus: document.getElementById("plus"),
  minus: document.getElementById("minus"),
  // ...

elements.plus.addEventListener("click", function(ev) {
  if (elements.range.value < levels.length - 1) {

elements.minus.addEventListener("click", function(ev) {
  if (elements.range.value > 0) {