I am using fullcalendar the non-es6 way, quite honestly because the bundled file was so large it was crashing stuff. Anyway, so I have loaded all the js files manually and all is well. Now I am trying to use Draggable. On the docs https://fullcalendar.io/docs/external-dragging it only shows you how to import Draggable from the interaction plugin. I have the interaction plugin up and running as I can drag events around on the calendar no problem, in fact I am editing bookings in Woo Bookings from them as they are dropped. I am now trying to drag resources from outside the calendar into the calendar and create bookings from them. I am getting Plugin file not loaded for draggable error in console, and of course Uncaught ReferenceError: Draggable is not defined
Here is my code
calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'resourceTimeline', 'interaction' ],
eventOverlap: false,
resourceGroupField: 'groupID',
resourceGroupText: 'groupText',
defaultView: 'resourceTimelineDay',
nowIndicator: true,
droppable: true,
defaultDate: currDate,
eventRender: function(info) {
$(info.el).find('.fc-content').attr("id", "event-" + info.event.id);
},
eventClick: function(info) {
info.jsEvent.preventDefault();
jQuery.colorbox({
href: wsccAppVars.standardajax,
data: {
action: 'fullcal_get_booking',
booking_id: info.event.id,
resource_id: info.event.resourceId
}
})
},
themeSystem: 'standard',
editable: true,
eventStartEditable: false,
eventDurationEditable: false,
resources: fcresources,
resourceColumns: [{
labelText: 'Lagoon',
field: 'lname'
}, {
labelText: 'Product',
field: 'pname'
}],
eventSources: [{
url: wsccAppVars.adminajax, // use the `url` property
color: 'yellow', // an option!
textColor: 'black' // an option!
}],
eventDrop: function(info) {
//console.log(info);
var data = {
booking_id: info.event.id,
resource_id: info.newResource.id,
protect: $("#calendar").data('cal-protect'),
action: 'wbsc_cal_booking_change'
}
//console.log(data);
$.post(wbscAppVars.standardajax, data, function(response) {
$("#calendar_messages").text(response.return_message)
if (!response.success) {
info.revert();
}
})
}
});
containerEl = document.getElementById('draggable_resources');
new Draggable(containerEl, {
itemSelector: '.draggable_resource'
});
calendar.render();```
Related
I have a premium version of this product, I am using the generic code they post on the site for this example. I have this code, which appears to be the correct way to implement the adaptive plugin, but I do not see a way to print the calendar?
What am I missing here?
jQuery.ajax({
type: "GET",
url: "index.php?option=com_ajax&plugin=getEmpData&format=json&ser="+ser+"&m_id="+m_id+"&formid="+formid+"&fdate="+fdate+"&tdate="+tdate,
success: function(data)
{
if (!data.data['0']) {
jQuery("#print-btn").hide();
jQuery("#geted-bschart").html('');
jQuery("#geted-results").html('No Data exist');
} else {
jQuery("#geted-results").html("");
const getEmpData = JSON.parse(data.data['0']);
let bs = getEmpData['0'];
getEmpData.shift();
var calendarEl = document.getElementById('geted-results');
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
initialView: 'dayGridMonth',
views: {
dayGridMonth: {
type: 'dayGrid',
duration: { months: mths },
monthMode: true,
fixedWeekCount: false,
}
},
plugins: [
adaptivePlugin
],
headerToolbar: {
left: '',
center: 'title',
right: ''
},
initialDate: fdtArray['2']+'-'+fdtArray['0']+'-'+fdtArray['1'],
editable: false,
selectable: true,
businessHours: true,
dayMaxEvents: true,
events: getEmpData
});
jQuery("#geted-bschart").html(bs.calc);
calendar.render();
jQuery("#print-btn").show();
if (jQuery( ".res-legends" ) && jQuery( ".res-legends" ).length) {
jQuery(".res-legends").remove();
}
jQuery(lhtml).insertAfter(".fc-header-toolbar");
}
jQuery('#getEmpDataForm input, #getEmpDataForm button').prop('disabled', false);
},
error(xhr,status,error,data)
{
jQuery('#getEmpDataForm input, #getEmpDataForm button').prop('disabled', false);
}
});```
I am trying to use this example -- https://fullcalendar.io/docs/other-calendar-dragging -- to create a page that shows 2 FullCalendar calendars and allows the user to drag events from one calendar to the other. I am able to render both calendars, and pull events for each via ajax from a php page. However, the events only display on the first calendar. If I comment out this line:
events: 'ajax/calendar.php?action=get_monthly_patrol_calendar'
from calendar1, then the events will display on calendar2 only. I'd really appreciate help to enable events to display on BOTH calendars.
FYI, here is my code:
HTML:
<div id="kt_calendar"></div>
<div id="kt_calendar2" ></div>
JS:
var todayDate = moment().startOf('day');
var show_now_indicator=true;
var YM = todayDate.format('YYYY-MM');
var YEAR = todayDate.format('YYYY');
var MONTH = todayDate.format('MM');
var YESTERDAY = todayDate.clone().subtract(1, 'day').format('YYYY-MM-DD');
var TODAY = todayDate.format('YYYY-MM-DD');
var TOMORROW = todayDate.clone().add(1, 'day').format('YYYY-MM-DD');
var NEXT_MONTH = todayDate.clone().add(1, 'month').format('YYYY-MM-DD');
var cal = document.getElementById('kt_calendar');
var calendar = new FullCalendar.Calendar(cal, {
plugins: [ 'bootstrap', 'interaction', 'dayGrid', 'dayGridPlugin', 'timeGrid', 'list' ],
themeSystem: 'bootstrap',
events: 'ajax/calendar.php?action=get_monthly_patrol_calendar',
showNonCurrentDates:false,
isRTL: KTUtil.isRTL(),
contentHeight: 'auto',
//aspectRatio: 3, // see: https://fullcalendar.io/docs/aspectRatio
nowIndicator: show_now_indicator,
now: TODAY,
defaultDate: TODAY,
initialDate: TODAY,
defaultView: 'dayGridMonth',
eventOrder: 'order_by',
eventLimit: false, // true to allow "more" link when too many events
navLinks: true,
eventResizableFromStart: false, //Whether the user can resize an event from its starting edge.
eventDurationEditable: false, //Allow events’ durations to be editable through resizing.
eventResourceEditable: reschedule,//Determines whether the user can drag events between resources.
droppable:reschedule,//Determines if external draggable elements or events from other calendars can be dropped onto the calendar.
eventStartEditable: reschedule,//Allow events’ start times to be editable through dragging.
editable: reschedule, //Determines whether the events on the calendar can be modified.
eventDrop: function(info) {
reschedule_event(info);
},
eventClick: function(info) {
do_event_click(info);
},
eventRender: function(info) {
var element = $(info.el);
},
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay'
},
views: {
dayGridMonth: { buttonText: 'monthly' },
dayGridWeek: { buttonText: 'weekly' },
dayGridDay: { buttonText: 'daily' }
},
});
calendar.render();
var cal2 = document.getElementById('kt_calendar2');
var calendar2 = new FullCalendar.Calendar(cal2, {
plugins: [ 'bootstrap', 'interaction', 'dayGrid', 'dayGridPlugin', 'timeGrid', 'list' ],
themeSystem: 'bootstrap',
events: 'ajax/calendar.php?action=get_monthly_patrol_calendar',
showNonCurrentDates:false,
isRTL: KTUtil.isRTL(),
contentHeight: 'auto',
//aspectRatio: 3, // see: https://fullcalendar.io/docs/aspectRatio
nowIndicator: show_now_indicator,
now: NEXT_MONTH,
defaultDate: NEXT_MONTH,
initialDate: NEXT_MONTH,
defaultView: 'dayGridMonth',
eventOrder: 'order_by',
eventLimit: false, // true to allow "more" link when too many events
navLinks: true,
eventResizableFromStart: false, //Whether the user can resize an event from its starting edge.
eventDurationEditable: false, //Allow events’ durations to be editable through resizing.
eventResourceEditable: reschedule,//Determines whether the user can drag events between resources.
droppable:reschedule,//Determines if external draggable elements or events from other calendars can be dropped onto the calendar.
eventStartEditable: reschedule,//Allow events’ start times to be editable through dragging.
editable: reschedule, //Determines whether the events on the calendar can be modified.
eventDrop: function(info) {
reschedule_event(info);
},
eventClick: function(info) {
do_event_click(info);
},
eventRender: function(info) {
var element = $(info.el);
},
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay'
},
views: {
dayGridMonth: { buttonText: 'monthly' },
dayGridWeek: { buttonText: 'weekly' },
dayGridDay: { buttonText: 'daily' }
},
});
calendar2.render();
Figured it out! The second call was failing bec it was running before the first call completed. I added a delay before loading the 2nd calendar, and now both months load fine:
setTimeout(function() { loadCal2(); }, 3000);
I am trying to use the Fullcalendar where I need to show multiple resources with respective multiple events. The same source may have more events, including the situation of overbooking.
In the front-end I use Ajax to retrieve the datas for the resources and the events separately.
The following is my code; but it does not work. It fetches the resources and the events, shows the resources but unable to show the respective events.
How can I do it? Thanks a lot.
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'interaction', 'resourceTimeline' ],
timeZone: 'Europe/Rome',
defaultDate: today,
locale: 'it',
views: {
timelineFourDays: {
type: 'timeline'
//,duration: { months: 4 }
}
},
defaultView: 'resourceTimelineMonth',
lang: 'it',
aspectRatio: 1.5,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth,resourceTimelineYear'
},
footer: {
left: 'prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth,resourceTimelineYear'
},
resourceAreaWidth: '30%',
resourceLabelText: 'IMPIANTI',
resourceGroupField: 'nome_tipologia',
resourceOrder: 'id',
resourcesInitiallyExpanded: true,
resourceText: 'title',
refetchResourcesOnNavigate: true,
resourceColumns: [
{
labelText: 'IMPIANTO',
field: 'id_impianto',
width: '5%'
},
{
labelText: 'IDENTIFICATIVO',
field: 'impianto_codifica',
width: '15%'
}
,
{
labelText: 'COMUNE',
field: 'nome_comune',
width: '15%'
},
{
labelText: 'ARTICOLO',
field: 'nome_articolo',
width: '15%'
}
],
resources:{
url: '/listallimpiantos',
method: 'get',
_token: CSRF_TOKEN
},
resourceRender: function(renderInfo) {
renderInfo.el.style.backgroundColor = 'green';
renderInfo.el.style.color = '#ffffff';
},
eventSources:{
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
},
eventRender: function(event, element) {
$(element).tooltip({title: event.title});
if (event.statovendita == 'VENDUTO') {
element.css("background-color", '#378006');
}
if (event.statovendita == 'OPZIONATO') {
element.css("background-color", '#FFA500');
}
},
eventColor: '#378006',
eventBackgroundColor: event.color,
editable: true,
eventStartEditable: true,
eventResizableFromStart: true,
eventDurationEditable: true,
eventResize: function(info) {
alert("Per il cliente " + info.event.title + " dal " + info.event.start.toISOString() + " al " + info.event.end.toISOString());
if (!confirm("Confermi?")) {
info.revert();
} else {
alert('Aggiornamento sul db!');
}
},
selectable: true,
selectAllow: function(select) {
return moment().diff(select.start) <= 0
},
});
}
});
calendar.render();
});
Your eventSources definition is incorrect.
The documentation for eventSources it states that you must provide an array for this option. However, you have provided an object instead.
Since you are only providing one event source, you can either
a) change eventSources to events (because that option will accept a single object), i.e.
events: {
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
},
or
b) give eventSources an array containing a single item:
eventSources: [{
url: '/listimpiantosperofferta',
method: 'get',
_token: CSRF_TOKEN,
resourceIds:'title'
}],
The other issue you might have is a similar data-type error: The resourceIds option of the event source object expects an array (again you should check the documentation carefully), not a string.
So again to fix that you can either a) use the singular resourceId option instead:
resourceId: 'title'
or continue to use resourceIds but give it an array containing a single item:
resourceIds: ["title"]
Always remember to study the documentation closely and ensure you're matching the relevant syntax, data types, option names etc. Since JavaScript doesn't have compile-time type checking it's easy to overlook this kind of issue, and it will also often fail silently. That's why you have to pay close attention to examples and specifications beforehand.
when I drag an external element on the calendar, I am not able to create an event on the calendar through it. eventReceive() callback is also not getting fired.
I have set the droppable option to true as well. Can someone please help? Have a look at the code:
HTML:
<div class="fc-event">Drag me !!</div>
JS:
$('.fc-event').each(() => {
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true, // maintain when user navigates (see docs on the renderEvent method)
duration: '02:00',
create: true,
});
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0, // original position after the drag
});
});
const calendarEl = document.getElementById('calendar');
calendar = new Calendar(calendarEl, {
themeSystem: 'standard',
selectable: true,
droppable: true,
columnHeader: true,
selectMirror: true,
editable: true,
plugins: [interactionPlugin, dayGridPlugin, timeGridPlugin],
eventResourceEditable: true,
select(selectionInfo) {
showTaskCreationPopup(selectionInfo.start, selectionInfo.end);
},
eventReceive(element) {
console.log('event received');
createTask(element.event);
},
drop(info) {
console.log('dropped');
createTask(info.jsEvent);
},
eventDrop(info) {
console.log('event dropped');
},
header: {
left: 'prevYear prev today next nextYear',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay',
},
buttonText: {
// eslint-disable-next-line new-cap
prevYear: new moment().year() - 1,
// eslint-disable-next-line new-cap
nextYear: new moment().year() + 1,
},
});
calendar.render();
The way that I was able to achieve this was not through the eventReceive -neither eventDrop- event but using the 'drop' event. The signature is something like:
customDrop = ({ resource, date, draggedEl: { id } }) => {})
var containerEl = document.getElementById('external-events-list');
var eventEls = Array.prototype.slice.call(
containerEl.querySelectorAll('.fc-event')
);
eventEls.forEach(function(eventEl) {
if (eventEl.textContent == "Event1") {
new Draggable(eventEl, {
eventData: {
id: 1,
title: eventEl.innerText.trim(),
color: 'Orange',
textColor:'black'
}
});
} else if (eventEl.textContent == "Event2") {
new Draggable(eventEl, {
eventData: {
id: 2,
title: eventEl.innerText.trim(),
color: '#ccccff',
textColor:'black'
}
});
}}); // end eventEls.forEach
I am migrating from Bootstrap DateTimePicker to Fullcalendar v4 and my problem is filtering events.
With DateTimePicker, I had much more freedom to manipulate with events shown on calendar (it also seems that Fullcalendar v3 had more freedom than v4).
I can't find a method that would just place events from array to screen. So far, this is how my code looks
var calendar = new FullCalendar.Calendar(element, {
plugins: [ 'dayGrid', 'timeGrid', 'list', 'interaction', 'bootstrap' ],
themeSystem: 'bootstrap',
events : function(info, successCallback, failureCallback) {
console.log('events');
self.eventsLoadingRequest(true);
calendarService.getEvents(moment(info.start), moment(info.end)).then(
function(result) {
ko.utils.arrayPushAll(self.events, self.parseByType(result));
self.eventsLoadingRequest(false);
successCallback(ko.utils.arrayMap(self.events(), function(item) { return item.serialize() }));
},
function(error) {
}
);
},
customButtons: {
filterEvents: {
text: 'Events',
click: function() {
self.eventsFilter(true, false);
}
},
filterAll: {
text: 'All',
click: function() {
self.eventsFilter(true, true);
}
},
filterGoals: {
text: 'Goals',
click: function() {
self.eventsFilter(false, true);
}
}
},
header: {
left: 'title',
right: 'prev,today,next dayGridMonth,timeGridWeek,timeGridDay,listWeek, filterEvents,filterAll,filterGoals'
},
navLinks: true,
editable: true,
eventLimit: true
});
And eventsFilter function merges two arrays into one. Is it possible to manually call events : function(info, successCallback, failureCallback)?
I want to avoid using multiple streams and reloading events to apply filter.