This is an example of an implementation of Fullcalendar v5 using the simplest way to get started, with Fullcalendar’s pre-built bundles and script tags. Will try to comment the code as much as I can. Nevertheless, most of the elements are available in the documentation.
This example is based on two PHP files, one for a form filter plus the calendar itself, and the second one for the getting the data for the calendar.
Note that I will be using in this example:
- jQuery 3.6.0
- Select2 4.0.7
- JavaScript Cookie v2.2.0
- Moment.js 2.19.3
- Fullcalendar v.5.10.0 (documentation)
Main PHP file with the calendar.
<link rel='stylesheet' type='text/css' href='/route_to/fullcalendar.5.10.0/main.css'/>
<script src="/route_to/fullcalendar.5.10.0/main.min.js" type="text/javascript"></script>
<script src="/route_to/fullcalendar.5.10.0/locales/pt.js" type="text/javascript"></script>
<form class="form" name='form_calendario' id='form_calendario'>
<!-- form elements, no need to exemplify this part -->
</form>
<!-- div placeholder for the calendar -->
<div id='calendario'></div>
The javascript part:
<script type='text/javascript'>
// some variables iniciation
var $form_filter = $("#form_calendario");
var $filtros = "form_calendariov2";
var $filter_cookie = Cookies.get($filtros);
var $formIDs = [];
var $locBase = "<?=LOC_BASE?>";
var elFiltro = $("#filtro");
var elDepartamentos = $("#id_departamento");
var elUtilizadores = $("#id_utilizador");
// check if that Cookies are set or not for the filter form inputs
// if they are set, fill out the fields with the data stored
if (!($filter_cookie === 'null' || $filter_cookie === undefined || $filter_cookie === null)) {
var fields = JSON.parse($filter_cookie);
for (var i = 0; i < fields.length; i++) {
var controlName = fields[i].name;
var controlValue = fields[i].value;
var tipo = $("#" + controlName).prop("type");
if (tipo === 'select-multiple') {
$("#" + controlName + " option[value=" + controlValue + "]").attr('selected', true);
}
else {
$("#" + controlName).val(controlValue);
}
}
filtro = elFiltro.val();
departamentos = elDepartamentos.val();
utilizadores = elUtilizadores.val();
}
// calendar initiation
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendario');
filtro = elFiltro.val();
departamentos = elDepartamentos.val();
utilizadores = elUtilizadores.val();
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left : 'prev,next today',
center: 'title',
right : 'dayGridMonth,timeGridWeek,timeGridDay,listWeek,myRefresh'
},
navLinks : true, // can click day/week names to navigate views
nowIndicator : true,
initialView : 'timeGridWeek',
weekNumbers : true,
weekNumberCalculation: 'ISO',
locale : 'pt',
editable : true,
selectable : true,
dayMaxEvents: true, // allow "more" link when too many events
slotMinTime: '07:00:00',
slotMaxTime: '22:00:00',
businessHours: [
{
// days of week. an array of zero-based day of week integers (0=Sunday)
daysOfWeek: [1, 2, 3, 4, 5], // Monday - Friday
startTime: '09:00', // a start time (10am in this example)
endTime : '13:00', // an end time (6pm in this example)
},
{
daysOfWeek: [1, 2, 3, 4, 5],
startTime: '14:30',
endTime : '18:30',
},
{
daysOfWeek: [6],
startTime: '10:00',
endTime : '13:00',
},
],
aspectRatio: 2.25,
expandRows: true,
events: {
// events will be loaded from a file with queries
// data returned das JSON
url : $locBase + "estatisticas/calendario_carrega_eventos.php",
// extra parameters that will be sent with the file requested above
// extra parameters are needed to be able to filter out results
// using the form information imputed above
extraParams: function () {
var filtro = elFiltro.val();
var departamentos = elDepartamentos.val();
var utilizadores = elUtilizadores.val();
return {
filtro : filtro,
departamentos: departamentos,
utilizadores : utilizadores
}
},
failure : function () {
document.getElementById('script-warning').style.display = 'block'
}
},
// eventDidMount - called right after the element has been added to the DOM.
// will need this since we want to add an icon after the time lables
eventDidMount: function (event) {
let $reagendamento = event.event.extendedProps.reagendamento;
let $tipoAccao = event.event.extendedProps.tipo_accao;
let $icon = event.event.extendedProps.icon;
let $start = event.event.extendedProps.startTime;
let $end = event.event.extendedProps.endTime;
let $title = event.event._def.title;
let $timeText = event.timeText;
let $viewType = event.view.type;
let $html = "";
if ($icon) {
if ($viewType === 'timeGridWeek') {
let elemento = $(event.el).find('.fc-event-time');
// console.log("elemento", elemento);
$html = " <i class='" + $icon + "'></i> ";
elemento.append($html);
}
if ($viewType === 'listWeek') {
let elemento = $(event.el).find('.fc-list-event-time');
// console.log("elemento", elemento);
$html = " <i class='" + $icon + "'></i> ";
elemento.append($html);
}
}
},
// This is triggered when the user clicks an event.
eventClick: function (info) {
// don't let the browser navigate just yet
info.jsEvent.preventDefault();
let $URL = info.event.url;
// info.el.style.borderColor = 'yellow';
if (info.event.url) {
window.open($URL, '_blank');
}
},
// This is triggered when the user clicks on a date or a time.
dateClick: function (info) {
window.open("?mostra=crm_actividades", '_blank');
},
// This is triggered when dragging stops and the event has moved to a different day/time.
eventDrop: function (info) {
let StartDate = moment(info.event.start).format('YYYY-MM-DD')
let StartTime = moment(info.event.start).format('HH:mm');
let EndDate = moment(info.event.end).format('YYYY-MM-DD')
let EndTime = moment(info.event.end).format('HH:mm');
let TodoDia = info.event.allDay;
let RecordID = info.event.id;
let Reagendamento = info.event.extendedProps.reagendamento;
let OrigemLnk = info.event.extendedProps.origem_lnk;
if (Reagendamento === 'nao_permite_reagendamento') {
info.revert();
}
// save changes made to the event made by dragging
$.ajax({
url : $locBase + 'estatisticas/calendario_grava_eventos.php',
dataType: 'json',
data : {
StartDate : StartDate,
StartTime : StartTime,
EndDate : EndDate,
EndTime : EndTime,
TodoDia : TodoDia,
RecordID : RecordID,
Origem : OrigemLnk,
Reagendamento: Reagendamento,
Task : 'drag'
},
success : function () {
}
});
},
// This will be triggered when resizing stops and the event has changed in duration.
eventResize: function (info) {
let StartDate = moment(info.event.start).format('YYYY-MM-DD')
let StartTime = moment(info.event.start).format('HH:mm');
let EndDate = moment(info.event.end).format('YYYY-MM-DD')
let EndTime = moment(info.event.end).format('HH:mm');
let TodoDia = info.event.allDay;
let RecordID = info.event.id;
let Reagendamento = info.event.extendedProps.reagendamento;
let OrigemLnk = info.event.extendedProps.origem_lnk;
if (Reagendamento === 'nao_permite_reagendamento') {
info.revert();
}
// save changes made to the event made by resizing
$.ajax({
url : $locBase + 'estatisticas/calendario_grava_eventos.php',
dataType: 'json',
data : {
StartDate : StartDate,
StartTime : StartTime,
EndDate : EndDate,
EndTime : EndTime,
TodoDia : TodoDia,
RecordID : RecordID,
Origem : OrigemLnk,
Reagendamento: Reagendamento,
Task : 'size'
},
success : function () {
}
});
},
// A custom button to force refresh the calendar, since calendar events
// are beeing added/changed all the time by other team members
customButtons: {
myRefresh: {
text: 'Refresh',
click: function() {
calendar.refetchEvents();
}
}
},
});
calendar.render();
elFiltro.change(function (e) {
guardaCookie();
calendar.refetchEvents();
});
elDepartamentos.select2().change(function () {
guardaCookie();
calendar.refetchEvents();
});
elUtilizadores.select2().change(function () {
guardaCookie();
calendar.refetchEvents();
});
});
function guardaCookie() {
if (elUtilizadores.length <= 0) {
elUtilizadores.val('0');
}
Cookies.set($filtros, JSON.stringify($form_filter.serializeArray()), {
path : '/',
expires: 1
});
}
function getFormData() { // GET ALL SELECT IDS //
$form_filter.find("input, select").each(function () { $formIDs.push(this.id); });
$form_data = {};
$.each($formIDs, function (index, value) {
$form_data[value] = $("#" + value, $form_filter).val();
});
// console.log($formIDs, $form_data);
return $form_data
}
</script>
Any questions? Please leave them in the comments.