I'm building a CRM and trying to make a button outside the calendar div and if I press the button, it should be creating an event on the and it's not working. Could someone please point me out what I'm doing wrong?
This is what I tried:
$(document).on("click", "#testbtn", function(){
var calendarEl = $("#calendar");
calendarEl.addEvent({events: [
{
title: 'Second Event',
start: '2020-08-08T12:30:00',
end: '2020-08-08T13:30:00'
}
]});
});
This is my whole script:
<html>
<body>
<script src='../lib/main.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
<!-- all the options here -->
calendar.render();
});
</script>
</head>
<body>
<button id="testbtn">Add lunch time</button>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
<script src="/assets/plugins/jquery/jquery.min.js"></script>
<script>
var options = { /*Add options here*/};
var calendarEl = $("#calendar");
var calendar = new FullCalendar.Calendar(calendarEl, options);
$(document).on("click", "#testbtn", function(){
calendar.addEvent({
title: 'Lunch',
start: '2020-08-08T12:30:00',
end: '2020-08-08T13:30:00'
});
calendar.render();
});
</script>
There are two issues:
calendarEl is a DOM element. It won't have a .addEvent property (at least not the FullCalendar one.)
The argument for addEvent is a single Event object, not an object with a key events and an array of events as a value.
The addEvent demo may be helpful for you.
You need to pass the FullCalendar.Calendar instance, which you create with the new keyword, to the event handling function.
var calendarEl = $("#calendar").get(0);
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
$("#testbtn").on("click", function(){
calendar.addEvent({
title: 'Second Event',
start: '2020-08-08T12:30:00',
end: '2020-08-08T13:30:00'
});
});
Looks like you need to post this after where you load the jquery script. This has already got events loaded. We are just adding an event.
Body
<body>
<button id="testbtn">Add lunch time</button>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
<script src="/js/jquery/jquery.min.js"></script>
</body>
Then call the full calendar plugin
<script>
var calendarEl = $("#calendar").get(0);
var calendar = new FullCalendar.Calendar(calendarEl, {
/*options...*/
events:
[
{
id: 1,
title: 'First Event',
start: '2020-08-08T10:30:00',
end: '2020-08-08T11:30:00',
extendedProps: {
description: 'Test 1'
},
color: '#336e03'
},
{
id: 2,
title: 'Second Event',
start: '2020-08-08T15:30:00',
end: '2020-08-08T16:30:00',
extendedProps: {
description: 'Test 2'
},
}
]
});
calendar.render();
/*this is the action when the button is pressed*/
$("#testbtn").on("click", function(){
calendar.addEvent({
title: 'Third Event',
start: '2020-08-08T12:30:00',
end: '2020-08-08T13:30:00'
});
});
</script>
Related
I am using FullCalendar 5 and JSON to populate the events:
id;
title;
daysOfWeek;
startRecur;
endRecur;
startTime;
endTime;
backgroundColor;
I have a series of Events with a start and end date. When I click on an Event the end date is showing as the date cell the Event occurrence is in. I want to retrieve the end date of the series of Events. I am using info.event.end.
This is the code:
eventClick: function(info) {
var eventObj = info.event;
$('#updateDescription').val(eventObj.title);
$('#updateStartDate').val(moment(eventObj.start).format('DD/MM/YYYY'));
$('#updateEndDate').val(moment(eventObj.end).format('DD/MM/YYYY')); //Shows as 29/11/2021 should be 01/12/2021
$('#updateStartTime').val(moment(eventObj.start).format('HH:mm'));
$('#updateEndTime').val(moment(eventObj.end).format('HH:mm'));
$('#updateColour').val(eventObj.backgroundColor);
$('#ecClickModal').modal('show');
},
id: '001,
title: 'Event A',
daysOfWeek: '[1, 4]',
startRecur: '2021-01-01',
endRecur: '2022-12-30',
startTime: '10:00',
endTime: '11:00',
backgroundColor: 'Red',
id: '002,
title: 'Event B',
daysOfWeek: '[2, 3]',
startRecur: '2021-05-01',
endRecur: '2023-05-30',
startTime: '09:00',
endTime: '10:00',
backgroundColor: 'Blue',
id: '003,
title: 'Event C',
daysOfWeek: '[5]',
startRecur: '2020-01-01',
endRecur: null,
startTime: '10:00',
endTime: '11:00',
backgroundColor: 'Green',
When I click on 'Event B' I want to get the end date '2023-05-30'.
Currently, if I click on the occurrence of 'Event B' on '30/11/2021' then:
info.event.start is 30/11/2021
info.event.end is 30/11/2021
Recurring Events do not need an end date. So the solution must be able to cater for 'Event C' (i.e., a null end date please).
Currently there are no in built functions in FullCalendar to fetch the last date from a series of events. You will have to fetch all events using calendar::getEvents and then find the end date of the last event.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: [
{
id: 'a',
title: 'my event a',
start: '2021-11-01',
end: '2021-11-02'
},
{
id: 'b',
title: 'my event b',
start: '2021-11-03',
end: '2021-11-04'
},
{
id: 'c',
title: 'my event c ',
start: '2021-11-05',
end: '2021-11-06'
},
{
id: 'd',
title: 'my event d',
start: '2021-11-07',
end: '2021-11-08'
},
],
});
calendar.render();
// Fetching all events
const allEvents = calendar.getEvents();
// Sorting the events based on the last date (descending)
allEvents.sort((eventA, eventB)=> {
return eventB.end-eventA.end;
});
const lastDate = allEvents[0].end;
});
info.event.end only gives you the end date of a single event.
Also, before I stumble into it, how do I manage a null end date please?
Could you please explain the issue?
This topic follows this one about using fullcalendar :
how to set duration for external events in fullcalendar
Now I'm trying to use the resources.
For now it's just testing so I used the following code:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'resourceTimeGrid' ],
timeZone: 'UTC',
defaultView: 'resourceTimeGridFourDay',
datesAboveResources: true,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimeGridDay,resourceTimeGridFourDay'
},
views: {
resourceTimeGridFourDay: {
type: 'resourceTimeGrid',
duration: { days: 4 },
buttonText: '4 days'
}
},
resources: [
{ id: 'a', title: 'Room A' },
{ id: 'b', title: 'Room B' }
],
events: 'https://fullcalendar.io/demo-events.json?with-resources=2'
});
calendar.render();
});
I'm inside a Symfony project.
In terms of Javascript calls I had this :
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/core#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/interaction#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/daygrid#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/timegrid#4.1.0/main.min.js"></script>
So I added these 2 calls:
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-common#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-timegrid#4.1.0/main.min.js"></script>
All of this was copy / pasted from the demo pages.
Now when I load my page I have this error message and i don't understand why :
Uncaught TypeError: Cannot read property 'addEventListener' of null
It seems the error is triggered here :
// Event Delegation
// ----------------------------------------------------------------------------------------------------------------
function listenBySelector(container, eventType, selector, handler) {
function realHandler(ev) {
var matchedChild = elementClosest(ev.target, selector);
if (matchedChild) {
handler.call(matchedChild, ev, matchedChild);
}
}
container.addEventListener(eventType, realHandler);
return function () {
container.removeEventListener(eventType, realHandler);
};
}
on this part :
container.addEventListener(eventType, realHandler);
What do you think may cause this issue ?
A javascript missinh maybe ?
The error was due to a bad id in the div supposed to contain the calendar...
Everything is actually working fine and I was able to combine dragging events + using resources. The full code is :
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/core#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/interaction#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/daygrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/timegrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-common#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-daygrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-timegrid#4.4.0/main.min.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable;
var calendarEl = document.getElementById('calendar-holder');
var containerEl = document.getElementById('external-events');
// initialize the external events
new Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
var json_event = eventEl.getAttribute("data-event");
var event_array = JSON.parse(json_event);
var event_duration = event_array['duration'];
var event_title = event_array['title'];
var event_color = event_array['color'];
return {
title: event_title, //eventEl.innerText,
duration: event_duration,
backgroundColor: event_color,
};
}
});
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'resourceTimeGrid' ],
timeZone: 'UTC',
defaultView: 'resourceTimeGridFourDay',
datesAboveResources: true,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimeGridDay,resourceTimeGridFourDay'
},
views: {
resourceTimeGridFourDay: {
type: 'resourceTimeGrid',
duration: { days: 4 },
buttonText: '4 days'
}
},
resources: [
{ id: 'a', title: 'Room A' },
{ id: 'b', title: 'Room B' }
],
events: 'https://fullcalendar.io/demo-events.json?with-resources=2'
});
calendar.render();
});
</script>
Thank you ADyson once again, for taking the time to help me !
I update my app with the new version of fullcalendar and I would like to copy/paste the events I drag-and-drop.
I set the editable option to true in my planning object and the drag-and-drop does work, but I wish it would copy the event instead of deplacing it.
I am currently trying to edit the event eventDragStart in order to create a clone of my event.
var jsonEvents = <?php echo json_encode($arrayEvenements); ?>;
var planning = {
plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
defaultView: 'timeGridWeek',
allDaySlot: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
editable: true,
events : jsonEvents,
eventClick : function goTo(info){
// Some link to my event page
},
eventDragStart : function cloneEvent(info) {
// Where I want the magic to happen I guess ???
var evenement = info.event;
console.log(evenement);
},
eventDragStop : function upadateEvent(info) {
var evenement = info.event;
console.log(info)
}
}
var calendarEl = $('#calendar1')[0]
var calendar = new FullCalendar.Calendar(calendarEl, planning)
calendar.render()
I want a clone of my drag-and-dropped event
I have a single drag-and-dropped event I am moving around for no reason
For cloning an event I believe it's too late trying to do anything in eventDragStart, the event has already started moving at this point.
If you aren't bothered about events being dragged and resized and only want to clone the event when dragging, the solution is quite simple. Just treat each event as an external event. With this approach, editable should not be true.
let containerEl = document.getElementById("calendar");
let calendarEl = document.getElementById("calendar");
new Draggable(containerEl, {
itemSelector: ".fc-event",
eventData: function(eventEl) {
return {
title: eventEl.innerText
};
}
});
var calendar = new Calendar(calendarEl, {
plugins: ["dayGrid", "interaction"],
defaultView: "dayGridMonth",
events: [
{
title: "Test 1",
start: "2019-04-01"
},
{
title: "Test 2",
start: "2019-04-03",
end: "2019-04-05"
},
{
title: "Test 3",
start: "2019-04-22",
end: "2019-04-25"
},
{
title: "Test 4",
start: "2019-04-19"
}
]
});
calendar.render();
Working example
If however, you do need to be able to drag and resize events you need some way of distinguishing between a regular drag and an external drag. In v3 I used to copy events when the control key was held down and the user started to drag. There appears to be a problem with this in v4, I plan to look into this further but in the meantime, I have a working example when holding the shift key.
If you drag without holding shift the event is moved, if you drag while holding shift the event is cloned.
let shiftIsPressed = false;
function setEventsCopyable(isCopyable) {
shiftIsPressed = !shiftIsPressed;
calendar.setOption("droppable", isCopyable);
calendar.setOption("editable", !isCopyable);
}
document.addEventListener("keydown", event => {
if (event.keyCode === 16 && !shiftIsPressed) {
setEventsCopyable(true);
}
});
document.addEventListener("keyup", event => {
if (shiftIsPressed) {
setEventsCopyable(false);
}
});
let containerEl = document.getElementById("calendar");
let calendarEl = document.getElementById("calendar");
new Draggable(containerEl, {
itemSelector: ".fc-event",
eventData: function(eventEl) {
return {
title: eventEl.innerText
};
}
});
var calendar = new Calendar(calendarEl, {
plugins: ["dayGrid", "interaction"],
defaultView: "dayGridMonth",
// Determines whether the events on the calendar can be modified.
editable: true,
// Determines if external draggable elements can be dropped onto the calendar.
dropAccept(el) {
return shiftIsPressed;
},
events: [
{
title: "Test 1",
start: "2019-04-01"
},
{
title: "Test 2",
start: "2019-04-03",
end: "2019-04-05"
},
{
title: "Test 3",
start: "2019-04-22",
end: "2019-04-25"
},
{
title: "Test 4",
start: "2019-04-19"
}
]
});
calendar.render();
Working example
I have an object that has multiple functions being registered to events on page load. This seems to be working fine. However, I am having an issue getting the scope of the object once the event happens. this seems to only pull in the element that is being triggered by the event. I was wondering if anyone could help and tell me where I went wrong?
EDIT 1
I felt that code snippet was pretty concise to the problem. However, I can see where my question may be perceived as lazy.
I have an object that has multiple functions triggered off of events that are dynamically being wired up on load which can be seen here:
var collection = function() {
var _c = {};
_c.el = '#container',
_c.buildItems = function(){
var $el = $('#content2');
var template = Handlebars.compile($("#tpl-collection-item-row").html());
var data = [
{id: 1, val: 'test 1', text: 'this is a test... 1'},
{id: 2, val: 'test 2', text: 'this is a test... 2'},
{id: 3, val: 'test 3', text: 'this is a test... 3'},
];
$el.append(template(data));
},
_c.clickStuff = function() {
alert("hey!");
},
_c.moreClicking = function() {
alert("i knew this would work");
},
_c.events = [
{target: '.row', event: 'click', func: 'clickStuff'},
{target: '#gettingIt', event: 'click', func: 'moreClicking'}
],
_c.initialize = function() {
var _this = this;
$.each(this.events, function(){
var func = _this[this.func]
$(_this.el).on(this.event, this.target, func);
});
},
_c.render = function() {
this.initialize();
this.buildItems();
}
return _c;
}
_c.buildItems is a function that is called to trigger my handlebars template from _c.render(). Prior to this happening I am calling a function to wire up events listed in my _c.events array that take the target object and the type of event happening and mapping to the func name within my object. This is happening in my _c.initialize function.
The events seem to be working perfectly fine. However, I am unsure how to get the scope of my collection function from within functions like _c.clickStuff when they are triggered. I am unsure how to do this and it would be great if someone can explain to me where I went wrong?
Here is a fiddle of my code:
https://jsfiddle.net/0s8vb8m3/3/
You can just reference the _c in your code as it is in the scope of your "collection" function.
var collection = function() {
var _c = {
el: '#container'
};
_c.buildItems = function() {
var $el = $('#content2');
var template = Handlebars.compile($("#tpl-collection-item-row").html());
var data = [{
id: 1,
val: 'test 1',
text: 'this is a test... 1'
}, {
id: 2,
val: 'test 2',
text: 'this is a test... 2'
}, {
id: 3,
val: 'test 3',
text: 'this is a test... 3'
}];
$el.append(template(data));
};
_c.clickStuff = function() {
console.log(_c.el);
};
_c.moreClicking = function() {
alert("i knew this would work");
};
_c.events = [{
target: '.row',
event: 'click',
func: 'clickStuff'
}, {
target: '#gettingIt',
event: 'click',
func: 'moreClicking'
}];
_c.initialize = function() {
$.each(_c.events, function(index, event) {
var func = _c[event.func];
$(_c.el).on(event.event, event.target, func);
});
};
_c.render = function() {
_c.initialize();
_c.buildItems();
};
return _c;
}
var c = collection();
c.initialize();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="row">Blah1</div>
<div class="row">Blah2</div>
<div class="row">Blah3</div>
</div>
I am trying to fire the clickDay event inside the calendarat initialization but its not working but same thing if I do with jQuery classic method to bind method on calendar events, its working!
Note: I have commented the jQuery classic method to bind
Plugin used: http://www.bootstrap-year-calendar.com/#Documentation/Events
Here Is the code
$(function() {
var currentYear = new Date().getFullYear();
var datas = [
{
id: 0,
name: 'Google I/O',
location: 'San Francisco, CA',
startDate: new Date(currentYear, 4, 28),
endDate: new Date(currentYear, 4, 28),
color: '#767676'
},
{
id: 1,
name: 'Microsoft Convergence',
location: 'New Orleans, LA',
startDate: new Date(currentYear, 2, 16),
endDate: new Date(currentYear, 2, 16),
color: '#676767'
}
]
$('#calendar').calendar({
clickDay: function(e) {
alert("sdtgfyh");
var yclick=e.date.getFullYear();
//console.log($(e.element).hasClass("day-start"));
console.log(yclick);
},
enableContextMenu: true,
style: "background",
contextMenuItems:[
{
text: 'Mark',
click: editMark
},
{
text: 'Un Mark',
click: deleteMark
}
],
selectRange: function(e) {
editMark({ startDate: e.startDate, endDate: e.endDate });
},
mouseOnDay: function(e) {
if(e.events.length > 0) {
var content = '';
$(e.element).popover({
trigger: 'manual',
container: 'body',
html:true,
content: content
});
//$(e.element).popover('show');
}
},
mouseOutDay: function(e) {
if(e.events.length > 0) {
$(e.element).popover('hide');
}
},
dayContextMenu: function(e) {
$(e.element).popover('hide');
},
dataSource:datas,
enableRangeSelection:(datas[0].color)
});
$('#save-event').click(function() {
saveMark();
});
/* $('#calendar').clickDay(function(e){
console.log($(e.element).hasClass("day-start"));
var dayStartVal = $(e.element).hasClass("day-start");
if(dayStartVal){
$('#event-modal').modal("hide");
}
});*/
});
I tried your code running on Fiddle.
Seems to work for me
A trimmed down version of your code is hosted on here
Maybe an issue with your Calendar binding the event even before the calendar is being rendered. As you seem to use a self invoking method. I am not sure if it is triggered well before your html is rendered with your calendar id tag.
One way to check is
Add a timeout on top of your function call like
setTimeout(function(){
// your calendar init code here
}, 2000); // Some delay to sure html is rendered with the calendar selector element.
And check if that is the issue. The code seems fine to me though.