I have checked the API and haven't been able to find what I'm looking for, is it possible to drag and re-arrange resources on the screen?
In this example, can I drag and re-order Rooms from A,B,C,D
to B,C,A,D
for example?
https://fullcalendar.io/js/fullcalendar-scheduler-1.6.2/demos/vertical-resource-view.html
Thank you
Sure, but not without external drag and drop code. Below, I've used jQueryUI's Sortable
functionality and hooked into its events.
To make this work the resource list is populated via a function. This means that we can reorder the resources and then call the Callendar's refetchResources
method to have it retrieve & redraw the display. I've added a sorting property to the calendar options - resourceOrder: 'sortOrder'
to make sure it orders the Resources correctly.
There are two distinct views with FullCalendar resources - vertical, with Resources as html th
cells, and horizontal with the Resources as html td
. With the vertical case the jQueryUI Sortable events are lost and must be reapplied after calling refetchResources
. I've included the code for both layouts below.
To run, save the html in \fullcalendar-scheduler-1.6.2\demos\
- the paths are relative to that folder.
Vertical View:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='../lib/fullcalendar.min.css' rel='stylesheet' />
<link href='../lib/fullcalendar.print.min.css' rel='stylesheet' media='print' />
<link href='../scheduler.min.css' rel='stylesheet' />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src='../lib/moment.min.js'></script>
<script src='../lib/jquery.min.js'></script>
<script src='../lib/fullcalendar.min.js'></script>
<script src='../scheduler.min.js'></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
var resources = [
{ id: 'a', sortOrder: 1},
{ id: 'b', sortOrder: 2, eventColor: 'green' },
{ id: 'c', sortOrder: 3, eventColor: 'orange' },
{ id: 'd', sortOrder: 4 },
{ id: 'e', sortOrder: 5 },
{ id: 'f', sortOrder: 6, eventColor: 'red' },
{ id: 'g', sortOrder: 7 }
];
$(function() { // document ready
$('#calendar').fullCalendar({
now: '2017-05-07',
editable: true, // enable draggable events
aspectRatio: 1.8,
scrollTime: '00:00', // undo default 6am scrollTime
header: {
left: 'today prev,next',
center: 'title',
right: ''
},
defaultView: 'agendaDay',
views: {},
resourceLabelText: 'Rooms',
resourceText: function(resource) {
return 'Auditorium ' + ('' + resource.id).toUpperCase();
},
resourceOrder: 'sortOrder',
resources: resourcesFunc,
events: [
{ id: '1', resourceId: 'b', start: '2017-05-07T02:00:00', end: '2017-05-07T07:00:00', title: 'event 1' },
{ id: '2', resourceId: 'c', start: '2017-05-07T05:00:00', end: '2017-05-07T22:00:00', title: 'event 2' },
{ id: '3', resourceId: 'd', start: '2017-05-06', end: '2017-05-08', title: 'event 3' },
{ id: '4', resourceId: 'e', start: '2017-05-07T03:00:00', end: '2017-05-07T08:00:00', title: 'event 4' },
{ id: '5', resourceId: 'f', start: '2017-05-07T00:30:00', end: '2017-05-07T02:30:00', title: 'event 5' }
]
});
function resourcesFunc(callback) {
callback(resources);
}
});
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
<script>
$(function() {
var initialPos, finalPos;
$("table thead tr").sortable({
items: "> th:gt(0)",
axis: "x"
})
.disableSelection()
.on("sortstart", function(event, ui) {
initialPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell
})
.on("sortupdate", function(event, ui) {
sortUpdate(event, ui);
});
function sortUpdate(event, ui) {
finalPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell
if (finalPos == -1) return; // "sortupdate" gets called twice for an unknown reason. Second time with finalPos == -1
var tmpResources = [];
for (var i = 0; i < resources.length; i++) {
tmpResources.push(resources[i]);
}
// reorder sorting to match
if (finalPos > initialPos) {
tmpResources[finalPos] = resources[initialPos];
tmpResources[finalPos].sortOrder = finalPos + 1;
for (var i = initialPos + 1; i <= finalPos; i++) {
//resources[i].sortOrder -= 1;
tmpResources[i - 1] = resources[i];
tmpResources[i - 1].sortOrder -= 1;
}
} else {
tmpResources[finalPos] = resources[initialPos];
tmpResources[finalPos].sortOrder = finalPos + 1;
for (var i = initialPos - 1; i >= finalPos; i--) {
//resources[i].sortOrder += 1;
tmpResources[i + 1] = resources[i];
tmpResources[i + 1].sortOrder += 1;
}
}
for (var i = 0; i < tmpResources.length; i++) {
resources[i] = tmpResources[i];
}
$('#calendar').fullCalendar('refetchResources'); // refresh display
// sorting is lost after a refetch when in vertical display, so need to reapply:
$("table thead tr").sortable({
items: "> th:gt(0)",
axis: "x"
})
.disableSelection()
.on("sortstart", function(event, ui) {
initialPos = ui.item.index() - 1; // need to subtract 1 because of the empty first header cell
})
.on("sortupdate", function(event, ui) {
sortUpdate(event, ui);
});
}
});
</script>
</body>
</html>
Horizontal View:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='../lib/fullcalendar.min.css' rel='stylesheet' />
<link href='../lib/fullcalendar.print.min.css' rel='stylesheet' media='print' />
<link href='../scheduler.min.css' rel='stylesheet' />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src='../lib/moment.min.js'></script>
<script src='../lib/jquery.min.js'></script>
<script src='../lib/fullcalendar.min.js'></script>
<script src='../scheduler.min.js'></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
var resources = [
{ id: 'a', sortOrder: 1},
{ id: 'b', sortOrder: 2, eventColor: 'green' },
{ id: 'c', sortOrder: 3, eventColor: 'orange' },
{ id: 'd', sortOrder: 4 },
{ id: 'e', sortOrder: 5 },
{ id: 'f', sortOrder: 6, eventColor: 'red' },
{ id: 'g', sortOrder: 7 }
];
$(function() { // document ready
$('#calendar').fullCalendar({
now: '2017-05-07',
editable: true, // enable draggable events
aspectRatio: 1.8,
scrollTime: '00:00', // undo default 6am scrollTime
header: {
left: 'today prev,next',
center: 'title',
right: ''
},
defaultView: 'timelineDay',
views: {
timelineThreeDays: {
type: 'timeline',
duration: {
days: 3
}
}
},
resourceLabelText: 'Rooms',
resourceText: function(resource) {
return 'Auditorium ' + ('' + resource.id).toUpperCase();
},
resourceOrder: 'sortOrder',
resources: resourcesFunc,
events: [
{ id: '1', resourceId: 'b', start: '2017-05-07T02:00:00', end: '2017-05-07T07:00:00', title: 'event 1' },
{ id: '2', resourceId: 'c', start: '2017-05-07T05:00:00', end: '2017-05-07T22:00:00', title: 'event 2' },
{ id: '3', resourceId: 'd', start: '2017-05-06', end: '2017-05-08', title: 'event 3' },
{ id: '4', resourceId: 'e', start: '2017-05-07T03:00:00', end: '2017-05-07T08:00:00', title: 'event 4' },
{ id: '5', resourceId: 'f', start: '2017-05-07T00:30:00', end: '2017-05-07T02:30:00', title: 'event 5' }
]
});
function resourcesFunc(callback) {
callback(resources);
}
});
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
<script>
$(function() {
var initialPos, finalPos;
$("table tbody").sortable({
axis: "y"
})
.disableSelection()
.on("sortstart", function(event, ui) {
initialPos = ui.item.index();
})
.on("sortupdate", function(event, ui) {
finalPos = ui.item.index();
if (finalPos == -1) return; // "sortupdate" gets called twice for an unknown reason. Second time with finalPos == -1
var tmpResources = [];
for (var i = 0; i < resources.length; i++) {
tmpResources.push(resources[i]);
}
// reorder sorting to match
if (finalPos > initialPos) {
tmpResources[finalPos] = resources[initialPos];
tmpResources[finalPos].sortOrder = finalPos + 1;
for (var i = initialPos + 1; i <= finalPos; i++) {
//resources[i].sortOrder -= 1;
tmpResources[i - 1] = resources[i];
tmpResources[i - 1].sortOrder -= 1;
}
} else {
tmpResources[finalPos] = resources[initialPos];
tmpResources[finalPos].sortOrder = finalPos + 1;
for (var i = initialPos - 1; i >= finalPos; i--) {
//resources[i].sortOrder += 1;
tmpResources[i + 1] = resources[i];
tmpResources[i + 1].sortOrder += 1;
}
}
for (var i = 0; i < tmpResources.length; i++) {
resources[i] = tmpResources[i];
}
$('#calendar').fullCalendar('refetchResources'); // refresh display
})
});
</script>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With