Overview
-
You can implement custom time range selection limits using the
onTimeRangeSelectingevent handler. -
This example applies dynamic minimum and maximum selection duration rules while the user is dragging over the Scheduler grid.
-
Requires DayPilot Pro for JavaScript version 2020.4.4728 or later.
-
Includes a trial version of DayPilot Pro for JavaScript (see License below).
License
Licensed for testing and evaluation purposes. Please see the licensing information included in the downloadable sample. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.
Limit Time Range Selection to One Cell
By default, the JavaScript Scheduler lets users select a time range without limitations. You can implement your own rules for time range selection using the onTimeRangeSelecting event handler.
This example limits the selection to one day. In combination with scale: "Day", this lets users select just a single cell. The same one-day limit is also available in the sample by choosing 1 day in the maximum-duration selector.
onTimeRangeSelecting: (args) => {
const movingEnd = args.anchor === args.start;
const maxDuration = DayPilot.Duration.ofDays(1);
if (args.duration > maxDuration) {
if (movingEnd) {
args.end = args.start.addTime(maxDuration.ticks);
}
else {
args.start = args.end.addTime(-maxDuration.ticks);
}
}
},
In the first step, we detect whether the user is extending the selection end or start:
const movingEnd = args.anchor === args.start;
We create a DayPilot.Duration object representing one day:
const maxDuration = DayPilot.Duration.ofDays(1);
If the current selection is longer than the maximum allowed duration, we reset the args.start or args.end value:
if (args.duration > maxDuration) {
if (movingEnd) {
args.end = args.start.addTime(maxDuration.ticks);
}
else {
args.start = args.end.addTime(-maxDuration.ticks);
}
}
Dynamic Time Range Selection Limit
It is possible to extend this logic to include more advanced rules. The following example reads the minimum and maximum duration from the toolbar. The any option has the value 0 and disables the corresponding rule.
onTimeRangeSelecting: (args) => {
const movingEnd = args.anchor === args.start;
const min = parseInt(document.querySelector("#min").value, 10);
const minEnabled = min !== 0;
const max = parseInt(document.querySelector("#max").value, 10);
const maxEnabled = max !== 0;
if (minEnabled) {
const duration = DayPilot.Duration.ofDays(min);
if (args.duration < duration) {
if (movingEnd) {
args.end = args.start.addTime(duration.ticks);
}
else {
args.start = args.end.addTime(-duration.ticks);
}
}
}
if (maxEnabled) {
const duration = DayPilot.Duration.ofDays(max);
if (args.duration > duration) {
if (movingEnd) {
args.end = args.start.addTime(duration.ticks);
}
else {
args.start = args.end.addTime(-duration.ticks);
}
}
}
},
Full Source Code
And this is the full source code of the example that limits the Scheduler time range selection duration:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JavaScript Scheduler: Limit Time Range Selection (Min/Max)</title>
<style type="text/css">
p, body, td, input, select, button { font-family: -apple-system,system-ui,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif; font-size: 14px; }
body { padding: 0px; margin: 0px; background-color: #ffffff; }
a { color: #1155a3; }
.space { margin: 10px 0px 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); }
.header a { color: white; }
.header h1 a { text-decoration: none; }
.header h1 { padding: 0px; margin: 0px; }
.main { padding: 10px; margin-top: 10px; }
.generated { color: #999; }
.generated a { color: #999; }
</style>
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
<style>
.toolbar {
margin: 10px 0px;
font-size: 14px;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.toolbar-item {
display: flex;
align-items: center;
gap: 5px;
}
.toolbar-item select {
font-size: 14px;
padding: 3px;
}
</style>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/44990/javascript-scheduler-limit-time-range-selection-min-max'>JavaScript Scheduler: Limit Time Range Selection (Min/Max)</a></h1>
<div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React/Vue</div>
</div>
<div class="main">
<div class="toolbar">
Time range selection limit:
<div class="toolbar-item">
min:
<select id="min">
<option value="0">any</option>
<option value="1">1 day</option>
<option value="2">2 days</option>
<option value="3">3 days</option>
</select>
</div>
<div class="toolbar-item">
max:
<select id="max">
<option value="0">any</option>
<option value="1">1 day</option>
<option value="2">2 days</option>
<option value="3">3 days</option>
<option value="4">4 days</option>
<option value="5">5 days</option>
<option value="6">6 days</option>
</select>
</div>
</div>
<div id="dp"></div>
<div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>
<script>
const dp = new DayPilot.Scheduler("dp", {
timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
scale: "Day",
days: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
timeRangeSelectedHandling: "Enabled",
onTimeRangeSelected: async (args) => {
const scheduler = args.control;
const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
scheduler.clearSelection();
if (modal.canceled) { return; }
scheduler.events.add({
start: args.start,
end: args.end,
id: DayPilot.guid(),
resource: args.resource,
text: modal.result
});
},
onTimeRangeSelecting: (args) => {
const movingEnd = args.anchor === args.start;
const min = parseInt(document.querySelector("#min").value, 10);
const minEnabled = min !== 0;
const max = parseInt(document.querySelector("#max").value, 10);
const maxEnabled = max !== 0;
if (minEnabled) {
const duration = DayPilot.Duration.ofDays(min);
if (args.duration < duration) {
if (movingEnd) {
args.end = args.start.addTime(duration.ticks);
}
else {
args.start = args.end.addTime(-duration.ticks);
}
}
}
if (maxEnabled) {
const duration = DayPilot.Duration.ofDays(max);
if (args.duration > duration) {
if (movingEnd) {
args.end = args.start.addTime(duration.ticks);
}
else {
args.start = args.end.addTime(-duration.ticks);
}
}
}
},
treeEnabled: true,
});
dp.init();
const app = {
init() {
const 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"},
{name: "Resource 8", id: "R8"},
{name: "Resource 9", id: "R9"},
];
const events = [];
dp.update({resources, events});
}
};
app.init();
</script>
</body>
</html>
History
April 23, 2026: Updated the sample to the current JavaScript project structure, modernized the selection-limit code, and added one-day maximum selection to the sample toolbar.
DayPilot




