Overview
Add a context menu icon to the upper-left corner of the JavaScript Scheduler using an active area
Dynamically build the context menu items on show
Show check marks next to visible column names in the context menu
Requires DayPilot Pro for JavaScript 2020.2.4373 or later
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.
Live Demo
Define Columns and Data
Lets start with the following configuration that displays three custom columns in the row headers (Name, ID, Capacity):
var dp = new DayPilot.Scheduler("dp", {
rowHeaderColumns: [
{name: "Name", display: "name"},
{name: "ID", display: "id"},
{name: "Capacity", display: "capacity"},
],
// ...
});
dp.resources = [
{name: "Resource 1", id: "R1", capacity: 50},
{name: "Resource 2", id: "R2", capacity: 10},
{name: "Resource 3", id: "R3", capacity: 10},
{name: "Resource 4", id: "R4", capacity: 50},
{name: "Resource 5", id: "R5", capacity: 20},
{name: "Resource 6", id: "R6", capacity: 30},
{name: "Resource 7", id: "R7", capacity: 50},
{name: "Resource 8", id: "R8", capacity: 60},
{name: "Resource 9", id: "R9", capacity: 50},
];
Add Icon that Opens a Context Menu
We will add an icon to the upper-left corner using an active area defined in onBeforeCornerRender event handler.
var dp = new DayPilot.Scheduler("dp", {
onBeforeCornerRender: function(args) {
args.areas = [
{
right: 5,
top: 5,
height: 20,
width: 20,
action: "ContextMenu",
icon: "icon icon-menu",
cssClass: "area-open-menu",
menu: new DayPilot.Menu()
}
]
}
});
Add Context Menu Item that Toggles "Capacity" Column
In this step, we add a testing menu item that toggles visibility of the third column ("Capacity").
It changes the hidden property of the respective rowHeaderColumns item and requests a partial update() that only refreshes the row headers.
var dp = new DayPilot.Scheduler("dp", {
onBeforeCornerRender: function(args) {
args.areas = [
{
right: 5,
top: 5,
height: 20,
width: 20,
action: "ContextMenu",
icon: "icon icon-menu",
cssClass: "area-open-menu",
menu: new DayPilot.Menu({
items: [
{ text: "Toggle 'Capacity' column",
onClick: function(args) {
dp.rowHeaderColumns[2].hidden = !dp.rowHeaderColumns[2].hidden;
dp.update({rowHeaderColumns: dp.rowHeaderColumns});
}
}
]
})
}
]
}
});
Generate the Menu Items Dynamically
In this final step, we use the onShow event handler to generate the context menu items dynamically from the columns array.
Each visible column will also show a check mark icon.
Clicking the menu item will toggle the column visibility.
If there is just one column visible, we will disable the corresponding menu item to make sure there is at least one column visible.
var dp = new DayPilot.Scheduler("dp", {
onBeforeCornerRender: function(args) {
args.areas = [
{
right: 5,
top: 5,
height: 20,
width: 20,
action: "ContextMenu",
icon: "icon icon-menu",
cssClass: "area-open-menu",
menu: new DayPilot.Menu({
onShow: function(args) {
var menu = this;
menu.items = [];
dp.rowHeaderColumns.forEach(function(col) {
menu.items.push({
_column: col,
text: col.name,
icon: col.hidden ? "" : "icon icon-checked",
onClick: function(args) {
// hide the menu, normally it stays visible until onClick completes
menu.hide();
var column = args.item._column;
column.hidden = !column.hidden;
// optimized update
dp.update({rowHeaderColumns: dp.rowHeaderColumns});
}
});
});
var visible = menu.items.filter(function(item) { return !item._column.hidden; });
// only one column visible, prevent action
if (visible.length === 1) {
visible[0].disabled = true;
}
}
})
}
]
}
});
Full Source Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JavaScript Scheduler: Show/Hide Columns using Context Menu</title>
<style type="text/css">
<!-- ... -->
</style>
<style>
i.icon { font-style: normal; }
.icon-checked:before {
content: '\2714';
}
.icon-menu:before {
content: '\2BC6';
}
.scheduler_default_main .area-open-menu {
font-size: 14px;
border: 1px solid #ccc;
box-sizing: border-box;
background-color: white;
text-align: center;
padding: 1px;
cursor: pointer;
}
</style>
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/49959/javascript-scheduler-show-hide-columns-using-context-menu'>JavaScript Scheduler: Show/Hide Columns using Context Menu</a></h1>
<div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React</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: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
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
}));
});
},
rowHeaderColumns: [
{name: "Name", display: "name"},
{name: "ID", display: "id"},
{name: "Capacity", display: "capacity"},
],
treeEnabled: true,
rowHeaderHideIconEnabled: true,
onBeforeCornerRender: function(args) {
args.areas = [
{
right: 5,
top: 5,
height: 20,
width: 20,
action: "ContextMenu",
icon: "icon icon-menu",
cssClass: "area-open-menu",
menu: new DayPilot.Menu({
onShow: function(args) {
var menu = this;
menu.items = [];
dp.rowHeaderColumns.forEach(function(col) {
menu.items.push({
_column: col,
text: col.name,
icon: col.hidden ? "" : "icon icon-checked",
onClick: function(args) {
// hide the menu, normally it stays visible until onClick completes
menu.hide();
var column = args.item._column;
column.hidden = !column.hidden;
// optimized update
dp.update({rowHeaderColumns: dp.rowHeaderColumns});
}
});
});
var visible = menu.items.filter(function(item) { return !item._column.hidden; });
// only one column visible, prevent action
if (visible.length === 1) {
visible[0].disabled = true;
}
}
})
}
]
}
});
dp.resources = [
{name: "Resource 1", id: "R1", capacity: 50},
{name: "Resource 2", id: "R2", capacity: 10},
{name: "Resource 3", id: "R3", capacity: 10},
{name: "Resource 4", id: "R4", capacity: 50},
{name: "Resource 5", id: "R5", capacity: 20},
{name: "Resource 6", id: "R6", capacity: 30},
{name: "Resource 7", id: "R7", capacity: 50},
{name: "Resource 8", id: "R8", capacity: 60},
{name: "Resource 9", id: "R9", capacity: 50},
];
dp.events.list = [];
dp.init();
</script>
</body>
</html>