Fullcalendar: how to know in which cell I am dropping an item? - javascript

I am creating the calendar where I can drop events from external list.
I took as example this sample - external-dragging.
I want to add specific logic that user can add only one event per day.
So for preventing dropping to 'filled' cell I am trying to use dropAccept method in the next way.
dropAccept: function (item) {
return [my condition];
},
I can get item that I am dropping from item element, I can get calendar's events but I can't get a cell (or a date) where I am putting my item.
How could I get a cell/date where I am dropping item?
Thank you.

I have solved this in another way.
I set all events as all day by default
I forbade an event overlapping
My code is:
$('#calendar').fullCalendar({
allDayDefault: true,
eventOverlap: false,
});

You can use drop function of full calendar.
Here is parameters
function( date, jsEvent, ui ) { }
Enjoy!

Related

How to prevent highlight (gray background) of an external event in fullcalendar

I already have start and end time for an external event but is there any correct way to set the end time on highlight (gray background) of the same external event.
Or if there is no way to set the end time on highlight then can we remove the fc-highlight completely from external/draggable events.
By the way, I already asked this question but didn't get correct response, so that's why I'm asking again
For more detail, please visit my another question here: Disable highlight of an external event in fullcalendar
Starting from your CodePen...
I managed to customise the draggable event in order to have a defined duration to be used as time calculation.
I added data-duration-hour and data-duration-minute attributes to the draggable event.
Those "data" attributes ares used to determine the ending time of the event, on drop.
NOW about the hightlight which occurs on drag (before drop) in the calendar...
It still hightlights 2 hours.
You'll have to to look at a function to add on drag in fullCalendar options.
I have no idea for the moment.
So... I may not have answered the right question (about the hightlight effect on drag).
But this is still an improvement for your project.
See in this CodePen
HTML modified:
<div class='fc-event' data-duration-hour="3" data-duration-minute="30">My Event 1</div>
JS modified:
function external_event_dropped(date, external_event) {
var event_object;
var copied_event_object;
var tempDate = new Date(date);
event_object = $(external_event).data('eventObject');
copied_event_object = $.extend({}, event_object);
copied_event_object.start = date;
// This is the dropped date object
console.log(date);
// This is the drop time in clear.
console.log( "dropped at: "+date.hour()+":"+date.minute() );
// Retreive the data-duration from the dragged element.
var durationHour = parseInt(external_event.data("duration-hour"));
var durationMinute = parseInt(external_event.data("duration-minute"));
console.log("DATA: "+durationHour+":"+durationMinute);
// Clone the time object to modify it in order to create de end time.
var dateEnd = date.clone();
dateEnd = dateEnd.hour(dateEnd.hour()+durationHour);
dateEnd = dateEnd.minute(dateEnd.minute()+durationMinute);
// This is the end time object.
console.log(dateEnd);
// This is the drop end time in clear.
console.log( "dropped at: "+dateEnd.hour()+":"+dateEnd.minute() );
// Now set it to the FullCalendar object.
copied_event_object.end = dateEnd;
copied_event_object.allDay = false;
copied_event_object.title = 'ADEEL';
external_event.remove();
$('#exampleCalendar').fullCalendar('renderEvent', copied_event_object, true);
}
For the complete solution check this out: Fullcalendar
External/Draggable Events Highlight
Effect
Well after reading the fullcalendar documentation and spent a lot of time on this issue, I come up with a solution and I hope it might help others as well.
So, the solution is:
I've added an option defaultTimedEventDuration which is a default duration of an external/draggable event, if there is no duration set on event.
e.g: defaultTimedEventDuration: '01:00:00'
Also added data-duration in html to get dynamic duration and highlighted effect.
e.g: <div class='fc-event' data-duration='03:00'>My Event 1</div>
N.B: Also possibility to set duration attribute in js data

FullCalendar removes all eventSources or events, either by event.id or event.source

Breaking my head over this and I need a little assistance.
Background Story
I'm creating a calendar selection tool to highlight free days as background events with fullCalendar. The UI allows a draggable selection of days or highlight a single day. When the user selects the highlight again, it should be removed. With AJAX I can add or remove the selections and when you refresh the page, the previous events are loaded from data-events on the container.
<div class="container" data-class="calendar" data-events='<?=$jsoncalendarinfo?>' data-user-id="<?php echo $id; ?>">
<div class="row">
<div class="col-lg-3 feedback p-y-2">
<?php
foreach ($calendarinfo as $item) {
?>
<ul data-start="<?=strtotime($item->date_from)?>">
<li>Vrij</li>
<li><?=date('d/m/Y',strtotime($item->date_from))?> - <?=date('d/m/Y',strtotime($item->date_to))?></li>
</ul>
<?php
}
?>
</div>
<div class="col-lg-9 calendar p-y-2"><!-- fullcalendar.js rendering --></div>
</div>
</div>
Problem
When I refresh the page and I click a single highlight (day or range), all highlights are removed. Now I must add I might be confused between events, eventSource and eventSources. The documentation isn't very explicit on the idea behind it so it's more like a trial and error for me.
My Code
eventSources: [this.formatEvents(this.events)],
selectOverlap: function (event) {
self.calendar.fullCalendar(events.removeEventSource, event.source);
self.removeFeedback(event);
return !event.block;
},
I've probably hijacked this functionality to get what I wanted but again, I can't seem to find a proper method to unselect a highlighted day or range. And it's not the unselect method.
Their code
There is no instance available in selectOverlap => self.calendar.fullCalendar
The doc states you can remove eventSources but not events ???
I've tried to add my jsondata in events and in eventSources => what's the f*** difference?
I've tried to remove by event.id and event.source => they all vannish !?!
I've tried to cleanup the event object but in event.sources.events all events are generically deeply nested.
I dove into the library to see what's going on => ln. 11161
function removeEventSource(matchInput) {
removeSpecificEventSources(
getEventSourcesByMatch(matchInput)
);
}
// if called with no arguments, removes all.
function removeEventSources(matchInputs) {
if (matchInputs == null) {
removeSpecificEventSources(sources, true); // isAll=true
}
else {
removeSpecificEventSources(
getEventSourcesByMatchArray(matchInputs)
);
}
}
It basically never compares since the objects are too different. If I use my event.id it tries to compare against an event object. When I use event.source it finds all events under the same source and BAM, all gone :s
Anyone here to cheer me up?
DEMO
https://jsfiddle.net/tive/vxrkmmn3/
Simply click the highlighted dates. These are 2 ranges and should only remove one range. Unfortunately it removes all.
If you highlight another day or range, you can remove it without a problem. Once the page is refreshed, it doesn't work anymore.
Event sources are just ways of grouping events, useful if your events come from different sources (backends). If you don't have multiple backends, or other logical grouping of events, you probably don't need them.
So if you remove an event source, you'll remove all the events that came from that source.
If you are trying to remove a single event when you select it, then the RemoveEvents method is the one you need.
The signature is:
.fullCalendar( 'removeEvents' [, idOrFilter ] )
where idOrFilter is either an eventID (which you can get from the event object provided by the selectOverlap method), or a function which looks at an event and decides if it should be removed or not.
Full docs at https://fullcalendar.io/docs/event_data/removeEvents

Add a event to full calendar from custom list

I have a hard time to understand how the full calendar plug in works if you want to add a new event.
Every example i have seen is hard coded events, not from textboxes.
I have a custom list where i can add new courses (making a course catalog), what i want with my calendar is that the events that is in the custom list will be showing in the calendar to, after the right date (from a textbox).
Does anyone know how to connect a custom list to a fullcalendar? So when a new event is added in the custom list, it also will be added into the full calendar!
will be really glad if someone could give me an example.
Doing it with javascript!
var createinfo = SP.ListCreationInformation();
var newtask = list.addItem(createinfo);
newtask.set_item('Kursnamn', $('#TextKursnamn').val());
newtask.set_item('Malgrupp', $('#TextMalgrupp').val());
newtask.set_item('Forkunskapskrav', $('#TextForkunskapskrav').val());
newtask.set_item('Matrielkrav', $('#TextMatriellkrav').val());
newtask.set_item('Omfattning', $('#SelectOmfattning').val());
newtask.set_item('Kursledare', $('#TextKursledare').val());
newtask.set_item('Telefonnr', $('#TextTelefonnummer').val());
newtask.set_item('Email', $('#TextEmail').val());
newtask.set_item('Startdatum', $('#TextStartdatum').val());
newtask.set_item('Slutdatum', $('#TextSlutdatum').val());
newtask.set_item('SistaAnmalninsgdag', $('#TextSistaanmalningsdag').val());
newtask.set_item('Fritext', $('#TextInformation').val());
newtask.update();
clientContext.load(newtask);
clientContext.executeQueryAsync(success_Createlist, onFail);
//And the calendar is just empty right now
$('#calendar').fullCalendar({
});

Fullcalendar: detect click in week or day view

I'm currently detecting double click events in month view. This works well:
dayRender: (date, element) => {
element.bind('dblclick', ...)
}
What I'm looking for is a way to do the same when the user is in day view or week view. I want to be able to detect a click event, and get the date and time they clicked on (note that time is relevant in day/week view, but not month view).
Any ideas?
For anyone that finds this in the future, here's the hacky solution I came up with:
Because fullcalendar doesn't render a <div> per time slot (eg. a single div representing 1pm-1:30pm on 1/2/2015), and instead visually represents a single time slot as the intersection of a row and a column, we need a way to figure out the time from a given click. Day info is already attached to each column (day) DOM element in the form of a data-date attribute. What I did was I forked fullcalendar, and added time info to each row (time slot) with a new data-time attribute.
Then, I listened on the double click event onViewRender, figured out the elements the user clicked on, and from those was able to derive both the date and the time slot:
viewRender: (view, element) ->
if view.type in ['agendaDay', 'agendaWeek']
element.on 'dblclick', (event) ->
els = document
.elementsFromPoint event.pageX, event.pageY
.filter (e) -> (e.hasAttribute 'data-date') or (e.hasAttribute 'data-time')
date = (_.find els, (e) -> e.hasAttribute 'data-date').getAttribute 'data-date'
time = (_.find els, (e) -> e.hasAttribute 'data-time').getAttribute 'data-time'
return unless date and time
startTime = moment "#{ date } #{ time }"
endTime = (moment startTime).add 30, 'minutes' # clone + increment
This is a really hacky solution, and mixes all sorts of concerns. However, until fullcalendar adds support for a timeClick event, this works pretty well.
Hope this helps someone else!

Disable jQuery UI draggable if element has particular class

I have an interactive basket whereby the user can drag and drop an item into the basket. However, the same item cannot be placed in the basket twice (but it remains visible, albeit faded), so once it is in the basket, the draggable property must be disabled.
I tried doing this:
$("#product_badges li:not(.on)").draggable({
// Options here
});
However, as this just initiates the draggable() property, the element is still draggable even if I do add the on class to it when it has been dropped.
I therefore cannot see a way of achieving this without having several instances for the draggable property like so:
$("#product_badges li:not(.on)").each(function(){
$(this).draggable({
// Options here
}
});
With the above method I can then call the individual product_badge and disable dragging like so:
This only gets called once the item has been placed into the basket (dropped)
$('.item',$('#product_badges')).draggable('disable');
Is there a better way of achieving this? Can you set an HTML element to only be draggable if it does not have a particular class?
Update
See example here: http://jsfiddle.net/mB6GK/2/
use the cancel property.
$("#product_badges li").draggable({ cancel: ".no" })
fiddle:
http://jsfiddle.net/sGguz/
You could use the start event,
$("#container").draggable({
start: function( event, ui )
{ return !$(ui.helper).hasClass('nodrop'); }});
http://jsfiddle.net/mB6GK/4/

Categories

Resources