There might be events that span over a weekend or another time period marked as non-business. In such cases, you may want to exclude the non-business hours from the total event duration.

The following features can assist you in implementing this scenario:

  • You can highlight the segments of the event that fall during non-business hours.

  • When moving the event, the Scheduler can automatically extend its duration to skip the non-business hours.

  • You can also adjust the event duration during creation and resizing using custom logic.

Highlighting the Non-Business Segments

javascript scheduler skip weekends highlight css

You can highlight the non-business segments using the onBeforeEventRender event handler (see also event active areas). This example highlights non-business weekends:

onBeforeEventRender: (args) => {
    const weekends = app.getWeekendsInRange(args.e.start, args.e.end);
    args.data.areas = weekends.map((w) => {
        return {
            start: w.start,
            end: w.end,
            top: 4,
            bottom: 1,
            cssClass: "weekend"
        };
    });
},

The app.getWeekendsInRange() returns an array of weekend ranges for the supplied dates:

const app = {
    getWeekendsInRange(start, end) {
        const weekends = [];
        let current = start;

        while (current <= end) {
            if (current.getDayOfWeek() === 6) {  // 6 is Saturday
                const weekendStart = current;
                const weekendEnd = current.addDays(2);

                if (weekendEnd <= end) {
                    weekends.push({
                        start: weekendStart,
                        end: weekendEnd
                    });
                } else if (weekendStart <= end) {
                    weekends.push({
                        start: weekendStart,
                        end: weekendEnd
                    });
                }
                current = current.addDays(7);  // Move to next Saturday
            } else {
                current = current.addDays(1);
            }
        }

        return weekends;
    }
};

And the weekend CSS class that adds semi-transparent stripes:

.weekend {
    background-image: repeating-linear-gradient(45deg, #00000033, #00000033 10px, transparent 10px, transparent 20px);
}

Skipping Non-Business Hours during Event Moving

The Scheduler supports

You can enable it using eventMovingSkipNonBusiness property:

{
  // ...
  eventMovingSkipNonBusiness: true,
}

In this case, the Scheduler will calculate the event duration based on business hours and will automatically adjust (either prolong or shorten) the event as necessary during drag and drop.

The following time segments will not be included in the new duration:

Skipping Non-Business Hours during Event Creation

During event creation, skipping non-business hours is not enforced automatically.

There are multiple ways to handle a new time range selection that starts or ends during a non-business segment:

  1. Shorten the selection to end at the previous business cell.

  2. Extend the selection to end at the next business cell.

  3. Mark the selection as invalid.

You can implement your own rule using the onTimeRangeSelecting event handler. The following example demonstrates how to extend the selection to end on the next business day:

{
  // ...
  onTimeRangeSelecting: (args) => {
    const cells = args.row.cells.forRange(args.start, args.end);
    let first = cells[0];
    let last = cells.last();

    while (first && !first.properties.business) {
      const minusDuration = new DayPilot.Duration(first.end, first.start);
      args.start = args.start.addTime(minusDuration);
      first = DayPilot.list(args.row.cells.forRange(args.start, args.start.addSeconds(1))).first();
    }
    if (!first) {
      args.start = dp.visibleStart();
      args.allowed = false;
      args.right.enabled = true;
      args.right.html = "Out of range";
    }

    while (last && !last.properties.business) {
      const duration = new DayPilot.Duration(last.start, last.end);
      args.end = args.end.addTime(duration);
      last = DayPilot.list(args.row.cells.forRange(args.end.addSeconds(-1), args.end)).first();
    }
    if (!last) {
      args.end = dp.visibleEnd();
      args.allowed = false;
      args.left.enabled = true;
      args.left.html = "Out of range";
    }
  },
}

For an example project, see the JavaScript Scheduler: Skip Non-Business Cells during Drag and Drop tutorial.

Skipping Non-Business Hours during Event Resizing

The same logic can be applied during event resizing. An example onEventResizing implementation that extends the target duration automatically could look like this (see also event resizing customization):

{
  // ...
  onEventResizing: function(args) {
    const cells = args.row.cells.forRange(args.start, args.end);
    let first = cells[0];
    let last = cells.last();

    while (first && !first.properties.business) {
      const minusDuration = new DayPilot.Duration(first.end, first.start);
      args.start = args.start.addTime(minusDuration);
      first = DayPilot.list(args.row.cells.forRange(args.start, args.start.addSeconds(1))).first();
    }
    if (!first) {
      args.start = dp.visibleStart();
      args.allowed = false;
      args.right.enabled = true;
      args.right.html = "Out of range";
    }

    while (last && !last.properties.business) {
      const duration = new DayPilot.Duration(last.start, last.end);
      args.end = args.end.addTime(duration);
      last = DayPilot.list(args.row.cells.forRange(args.end.addSeconds(-1), args.end)).first();
    }
    if (!last) {
      args.end = dp.visibleEnd();
      args.allowed = false;
      args.left.enabled = true;
      args.left.html = "Out of range";
    }
  },
}

For an example project, see the JavaScript Scheduler: Skip Non-Business Cells during Drag and Drop tutorial.