I need to be able to let users move some events around on my fullcalendar. And I want to go to server and fetch counterparties' busy times and display them as background events on the calendar when the dragging is going on. However, when I call .fullcalendar('renderEvents', [...]) while the dragging is happening, the dragging mechanism within fullcalendar breaks and stops.
Is there a way to either add events without breaking dragging or some other way highlight busy times that have to be retrieved with ajax call?
The example is here: https://jsbin.com/qikiganelu/1/edit?js,output. Try dragging 'Meeting with Bob'.
$(function() { // document ready
$('#calendar').fullCalendar({
header: {
left: '',
center: '',
right: ''
},
defaultView: 'agenda',
duration: {days: 2},
allDaySlot: false,
defaultDate: '2017-04-27',
minTime: '9:00',
maxTime: '17:00',
events: [
{
title: 'Keynote',
start: '2017-04-27T09:00',
end: '2017-04-27T11:00',
editable: false,
color: "gray",
},
{
title: 'Meeting with Bob',
start: '2017-04-27T12:30',
end: '2017-04-27T13:00',
editable: true,
},
],
eventDragStart: function(event, jsEvent, ui, view){
// fetch Bob's busy times and add them as background events
var busyTimes = [
{
start: '2017-04-27T14:00',
end: '2017-04-27T16:00',
rendering: 'background',
},
{
start: '2017-04-28T9:00',
end: '2017-04-28T12:00',
rendering: 'background',
}
];
$('#calendar').fullCalendar('renderEvents', busyTimes);
},
});
});
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;
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='https://fullcalendar.io/js/fullcalendar-3.4.0/fullcalendar.css' rel='stylesheet' />
<link href='https://fullcalendar.io/js/fullcalendar-3.4.0/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js'></script>
<script src='//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://fullcalendar.io/js/fullcalendar-3.4.0/fullcalendar.js'></script>
<!-- the code from the JavaScript tab will go here -->
<!-- the code from the CSS tab will go here -->
</head>
<body>
<div id='calendar'></div>
</body>
</html>
As a workaround, try preloading all the background events, but hiding them via CSS until the drag operation happens. For instance:
// hide all background events by default
.fc-bgevent {
display: none;
}
// redisplay once "show-background-events" class toggled on
.fc-bgevent.show-background-events {
display: block;
}
Show / hide the background events by toggling the .show-background-events class like so:
eventDragStart: function(event, jsEvent, ui, view){
$(".fc-bgevent").addClass("show-background-events");
},
eventDragStop: function(event, jsEvent, ui, view){
$(".fc-bgevent").removeClass("show-background-events");
}
Example at: https://jsbin.com/vuvacisibu/1/edit?css,js,output
My bad, I now see the problem. And your mistake is the place you put your $('#calendar').fullCalendar('renderEvents', busyTimes); and also the way you write the array, I also changed the ISO8601 time string a bit to be sure.
You can remove the seconds from the time string and write 2017-04-27T12:35Z instead of 2017-04-27T12:35:02Z for example
<script>
$(function() { // document ready
$('#calendar').fullCalendar({
header: {
left: '',
center: '',
right: ''
},
defaultView: 'agenda',
duration: {days: 2},
allDaySlot: false,
defaultDate: '2017-04-27',
minTime: '9:00',
maxTime: '17:00',
events: [
{
title: 'Keynote',
start: '2017-04-27T09:00',
end: '2017-04-27T10:00',
editable: false,
color: "gray",
},
{
title: 'Meeting with Bob',
start: '2017-04-27T10:35:02Z',
end: '2017-04-27T11:35:02Z',
editable: true,
},
],
eventDragStart: function(event, jsEvent, ui, view){
}
});
//this is the new place for the fetching and calling renderEvents
// fetch Bob's busy times and add them as background
var busyTimes = [
{title: 'Event One', start: '2017-04-27T12:35:02Z', end: '2017-04-27T13:35:02Z'},
{title: 'Event Two', start: '2017-04-27T14:35:02Z', end: '2017-04-27T15:35:02Z'}
];
$('#calendar').fullCalendar('renderEvents', busyTimes);
});
</script>
Related
In FullCalendar v3, there has an option to catch after loading all events.
eventAfterAllRender
It seems removed in v4. As saying here:
https://fullcalendar.io/docs/v4/upgrading-from-v3
Here has a code snippet to prepare a demo calendar in v5.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='https://cdn.jsdelivr.net/npm/fullcalendar#5.5.1/main.min.css' rel='stylesheet' />
<script src='https://cdn.jsdelivr.net/npm/fullcalendar#5.5.1/main.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
initialDate: '2020-09-12',
navLinks: true, // can click day/week names to navigate views
businessHours: true, // display business hours
editable: true,
selectable: true,
events: [
{
title: 'Business Lunch',
start: '2020-09-03T13:00:00',
constraint: 'businessHours'
},
{
title: 'Meeting',
start: '2020-09-13T11:00:00',
constraint: 'availableForMeeting', // defined below
color: '#257e4a'
},
{
title: 'Conference',
start: '2020-09-18',
end: '2020-09-20'
},
{
title: 'Party',
start: '2020-09-29T20:00:00'
},
// areas where "Meeting" must be dropped
{
groupId: 'availableForMeeting',
start: '2020-09-11T10:00:00',
end: '2020-09-11T16:00:00',
display: 'background'
},
{
groupId: 'availableForMeeting',
start: '2020-09-13T10:00:00',
end: '2020-09-13T16:00:00',
display: 'background'
},
// red areas where no events can be dropped
{
start: '2020-09-24',
end: '2020-09-28',
overlap: false,
display: 'background',
color: '#ff9f89'
},
{
start: '2020-09-06',
end: '2020-09-08',
overlap: false,
display: 'background',
color: '#ff9f89'
}
]
});
calendar.render();
});
</script>
<style>
body {
margin: 40px 10px;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>
Codepen: https://codepen.io/wetruck/pen/poEXEve
Is there any option to perform an action after loading all events in v5?
I'm actually using a html loader. It's showing with the page load. But after loading all events, it should be removed.
For this situation where you have a loader you want to show and hide, please see the loading callback option for something which will do the job - you can use that callback to make a loader show/hide when the AJAX part of the task starts and stops.
e.g.
loading: function( isLoading ) {
if (isLoading == true) {
//show your loader
} else {
//hide your loader
}
}
Unlike the old eventAfterAllRender it starts and stops on the start/end of the AJAX request and doesn't cover the rendering of the events by fullCalendar, but that's normally very fast unless you have an absurd number of events being downloaded for a single time period.
I'm using fullcalendar.io.I want to scroll up to the current date after the render of the calendar on listMonth view.
calendar code:
if ($(window).width() < 768) {
columnFormat = 'ddd';
defaultView = 'listMonth';
left = 'prev,next';
right = 'month,listMonth';
} else {
columnFormat = 'dddd';
defaultView = 'month';
left = 'prev';
right = 'next';
}
$('#calendar').fullCalendar({
header: {
left: left,
center: 'title',
right: right
},
timeFormat: 'H:mm',
columnFormat: columnFormat,
defaultView: defaultView,
events: {
url: MyAjax.ajaxurl,
type: 'POST',
data: {
action: 'events_list',
security: MyAjax.security,
},
},
eventClick: function (event, jsEvent, view) {
if (event.url) {
window.open(event.url, "_blank");
return false;
}
},
});
Please help me to do it.
Example: https://jewlife.by/
Muhammad's answer is fine for most of FullCalendar's views, but alas the listMonth view does not support that approach for jumping to a particular day in the current month.
Instead, you need to programmatically scroll to the current day. Something like the following will work fine:
// Initialise the calendar
$("#calendar").fullCalendar({
eventAfterAllRender: function (view) {
if (view.name === "listMonth") {
var viewStartDate = $("#calendar").fullCalendar("getDate");
var target = $(".fc-listMonth-view .fc-list-heading[data-date=" + viewStartDate.format("YYYY-MM-DD") + "]");
if (target.length) {
$(".fc-listMonth-view .fc-scroller").scrollTop(target.position().top);
}
}
},
// Other initial settings here
});
Tested and working as of FullCalendar v3.9.0.
you should use goToDate() if you want to navigate to a date after the calendar has loaded, via the click of a button, it moves the calendar to an arbitrary date.
$('#calendar').fullCalendar( 'gotoDate', date )
Note: date can be a `Moment object or anything the Moment constructor accepts.
Or if you like the calendar to load on a specific date then you should use the defaultDate option while initializing the calendar.
You can learn more here
$(document).ready(function() {
var calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
defaultDate: '2017-11-12',
defaultView: 'listMonth',
navLinks: true, // can click day/week names to navigate views
editable: true,
eventLimit: true, // allow "more" link when too many events
events: [{
title: 'Old Day Event',
start: '2014-05-01'
}, {
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-11',
end: '2017-11-13'
},
{
title: 'Meeting',
start: '2017-11-12T10:30:00',
end: '2017-11-12T12:30:00'
},
{
title: 'Lunch',
start: '2017-11-12T12:00:00'
},
{
title: 'Meeting',
start: '2017-11-12T14:30:00'
},
{
title: 'Happy Hour',
start: '2017-11-12T17:30:00'
},
{
title: 'Dinner',
start: '2017-11-12T20:00:00'
},
{
title: 'Birthday Party',
start: '2017-11-13T07:00:00'
},
{
title: 'Click for Google',
url: 'http://google.com/',
start: '2017-11-28'
}
]
});
var local = $.fullCalendar.moment('2014-05-01T12:00:00');
calendar.fullCalendar('gotoDate', local);
});
#goto {}
<script src="https://fullcalendar.io/js/fullcalendar-3.7.0/lib/moment.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://fullcalendar.io/js/fullcalendar-3.7.0/fullcalendar.min.js"></script>
<link href="https://fullcalendar.io/js/fullcalendar-3.7.0/fullcalendar.min.css" rel="stylesheet" />
<link href="https://fullcalendar.io/js/fullcalendar-3.7.0/fullcalendar.print.min.css" rel="stylesheet" />
<p>calendar is navigated to previous date November in 2014 after loading on 2017 by default </p>
<div id='calendar'></div>
Issue
I am struggling to get my events to populate the Full Calendar on load. The events work fine when I change the month, but when the application first loads they don't seem to appear.
Code
Here is my code for for the UIConfig of the Calendar:
//THIS CALLS MY GET METHOD.
var holidaysnew = getUserEventsById.getUserEventsById();
$scope.uiConfig = {
calendar: {
viewRender: function (view, element) {
holidaysnew.forEach(function (hol) {
$scope.eventSources[0].events.push({
end: $filter('dateFilter')(hol.HOLIDAY_END),
start: $filter('dateFilter')(hol.HOLIDAY_START),
title: hol.HOLIDAY_TITLE,
color: $filter('colorEventFilter')(hol.HOLIDAY_EVENT_STATE_ID)
});
});
},
height: 850,
editable: true,
header: {
left: '',
center: '',
right: ''
},
}
};
Now the viewRender gets hit on load aswell as when I change the month. The weird thing is it only works when you click a new month.
#Ben problem is that you are making http call in service. But here calendar will not wait for http response. So calendar loads first then after you will receive http response that's why you are not getting response first time. You need to change the way to load events like below.
$scope.uiConfig = {
calendar: {
events: function(start, end, timezone, callback) {
$http({
method : "GET",
url : 'your_url_to_fatch_events',
data : {start: startDate, end: endDate, id: userId}
}).then(
function (olidaysnew) {
var events = [];
// or make your events
olidaysnew.forEach(function (hol) {
events.push({
end: $filter('dateFilter')(hol.HOLIDAY_END),
start: $filter('dateFilter')(hol.HOLIDAY_START),
title: hol.HOLIDAY_TITLE,
color: $filter('colorEventFilter')(hol.HOLIDAY_EVENT_STATE_ID)
});
)}
callback(events);
}
)
},
height: 850,
editable: true,
header: {
left: '',
center: '',
right: ''
},
}
}
I am using FullCalendar v2 and bootstrap v3.3.2. I am trying to show a popover inside of the slot where the user click. Here there an example that I try to do http://jsfiddle.net/5g396/ but the problem is that it uses FullCalendar v1 and I need FullCalendar V2.
This is my code, http://jsfiddle.net/beckymo/nmwyz269/, but the popover is only shown in the same position of the Calendar.
My questions is: How to show popover bootstrap v3.3.2. in FullCalendar v2 on the top of slot when the user click? Thanks!
$('#calendar-holder').fullCalendar({
header: {
left: 'prev, next',
center: 'title',
right: 'month, agendaWeek, agendaDay'
},
businessHours: {
start: '09:00',
end: '19:00',
dow: [1, 2, 3, 4, 5]
},
allDaySlot: false,
defaultView: 'agendaWeek',
lazyFetching: true,
firstDay: 1,
selectable: true,
timeFormat: {
agenda: 'h:mmt',
'': 'h:mmt'
},
dayClick: function (date, jsEvent, view) {
$(this).popover({
title: 'haha',
placement: 'right',
content: 'haha',
html: true,
container: 'body'
});
$(this).popover('show');
}
});
Thanks!!!
Firstly you need add the option "selectable: true" because it create a div inside of slot where you click.
Secondly you can use this div as selector (.fc-highlight") for call popover like this:
dayClick: function (date, jsEvent, view) {
$(".fc-highlight").popover({
title: 'haha',
placement: 'right',
content: 'haha',
html: true,
container: 'body'
});
$(".fc-highlight").popover('show');
}
Default weekview is like this one, no time of the day on left side:
http://fullcalendar.io/views/basicWeek/
but I'd like to make the view this way, with time of the day on left side:
http://fullcalendar.io/js/fullcalendar-2.3.1/demos/agenda-views.html
click 'week' on upper button panel to see it.
How do I configure it to make it looks like this way?
Thanks!
You want to use the defaultView property. This sets, as specified in the docs, the initial view when the calendar loads. The specific view you want is agendaWeek (list of available views).
So when you initialize your calendar, you'll put defaultView: 'agendaWeek'.
Example:
$('#fullCal').fullCalendar({
events: [{
title: 'Random Event 1',
start: moment().add(-4, 'h'),
end: moment().add(-2, 'h'),
allDay: false
}, {
title: 'Random Event 2',
start: moment().add(1, 'h'),
end: moment().add(2, 'h'),
allDay: false
}, {
title: 'Random Event 3',
start: moment().add(6, 'h'),
end: moment().add(8, 'h'),
allDay: false
}],
header: {
left: '',
center: 'prev title next today',
right: ''
},
timezone: 'local',
defaultView: 'agendaWeek' /* this is the line you need */
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.1.1/fullcalendar.min.js"></script>
<div id="fullCal"></div>