jQuery FullCalendar multiple calendars, get dropped on calendar id - javascript

I am using the jQuery FullCalendar by Adam Shaw. I am creating multiple calendars on the same page, and dragging external elements onto the calendars. I need to get the calendar id that the element was dropped onto in order to update in my database. What would be the easiest way to get the id?
I have tried using closest
$(this).closest('div.calendar').attr('id');
or
$(this).closest('div.fc').attr('id');
or
$(this).closest('div.fc-ltc').attr('id');
all of these result in undefined.
javascript (simplified)
$(document).ready(function() {
$('#external-events div.external-event').each(function() {
var eventObject = {
title: $.trim($(this).text())
};
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
$('.calendar').fullCalendar({
header: {
left: '',
center: 'title',
right: ''
},
defaultView: 'agendaWeek',
editable: true,
droppable: true,
drop: function(date, allDay,jsEvent, ui,) {
//GET calendar id
var calendarid = $(this).closest('div.calendar').attr('id');
var originalEventObject = $(this).data('eventObject');
var copiedEventObject = $.extend({}, originalEventObject);
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// Using calendarid here
copiedEventObject.calendar = calendarid;
// Using calendarid here
$('#'+calendarid).fullCalendar('renderEvent', copiedEventObject, true);
$(this).hide();
}
});
});
html (simplified)
<div id='external-events'>
<h4>Draggable Events</h4>
<div class='external-event'>My Event 1</div>
<div class='external-event'>My Event 2</div>
<div class='external-event'>My Event 3</div>
<div class='external-event'>My Event 4</div>
<div class='external-event'>My Event 5</div>
</div>
<div id='calendar1' class='calendar'></div>
<div id='calendar2' class='calendar'></div>
<div id='calendar3' class='calendar'></div>
So how would I find the div id of the calendar (ie. calendar1) that the event was dropped on?
Update
I found that by using .elementFromPoint() and jsEvents screenX/screenY coordinates where the event was dropped I could then find the parent calendar id.
var calendarid = $(document.elementFromPoint(jsEvent.screenX, jsEvent.screenY)).closest('div.calendar').attr('id');
updated js
$('.calendar').fullCalendar({
header: {
left: '',
center: 'title',
right: ''
},
defaultView: 'agendaWeek',
editable: true,
droppable: true,
drop: function(date, allDay,jsEvent, ui,) {
//GET calendar id
var calendarid = $(document.elementFromPoint(jsEvent.screenX, jsEvent.screenY)).closest('div.calendar').attr('id');
var originalEventObject = $(this).data('eventObject');
var copiedEventObject = $.extend({}, originalEventObject);
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// Using calendarid here
copiedEventObject.calendar = calendarid;
// Using calendarid here
$('#'+calendarid).fullCalendar('renderEvent', copiedEventObject, true);
$(this).hide();
}
});
Is .elementFromPoint() / document.elementFromPoint(jsEvent.screenX, jsEvent.screenY) an accurate and/or best way to accomplish this?

I do have the solution and its working fine for past one year for me, it might help you as well.
initialize the calendar
-----------------------------------------------------------------*/
function initializeCalendar( calId /*pass as many custom parameters*/ ) {
$('#calendar'+calId ).fullCalendar({
drop: function(date, allDay,jsEvent, ui,) {
//GET calendar id
var calendarid = calId;
var originalEventObject = $(this).data('eventObject');
var copiedEventObject = $.extend({}, originalEventObject);
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// Using calendarid here
copiedEventObject.calendar = calendarid;
// Using calendarid here
$('#'+calendarid).fullCalendar('renderEvent', copiedEventObject, true);
$(this).hide();
}
});
}
This is so far the most accurate and optimized way i have came across.

Seems like we can use view parameter to identify the id. This worked for me. Create one function to pull out the id. And call it from the callbacks functions with view as parameter.
function getCalendarId(view) {
return (view.calendar.view.el.parents('div.calendar').attr('id'))
}
function onSelectTimeFrame(start, end, jsEvent, view) {
let calendarId = getCalendarname(view);
//Use calendarId.
}

Related

Full Calendar drag and drop event call back

When i try to add external event to it i require date and time from the calendar how can i achieve that here is my code which i have worked over.
document.addEventListener('DOMContentLoaded', function () {
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable
//// the individual way to do it
var containerEl = document.getElementById('external-events-list');
var eventEls = Array.prototype.slice.call(
containerEl.querySelectorAll('.fc-event')
);
eventEls.forEach(function(eventEl) {
new Draggable(eventEl, {
eventData: {
title: eventEl.innerText.trim(),
}, // this allows things to be dropped onto the calendar
drop: function (arg) {
// is the "remove after drop" checkbox checked?
alert(arg);
}, // this allows things to be dropped onto the calendar
eventReceive: function (arg) {
// is the "remove after drop" checkbox checked?
alert(arg);
},
eventDrop: function (event, delta, revertFunc) {
//inner column movement drop so get start and call the ajax function......
console.log(event.start.format());
console.log(event.id);
var defaultDuration = moment.duration($('#calendar').fullCalendar('option', 'defaultTimedEventDuration'));
var end = event.end || event.start.clone().add(defaultDuration);
console.log('end is ' + end.format());
//alert(event.title + " was dropped on " + event.start.format());
}
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
var calendarEl = document.getElementById('calendar');
var calendar = new Calendar(calendarEl, {
plugins: ['interaction', 'dayGrid', 'timeGrid', 'list'],
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
drop: function (arg) {
// is the "remove after drop" checkbox checked?
if (document.getElementById('drop-remove').checked) {
// if so, remove the element from the "Draggable Events" list
arg.draggedEl.parentNode.removeChild(arg.draggedEl);
}
},
eventDrop: function (info) {
alert(info.event.title + " was dropped on " + info.event.start.toISOString());
if (!confirm("Are you sure about this change?")) {
info.revert();
}
},
//eventRender: function (info) {
// console.log(info.event.extendedProps);
// // {description: "Lecture", department: "BioChemistry"}
//}
});
calendar.render();
});
i am trying to add event callback function in the new Draggable but to no use as event are not fired from it when i drag within the calendar then it fires back from new Calendar, so i require that after dragging event externally in the calendar i need to get date and time from it.

Errors in efforts to write code for fullCalendar without using jQuery

I saw a CodePen that allowed dragging an event from FullCalendar to trash or back to an external list. I forked the CodePen: https://codepen.io/hlim18/pen/EMJWQP?editors=1111. The JavaScript part of the working code with jQuery is the following:
$(document).ready(function() {
/* 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
-----------------------------------------------------------------*/
$('#calendarSchedule').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
dragRevertDuration: 0,
drop: function() {
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
console.log(this);
$(this).remove();
}
},
eventDragStop: function( event, jsEvent, ui, view ) {
if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) {
$('#calendar').fullCalendar('removeEvents', event._id);
var el = $( "<div class='fc-event'>" ).appendTo( '#external-events-listing' ).text( event.title );
el.draggable({
zIndex: 999,
revert: true,
revertDuration: 0
});
el.data('event', { title: event.title, id :event.id, stick: true });
}
}
});
var isEventOverDiv = function(x, y) {
var external_events = $( '#external-events' );
var offset = external_events.offset();
offset.right = external_events.width() + offset.left;
offset.bottom = external_events.height() + offset.top;
// Compare
if (x >= offset.left
&& y >= offset.top
&& x <= offset.right
&& y <= offset .bottom) { return true; }
return false;
}
});
I would like to write the code without using jQuery. So, I tried to change jQuery to vanilla JavaScript. But, the calendar is not even displayed in the screen.
This is how I tried: https://codepen.io/hlim18/pen/bZyaQj?editors=1111.
The JavaScript part with vanilla JavaScript I tried is the following:
/* initialize the external events
-----------------------------------------------------------------*/
var draggable_events = document.querySelectorAll('#external-events .fc-event');
for(var i=0; i<draggable_events.length; i++){
// store data so the calendar knows to render an event upon drop
draggable_events[i].fullCalendar('renderEvent', {
title: draggable_events[i].innerText, // 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
draggable_events[i].draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
}
/* initialize the calendar
-----------------------------------------------------------------*/
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendarSchedule');
var calendar = new FullCalendar.Calendar(calendarEl, {
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
dragRevertDuration: 0,
drop: function() {
// is the "remove after drop" checkbox checked?
if (document.getElementById('drop-remove').checked = true) {
// if so, remove the element from the "Draggable Events" list
this.remove();
}
},
eventDragStop: function( event, jsEvent, ui, view ) {
if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) {
calendarEl.fullCalendar('removeEvents', event._id);
var el = document.querySelector('fc-event').setAttribute("id", "external-events-listing").text( event.title );
el.draggable({
zIndex: 999,
revert: true,
revertDuration: 0
});
el.data('event', { title: event.title, id :event.id, stick: true });
}
}
}
});
var isEventOverDiv = function(x, y) {
var external_events = document.getElementById('external-events');
var offset = external_events.offset();
offset.right = external_events.width() + offset.left;
offset.bottom = external_events.height() + offset.top;
// Compare
if (x >= offset.left && y >= offset.top && x <= offset.right && y <= offset .bottom){
return true;
}
return false;
}
In the CodePen, I don't see any errors. But, when I test with my app I'm working on, I see the following error:
Uncaught TypeError: draggable_events[i].fullCalendar is not a function
at viewMonthly.js:15
I'm not even sure how many problems are there in total to solve to make the code work with vanilla JavaScript... :(
So, I'd appreciate any advice. Thank you in advance! :)
fullCalendar in versions prior to V4 is a jquery plugin and needs jquery to work

How to change the date in agendaView of FullCalendar javascript plugin

I am using this great javascript FullCalendar plugin.
I have to display a month calendar, and when a day is selected, show the agendaView next to it like so:
In that example image, the user has clicked on July 1st, and I need the agendaView on the right to display for July 1st, but it always loads today's date.
Here is the code. You can see the commented code where I tried to set the visible range when the 'day' calendar (agendaView) is loaded, but that did not work. Currently at the end I'm trying to use the changeView function, but that also didn't work.
$(document).ready(function () {
// page is now ready, initialize the calendar...
var selectedDay = null;
var selected = moment();
$('#calendar').fullCalendar({
// options and callbacks here
aspectRatio: 1.5,
dayClick: function (date, jsEvent, view) {
// alert('Clicked on: ' + date.format());
// alert('Current view: ' + view.name);
// reset previously selected day's background color
if (selectedDay !== null) {
$(selectedDay).css('background-color', 'transparent')
};
// change the newly selected day's background color
$(this).css('background-color', '#A5DC86');
selectedDay = this;
// selected = this.fullCalendar.moment();
selected = this.date;
$('#day').fullCalendar({
// visibleRange: function(currentDate) {
// return {
// start: selected.date,
// end: selected.date.clone().add(1, 'days') // exclusive end
// };
// },
aspectRatio: 1.5,
defaultView: 'agendaDay',
header: {left: '', center: 'title', right: ''},
allDaySlot: false,
slotDuration: '00:60:00',
scrollTime: '00:00:00'
}),
$('#day').fullCalendar('changeView', 'agendaDay', selectedDay.date )
}
});
});
It turns out that changeView expects a formatted date, so:
$('#day').fullCalendar('changeView', 'agendaDay', date.format() )
is the solution.

FullCalender check if selection days has an event?

I am using the Full Calender js plugin, so far so good. but i want to check if a selection between the start and end has events?
I just need a true or false returned. Basically i want to stop users from creating events if an even already exists on the date selection.
var calendar = $('#calendar').fullCalendar({
selectable: true,
selectHelper: true,
firstDay: 5,
weekNumbers: false,
select: function (start, end, allDay, event) {
var TitleSet = false;
StartDate = start;
EndDate = end;
if (event) {}
if (TitleSet) {
calendar.fullCalendar('renderEvent', {
title: title,
start: start,
end: end,
allDay: allDay
},
true // make the event "stick"
);
}
calendar.fullCalendar('unselect');
},
editable: true,
events: EventsArr,
eventRender: function (event, element) {
element.qtip({
content: event.description
});
}
});
I tried this methode and it looks fine
// check if this day has an event before
function IsDateHasEvent(date) {
var allEvents = [];
allEvents = $('#calendar').fullCalendar('clientEvents');
var event = $.grep(allEvents, function (v) {
return v.start === date;
});
return event.length > 0;
}
then you can call it from dayclick event
dayClick: function (date, allDay, jsEvent, view) {
if (!IsDateHasEvent(date)) {
selectedDate = date;
$("#divAddNewAppointment").dialog("open");
}
else {
$('<%= "#" + lblMessage.ClientID%>').html(" your error msg");
$("#divMessage").dialog("open");
}
}
You will need to create a method to get the array of events already loaded in calendar, after that use that array to get all days that have events and if user clicks on one of that dates don´t let create another event. This is something that only you can make and figure out, you will need to make an algorithm for yourself...
Check this clientEvents

Child html element's onclick event is blocked. how to conquer? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Prevent execution of parent event handler
I need to attach functions to onclick events of hierarchical divs.
I have this HTML
<div onclick="event1()" class="wrapper">
main contents
<div onclick="event2()"class="inner">
inner contents
</div>
</div>
now when i click on inner div event1() is being called, and event2() is not being called because I think my jquery plugin blocks it.
Edited ::
actually my plugin blocks the child node events so event2() is never being called how can i stop that ?
I am using jquery full callender plugin : http://arshaw.com/fullcalendar/
and below is my configuration function which is being called on onready.
function calenderEvents(events, account_id) {
//Dynamically Set options as account type wise
var selectable_opt = '';
if (account_id == 'default') {
selectable_opt = true;
} else {
selectable_opt = false;
}
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: selectable_opt,
selectHelper: true,
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
AfterMove(event);
},
select: function(start, end, allDay) {
var title = prompt('Event Title:');
if (title) {
var details = {
title: title,
start: start,
end: end,
allDay: allDay
};
$.post(SITE_URL + '/calendar/add-event', {
details: details
}, function() {
});
calendar.fullCalendar('renderEvent', {
title: title,
start: start,
end: end,
allDay: allDay,
}, true // make the event "stick"
);
}
calendar.fullCalendar('unselect');
},
/*eventMouseover: function() {
$('.fc-event-delete').css('display','block');
},
eventMouseout: function() {
$('.fc-event-delete').css('display','none');
},*/
editable: true,
events: events,
});
//}).limitEvents(2);
}
You can add the event handler to the container element and supply a selector so only events triggered by elements that match that selector will invoke the handler. Because the handler is being attached to the containing element, child elements that are added to the DOM later will still invoke the handler, if they match the selector.
http://api.jquery.com/on/
This code will create an event handler that will be triggered on new elements that are added to the div#wrapper element. The #adder click handler will add new elements to the wrapper.
HTML
<div id="adder">click to add elements</div>
<div class="wrapper">
contents:
<div class="inner">0</div>
</div>​
JS
var $inner = $('.inner').first(),
$wrapper = $('.wrapper'),
count = 0;
$wrapper.on('click', '.inner', function(e) {
alert('click from ' + $(this).text());
});
$('#adder').on('click', function() {
$wrapper.append($inner.clone().text(++count));
});
The main thing is the use of the .inner selector when the click event handler is added to $wrapper.
Shown in this jsFiddle.
You need to stop the event being propagated to the parent.
Use event.stopPropagation();
$(".inner").click(function(event){
//do something
event.stopPropagation();
});
This effect is call event propagation.
Inner div click handler has to be just like this to prevent propagation:
var event2 = function(event) {
event = event || window.event;
if (event.stopPropagation) {
// for adequate browsers
event.stopPropagation()
} else {
// for IE
event.cancelBubble = true
}
}
demo - http://jsfiddle.net/Qw92P/
Just use one click event on the wrapper but make it "live". Detect if the click was actually on the child using targetElement (or is it srcElement--you can look up this part).

Categories

Resources