Overview
Add a context menu to JavaScript Scheduler events with “Lock” and “Unlock” items.
Users will not be able to move or change the locked events
The context menu is updated dynamically depending on the event status.
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.
Context Menu with “Lock” Item
Lets define a context menu that will allow users lock the Scheduler event:
var dp = new DayPilot.Scheduler("dp", {
contextMenu: new DayPilot.Menu({
items: [
{ text: "Lock",
onClick: function lockToggle(args) {
var e = args.source;
var locked = e.data.tags && e.data.tags.locked;
if (!e.data.tags) {
e.data.tags = {};
}
e.data.tags.locked = !locked;
dp.events.update(e);
}
},
{ text: "-"},
{ text: "Edit...",
onClick: function (args) {
editEvent(args.source);
}
},
],
}),
});
The onClick
event handler of the “Lock” menu item sets the locked
custom property to true
. The custom property is saved under tags
object of the event data object to prevent naming conflicts.
Locking the JavaScript Scheduler Event
We will lock the item using onBeforeEventRender.
var dp = new DayPilot.Scheduler("dp", {
// ...
onBeforeEventRender: function(args) {
var locked = args.data.tags && args.data.tags.locked;
if (locked) {
args.data.moveDisabled = true;
args.data.resizeDisabled = true;
args.data.clickDisabled = true;
}
},
// ...
});
If the “locked” status is detected (args.data.tags.locked
) the drag and drop event operations (moving, resizing) are disabled, as well as the click action.
For more options on making the Scheduler events (or the whole Scheduler) read-only please see the following tutorial:
Locked Event Icon
We will also use onBeforeEventRender
event handler to display a padlock icon inside the locked event:
var dp = new DayPilot.Scheduler("dp", {
// ...
onBeforeEventRender: function(args) {
var locked = args.data.tags && args.data.tags.locked;
if (locked) {
// ...
args.data.areas = [
{ top: 10, right: 4, width: 15, height: 15, image: "padlock-15x15.svg", xhtml: "🚫"}
];
}
},
// ...
});
Unlocking the Scheduler Event
We will use the onShow event of the context menu object to change the context menu items depending on the event status.
If the event is locked, the following changes will be made:
The first menu item (“Lock”) text will be changed to “Unlock”
The “Edit…” item will be disabled
contextMenu: new DayPilot.Menu({
items: [
{ text: "Lock",
onClick: function lockToggle(args) {
var e = args.source;
var locked = e.data.tags && e.data.tags.locked;
if (!e.data.tags) {
e.data.tags = {};
}
e.data.tags.locked = !locked;
dp.events.update(e);
}
},
{ text: "-"},
{ text: "Edit...",
onClick: function (args) {
editEvent(args.source);
}
},
],
onShow: function(args) {
var e = args.source;
var locked = e.data.tags && e.data.tags.locked;
dp.contextMenu.items[0].text = locked ? "Unlock" : "Lock";
dp.contextMenu.items[2].disabled = locked;
}
}),
Full Source Code
This is the full source code of our example that adds a context menu to the JavaScript Scheduler events with an option to lock the event.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JavaScript Scheduler: Lock Events using Context Menu</title>
<style type="text/css">
<!-- ... -->
</style>
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/30746/javascript-scheduler-lock-events-using-context-menu'>JavaScript Scheduler: Lock Events using Context Menu</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 id="dp"></div>
<div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>
<script>
var dp = new DayPilot.Scheduler("dp", {
timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
scale: "Day",
days: 31,
startDate: "2021-08-01",
timeRangeSelectedHandling: "Enabled",
onTimeRangeSelected: function (args) {
var 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
}));
});
},
onBeforeEventRender: function(args) {
var locked = args.data.tags && args.data.tags.locked;
if (locked) {
args.data.moveDisabled = true;
args.data.resizeDisabled = true;
args.data.clickDisabled = true;
args.data.areas = [
{ top: 10, right: 4, width: 15, height: 15, image: "padlock-15x15.svg", xhtml: "🚫"}
];
}
},
onEventClick: function(args) {
editEvent(args.e);
},
contextMenu: new DayPilot.Menu({
items: [
{ text: "Lock",
onClick: function lockToggle(args) {
var e = args.source;
var locked = e.data.tags && e.data.tags.locked;
if (!e.data.tags) {
e.data.tags = {};
}
e.data.tags.locked = !locked;
dp.events.update(e);
}
},
{ text: "-"},
{ text: "Edit...",
onClick: function (args) {
editEvent(args.source);
}
},
],
onShow: function(args) {
var e = args.source;
var locked = e.data.tags && e.data.tags.locked;
dp.contextMenu.items[0].text = locked ? "Unlock" : "Lock";
dp.contextMenu.items[2].disabled = locked;
}
}),
treeEnabled: true,
});
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"},
{name: "Resource 8", id: "R8"},
{name: "Resource 9", id: "R9"},
];
dp.events.list = [
{id: 1, start: "2021-08-05T00:00:00", end: "2021-08-10T00:00:00", text: "Event 1", resource: "R2"}
];
dp.init();
function editEvent(e) {
var form = [
{name: "Name", id: "text"}
];
var data = e.data;
DayPilot.Modal.form(form, data).then(function(modal) {
if (modal.canceled) {
return;
}
e.data = modal.result;
dp.events.update(e);
});
}
</script>
</body>
</html>