Procházet zdrojové kódy

make external event dragging work with constraint/overlap system

Adam Shaw před 11 roky
rodič
revize
7acef25205
2 změnil soubory, kde provedl 71 přidání a 39 odebrání
  1. 51 33
      src/EventManager.js
  2. 20 6
      src/common/View.js

+ 51 - 33
src/EventManager.js

@@ -597,11 +597,12 @@ function EventManager(options) { // assumed to be a calendar
 
 	// If the given event is a recurring event, break it down into an array of individual instances.
 	// If not a recurring event, return an array with the single original event.
+	// If given a falsy input (probably because of a failed buildEventFromInput call), returns an empty array.
 	function expandEvent(abstractEvent) {
 		var events = [];
+		var view;
 		var _rangeStart = rangeStart;
 		var _rangeEnd = rangeEnd;
-		var view;
 		var dowHash;
 		var dow;
 		var i;
@@ -617,48 +618,50 @@ function EventManager(options) { // assumed to be a calendar
 			_rangeEnd = view.end;
 		}
 
-		if (abstractEvent._recurring) {
+		if (abstractEvent) {
+			if (abstractEvent._recurring) {
 
-			// make a boolean hash as to whether the event occurs on each day-of-week
-			if ((dow = abstractEvent.dow)) {
-				dowHash = {};
-				for (i = 0; i < dow.length; i++) {
-					dowHash[dow[i]] = true;
+				// make a boolean hash as to whether the event occurs on each day-of-week
+				if ((dow = abstractEvent.dow)) {
+					dowHash = {};
+					for (i = 0; i < dow.length; i++) {
+						dowHash[dow[i]] = true;
+					}
 				}
-			}
 
-			// iterate through every day in the current range
-			date = _rangeStart.clone().stripTime(); // holds the date of the current day
-			while (date.isBefore(_rangeEnd)) {
+				// iterate through every day in the current range
+				date = _rangeStart.clone().stripTime(); // holds the date of the current day
+				while (date.isBefore(_rangeEnd)) {
 
-				if (!dowHash || dowHash[date.day()]) { // if everyday, or this particular day-of-week
+					if (!dowHash || dowHash[date.day()]) { // if everyday, or this particular day-of-week
 
-					startTime = abstractEvent.start; // the stored start and end properties are times (Durations)
-					endTime = abstractEvent.end; // "
-					start = date.clone();
-					end = null;
+						startTime = abstractEvent.start; // the stored start and end properties are times (Durations)
+						endTime = abstractEvent.end; // "
+						start = date.clone();
+						end = null;
 
-					if (startTime) {
-						start = start.timeDuration(startTime);
-					}
-					if (endTime) {
-						end = date.clone().timeDuration(endTime);
+						if (startTime) {
+							start = start.timeDuration(startTime);
+						}
+						if (endTime) {
+							end = date.clone().timeDuration(endTime);
+						}
+
+						event = $.extend({}, abstractEvent); // make a copy of the original
+						assignDatesToEvent(
+							start, end,
+							!startTime && !endTime, // allDay?
+							event
+						);
+						events.push(event);
 					}
 
-					event = $.extend({}, abstractEvent); // make a copy of the original
-					assignDatesToEvent(
-						start, end,
-						!startTime && !endTime, // allDay?
-						event
-					);
-					events.push(event);
+					date.add(1, 'days');
 				}
-
-				date.add(1, 'days');
 			}
-		}
-		else {
-			events.push(abstractEvent); // return the original event. will be a one-item array
+			else {
+				events.push(abstractEvent); // return the original event. will be a one-item array
+			}
 		}
 
 		return events;
@@ -882,6 +885,7 @@ function EventManager(options) { // assumed to be a calendar
 
 	t.isEventAllowedInRange = isEventAllowedInRange;
 	t.isSelectionAllowedInRange = isSelectionAllowedInRange;
+	t.isExternalDragAllowedInRange = isExternalDragAllowedInRange;
 
 
 	function isEventAllowedInRange(event, start, end) {
@@ -911,6 +915,20 @@ function EventManager(options) { // assumed to be a calendar
 	}
 
 
+	function isExternalDragAllowedInRange(start, end, eventInput) { // eventInput is optional associated event data
+		var event;
+
+		if (eventInput) {
+			event = expandEvent(buildEventFromInput(eventInput))[0];
+			if (event) {
+				return isEventAllowedInRange(event, start, end);
+			}
+		}
+
+		return isRangeAllowed(start, end);
+	}
+
+
 	// Returns true if the given range (caused by an event drop/resize or a selection) is allowed to exist
 	// according to the constraint/overlap settings.
 	// `event` is not required if checking a selection.

+ 20 - 6
src/common/View.js

@@ -258,12 +258,13 @@ View.prototype = {
 	documentDragStart: function(ev, ui) {
 		var _this = this;
 		var calendar = this.calendar;
-		var eventStart = null;
+		var eventStart = null; // a null value signals an unsuccessful drag
 		var eventEnd = null;
 		var visibleEnd = null; // will be calculated event when no eventEnd
 		var el;
 		var accept;
 		var meta;
+		var eventProps; // if an object, signals an event should be created upon drop
 		var dragListener;
 
 		if (this.opt('droppable')) { // only listen if this setting is on
@@ -275,6 +276,7 @@ View.prototype = {
 			if ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) {
 
 				meta = getDraggedElMeta(el); // data for possibly creating an event
+				eventProps = meta.eventProps;
 
 				// listener that tracks mouse movement over date-associated pixel regions
 				dragListener = new DragListener(this.coordMap, {
@@ -282,20 +284,33 @@ View.prototype = {
 						eventStart = cellDate;
 						eventEnd = meta.duration ? eventStart.clone().add(meta.duration) : null;
 						visibleEnd = eventEnd || calendar.getDefaultEventEnd(!eventStart.hasTime(), eventStart);
-						_this.renderDrag(eventStart, visibleEnd);
+
+						// keep the start/end up to date when dragging
+						if (eventProps) {
+							$.extend(eventProps, { start: eventStart, end: eventEnd });
+						}
+
+						if (calendar.isExternalDragAllowedInRange(eventStart, visibleEnd, eventProps)) {
+							_this.renderDrag(eventStart, visibleEnd);
+						}
+						else {
+							eventStart = null; // signal unsuccessful
+							disableCursor();
+						}
 					},
 					cellOut: function() {
-						eventStart = eventEnd = visibleEnd = null;
+						eventStart = null;
 						_this.destroyDrag();
+						enableCursor();
 					}
 				});
 
 				// gets called, only once, when jqui drag is finished
 				$(document).one('dragstop', function(ev, ui) {
-					var eventProps = meta.eventProps;
 					var renderedEvents;
 
 					_this.destroyDrag();
+					enableCursor();
 
 					if (eventStart) { // element was dropped on a valid date/time cell
 
@@ -307,9 +322,8 @@ View.prototype = {
 						// trigger 'drop' regardless of whether element represents an event
 						_this.trigger('drop', el[0], eventStart, ev, ui);
 
-						// create an event from the given properties and the newly calculated dates
+						// create an event from the given properties and the latest dates
 						if (eventProps) {
-							$.extend(eventProps, { start: eventStart, end: eventEnd });
 							renderedEvents = calendar.renderEvent(eventProps, meta.stick);
 							_this.trigger('eventReceive', null, renderedEvents[0]); // signal an external event landed
 						}