Features

  • Implementing 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 but the snap-to-grid uses 5-minute steps
  • 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. Buy a license.

JavaScript Scheduler Configuration

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

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

<script>
  var dp = new DayPilot.Scheduler("dp", {
    timeHeaders: [{"groupBy":"Day"},{"groupBy":"Hour"}],
    scale: "Hour",
    snapToGrid: false,
    useEventBoxes: "Never",
    days: 1,
    startDate: DayPilot.Date.today(),
    // ...
  });
  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 24 hours of one day (one cell per hour):

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

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 Creating

javascript-scheduler-event-creating-snap-to-grid.png

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 start and end time of the selection (args.left.html, args.right.html).

onTimeRangeSelecting: function(args) {
  const snapToMinutes = 5;
  const offsetStart = args.start.getMinutes() % snapToMinutes;
  if (offsetStart) {
    args.start = args.start.addMinutes(-offsetStart);
  }

  const offsetEnd = args.end.getMinutes() % snapToMinutes;
  if (offsetEnd) {
    args.end = args.end.addMinutes(-offsetEnd).addMinutes(snapToMinutes);
  }

  // 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 first onTimeRangeSelected events which adds a new event to the data source:

onTimeRangeSelected: function (args) {
  const 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
    }));
  });
}

Snap-To-Grid for Event Moving

javascript-scheduler-event-moving-snap-to-grid.png

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: function(args) {
  const snapToMinutes = 5;
  const offset = args.start.getMinutes() % snapToMinutes;
  if (offset) {
    args.start = args.start.addMinutes(-offset);
    args.end = args.end.addMinutes(-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.png

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: function(args) {
  const snapToMinutes = 5;
  if (args.start !== args.e.start()) {
    const offsetStart = args.start.getMinutes() % snapToMinutes;
    if (offsetStart) {
      args.start = args.start.addMinutes(-offsetStart);
    }
  }
  else if (args.end !== args.e.end()) {
    const offsetEnd = args.end.getMinutes() % snapToMinutes;
    if (offsetEnd) {
      args.end = args.end.addMinutes(-offsetEnd).addMinutes(snapToMinutes);
    }
  }
  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");
}