Issue 396: Disable overlapping events, constrain events to certain times
Status:  Released
Owner: ----
Closed:  Nov 2014
Reported by asumaw...@gmail.com, Mar 14, 2010
An option to prevent overlapping events. Events revert when overlaps with
another event.
Mar 15, 2010
Project Member #1 adamrs...@gmail.com
would be a good enhancement. ive seen other people ask for this as well
Status: Accepted
Mar 18, 2010
#2 bibendus...@gmail.com
Like me :D
Jul 5, 2010
#3 marco.bi...@gmail.com
Do you have a roadmap when this will be implemented?
Nov 21, 2010
Project Member #4 adamrs...@gmail.com
 Issue 700  has been merged into this issue.
Jan 1, 2011
Project Member #5 adamrs...@gmail.com
 Issue 672  has been merged into this issue.
Feb 22, 2011
#6 Lanceguy...@gmail.com
Keen as for this.
Apr 30, 2011
#7 gkexte...@gmail.com
same here ...  very interested in this feature
Jun 2, 2011
#8 florian....@gmail.com
Very interested on how to do this as well :)

Do you have some workaround before the implementation in the core ?


Jun 3, 2011
#9 maximsch...@gmail.com
Hi Florian, 

I had the issue a half year ago or so. I overcame the problem with just simple PHP. When a user add's an event, the JS will send it via ajax to a php script that put's it in my database. But this is the answer: it first checks wether or not it overlaps an event already stored. If it returns false or a variable with an error it uses the 'revertFunc()' build in Fullcalendar to disregard the changes made. 

an example with the drop functionality looks like:

eventDrop: function(event,dayDelta,minuteDelta,allDay,revertFunc) {

  			$.post("/"+base_path+"library/handlers/handler_business.php", {id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay, type: 'booking_drop'}, function(data) {

				$('#updateBox').prepend($(data.message).fadeIn('slow'));

				if(data.test == 'multiple'){revertFunc();}

				else {$('#calendar').fullCalendar( 'refetchEvents', event );};

			}, 'json');		    
		},
Nov 12, 2011
#11 drobinoh...@gmail.com
Hi guys!

First of all thanks for this awesome plugin! It really rocks!

I solved the problem with overlapping events by preventing the user to drag an event over another one, or resize an event so big to overlap another one. You can solve it by  writing into the source code, but this method does not need this.

I'm really interested in simpler solutions, so feel free to share. :)

Here's the code:

eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc)
                                                {
                                                    var validDrop = true;
                                                    var ev = $("#calendar").fullCalendar("clientEvents");
                                                    for(var e in ev)
                                                    {   
                                                        if(ev[e].id!=event.id)
                                                        {
                                                            if(ev[e].start>=event.start && ev[e].end<=event.end)
                                                                validDrop=false;
                                                            if(ev[e].start<=event.start && ev[e].end>=event.end) 
                                                                validDrop=false;
                                                            if(ev[e].start<event.start && ev[e].end<event.end && ev[e].end>event.start)
                                                                validDrop=false;
                                                            if(ev[e].end>event.end && ev[e].start>event.start && ev[e].start<event.end)
                                                                validDrop=false;
                                                        }
                                                    }
                                                    
                                                    if(!validDrop)
                                                    {
                                                        revertFunc();
                                                    }
                                                }
                                                eventResize: function(event, dayDelta, minuteDelta, revertFunc)
                                                {
                                                    var validDrop = true;
                                                    var ev = $("#calendar").fullCalendar("clientEvents");
                                                    for(var e in ev)
                                                    {   
                                                        if(ev[e].id!=event.id)
                                                        {
                                                            if(ev[e].start>=event.start && ev[e].end<=event.end)
                                                                validDrop=false;
                                                            if(ev[e].start<=event.start && ev[e].end>=event.end) 
                                                                validDrop=false;
                                                            if(ev[e].start<event.start && ev[e].end<event.end && ev[e].end>event.start)
                                                                validDrop=false;
                                                            if(ev[e].end>event.end && ev[e].start>event.start && ev[e].start<event.end)
                                                                validDrop=false;
                                                        }
                                                    }
                                                    
                                                    if(!validDrop)
                                                    {
                                                        revertFunc();
                                                    }
                                                }

p.s.: It only works with resizing and dragging. If you add a new event, it will still overlap.
p.s.: I don't know how it works with bigger calendars with thousands of events, but it could be really slow. :-/
Dec 18, 2011
#12 andrew.h...@gmail.com
Would love to see this implemented. 
Feb 10, 2012
#14 a.gunas...@gmail.com
Look here for the best solution so far by ecruz imho

http://stackoverflow.com/questions/2369683/prevent-overlapping-events-in-jquery-fullcalendar

so you have this function:

function isOverlapping(event){
    var array = calendar.fullCalendar('clientEvents');
    for(i in array){
        if(array[i].id != event.id){
            if(!(array[i].start >= event.end || array[i].end <= event.start)){
                return true;
            }
        }
    }
    return false;
}

and inside fullcalendar init:

eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
	if (isOverlapping(event)) {revertFunc()};
},
eventResize: function(event, dayDelta, minuteDelta, revertFunc) {
	if (isOverlapping(event)) {revertFunc()};
},
select: function(start, end, allDay) {
	var event = new Object();
	event.start = start;		
	event.end = end;

	var title = prompt('Event Title:');
	if (title && !isOverlapping(event)) {
		calendar.fullCalendar('renderEvent', {
			title: title,
			start: start,
			end: end,
			allDay: allDay
		},
		true // make the event "stick"
		);
	}
	calendar.fullCalendar('unselect');
}

Make sure your end-dates are specified in your event-source!
If not these will be null and it won't work because they are not comparable.

Would be nice to see end-date automatically set to start-date + defaultEventMinutes if no end-date is provided.


Feb 10, 2012
#17 a.gunas...@gmail.com
Maybe not the best option, but to set end-date automatically to add defaultEventMinutes if no end-date is present:

Find the function normalizeEvent(event) in fullcalendar.js

then after:

event._start = cloneDate(event.start = parseDate(event.start, ignoreTimezone));

add:

if (!event.end) {
	event.end = cloneDate(event.end = event._start.setMinutes(event._start.getMinutes() + options.defaultEventMinutes));
}
Apr 23, 2013
#18 ethan.hu...@web.de
Hi, is this issue scheduled for a release?

ragards
Partrick
Aug 13, 2013
Project Member #19 adamrs...@gmail.com
(No comment was entered for this change.)
Labels: -Type-Enhancement Type-Feature
Aug 14, 2013
Project Member #20 adamrs...@gmail.com
 Issue 1193  has been merged into this issue.
Aug 14, 2013
Project Member #21 adamrs...@gmail.com
 Issue 1200  has been merged into this issue.
Aug 14, 2013
Project Member #22 adamrs...@gmail.com
as brought up by  issue 1200 , it would be very nice to be able to specify this on a per-event basis. For each event, a boolean meaning, "are other events allow to overlap with this one?"
Aug 15, 2013
Project Member #23 adamrs...@gmail.com
 Issue 1338  has been merged into this issue.
Aug 18, 2013
Project Member #24 adamrs...@gmail.com
 Issue 1587  has been merged into this issue.
Aug 24, 2013
Project Member #25 adamrs...@gmail.com
 Issue 1887  has been merged into this issue.
Aug 24, 2013
Project Member #26 adamrs...@gmail.com
 Issue 1902  has been merged into this issue.
Apr 25, 2014
#27 modi08...@gmail.com
Hi All,
It would be very nice to have this feature on dropping external event on to the fullcalendar??


Thanks in advance
Manish.
Sep 2, 2014
Project Member #28 adamrs...@gmail.com
 Issue 656  has been merged into this issue.
Sep 2, 2014
Project Member #29 adamrs...@gmail.com
the scope of this feature request will now include:
A) constraining events to certain dates/times
B) integration with the proposed "background" (or "annotation") events systems

Also adding this to the next big milestone, "annotation", which will contain a group of related features
Summary: Disable overlapping events, constrain events to certain times (was: Disable overlapping events)
Labels: milestone-annotation
Sep 25, 2014
#30 chrishil...@gmail.com
Hello all.

I have written a solution to events being "busy" with a little help from _js and session variables

on document ready......

        var clientEvents = $('#sellers-viewings-calendar').fullCalendar('clientEvents');
        var eventArray = _.map(clientEvents, function(event){ return event._start._i; });
        Session.set('takenSlots', eventArray);
        // set the session

        eventDrop: function (event, delta, revertFunc) {
            var eventArray = Session.get('takenSlots');
            var droppedOn = event.start.format();
            var busy = _.contains(eventArray, droppedOn);
            if (busy) {
                revertFunc();
                alert('Sorry we are busy!!')
            }
            else {
              // run your event drop code here
            }
        },



Sep 25, 2014
#31 thi...@thiagomt.com
Chris would be very useful for everyone if you provide details of your solution, which seems to be very interesting. 

First, because mixing Underscore with jQuery? 
Why save the session? You manipulate that session at another location? What script is this "Session"?
Sep 25, 2014
#32 paul.wol...@gmail.com
I handle this in my php backend, and send succes=false and an error back to the front.