Overview

  • You can highlight holiday cells using onBeforeCellRender

  • This sample displays global holidays (apply to all resources) and resource-specific holidays

  • In addition to color highlighting, you can disable drag and drop for the holiday cells

  • Includes a trial version of DayPilot Pro for JavaScript (see License below)

License

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.

Live Demo

Displaying Holidays in the Scheduler

javascript scheduler displaying global holidays

First, we will define the holiday data. We will use a simple static array in this example:

var globalHolidays = [
  { start: "2019-07-15", end: "2019-07-15", backColor: "#fff2cc", headerColor: "#f1c232"}
];

Each item can be a single day (start date equals end date) or it can span multiple days. The end date is specified as a date-only value.

In a typical web application, you would probably load the holiday data from the server using an AJAX call instead.

Now we want to display the holidays in the JavaScript Scheduler component. We will use the cell customization feature and set a custom background color for the holiday cells:

var dp = new DayPilot.Scheduler("dp", {
  onBeforeCellRender: function(args) {

    var item = globalHolidays.find(function(range) {
      var start = new DayPilot.Date(range.start);
      var end = new DayPilot.Date(range.end).addDays(1);
      return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
    });

    if (item) {
      args.cell.backColor = item.backColor;
    }
  
  },

  // ...

});

The onBeforeCellRender event handler is called once for every Scheduler grid cell and you can use it to define custom cell behavior and appearance. We will compare the cell start and end time with items of the globalHolidays array and set the defined background color if there is an overlap.

Resource-Specific Holidays

javascript scheduler displaying resource specific holidays

We can also define holidays that will be only applied to selected resources/rows.

In this case, we will add the holiday data to the resource array which defines the Scheduler rows:

dp.resources = [
  { name: "Resource A", id: "A", holidays: [
      { start: "2019-07-05", end: "2019-07-10", backColor: "#f4cccc"}
    ]},
  { name: "Resource B", id: "B", holidays: [
      { start: "2019-07-04", end: "2019-07-06", backColor: "#d9ead3"}
    ]},
  { name: "Resource C", id: "C"},
  { name: "Resource D", id: "D"},
  { name: "Resource E", id: "E"},
  { name: "Resource F", id: "F"},
  { name: "Resource G", id: "G"},
  { name: "Resource H", id: "H"},
  { name: "Resource I", id: "I"},
  { name: "Resource J", id: "J"},
];

The holidays are specified using a custom holidays property of each resource array item. The structure is the same as above where we defined the global holidays.

As in the previous step, we use onBeforeCellRender to lookup the cell in the holidays array of the resource. If there is a match, we highlight the cell by setting a custom background color.

var dp = new DayPilot.Scheduler("dp", {
  onBeforeCellRender: function(args) {

      // ...

      var row = dp.rows.find(args.cell.resource);
      var holidays = row.data.holidays;
      if (!holidays) {
        return;
      }
      var item = holidays.find(function(range) {
        var start = new DayPilot.Date(range.start);
        var end = new DayPilot.Date(range.end).addDays(1);
        return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
      });

      if (item) {
        args.cell.backColor = item.backColor;
      }


  },

  // ...

});

Full Source Code

This is the full source code of the Scheduler configuration that displays global and per-resource holidays:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>JavaScript Scheduler: Displaying Holidays</title>

  <style type="text/css">
    p, body, td { font-family: Tahoma, Arial, Helvetica, sans-serif; font-size: 10pt; }
    body { padding: 0px; margin: 0px; background-color: #ffffff; }
    a { color: #1155a3; }
    .space { margin: 10px 0px; }
    .header { background: #003267; background: linear-gradient(to right, #011329 0%,#00639e 44%,#011329 100%); padding:20px 10px; color: white; box-shadow: 0px 0px 10px 5px rgba(0,0,0,0.75); margin-bottom: 10px;}
    .header a { color: white; }
    .header h1 a { text-decoration: none; }
    .header h1 { padding: 0px; margin: 0px; }
    .main { padding: 10px }
    .generated { color: #999; }
    .generated a { color: #999; }
  </style>

  <!-- DayPilot library -->
  <script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
  <h1><a href='https://code.daypilot.org/93068/javascript-scheduler-displaying-holidays'>JavaScript Scheduler: Displaying Holidays</a></h1>
  <div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React</div>
</div>


<div class="main">

  <div class="space">
    <label><input type="checkbox" id="disable"> Disable drag and drop for holidays</label>
  </div>

  <div id="dp"></div>
  <div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>


<script>

  var globalHolidays = [
    { start: "2021-07-15", end: "2021-07-15", backColor: "#fff2cc", headerColor: "#f1c232"}
  ];

  var holidaysDisabled = false;

  var dp = new DayPilot.Scheduler("dp", {
    timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
    scale: "Day",
    days: 31,
    startDate: "2021-07-01",
    timeRangeSelectedHandling: "Enabled",
    onTimeRangeSelected: function (args) {
      var dp = this;
      DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function(modal) {
        dp.clearSelection();
        if (!modal.result) { return; }
        dp.events.add(new DayPilot.Event({
          start: args.start,
          end: args.end,
          id: DayPilot.guid(),
          resource: args.resource,
          text: modal.result
        }));
      });
    },
    treeEnabled: true,
    onBeforeCellRender: function(args) {
      (function highlightResourceHolidays() {

        var row = dp.rows.find(args.cell.resource);
        var holidays = row.data.holidays;
        if (!holidays) {
          return;
        }
        var item = holidays.find(function(range) {
          var start = new DayPilot.Date(range.start);
          var end = new DayPilot.Date(range.end).addDays(1);
          return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
        });

        if (item) {
          args.cell.backColor = item.backColor;
          if (holidaysDisabled) {
            args.cell.disabled = true;
          }
        }
      })();

      (function highlightGlobalHolidays() {
        var item = globalHolidays.find(function(range) {
          var start = new DayPilot.Date(range.start);
          var end = new DayPilot.Date(range.end).addDays(1);
          return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
        });

        if (item) {
          args.cell.backColor = item.backColor;

          if (holidaysDisabled) {
            args.cell.disabled = true;
          }

        }
      })();
    },
    onBeforeTimeHeaderRender: function(args) {
      if (args.header.level === 1) {
        var item = globalHolidays.find(function(range) {
          var start = new DayPilot.Date(range.start);
          var end = new DayPilot.Date(range.end).addDays(1);
          return DayPilot.Util.overlaps(start, end, args.header.start, args.header.end);
        });

        if (item) {
          var start = new DayPilot.Date(item.start);
          var end = new DayPilot.Date(item.end).addDays(1);

          args.header.areas = [
            { start: start, end: end, bottom: 0, height: 5, backColor: item.headerColor}
          ];
        }
      }
    }
  });
  dp.resources = [
    { name: "Resource A", id: "A", holidays: [
        { start: "2021-07-05", end: "2021-07-10", backColor: "#f4cccc"}
      ]},
    { name: "Resource B", id: "B", holidays: [
        { start: "2021-07-04", end: "2021-07-06", backColor: "#d9ead3"}
      ]},
    { name: "Resource C", id: "C"},
    { name: "Resource D", id: "D"},
    { name: "Resource E", id: "E"},
    { name: "Resource F", id: "F"},
    { name: "Resource G", id: "G"},
    { name: "Resource H", id: "H"},
    { name: "Resource I", id: "I"},
    { name: "Resource J", id: "J"},
  ];
  dp.events.list = [];
  dp.init();
</script>



<script>
  var elements = {
    disable: document.getElementById("disable")
  };

  (function init() {
    elements.disable.addEventListener("change", function(ev) {
      holidaysDisabled = this.checked;
      console.log("holidaysDisabled", holidaysDisabled);
      dp.update();
    });
  })();
</script>

</body>
</html>