slot_event_overlap.html 5.24 KB
<!DOCTYPE html>
<html>
<head>
<link href='../dist/fullcalendar.css' rel='stylesheet' />
<link href='../dist/fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../lib/jquery/dist/jquery.js'></script>
<script src='../lib/moment/moment.js'></script>
<script src='../dist/fullcalendar.js'></script>
<script>

	$(document).ready(function() {
		
		$('#calendar').fullCalendar({
			header: {
				left: 'prev,next today',
				center: 'title',
				right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
			},
			editable: true,
			defaultView: 'agendaDay',
			firstHour: 0,
			year: 2013,
			month: 6, // July
			date: 31,
			events: 'slot_event_overlap.json',
			eventAfterAllRender: function() {
				testOverlap($('#calendar'), true, false);
			}
		});

		$('#calendar-nooverlap').fullCalendar({
			header: {
				left: 'prev,next today',
				center: 'title',
				right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
			},
			editable: true,
			defaultView: 'agendaDay',
			firstHour: 0,
			year: 2013,
			month: 6, // July
			date: 31,
			events: 'slot_event_overlap.json',
			slotEventOverlap: false,
			eventAfterAllRender: function() {
				testOverlap($('#calendar-nooverlap'), false, false);
			}
		});

		$('#calendar-rtl').fullCalendar({
			header: {
				left: 'prev,next today',
				center: 'title',
				right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
			},
			editable: true,
			defaultView: 'agendaDay',
			firstHour: 0,
			year: 2013,
			month: 6, // July
			date: 31,
			events: 'slot_event_overlap.json',
			isRTL: true,
			eventAfterAllRender: function() {
				testOverlap($('#calendar-rtl'), true, true);
			}
		});

		$('#calendar-rtl-nooverlap').fullCalendar({
			header: {
				left: 'prev,next today',
				center: 'title',
				right: 'month,agendaWeek,basicWeek,agendaDay,basicDay'
			},
			editable: true,
			defaultView: 'agendaDay',
			firstHour: 0,
			year: 2013,
			month: 6, // July
			date: 31,
			events: 'slot_event_overlap.json',
			isRTL: true,
			slotEventOverlap: false,
			eventAfterAllRender: function() {
				testOverlap($('#calendar-rtl-nooverlap'), false, true);
			}
		});
		
	});

	function testOverlap(el, allowOverlap, isRTL) {
		if (_testOverlap(el, allowOverlap, isRTL)) {
			el.prev('h2').find('span').css('color', 'green').text('passed');
		}
		else {
			el.prev('h2').find('span').css('color', 'red').text('failed');
		}
	}

	function _testOverlap(el, allowOverlap, isRTL) {

		var events = el.find('.fc-event');

		var cell = el.find('.fc-slot0 td');
		var cellLeft = Math.round(cell.offset().left);
		var cellWidth = Math.round(cell.outerWidth());

		if (!events.length) { // json events probably couldn't load
			console.log('need to run this from a real web server');
			return false;
		}

		for (var i=0; i<events.length; i++) {

			var event = $(events[i]);
			var offset = event.offset();
			var top = Math.ceil(offset.top);
			var left = Math.ceil(offset.left);
			var width = Math.floor(event.outerWidth());
			var height = Math.floor(event.outerHeight());

			if (left < cellLeft || left + width > cellLeft + cellWidth) {
				console.log('event is out of bounds', event[0]);
				return false;
			}

			if (width < 10 || height < 10) {
				console.log('event is suprisingly small', event[0]);
				return false;
			}

			if (allowOverlap) {
				width /= 2; // make sure nothing overlaps the first half of the event
				if (isRTL) {
					left += width;
				}
			}

			for (var j=i+1; j<events.length; j++) {
				// only test again events that are ahead in the DOM, meaning they have a higher
				// implicit z-index and an top of the current event

				var otherEvent = $(events[j]);
				var otherOffset = otherEvent.offset();
				var otherTop = Math.ceil(otherOffset.top);
				var otherLeft = Math.ceil(otherOffset.left);
				var otherWidth = Math.floor(otherEvent.outerWidth());
				var otherHeight = Math.floor(otherEvent.outerHeight());

				if (
					top < otherTop + otherHeight &&
					top + height > otherTop &&
					left < otherLeft + otherWidth &&
					left + width > otherLeft
				) {
					console.log('failed on', event[0], otherEvent[0]);
					return false; // a collision
				}
			}
		}

		if (!allowOverlap) {
			// we know of certain events that should have the same width
			// because they share a liquid area...

			var equalwidth1 = events.filter('.equalwidth1');
			if (equalwidth1.eq(0).outerWidth() - equalwidth1.eq(1).outerWidth() > 1) {
				console.log('not equal width', equalwidth1.toArray());
				return false;
			}

			var equalwidth2 = events.filter('.equalwidth2');
			if (equalwidth2.eq(0).outerWidth() - equalwidth2.eq(1).outerWidth() > 1) {
				console.log('not equal width', equalwidth2.toArray());
				return false;
			}

		}

		return true;
	}

	// TODO: add tests for viewing events in week-mode also

</script>
<style>

	body {
		font-size: 13px;
		font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
	}

	.calendar {
		width: 900px;
		margin: 50px auto;
	}

</style>
</head>
<body>

<h2>Default: <span></span></h2>
<div id='calendar' class='calendar'></div>

<h2>No overlap: <span></span></h2>
<div id='calendar-nooverlap' class='calendar'></div>

<h2>RTL: <span></span></h2>
<div id='calendar-rtl' class='calendar'></div>

<h2>RTL, no overlap: <span></span></h2>
<div id='calendar-rtl-nooverlap' class='calendar'></div>

</body>
</html>