JavaScript Yearly Scheduler

The JavaScript Scheduler component can be configured to display a yearly scheduler where each row represents one month.

Available since 2024.2.5392.

A similar yearly view with switched axes can be created using the Calendar component.

How to Create the Yearly Scheduler

In order to show months as rows, it is necessary to define 12 rows with a custom start:

for (let i = 0; i < 12; i++) {
    const month = year.addMonths(i);
    resources.push({
        name: month.toString("MMMM"),
        start: month
    });
}

Unlike the standard Resources view of the Scheduler, the row don’t use any ID.

The length of timeline (which is displayed on the horizontal axis) needs to be set to 31 days:

{
  days: 31,
  scale: "Day",
  // ...
}

The startDate needs to be set to the first day of the year. This value will be used for the time header displayed on the X axis.

{
  startDate: DayPilot.Date.today().firstDayOfYear(),
  // ...
}

You can configure the time header to display the day numbers using the timeHeaders config property:

{
  timeHeaders: [
      {groupBy: "Day", format: "d"}
  ],
  // ...
}

Some months are shorter than 31 days, so we need to shade-out the extra days in each row using onBeforeCellRender:

{
  onBeforeCellRender: args => {
      const belongsToCurrentMonth = args.cell.x + 1 === args.cell.start.getDay();

      if (!belongsToCurrentMonth) {
         args.cell.properties.backColor = "#dddddd";
      }
  },
  // ...
}

In most cases, it might be useful to set the cell width automatically so that the cell fill the available width:

{
  cellWidthSpec: "Auto",
  // ...
}

Demo

JavaScript Example

<div id="dp"></div>

<script>

    const dp = new DayPilot.Scheduler("dp", {
        days: 31,
        scale: "Day",
        timeHeaders: [
            {groupBy: "Day", format: "d"}
        ],
        cellWidthSpec: "Auto",
        onBeforeCellRender: args => {
            const belongsToCurrentMonth = args.cell.x + 1 === args.cell.start.getDay();

            if (!belongsToCurrentMonth) {
               args.cell.properties.backColor = "#dddddd";
            }
        }
    });
    dp.init();

    const app = {
        loadData() {
            const resources = [];

            const year = DayPilot.Date.today().firstDayOfYear();

            for (let i = 0; i < 12; i++) {
                const month = year.addMonths(i);
                resources.push({
                    name: month.toString("MMMM"),
                    start: month
                });
            }

            const events = [];

            dp.update({
                resources,
                events,
                startDate: year
            });
        },
    };
    app.loadData();

</script>