I'm having trouble getting custom controls to work when clicking the 'today' button that is part of Fullcalendar.
All the documentation I can find tells me that Fullcalendar's built-in controls can be affected using two methods:
So, this one works for me when it's applied to previous, next, month, agendaWeek and agendaDay, but not for 'today' (button.fc-today-button):
$('body').on('click', 'button.fc-next-button', function() {
console.log('I Clicked Next');
});
Some documentation also say that this works, although I can't make it do so on any button:
$('.fc-next-button span').click(function(){
console.log('I Clicked Next');
});
Does anyone know why this is and what I'm doing wrong?
Well, you want to affect the "today" button, yet you are adding code for the "next" button. You want to do something like:
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
This applies a click event to anything with the class "fc-today-button" (that is the class that the Today button will have).
Working example:
$('#fullCal').fullCalendar({
events: [{
title: 'Event 1',
start: moment().add(1, 'h'),
end: moment().add(2, 'h'),
allDay: false
}],
header: {
left: '',
center: 'prev title next today',
right: ''
},
timezone:'local',
defaultDate: '2014-11-15',
editable: false,
eventLimit: false,
firstDay: 6,
defaultView: 'agendaWeek',
});
$(".fc-today-button").click(function() {
alert('Clicked Today!');
});
<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>
After investigation and the help of MikeSmithDev (thanks Mike - your help was invaluable), it appears as though the 'today' event only gets triggered if it physically positioned below/after the calendar, the rest of the header controls (button.fc-next-button etc) don't seem to mind where they are physically positioned.
Likely the first function executes before the calendar is finished loading... so it works, there is just no button to bind it to.
I was able to more or less achieve this with a native workaround of sorts. You may utilize the "customButtons" and "headerToolbar" in combination to effectively remove the original today button and replace it with your own which can trigger custom function code upon being clicked.
I'm actually using this with VueJS, but should be equally feasible with Vanilla JS.
// these are the options you can pass when initializing a fullcalendar
customButtons: {
focusButton: {
text: "focus",
click: this.scrollToCurrentDay // this is a vue component function, but you could just as well pass a vanilla JS function
}
},
headerToolbar: { // this effectively removes the original today button and adds our custom button to the header of the calendar
left: '',
center: 'title',
right: 'prev focusButton next'
}
I wanted to do this because I wanted to not only focus the month when today was clicked, but also to scroll the calendar to the day (useful when using small screens like phones).
My custom today button click handler:
scrollToCurrentDay: function(arg) {
let CalendarAPI = this.$refs.calendar.getApi();
CalendarAPI.today();
var todayElement = document.getElementsByClassName('fc-day-today')[0];
var calendarElement = document.getElementsByClassName('fc')[0];
if (todayElement) {
todayElement.scrollIntoView();
} else {
calendarElement.scrollIntoView();
}
},
Related
I am not sure how to approach fullcalender.io. As I will be refreshing the calender, I thought I would return the calendar object like this.
var calendar = function (eventsObj) {
console.log(eventsObj);
return new FullCalendar.Calendar(document.getElementById("calendar"), {
plugins: ['interaction', 'dayGrid', 'timeGrid'],
defaultView: 'dayGridMonth',
defaultDate: new Date().getDate(),
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: eventsObj
});
}
I did it this way because I need to refresh all my events inside a bootstrap modal.
When Modal is shown I recall this function.
$("#assignModal").on("shown.bs.modal", function () {
calendar(globalEvents).rerenderEvents();
Here globalEvents is an array with all the events.
I initially render the calendar like this
window.onload = function () {
calendar(globalEvents).render();
};
Issue is that the calendar renders but It does not have any events whereas if I just render the calendar, it keeps all the events. I checked on their docs, they have different features in different versions. Any ideas? please?
So basically according to the v4 guides.
calendar.getEventSources().forEach(function (item) {
item.remove();
});
calendar.addEventSource(globalEvents);
This is how you would have to remove the events and render new ones. Here globalEvents is just an array I use to keep track of my refreshed events.
you can do something like below just remove old events attach new events and rerenderevents
below is some APIS which will help you
//remove old data
$('#fullCalendar').fullCalendar('removeEvents');
//Getting new event json data
$("#fullCalendar").fullCalendar('addEventSource', response);
//Updating new events
$('#fullCalendar').fullCalendar('rerenderEvents');
//getting latest Events
$('#fullCalendar').fullCalendar( 'refetchEvents' );
//getting latest Resources
$('#fullCalendar').fullCalendar( 'refetchResources' );
here is working example
I am trying to implement a Fullcalendar functionality like so: an external event is dragged to the calendar, then the event is saved to the database via ajax, with its title, start and end dates.
I did achieve making the event title and start date/time to be saved to the DB, however I cannot fix the following couple of issues:
Currently, the end date/time saved to the DB is the same as the start date/time.
How do I make the end date to be 24h after the start date for all day events?
How do I get the exact start and end dates for a fixed duration event?
Once the event is dragged and saved to the DB, I cannot drag-drop any more events until I hit F5
My HML is the following:
<div id='external-events'>
<div class="fc-events-container">
<div>All Day Events</div>
<div class='fc-event' data-color='#28A745'>All Day Event</div>
<div>Fixed Duration Events</div>
<div class='fc-event' data-color='#50C1E9'>Event From 8am till 5 pm</div>
</div>
</div>
JQuery:
$('#external-drag').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true,
defaultDate: new Date(),
selectable: true,
events: "../../ajax/get_events.php",
drop: function( date, allDay, jsEvent, ui ) {
var start = date.format();
var end = date.format();
var title = $.trim($(this).text());
$.ajax({
url: '../../ajax/add_event.php',
data: 'title='+ title+'&start='+ start +'&end='+ end,
type: "POST",
success: function(json) {
alert('Added Successfully');
},
error: function() {
alert('Error');
}
});
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay
},
true
);
}
});
Firstly, some background context to what you're experiencing: although you've labelled your second event as "from 8 to 5pm", that has no actual practical effect. If you drop either of your draggable items onto a time-aware calendar view (e.g. week view) then it will gain a start date and time. On a view such as month, which has no concept of specific times of day, then it will just gain a start date, without a time attached.
However in both cases, there is no end date. Once you add the event to the calendar via renderEvent, then fullCalendar will assign it a default duration (as per the
defaultAllDayEventDuration or defaultTimedEventDuration settings, as appropriate). You can use that to work out the notional end date (although the event object doesn't actually have its end property set unless you set forceEventDuration to true).
Now to a solution:
If you want to control it so that specific dragged items have pre-defined times, you would have to specify the time data in the data- properties of the relevant draggable items. Then you need to get those values in your drop callback, the same way as you do with the title, and use them when creating your event.
It took a bit of fiddling to get to this point, especially with the moment objects, but it now appears to do what you want - as far as I understand it.
drop: function(date, jsEvent, ui) {
var element = $(this);
var title = $.trim(element.text());
var color = element.data("color");
var start = moment(date.format()); //lose the extended fullCalendar moment with its "ambiguously-timed" feature, which gets in the way here
var end = start.clone();
var allDay = true;
console.log(start.format(), end.format());
if (typeof element.data("starttime") !== 'undefined') {
//timed events
var starttime = moment.duration(element.data("starttime"));
var endtime = moment.duration(element.data("endtime"));
start.set({ "hour": starttime.hours(), "minute": starttime.minutes()});
end.set({ "hour": endtime.hours(), "minute": endtime.minutes()});
allDay = false;
console.log(starttime.hours());
} else {
//allday events
end.add({ days: 1 });
}
console.log("title=" + title + "&start=" + start.format() + "&end=" + end.format());
$.ajax({
url: '../../ajax/add_event.php',
data: 'title='+ title+'&start='+ start.format() +'&end='+ end.format(),
type: "POST",
success: function(json) {
alert('Added Successfully');
},
error: function() {
alert('Error');
}
});
calendar.fullCalendar(
"renderEvent",
{
title: title,
start: start,
end: end,
color: color,
allDay: allDay
},
true
);
}
Demo: https://codepen.io/ADyson82/pen/GRRXwRL?editors=1010
N.B. Note that if a user drags an event onto a time-aware view like the week view, it will still create the events exactly as per the settings in the draggable, and will ignore whatever time of day they dropped it on. It's possible this could be confusing or irritating to some users - but I guess it depends what you're trying to achieve exactly.
P.S. I don't know where you got the idea that the drop callback has an allDay parameter. It's clearly not there in the documentation. You can't use that, so I've removed it in my version.
I am trying to run a very basic script that uses the interaction plugin of fullcalendar. I want the users to input events via marking the right date or time in the calendar (select). After marking for example 5th August to 9th August, a prompt would aks for the event title. User types in "vacation" and the script automatically streams the information "from... to" to the event data. But the problem is, after marking the date and typing in the event title, the event does not appear on the calendar.
As long as the site isn't being reloaded, I also cannot mark a new event. In addition, the firefox browser console says fullCalender is not a function. The majority of what is to be found on the web about this issue is that it is most likely the library, which isn't being loaded properly, but according to the browser console its loaded properly indeed. The calendar is visible and I am able to select the date, therefore I do not see the problem. I already put hours into this....
I already tried to change the library from local to CDN, that didn't change no thing.
Here is the code, that I've mixed out of the documentation of fullcalendar and this code pen: https://codepen.io/JSFanatik/pen/QVvxvw
<script type="text/javascript" src='/calendar/fullcalendar/jquery-3.4.1.min.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/core/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/interaction/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/daygrid/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/timegrid/main.js'></script>
<script type="text/javascript" src='/calendar/fullcalendar/dist/core/locales/de.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
locale: "de",
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
selectable: true,
navLinks: true,
defaultView: "dayGridMonth",
selectable: true,
selectHelper: false,
editable: true,
eventLimit: false,
select: function(start, end) {
var title = prompt("Event Title?");
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$("#calendar").fullCalendar("renderEvent", eventData, true); // stick? = true
}
$("#calendar").fullCalendar("unselect");
},
eventRender: function(event, element) {
element
.find(".fc-content")
.prepend("<span class='closeon material-icons'></span>");
element.find(".closeon").on("click", function() {
$("#calendar").fullCalendar("removeEvents", event._id);
});
},
eventClick: function(calEvent) {
var title = prompt("Change Title:", calEvent.title);
calEvent.title = title;
$("#calendar").fullCalendar("updateEvent", calEvent);
}
});
calendar.render();
});
</script>
I hope you guys can help me with that. I have to say I don't know much about JavaScript, I just have build a website and thought this calendar would be a very useful addition. Thanks!
i've been had same issue, am not sure what cause my problem. but when i check at the debug console it shows "[Violation] 'load' handler took 166ms".
i solve my problem with moving out the code outside method : document.addEventListener('DOMContentLoaded', function() { ..
hope it helps.
Try this:
calendar.refetchEvents();
calendar.render();
I've been working with FullCalendar lately for a reservation system.
The problem is that whenever I select a time range it all adds to the eventData object. What I am trying to do is select one time range only.
When I click the $('#btn-reserve') button it should render the event on the calendar.
What's happening is that even my previous selections are getting rendered on the calendar. I only want to render the last selection I made.
here is my code
$('.calendar').fullCalendar({
selectable: true,
select: function(start, end) {
$('#end_time').val(end);
$('#start_time').val(start);
$('#newScheduleModal').modal({
show : true,
backdrop: 'static',
keyboard: false
});
$('#btn-reserve').click(function(){
eventData = {
title: 'Lesson Schedule',
start: start,
end: end
};
$('.calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
$('#newScheduleModal').modal('hide');
});
$('#btn-cancel-reserve').click(function(){
$('.calendar').fullCalendar('unselect');
eventData = {};
})
},
})
You are adding a new click event every time the calendar is selected. You need to unbind the click before adding it like so:
$('#btn-reserve').off('click').click(function
You might want to do the same for your "#btn-cancel-reserve" element.
I am fairly new to angular I am trying to implement a calendar using ui-calendar. So far I have been able to display a very basic calendar and some events on it.
Now I need to be able to click on a day and display the detailed events on a side tab. I seem to be lost on how to achieve this clicking day thing. This may seems very naive, I thought i'd find the html for each day cell on the calendar, and then it would be as easy as attaching a ng-click to it. But I cant seem to find any template where the html for calendar is. All I can see is the directive, which doesnt help much. I dont understand jquery at all, so I am really struggling to find any answers too.
To sum things up, I just want to know how to make a day on calendar clickable.
Thanks in advance.
code:
$scope.uiConfig = {
calendar: {
height: 450,
editable: true,
header: {
left: 'title',
center: '',
right: 'today prev,next'
},
eventClick: $scope.alertOnEventClick,
eventDrop: $scope.alertOnDrop,
eventResize: $scope.alertOnResize,
eventRender: $scope.eventRender,
dayClick: function(date, jsEvent, view) {
console.log("inside dayClick");
alert('Clicked on: ' + date.format());
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
}
};
In your configuration variable you can add a dayClick callback , in this callback you can do something like this:
dayClick: function( date, jsEvent, view ) {
var events = myCalendar.fullCalendar('clientEvents', function(event) {
return event.start.isSame(date) || event.end.isSame(date) || date.isBetween(event.start, event.end); // Will return all events starting/ending on this date or overlapping this date
});
}
This will return all the events that either are on this day or overlap it.
FullCalendar docs can be found here.