Features

  • Implementation of custom snap-to-grid rules using onTimeRangeSelecting, onEventMoving and onEventResizing event handlers.

  • The snap-to-grid matrix doesn't have to correspond to the Scheduler grid cells. This example uses one cell per hour and the snap-to-grid uses 5-minute steps.

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

JavaScript Scheduler Configuration

Let's start with the following JavaScript Scheduler component configuration:

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

<script>
  const dp = new DayPilot.Scheduler("dp", {
    timeHeaders: [{groupBy: "Day"}, {groupBy: "Hour"}],
    scale: "Hour",
    snapToGrid: false,
    useEventBoxes: "Never",
    days: 7,
    startDate: DayPilot.Date.today().firstDayOfWeek(),
    // ...
  });
  dp.resources = [
    {name: "Resource 1", id: "R1"},
    {name: "Resource 2", id: "R2"},
    {name: "Resource 3", id: "R3"},
    {name: "Resource 4", id: "R4"},
    {name: "Resource 5", id: "R5"},
    {name: "Resource 6", id: "R6"},
    {name: "Resource 7", id: "R7"}
  ];
  dp.events.list = [];
  dp.init();

</script>

It's a simple setup that displays the current week (one cell per hour):

scale: "Hour",
days: 7,
startDate: DayPilot.Date.today().firstDayOfWeek(),

The time header displays the date in the first row and hours of day in the second row:

timeHeaders: [{groupBy: "Day"}, {groupBy: "Hour"}]

The built-in snap-to-grid support is turned off (we will use our own implementation):

snapToGrid: false

The event boxes (alignment of events with the grid cell) are turned off as well:

useEventBoxes: "Never"

Snap-To-Grid for Event Creation

javascript scheduler event creation snap to grid

New events can be created using drag and drop time range selecting feature. We will use onTimeRangeSelecting real-time event handler to adjust the selection start and end during dragging (args.start, args.end).

We will also display the adjusted start and end time of the selection (args.left.html, args.right.html).

onTimeRangeSelecting: (args) => {
  const snapToMinutes = 5;
  const snapToMillis = snapToMinutes * 60 * 1000;
  const offsetStart = args.start.getTimePart() % snapToMillis;
  if (offsetStart) {
    args.start = args.start.addMilliseconds(-offsetStart);
  }

  const offsetEnd = args.end.getTimePart() % snapToMillis;
  if (offsetEnd) {
    args.end = args.end.addMilliseconds(-offsetEnd).addMilliseconds(snapToMillis);
  }

  // floor
  args.start = args.start.addSeconds(-args.start.getSeconds()).addMilliseconds(-args.start.getMilliseconds());
  args.end = args.end.addSeconds(-args.end.getSeconds()).addMilliseconds(-args.end.getMilliseconds());

  args.left.enabled = true;
  args.left.html = args.start.toString("h:mm tt");
  args.right.enabled = true;
  args.right.html = args.end.toString("h:mm tt");
},

As soon as the selection is complete (on mouse button release) the Scheduler fires the onTimeRangeSelected event which adds a new event to the data source:

onTimeRangeSelected: async (args) => {
  const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
  dp.clearSelection();
  if (modal.canceled) { return; }
  dp.events.add({
    start: args.start,
    end: args.end,
    id: DayPilot.guid(),
    resource: args.resource,
    text: modal.result
  });
},

Snap-To-Grid for Event Moving

javascript scheduler event moving snap to grid

The next step will be customization of the drag and drop event moving. This can be done using onEventMoving event handler.

The logic is the same here, we adjust the start and end times and display indicators with the time information:

onEventMoving: (args) => {
  const snapToMinutes = 5;
  const snapToMillis = snapToMinutes * 60 * 1000;
  const offset = args.start.getTimePart() % snapToMillis;
  if (offset) {
    args.start = args.start.addMilliseconds(-offset);
    args.end = args.end.addMilliseconds(-offset);
  }

  args.left.enabled = true;
  args.left.html = args.start.toString("h:mm tt");
  args.right.enabled = true;
  args.right.html = args.end.toString("h:mm tt");
}

Snap-To-Grid for Event Resizing

javascript scheduler event resizing snap to grid

We also need to adjust the event resizing behavior. The onEventResizing event handler will update the start and end (depending on how the event is resized) and display the new time:

onEventResizing: (args) => {
  const snapToMinutes = 5;
  const snapToMillis = snapToMinutes * 60 * 1000;
  if (args.start !== args.e.start()) {
    const offsetStart = args.start.getTimePart() % snapToMillis;
    if (offsetStart) {
      args.start = args.start.addMilliseconds(-offsetStart);
    }
  }
  else if (args.end !== args.e.end()) {
    const offsetEnd = args.end.getTimePart() % snapToMillis;
    if (offsetEnd) {
      args.end = args.end.addMilliseconds(-offsetEnd).addMilliseconds(snapToMillis);
    }
  }
  args.left.enabled = true;
  args.left.html = args.start.toString("h:mm tt");
  args.right.enabled = true;
  args.right.html = args.end.toString("h:mm tt");
}