Drag an event to the fullCalendar component with a specific duration

I saw a solution to drag external events into fullcalendar . But in this demo, all external events are 2 hours long (since the defaultEventMinutes parameter is set to 120). I am trying to modify this demo to manage events with different durations. Say, "My event 1" is 45 minutes long, "My event 2" is 165 minutes, etc.

In the beginning, although there may be an attribute for storing duration in eventObject, but according to the documentation this is not so. Then I thought that when dragging an event it would be possible to change the value of 'defaultEventMinutes'. But apparently, I can’t do this without rebuilding the entire calendar.

In your opinion, what is the best way to meet this requirement? Thank you in advance for your advice ...

+4
source share
7 answers

Worked on this and decided the duration shown on fullCalendar like this:

  • The presence of a custom function "setOptions" for fullCalendar.
  • Having a fullCalendar property called "dragMinutes" that can be set during the $ (this) .draggable ({start: ...}) elements.

Here is the code for custom setOptions:

... function Calendar(element, options, eventSources) { var t = this; // hack for setting options that updates function setOptions(new_options, refresh) { $.extend(options, new_options); if (refresh) { var viewName = currentView.name; changeView(viewName, true); } } // exports ... t.setOptions = setOptions; ... 

Here is the code for handling the dragMinutes option in fullCalendar:

 /* External Dragging --------------------------------------------------------------------------------*/ function dragStart(_dragElement, ev, ui) { hoverListener.start(function (cell) { clearOverlays(); if (cell) { if (cellIsAllDay(cell)) { renderCellOverlay(cell.row, cell.col, cell.row, cell.col); } else { var d1 = cellDate(cell); if (opt('dragMinutes')) var d2 = addMinutes(cloneDate(d1), opt('dragMinutes')); else var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes')); renderSlotOverlay(d1, d2); } } }, ev); } 

And here is how I can drag the event and update "dragMinutes":

  // make the event draggable using jQuery UI $(this).draggable({ containment: 'document', // return a custom styled elemnt being dragged helper: function (event) { return $('<div class="uv-planning-dragging"></div>').html($(this).html()); }, opacity: 0.70, zIndex: 10000, appendTo: 'body', cursor: 'move', revertDuration: 0, revert: true, start: function (e, ui) { // set the "dragMinutes" option in fullCalendar so shown interval about to be added is correct. var data = $(this).data('eventObject'); if (data) { var min = data.jsonProps.durationMsec / 1000 / 60; if (macroCalendar.calendar) { macroCalendar.calendar.fullCalendar('setOptions', { dragMinutes: Math.round(min) }, false); } } }, stop: function (e, ui) { // further process } }); 

Hope this helps.

+3
source

Currently, the best solution I have found is to add a duration attribute for my event object, then the code to create my fullCalendar is as follows:

  $('#calendar').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 !!! drop: function(date, allDay) { // this function is called when something is dropped // retrieve the dropped element stored Event Object var originalEventObject = $(this).data('eventObject'); // we need to copy it, so that multiple events don't have a reference to the same object var copiedEventObject = $.extend({}, originalEventObject); // assign it the date that was reported copiedEventObject.start = date; // HERE I force the end date based on the start date + duration copiedEventObject.end = new Date(date.getTime() + copiedEventObject.duration * 60 * 1000); copiedEventObject.allDay = allDay; // render the event on the calendar // the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/) $('#calendar').fullCalendar('renderEvent', copiedEventObject, true); // is the "remove after drop" checkbox checked? if ($('#drop-remove').is(':checked')) { // if so, remove the element from the "Draggable Events" list $(this).remove(); } } }); 

The only drawback is the drag and drop of the event, the duration of the event looks like defaultEventMinutes, not the actual duration, but I do not know how to fix it.

+2
source

If someone is still visiting the stream and cannot find a solution, then the solution would be to set the duration parameter in the event div ... and then call drag and drop on that div.

 $(this).data('event', { title: 'new event title', // use the element text as the event title id: $(this).attr('id'), stick: true, // maintain when user navigates (see docs on the renderEvent method) duration: '03:00:00' // will set the duration during drag of event }); 
+2
source

These special properties can be specified in the provided event object or can be stand-alone data attributes:

 <!-- DURATION OF 3 hours EVENT WILL PROPAGATE TO CALENDAR WHEN DROPPED --> <div class='draggable' data-event='1' data-duration='03:00' /> 

https://fullcalendar.io/docs/dropping/eventReceive/

+1
source

With the latest fullcalendar v2.0.2 , if you want the overlay to have a specific duration, you can update this function fullcalendar-arshaw.js

 function dragStart(_dragElement, ev, ui) { hoverListener.start(function(cell) { clearOverlays(); if (cell) { var seconds = duration_in_minutes * 1000 * 60 ; // we need to pass seconds into milli-seconds if (d1.hasTime()) { d2.add(seconds); renderSlotOverlay(d1, d2, cell.col); } else { d2.add(calendar.defaultAllDayEventDuration); renderDayOverlay(d1, d2, true, cell.col); } } }, ev); } 

Here, spend your duration in the external event object and in the object that you can get in _dragElement , and then convert it to milliseconds and pass it to d2.add(seconds) . This will create the shadow of these milliseconds on this calendar.

0
source

For non-external events, you can use the full calendar settings:

 defaultTimedEventDuration: (hours+':00:00'), forceEventDuration: true, // defaultEventMinutes: hours*60, // not needed 

and in the event data you do not set the end property (or its value is null):

 eventData = { title: title, start: start, // end: end, // MUST HAVE no end for fixedduration color: '#00AA00', editable: true, // for dragging }; 

Link: http://fullcalendar.io/docs/event_data/defaultTimedEventDuration/

Tip. If you want to prevent event resizing, which is possibly due to editable: true , you can use CSS to hide the handle: .fc-resizer.fc-end-resizer { display:none; } .fc-resizer.fc-end-resizer { display:none; }

0
source

Starting with version 4, some of the above options do not work at all. The problem I ran into was this:

All items of the day have a duration, but not a start time. When I select the start time by dragging and dropping, the start time is set, but as soon as I set the end date (which is done similarly to the previous answers), the end date is reset again .. there is something buggy in setDate ... the end date is set, this the part works, then it performs the comparison itself to find out the time difference between the dates, but the system itself sets the date, as a result of which the difference becomes equal to 0, which causes the end date to be reset to zero ......

A huge pain in my neck, I have to say ... it works great when it stays within the schedule, but more about that.

I managed to β€œfix”, more like destruction, using this line in the eventDrop event, but this will also work in any other events that you can use:

  • update your event with ajax here as you have a start and end date *
  • calendar.refetchEvents (); in function of success

It will repeat all the events, it sounds pretty deadly for performance, but it doesn't seem to take long, try it yourself. So my headers, time, etc. Always updated, and the calendar displays the correct end date.

0
source

Source: https://habr.com/ru/post/1435752/


All Articles