I don't want user to be able to create allDay events in my calendar. I want calendar to change view from month view to agendaDay view by clicking the date, but everytime when I click the date calendar changes the view to agendaDay but it tries to create an allDay event.
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
dayClick: function(date,allDay, jsEvent, view) {
if (allDay) {
// Clicked on the entire day
$('#calendar').fullCalendar('gotoDate',date)
$('#calendar').fullCalendar('changeView', 'agendaDay')
}
view = $('#calendar').fullCalendar('getView');
},
selectable: function(){
if(view.name=='agendaDay' ){
return true;
}else{
return false;
}
},
selectHelper: true,
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);
}
$('#calendar').fullCalendar('unselect');
}
});
You're handling dayClick, selectable and select; whereas this could be achieved by only handling select:
select: function(start, end, jsEvent, view) {
if (view.name=='month') {
$('#calendar').fullCalendar('changeView', 'agendaDay');
$('#calendar').fullCalendar('gotoDate', start)
} else {
var title = prompt('Event Title:');
var eventData;
if (title) {
eventData = {
title: title,
start: start,
end: end
};
$('#calendar').fullCalendar('renderEvent', eventData, true);
}
}
$('#calendar').fullCalendar('unselect');
}
See http://jsfiddle.net/wijgerden/t81qtupz/ for a JSFiddle demo using FullCalendar v2.1.1; note that this still allows users to create all-day events on the agendaWeek and agendaDay views. On month view selecting date(s) will switch the view to agendaDay (first day in case of multi-select), while still allowing clicking on events.
Related
Does anybody know why is the end date null on those "allday=false" events?
Fiddle Sample: https://jsfiddle.net/L1g0z3jd/
I instantiate it differently from the start date, it shows just fine in the calendar view, but for some reason I can't understand whenever i get clientEvents, even thought i have not changed it, I got a null in the event end date!
PS: Just for the sake of "conscience" I must add ... I'm using and old version of google chrome (v 57.0.2987.133 64-bit) and an old ubuntu version (Linux Mint 18.1 Serena)
Its getting me crazy! Thanks!
HTML Code:
<button onclick="javascript:getEvents()">Get Events</button>
<div id='calendar'></div>
Javascript Code:
$(function() {
$('#calendar').fullCalendar({
header: false,
allDaySlot: false,
visibleRange: {start: moment('2000-01-02'), end: moment('2000-01-09')},
editable: true,
selectable: true,
views: {
settimana: {
type: 'agenda',
columnFormat: 'ddd',
hiddenDays: []
}
},
defaultView: 'settimana',
defaultDate: $.fullCalendar.moment().startOf('week'),
slotMinutes: 30,
events: [
$.fn.getAgendaWorktime(1, "08:00:00", 60),
$.fn.getAgendaWorktime(2, "08:30:00", 120),
],
select: function(startDate, endDate) {
$('#calendar').fullCalendar('renderEvent', {
title: 'free time',
start: startDate.format(),
end: endDate.format(),
allDay: false
});
},
eventClick: function(calEvent, jsEvent, view) {
console.log(calEvent, jsEvent, view);
if(doubleClick==calEvent._id){
if (confirm('Delete it?')) {
$('#calendar').fullCalendar('removeEvents',calEvent._id);
}
doubleClick = null;
}else{
doubleClick=calEvent._id;
}
},
});
});
function getEvents() {
var e=0,err=false,$data = []
$('#calendar').fullCalendar('clientEvents').forEach(periodo => {
if (periodo.end==null || periodo.start.format().substr(0,10)!=periodo.end.format().substr(0,10)) {
if (e==0) {
err = true;
e++;
alert('Event startint at '+periodo.start.format()+' cant spread to multiple days');
}
} else {
$data.push({'ini': periodo.start.format(), 'fim': periodo.end.format()});
}
});
alert($data);
}
jQuery.fn.getAgendaWorktime = function ($dow, $start, $elapsed) {
var r = {
allDay: false,
title: 'free time',
start: new Date('2000-01-02 '+$start),
end: new Date('2000-01-02 '+$start)
};
r.start.setDate(r.start.getDate()+$dow);
r.end.setDate(r.end.getDate()+$dow);
r.end.setHours(r.end.setHours()+($elapsed*60));
return(r);
}
I figured out how to solve the question, I will reply to it here for I have not found any workaround or further analysis of the problem in the internet ....
I didn't review my problem to determine if it was specific related to the fact that I was setting the event's end time incorrectly and the calendar wasn't giving me any errors on the issue or anything else, but if you're gowing by the same road i went i can tell you:
Check to see if the end time is been created corretly (that seams to be my real mistaken, I was using setHours instead getHours in the getAgendaWorktime function, which turned the final value to be null. I corrected it in the sample below, but let it incorrectly in the fiddle to show the use of the forceEventDuration attribute);
Set "forceEventDuration" parameter to "true" (that forces the "end" attribute to always be filled easying me up in my code for I can always awaits for an string from ".format()" method of the attibute);
for meny reasons fullcalendar.io some times does not sets the event end date and this was getting me problems whenever avaluating the event end time (Ok, I could work around it but I was intrigged for why does it was getting me those results when it sould not, and the answare was a buged code). With "forceEventDuration: true" fullcalendar gave me the end time every time therefor i could find out that the input method i was using was seting the end date incorrectly and gave me the chance to correct it as well.
Links related:
Calendar parameter documentation https://fullcalendar.io/docs/forceEventDuration
Corrected Fiddle https://jsfiddle.net/gjrfox05/
I hope this answer could be of some help for newcomers at fullcalendar.io as me.
Fiddle Javascript part corrected sample:
$(function() {
$('#calendar').fullCalendar({
header: false,
allDaySlot: false,
forceEventDuration: true,
visibleRange: {start: moment('2000-01-02'), end: moment('2000-01-09')},
editable: true,
selectable: true,
views: {
settimana: {
type: 'agenda',
columnFormat: 'ddd',
hiddenDays: []
}
},
defaultView: 'settimana',
defaultDate: $.fullCalendar.moment().startOf('week'),
slotMinutes: 30,
events: [
$.fn.getAgendaWorktime(1, "08:00:00", 60),
$.fn.getAgendaWorktime(2, "08:30:00", 120),
],
select: function(startDate, endDate) {
$('#calendar').fullCalendar('renderEvent', {
title: 'free time',
start: startDate.format(),
end: endDate.format(),
allDay: false
});
},
eventClick: function(calEvent, jsEvent, view) {
console.log(calEvent, jsEvent, view);
if(doubleClick==calEvent._id){
if (confirm('Delete it?')) {
$('#calendar').fullCalendar('removeEvents',calEvent._id);
}
doubleClick = null;
}else{
doubleClick=calEvent._id;
}
},
});
});
function getEvents() {
var e=0,err=false,$data = []
$('#calendar').fullCalendar('clientEvents').forEach(periodo => {
if (periodo.end==null || periodo.start.format().substr(0,10)!=periodo.end.format().substr(0,10)) {
if (e==0) {
err = true;
e++;
alert('Event startint at '+periodo.start.format()+' cant spread to multiple days');
}
} else {
$data.push({'ini': periodo.start.format(), 'fim': periodo.end.format()});
}
});
alert($data[0].fim);
}
jQuery.fn.getAgendaWorktime = function ($dow, $start, $elapsed) {
var r = {
allDay: false,
title: 'free time',
start: new Date('2000-01-02 '+$start),
end: new Date('2000-01-02 '+$start)
};
r.start.setDate(r.start.getDate()+$dow);
r.end.setDate(r.end.getDate()+$dow);
r.end.setHours(r.end.getHours()+($elapsed*60));
return(r);
}
By default FullCalendar end date null when event end_date = start_date.
I Just pass another fiend with same date from database (Django View).
event_sub_arr['end'] = end_date
event_sub_arr['end_same_date'] = end_date
And check in javaScript
eventClick: function(info) {
var modal = document.getElementById('DeleteEventModal')
getEventDeleteUrl(info.event.id)
getEventUpdateUrl(info.event.id)
modal.style.display = 'block'
calendar.unselect()
var start = info.event.start
var end_same_date = info.event.end_same_date
var end = info.event.end || end_same_date
$("#event_id_name").text(info.event.title)
$("#event_id_start").text(moment(start).format('h:mm:ss a, MMMM Do YYYY'))
$("#event_id_end").text(moment(end).format('h:mm:ss a, MMMM Do YYYY'))
console.log(info.event.start)
console.log(info.event.end)
console.log({{ event_data|safe }})
},
ITS WORK FOR ME
i'm trying to upgrade my fullCalendar version to the latest ( 3.9.0 ) but i can't seams to make the renderEvent function work. The event simply does not render. I'm also using the latest version of the scheduler plugin ( 1.9.3 )
I tried adding events using the $('#calendar').fullCalendar('renderEvent', event, true) like I used to, but now it does not seams to work.
I also tried $('#calendar').fullCalendar('addEventSource', event) followed by $('#calendar').fullCalendar('refetchEventSources') nothing seams to be working.
Here is my code.
$(document).ready(function() {
//Calendar option
const LOCALE_DEFAULT = 'fr';
const TIMEZONE_DEFAULT = 'local';
const IGNORE_TIMEZONE_DEFAULT = false;
const HEIGHT_DEFAULT = 'auto';
const DROPPABLE_DEFAULT = true;
const ALL_DAY_DEFAULT_DEFAULT = false;
const ALL_DAY_DEFAULT = false;
const ALL_DAY_SLOT_DEFAULT = false;
const TIME_EVENT_DURATION_DEFAULT = '03:00:00';
const SELECTABLE_DEFAULT = true;
const SLOT_EVENT_OVERLAPP_DEFAULT = false;
const SELECT_HELPER_DEFAULT = false;
const EVENT_RESOURCE_EDITABLE_DEFAULT = false;
const PUBLISHED = true;
const SCHEDULER_LICENCE = 'CC-Attribution-NonCommercial-NoDerivatives';
let events = [{"id":2,"title":"test","start":"2018-03-18T15:30:00.000Z","end":"2018-03-18T19:30:00-04:00","creationDate":"2018-03-18 14:55:25","resourceFullName":"testRessource","resourceId":3,"type":"shift"}];
let resources = [{
fullname: "resource 1",
id: 1
},
{
fullname: "resource 3",
id:3
}]
$("#calendar").fullCalendar({
locale: LOCALE_DEFAULT,
timezone: TIMEZONE_DEFAULT,
ignoreTimezone: IGNORE_TIMEZONE_DEFAULT,
slotDuration: '00:30:00',
height: HEIGHT_DEFAULT,
header: {
left: 'prev,next today',
center: 'title',
right: 'timelineDay, weekCustom' + /*, timelineWeek */', month, agendaDay'
},
buttonText: {
today: "today",
timelineDay: "timelineDay",
timelineWeek: "timelineWeek",
month: "month",
agendaDay: "agenda"
},
views: {
weekCustom: {
type: 'timeline',
timeFormat: 'H(:mm)',
buttonText: 'Semaine',
displayEventEnd: true,
duration: {week: 1},
slotDuration: {days: 1}
}
},
defaultView: "weekCustom",
lang: 'fr'/*$filter('translate')('language')*/,
scrollTime: "08:00:00",
resourceAreaWidth: "220px",
events: events,
editable: true,
droppable: DROPPABLE_DEFAULT,
allDayDefault: ALL_DAY_DEFAULT_DEFAULT,
allDay: ALL_DAY_DEFAULT,
allDaySlot: ALL_DAY_SLOT_DEFAULT,
defaultTimedEventDuration: TIME_EVENT_DURATION_DEFAULT,
resourceLabelText: "resources",
schedulerLicenseKey: SCHEDULER_LICENCE,
selectable: SELECTABLE_DEFAULT,
slotEventOverlap: SLOT_EVENT_OVERLAPP_DEFAULT,
selectHelper: SELECT_HELPER_DEFAULT,
eventResourceEditable: EVENT_RESOURCE_EDITABLE_DEFAULT,
resources: resources,
select: function (start, end, jsEvent, view, resourceObj) {
let event = {
start: start,
end: end,
title: "test"
};
//$("#calendar").fullCalendar('addEventSource', [event]);
//$("#calendar").fullCalendar('refetchEventSources', [event]);
//true for stick events
$("#calendar").fullCalendar('renderEvent', event, true);
},
eventClick: function (event, jsEvent, view) {
},
eventDrop: function (event, delta, revertFunc) {
},
eventResize: function (event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, view) {
},
viewRender: function (view) {
},
loading: function (bool, view) {
}
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.3/scheduler.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.21.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.3/scheduler.min.js"></script>
<div id="calendar">
</div>
P.S. use the timeline day for a more efficient test.
Your code works fine, and creates the event quite happily - try it: select a time period (in any view), remember the date/time you chose, and then go to your "month" view. You will see the created event in the timeslot you selected.
The problem comes when you try to view the event in a view which uses resources. Your code does not specify a resourceId for the new event. Therefore, fullCalendar has no idea which resource to show the event on, and so cannot display it at all in any resource-aware view.
To fix this, simply take the resourceId supplied in the resourceObj parameter of the select callback, and include it in your new event object:
let event = {
start: start,
end: end,
title: "test",
resourceId: resourceObj.id
};
P.S. you should also run "unselect" after the call to "renderEvent", otherwise the timeslot chosen will remain highlighted on the calendar behind the created event (until or unless the user clicks elsewhere). In some views this is more obvious than others, but it doesn't look right. The command is simply:
$("#calendar").fullCalendar('unselect');
I have a calendar that accepts external events, when you click the calendar an event is created, using eventDrop I block (revertFunc()) the addition of an event if the date is in the past, now I would also like to revertFunc() when the event being added or dropped matches an event that is already on that specific date. At first I was trying to compare event.Title but I can't find in the eventDrop parameters, any functions, or properties that house what is already there. I also looked at setting overlap to false but that won't work because I want to allow overlap in all cases except when duplicate.
Please see Fiddle for example. In this fiddle you can Add Product A to the same date over and over, if you un-comment the eventOverlap: false code then you can't drag product A or product B onto a date that already contains a product. Instead I need it to not allow a Drop/Add only if the date already contains the product you are trying to drop/add. I hope I am making sense.
<select id="productDd">
<option selected="selected">Select Product...</option>
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</select>
<div id="calendar">
</div>
var todaysDate = moment();
$('#calendar').fullCalendar({
theme: true,
header: {
left: '',
center: 'title',
right: ''
},
selectable: true,
eventDurationEditable: false,
select: function(start, end, jsEvent) {
if (end < todaysDate) {
//block addition of dates to old calendars
Alert("Sorry product order dates can not be added to days in the past.")
return false;
}
var title, code, eventData;
if ($('#productDd option:selected').text() == "Select Product...") {
$('body').scrollTop(0);
Alert("Please select a product from the drop down in order to add products to the calendar.");
} else {
title = $('#productDd option:selected').text();
code = $('#productDd option:selected').val();
}
if (title) {
eventData = {
title: title,
start: start,
end: end,
className: title,
productCode: code
};
$('#calendar').fullCalendar('renderEvent', eventData, true);
}
$('#calendar').fullCalendar('unselect');
},
//eventOverlap: false,
eventDrop: function(eventData, delta, revertFunc) {
if (moment(eventData._start).format('YYYY-MM-DD') < todaysDate.format('YYYY-MM-DD')) {
//block modification of old dates
revertFunc();
}
},
eventClick: function (calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', calEvent._id);
},
editable: true,
businessHours: {
start: '7:00',
end: '18:00',
dow: [1, 2, 3, 4, 5]
},
eventLimit: true
});
Thanks for looking at this with me.
I was able to figure it out using fullCalendars builtin functions: selectOverlap and eventOverLap
selectOverlap: function (event) {
if (event.title === $('#productDd option:selected').text()) {
alert("You may not add a duplicate event.");
return false;
}
return true;
},
eventOverlap: function(stillEvent, movingEvent) {
return stillEvent.title !== movingEvent.title;
},
See FIDDLE
In my fullcalendar http://fullcalendar.io/
I want to prevent a user to be able to create an event on multiple days
$('#calendar').fullCalendar({
defaultView: 'agendaWeek',
lang: "fr",
header: false,
timezone: 'local',
minTime: "08:00:00",
columnFormat: 'dddd',
selectHelper: true,
selectable: true,
select: function(start, end, id, allDay) {
var eventData = {
start: start,
end: end,
id: 1,
block: true,
editable: true,
backgroundColor: "#469278"
};
// console.log(moment(eventData.start["_d"]).format("dddd"));
// console.log(moment(eventData.end["_d"]).format("dddd"));
$('#calendar').fullCalendar('renderEvent', eventData, true); // stick? = true
// console.log(eventData);
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
var day = moment(eventData.start["_d"]).format("dddd");
var start_time = moment(eventData.start["_d"]).format("HH:mm");
var end_time = moment(eventData.end["_d"]).format("HH:mm");
var id = moment(eventData.end["_id"]);
var slot = {
day: day,
start_time: start_time,
end_time: end_time
};
array_dispo.push(slot);
$("#dispo_array").val(JSON.stringify(array_dispo));
$('#calendar').fullCalendar('unselect');
},
});
});
When a user is selecting a start date that is different from the end date of his event I thus tried to use the unselect method from the doc http://fullcalendar.io/docs/selection/unselect_method/ like this :
if (moment(eventData.start["_d"]).format("dddd") != moment(eventData.end["_d"]).format("dddd")) {
$('#calendar').fullCalendar('unselect');
};
But unfortunately this code doesnt automatically deselects the current selection...
You can do a check in your select method and then decide whether you want to render the event or not.
I also use Moment.js to calculate dates and durations, this library is included with FullCalendar (http://fullcalendar.io/docs/utilities/Moment/)
So I played around and came up with this:
select: function (start, end) {
var mEnd = $.fullCalendar.moment(end);
var mStart = $.fullCalendar.moment(start);
if (mEnd.isAfter(mStart, 'day')) {
$('#calendar').fullCalendar('unselect');
} else {
$('#calendar').fullCalendar('renderEvent', {
start: mStart,
end: mEnd,
allDay: false
},
true // stick the event
);
$('#calendar').fullCalendar('unselect');
}
}
Here is the jsfiddle if you want to see it in action: here
You can do it using this way:
eventResize: function(eventResizeInfo) {
console.log('eventResize is called');
var event = eventResizeInfo.event;
if (event.start.getDay() !== event.end.getDay()) {
eventResizeInfo.revert();
}
},
To prevent users from selecting multiple days at a time
selectAllow: function(selectedEvent) {
let startDate = selectedEvent.start;
let endDate = selectedEvent.end;
endDate.setSeconds(endDate.getSeconds() - 1);
if (startDate.getDate() === endDate.getDate()) {
return true;
} else {
return false;
}
}
Simply add the following option to your calendar:
selectAllow: (selectInfo) => { return selectInfo.start.getDay() === selectInfo.end.getDay() },
I've just started out using this plugin and I am having some trouble removing events that I have just created. I can delete all the events when using eventClick, but not particular ones on eventClick.
Any help would be appreciated. Here is my code.
<script type='text/javascript'>
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
var calendar = $('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
selectable: true,
selectHelper: true,
select: function(start, end, allDay) {
var title = prompt('Trade Show Name:');
if (title) {
calendar.fullCalendar('renderEvent',
{
title: title,
start: start,
end: end,
allDay: allDay,
id: 12
},
true // make the event "stick"
);
$('input[name="startDate"]').val(start);
}
calendar.fullCalendar('unselect');
},
eventClick: function(calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});,
editable: true
});
});
You can do this in 2 ways:
1) Set a unique ID to each of your events and pass those IDs to the removeEvents call.
eventClick: function (calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', calEvent._id);
}
Here _id is the unique ID fullCalendar generates.
2) Pass a filter function to delete the event you want.
Considering that you are trying to do this in eventClick, I would suggest you use the 2nd. An example to your case is as follows:
eventClick: function (calEvent, jsEvent, view) {
$('#calendar').fullCalendar('removeEvents', function (calEvent) {
return true;
});
}
Here the filter function passed to removeEvents accepts the event you want to delete and returns true. Since you are doing this in eventClick, all you have to do is pass calEvent.
Hope this helps!