How to stop fullcalendar from interrupting dragging and resizing when polled - javascript

I have been trying to get fullcalendar to react to polling for new events, but whenever it calls refetchEvents, if I am dragging or resizing something, it stops me, as if I have released the mouse at the position I am in, which moves or resizes the event respectively to the wrong spot.
I have a jsfiddle, to show this in action.
Here is the code, if it helps:
$(document).ready(function() {
/* initialize the calendar
-----------------------------------------------------------------*/
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
events: [{
title: 'event1',
start: '2017-01-26T08:00:00',
end: '2017-01-26T10:00:00'
}, {
title: 'event2',
start: '2017-01-05',
end: '2017-01-07'
}, {
title: 'event3',
start: '2017-01-09T06:30:00',
end: '2017-01-09T09:30:00',
}]
});
});
setInterval(function() {
$('#calendar').fullCalendar('refetchEvents');
console.log('refetchEvents called');
}, 5000);

May be not the most efficient, using fetchEventsLock reference on eventDragStart and eventDragStop and fetch events only when released === false.
var fetchEventsLock = false;
$(document).ready(function () {
/* initialize the calendar
-----------------------------------------------------------------*/
function toggleLock() {
fetchEventsLock = !fetchEventsLock;
console.log('Set To ' + fetchEventsLock)
}
$('#calendar').fullCalendar({
eventDragStart: toggleLock,
eventDragStop: toggleLock,
/* Other option removed */
});
});
setInterval(function () {
if (fetchEventsLock === false) {
$('#calendar').fullCalendar('refetchEvents');
console.log('refetchEvents called');
}
}, 5000);

Related

Not able to drop external elements on calendar

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

Allow events to be dragged only onto background events

I am managing appointments on fullcalendar. I have available slots of time where I can create new appointments. Also I can drag appointments onto available time slots which are shown as background events.
I only want the drop functionality on background event slots.
I have tried the eventOverlap method but it only works when the event is dropped on a background event. If the event is dropped elsewhere then I am unable to detect whether I am dropping the event on background event or on empty slot.
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
defaultView: 'timeGridWeek',
// height: 1080,
plugins: ['dayGrid', 'timeGrid', 'interaction'],
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: {
url: getUrl(),
failure: function() {
toastr.error('Unable to load calendar data, Please try later');
},
success: function() {
}
},
loading: function(bool) {
},
defaultDate: Date.now(),
editable: true,
eventLimit: true,
eventClick: function(info) {
if (info.event.extendedProps.type == 'Calendar') {
showCreateModal(info.event);
}
if (info.event.extendedProps.type == "Appointment") {
showUpdateModal(info.event);
}
},
eventOverlap: function(stillEvent, movingEvent) {
return stillEvent.extendedProps != '' && stillEvent.extendedProps.type === 'Calendar' ? true : false;
},
eventDrop: function(info) {
// check if event is being dropped on past date / slot
if (moment(info.event.start) < moment()) {
info.revert();
return;
}
// check if event is being dropped on future slot
if (moment(info.event.start) > moment()) {
swal({
title: "Are you sure?",
text: "You are about to re-schedule this appointment!",
icon: "warning",
// buttons: true,
buttons: ["No", "Yes !"],
dangerMode: true,
})
.then((response) => {
if (response) {
submitForm(false, true, info.event);
} else {
info.revert();
}
});
}
}
});
calendar.render();
This is what I want:
You're correct that eventOverlap doesn't help you here, because it's only triggered when the event is dropped onto a background event. It doesn't help you when the event is dropped somewhere else.
In fullCalendar 4 you can achieve what you need via the eventConstraint setting. This allows you to limit event dragging to specific windows of time. As the documentation says, you can provide a groupId value to this setting, and then
...events that are being dragged or resized must be fully contained by at least one of the events linked to by the given groupId.
All you need to do as well as that is give all your background events the same groupId.
For example, if you set:
eventConstraint: 1
and then have entries such as these within your event data:
{
start: "2019-07-10 09:00",
end: "2019-07-10 12:00",
rendering: "background",
groupId: 1
},
{
start: "2019-07-11 09:00",
end: "2019-07-11 12:00",
rendering: "background",
groupId: 1
},
This would mean that you would only be allowed to drag or resize an existing calendar event if you drag/resize it so that it falls entirely within the time periods covered by those background events which have a groupId of 1.
Here's a working demonstration: https://codepen.io/ADyson82/pen/jjdEjB

Adding a class to Fullcalendar Allday tag

I would like to add a class to the allday row in agendaDay view to highlight it when the user selects it.
Currently my code looks like this:
$('#calendar').fullCalendar({
header: {
left: 'prevYear,prev,today,next,nextYear',
center: 'title',
right: 'agendaDay,agendaWeek,month,listMonth'
},
defaultView: defaultView,
navLinks: true,
eventColor: 'blue',
allDaySlot: true,
height: "auto",
events: {title: 'All Day Event', start: '2018-03-01',id: 999},
dayClick: function(date, jsEvent, view) {
if(view.name != 'agendaDay'){
$(".fc-state-highlight").removeClass("fc-state-highlight");
$("td[data-date=" + date.format('YYYY-MM-DD') + "]").addClass("fc-state-highlight");
}
if(view.name == 'agendaDay'){
$(".fc-state-highlight").removeClass("fc-state-highlight");
$('[data-time="'+date.format('hh:mm:ss')+'"]').addClass("fc-state-highlight");
}
if (clickTimer == null) {
clickTimer = setTimeout(function () {
clickTimer = null;
console.log("single");
///Single Click code here
console.log(date.format());
$('#calendar').fullCalendar('changeView', 'agendaDay', date);
///
}, 500)
} else {
clearTimeout(clickTimer);
clickTimer = null;
console.log("double");
///Double Click Code here
}
}
});
Is it possible to add a class when the user clicks on it and if not where in the fullcalendar.js file should i add a class to it?
The css is:
.fc-state-highlight {
background:cyan;
}
You can do it quite straightforwardly, for both "month" and "agenda" view types, like this:
JS:
$('#calendar').fullCalendar({
header: {
left: 'prevYear,prev,today,next,nextYear',
center: 'title',
right: 'agendaDay,agendaWeek,month,listMonth'
},
dayClick: function(date, jsEvent, view) {
$(".highlight").removeClass("highlight");
$("td[data-date="+date.format('YYYY-MM-DD')+"]").addClass("highlight");
}
});
CSS:
.highlight
{
background-color:red;
}
I think your main difficulty was that the "fc-state-highlight" class you were using doesn't actually do anything.
See http://jsfiddle.net/sbxpv25p/436/ for a working demo.
You can of course adjust it if you want a different colour, or you only want the highlight to occur in more restricted circumstances etc.

Logic to show Bootstrap popover acting abnormally

I'm having 2 weird issues with my popovers shown here in fiddle
After I have selected a day (in fullcalendar) and the popover shows, I click the day again to hide the popover, then I click again in the same day to show again, but no popover!. It's after I click to show, hide, then click to show again that I'm having issues.
When I click on an eventLimitClick event inside a day (April 20th in fiddle), then click on the day (April 20th). The popover hides after I click the day, but then doesn't show any popover for the day like it should.
Here is some of the logic, but please refer to the fiddle link above for working code.
var $calPopOver;
$('#fullcalendar').fullCalendar({
header: {
left: 'prev,next', //today',
center: 'title',
right: ''
},
defaultView: 'month',
editable: true,
allDaySlot: false,
selectable: true,
eventLimit: 1,
events: function(start, end, timezone, callback) {
$.ajax({
url: '/ManageSpaces/GetDiaryEvents/',
dataType: 'json',
data: {
start: start.format(),
end: end.format(),
id: $("#HiddenYogaSpaceId").val()
},
success: function(doc) {
var events = [];
$(doc).each(function() {
events.push({
title: "1 Event", //$(this).attr('title'),
start: $(this).attr('start') // will be parsed
});
});
callback(events);
}
});
},
eventLimitText: function(numberOfEvents) {
return numberOfEvents + " Events";
},
eventLimitClick: function(cellInfo, jsEvent) {
$(cellInfo.dayEl).popover({
html: true,
placement: 'bottom',
container: 'body',
title: function() {
return $("#events-popover-head").html();
},
content: function() {
return $("#events-popover-content").html();
}
});
//$(cellInfo.dayEl).popover('toggle');
if ($calPopOver) {
$calPopOver.popover('destroy');
}
$calPopOver = $(cellInfo.dayEl).popover('show');
},
eventClick: function(calEvent, jsEvent, view) { //function (data, event, view) {
//var s = cellInfo.segs;
$("#eventDetails.collapse").collapse('toggle');
if ($calPopOver)
$calPopOver.popover('destroy');
},
dayClick: function(data, event, view) {
$dayClickedDate = data.format();
$(this).popover({
html: true,
placement: 'bottom',
container: 'body',
title: function() {
return $("#day-popover-head").html();
},
content: function() {
return $("#day-popover-content").html();
}
});
//$(this).popover('toggle');
if ($calPopOver) {
$calPopOver.popover('destroy');
}
$calPopOver = $(this).popover('show');
}
});
Maybe you can look into these bootstrap examples. If you can manage to get a copy of the examples, it's simple a copy and paste scenario IMO.
http://getbootstrap.com/javascript/
Search for "Popovers popover.js" on this page and scroll a bit down for the examples.

Full Calendar wrong time on click event google calendar

I needed to make Google calendars look nice for a client, so I used Fullcalendar and it now looks great, thanks!
I have one problem though:
When I click on an event, the details display the GMT time. I tried a few things, but I am definitely not a developer, so I need help :)
Any help would be greatly appreciated! Here is my js code so far:
$(document).ready(function() {
$('#calendar').fullCalendar({
theme: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
googleCalendarApiKey: 'my api key',
events: 'my event',
eventClick: function(event) {
// opens events in a popup window
window.open(event.url, 'gcalevent', 'width=600,height=400');
return false;
$scope.start = event;
},
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});
$(document).ready(function() {
$('#calendar').fullCalendar({
events: function(start, end, timezone, callback) {
$.ajax({
url: 'my calendar xml link',
dataType: 'xml',
data: {
start: start.unix(),
end: end.unix()
},
success: function(doc) {
var events = [];
$(doc).find('event').each(function() {
events.push({
title: $(this).attr('title'),
start: $(this).attr('start') // will be parsed
});
});
callback(events);
}
});
},
theme: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
googleCalendarApiKey: 'my api key',
events: 'my calendar id',
eventClick: function(event) {
// opens events in a popup window
window.open(event.url, 'gcalevent', 'width=600,height=400');
return false;
$scope.start = event;
},
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});

Categories

Resources