FullCalendar, modify calendar on eventMouseover/eventMouseout - fullcalendar

https://fullcalendar.io
I have a need to render a background event when mousing over calendar events. Each calendar event has a datetime range associated with it that I would like to display on the calendar when the user hovers the mouse over it (and subsequently remove the background event from the calendar on eventMouseout). However, I've ran into an issue where the eventMouseover and eventMouseout events are triggered multiple times over and over when attempting to modify the fullCalendar on mouse enter/leave. I imagine this has something to do with the calendar being re-rendered when any of its events are touched adding/removing events to the calendar.
If you take a look at this codepen, open up DevTools and watch the console as you move your mouse over/out of any of the calendar events. If you move your mouse back and forth within an event you'll see the over/out events firing back to back, over and over.
What I'd like to have happen is a backgroundEvent (such as the following) to be updated with the datetime range on any given event. Then on mouseout, remove the backgroundEvent from the calendar.
// I'm only here because StackOverflow requires code to be present when a codepen link is shared.
var bgEvent = {
id: -1,
start: null,
end: null,
rendering: 'background',
backgroundColor: 'orange'
};
Instead what happens is the eventMouseover fires, renders the event, followed by the eventMouseout, which immediately removes the event.
EDIT 1:
I'm in the middle of creating a scheduling app, and the calendar events essentially represent individual tasks belonging to a greater "appointment" object. Thus, when hovering over an individual "task" I desire to display its associated "appointment" range on the calendar to assist the user in deciding whether that task can be moved to a different date/time or not.
EDIT 2:
Submitted an issue on FullCalendar's github repo. Will update with any developments from there.
CODE FROM THE ABOVE CODEPEN
HTML
<div id="calendar"></div>
CSS
body {
margin: 40px 10px;
padding: 0;
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 0 auto;
}
JAVASCRIPT
$(function() {
var calendar = $('#calendar');
var bgEvent = {
id: -1,
start: null,
end: null,
rendering: 'background',
backgroundColor: 'orange'
};
calendar.fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek'
},
eventMouseover: function (event, jsEvent, view) {
console.log('in');
bgEvent.start = event.start;
bgEvent.end = event.end;
var events = calendar.fullCalendar('clientEvents', bgEvent.id);
if (events.length) {
var e = events[0];
calendar.fullCalendar('updateEvent', e);
}
else
calendar.fullCalendar('renderEvent', bgEvent);
},
eventMouseout: function (event, jsEvent, view) {
console.log('out');
calendar.fullCalendar('removeEvents', bgEvent.id);
},
defaultDate: '2017-11-06',
editable: true,
eventLimit: true, // allow "more" link when too many events
events: [
{
title: 'All Day Event',
start: '2017-11-01'
},
{
title: 'Long Event',
start: '2017-11-07',
end: '2017-11-10'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-11-09T16:00:00'
},
{
id: 999,
title: 'Repeating Event',
start: '2017-11-16T16:00:00'
},
{
title: 'Conference',
start: '2017-11-05',
end: '2017-11-07'
},
{
title: 'Meeting',
start: '2017-11-06T10:30:00',
end: '2017-11-06T12:30:00'
},
{
title: 'Lunch',
start: '2017-11-06T12:00:00'
},
{
title: 'Meeting',
start: '2017-11-06T14:30:00'
},
{
title: 'Happy Hour',
start: '2017-11-06T17:30:00'
},
{
title: 'Dinner',
start: '2017-11-06T20:00:00'
},
{
title: 'Movie',
start: '2017-11-07T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2017-11-28'
}
]
});
});

Adam Shaw from the FullCalendar project comments that "whenever any events are rendered or rerendered, ALL events are rerendered. What you are seeing is a flash rerender of the foreground event causing a real mouseout. When #3003's optimization is made, this will be fixed."

Related

how to display hours and minutes in allDay-slot in fullcalendar

I am trying to create a view in fullcalendar to show when some people are off duty.
People might be off the from eg. 10:00AM to 09:00AM the next day and I would like to show the event in the allDay-slot in fullcalendar and also show the start and end of the event as part of the title.
If I set the allDay-property on the event, it will display the event in the allDay-slot but it displays the start and end as '00:00' instead of '10:00' and '09:00'.
The other option I have tried is setting a custom property on the event-object called isDayOff, and then in the eventRender-callback set the standard allDay-property on the rendered event. This seems to work, but the event is not rendered in the allDay-slot on load, but only rendered in the allDay-slot when clicking back or forth to the prev/next day and then back.
How do I create this view?
I have created a fiddle to exemplify: http://jsfiddle.net/2ptqe5na/31
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: '',
center: 'title'
},
defaultDate: '2018-07-23',
defaultView: 'agendaDay',
events: [
{
title: 'A',
start: '2018-07-23T10:00:00',
end: '2018-07-24T09:00:00',
allDay: true //standard property
},
{
title: 'B',
start: '2018-07-23T08:00:00',
end: '2018-07-23T08:30:00',
isDayOff: true //custom property
}
],
eventClick: function(calEvent, jsEvent, view) {
alert('Event: ' + calEvent.title);
},
eventRender: function(event, element, view)
{
if(event.isDayOff==true)
{
event.allDay = event.isDayOff;
}
event.title = event.title+"\n "+event.start.format('MMM DD HH:mm')+" - "+event.end.format('MMM DD HH:mm');
}
});
});

Fix external event item start/end time with background per rooms

i'm using fullcalendar version 3 with external event. and my problem was that wanted to fix dropped point when drag/drop left side item to calendar.
for example, if external "My event 1" drag to "test1 room" (has start:13:00:00/end:17:00:00 time attribute) calendar.
"My event 1" will be on 13:00:00 start and 17:00:00 end time ONLY. never change to another time on "test1 room" row.
$(function() { // document ready
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events .fc-event').each(function() {
// 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)
});
// 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
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
$('#calendar').fullCalendar({
now: '2016-01-07',
editable: true, // enable draggable events
droppable: true, // this allows things to be dropped onto the calendar
aspectRatio: 1.8,
scrollTime: '00:00', // undo default 6am scrollTime
header: {
left: 'today prev,next',
center: 'title',
right: 'timelineDay,timelineThreeDays,agendaWeek,month'
},
defaultView: 'timelineDay',
views: {
timelineThreeDays: {
type: 'timeline',
duration: { days: 3 }
}
},
resourceLabelText: 'Rooms',
resources: [
{ id: 'a', title: 'test1 room', start:"2016-01-07T13:00:00",end: '2016-01-07T17:00:00' },
{ id: 'b', title: 'test2 room', eventColor: 'green' },
{ id: 'c', title: 'test3 room', eventColor: 'orange' },
],
events: [
{ id: '1', resourceId: 'b', start: '2016-01-07T02:00:00', end: '2016-01-07T07:00:00', title: 'event 1' }
],
drop: function(date, jsEvent, ui, resourceId) {
console.log('drop', date.format(), resourceId);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
},
eventReceive: function(event) { // called when a proper external event is dropped
console.log('eventReceive', event);
},
eventDrop: function(event) { // called when an event (already on the calendar) is moved
console.log('eventDrop', event);
}
});
});
To stop events being dragged around after they're placed on the calendar, you can simply set the editable option:
editable: false
This stops internal dragging/dropping, but doesn't affect external dropping (which is controlled by the "droppable" option).
If you only want this rule to apply to specific events, you can set editable: true in general, but then set editable: false as a property of individual events - this will override the global setting. See https://fullcalendar.io/docs/event_data/Event_Object/ for details of which settings can be over-ridden at the event level.

change placeholder duration dynamically in fullcalendar

i'm trying to change external duration on fullcalendar external-dragging example.
https://fullcalendar.io/js/fullcalendar-scheduler-1.2.0/demos/external-dragging.html
the example duration was 02:00:00. but I would like to be changed when drag on calendar.
for example baed on above link, pre-duration of rooms were 02:00:00 and 03:00:00 like "Auditorium A" was 02:00:00 and "Auditorium B" was 03:00:00.
and then, when I drag some external item to calendar. then change the item duration 02:00:00 on "Auditorium A" or 03:00:00 on "Auditorium B".
$(function() { // document ready
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events .fc-event').each(function() {
// 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)
});
// 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
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
$('#calendar').fullCalendar({
now: '2016-01-07',
editable: true, // enable draggable events
droppable: true, // this allows things to be dropped onto the calendar
aspectRatio: 1.8,
scrollTime: '00:00', // undo default 6am scrollTime
header: {
left: 'today prev,next',
center: 'title',
right: 'timelineDay,timelineThreeDays,agendaWeek,month'
},
defaultView: 'timelineDay',
views: {
timelineThreeDays: {
type: 'timeline',
duration: { days: 3 }
}
},
resourceLabelText: 'Rooms',
resources: [
{ id: 'a', title: 'Auditorium A' },
{ id: 'b', title: 'Auditorium B', eventColor: 'green', start:"09:00", end:"11:00" },
{ id: 'c', title: 'Auditorium C', eventColor: 'orange', start:"13:30",end:"16:00" }
],
events: [
],
drop: function(date, jsEvent, ui, resourceId) {
console.log('drop', date.format(), resourceId);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
},
eventReceive: function(event) { // called when a proper external event is dropped
console.log('eventReceive', event);
},
eventDrop: function(event) { // called when an event (already on the calendar) is moved
console.log('eventDrop', event);
}
});
});
one of above code, there are start/end attribute in resources. so I would like to be applied start/end time when left side external drag on calendar each of rooms.

Fullcalendar event url - add class if url contains

Some of my Fullcalendar events have links. The links point to either public webpages, pdf documents or webpages which are restricted access.
I would like to add a class to format the links to add an icon, based on url string.
If the url contains:
"pdf" addclass "fc-pdf"
"restricted" addclass "fc-lock"
I assume it should be with and eventRender... but I'm having trouble find the right syntax. Can someone help me with this?
http://jsfiddle.net/lbriquet/oez9Ltym/
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'listDay,listWeek,month'
},
views: {
listDay: {
buttonText: 'list day'
},
listWeek: {
buttonText: 'list week'
}
},
defaultView: 'listDay',
defaultDate: '2016-09-12',
navLinks: true, // can click day/week names to navigate views
events: [{
title: 'Conference (website)',
start: '2016-09-11',
end: '2016-09-13',
url: "https://www.ted.com/talks"
}, {
title: 'Meeting (download document)',
start: '2016-09-12T10:30:00',
end: '2016-09-12T12:30:00',
url: "http://storage.ted.com/tedx/manuals/tedx_speaker_guide.pdf"
}, {
title: 'Lunch',
start: '2016-09-12T12:00:00'
}, {
title: 'Meeting (members only)',
start: '2016-09-12T14:30:00',
url: "http://www.dictionary.com/browse/restricted"
}, {
title: 'Happy Hour',
start: '2016-09-12T17:30:00'
}, {
title: 'Dinner',
start: '2016-09-12T20:00:00'
}],
eventRender: function eventRender(event, element, view) {
}
});
The way I got this to work was by adding a type to the events simply because I think it would be easier than dealing with regex that might not always work. So events don't need a type but they can have a type pdf, restricted or whatever else you need. In eventRender I added the following:
eventRender: function eventRender(event, element, view) {
if(typeof event.type !== 'undefined') {
if(event.type === 'pdf') {
element.addClass('fc-pdf');
} else if(event.type === 'restricted') {
element.addClass('fc-lock');
}
}
}
A check to see if the type is provided or not and then if statements for adding the class based on the type. I also had to make a small change to the css selector, changing a.fc-lock to .fc-lock a to allow it to display properly. Here is the JS Fiddle showing this.

How to get the date when calendar rendering date cells

I've a situation where I need to get the date to attach in each event url (For event url's I'm adding the href attr using jquery) query string but after checking the docs I found both eventClick and eventRender do not returns the date of cell upon which event is showing.
I tried google for it and found tricky solutions using the eventClick callback and use page X and Y and then get the nearest element which holds the data attribute with date for the particular cell date but
eventClick:function(event,jsEvent,view){
var clickedDate = $.nearest({x: jsEvent.pageX, y: jsEvent.pageY}, '.fc-day').attr('data-date');
alert(clickedDate);
}
But this solutions fails when I've multiple event on the same date cell and more events will be shown in a popup.
Note : $.nearest is the jquery plugin to find the nearest element from given X,Y postions
Note : I'm using v2
Does this work sufficiently well for you?
http://jsfiddle.net/3E8nk/531/
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultDate: '2014-06-12',
editable: true,
eventRender: function(event, element, view) {
var start = event.start.clone().startOf('day');
var end = event.end ? event.end.clone().endOf('day') : start.clone().endOf('day');
//Known bug: We get all "touching" events and not just necessarily events on the day we clicked
var events = $('#calendar').fullCalendar('clientEvents');
var touchingEvents = events.filter(function(event) {
var
eventStartWithin = event.start.isWithin(start, end),
eventEndWithin = event.end ? event.end.isWithin(start, end) : false;
return eventStartWithin || eventEndWithin;
});
console.log(touchingEvents);
},
events: [
{
title: 'All Day Event',
start: '2014-06-01'
},
{
title: 'Long Event',
start: '2014-06-07',
end: '2014-06-10'
},
{
id: 999,
title: 'Repeating Event',
start: '2014-06-09T16:00:00'
},
{
id: 999,
title: 'Repeating Event',
start: '2014-06-16T16:00:00'
},
{
title: 'Meeting',
start: '2014-06-12T10:30:00',
end: '2014-06-12T12:30:00'
},
{
title: 'Lunch',
start: '2014-06-12T12:00:00'
},
{
title: 'Birthday Party',
start: '2014-06-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2014-06-28'
}
]
});

Resources