Просмотр исходного кода

rework rendering logic. more responsibility to DateComponent

Adam Shaw 8 лет назад
Родитель
Сommit
c55a90b27f
3 измененных файлов с 259 добавлено и 109 удалено
  1. 27 61
      src/View.js
  2. 33 34
      src/agenda/AgendaView.js
  3. 199 14
      src/component/DateComponent.js

+ 27 - 61
src/View.js

@@ -246,32 +246,20 @@ var View = FC.View = InteractiveDateComponent.extend({
 
 
 	bindEventChanges: function() {
-		this.listenTo(this.calendar, 'eventsReset', this.resetEvents);
+		// can write this shorter?
+		this.listenTo(this.calendar, 'eventsReset', this.handleEventsReset);
+		//this.listenTo(this.calendar, 'eventAdd', this.handleEventAddOrUpdate);
+		//this.listenTo(this.calendar, 'eventUpdate', this.handleEventAddOrUpdate);
+		//this.listenTo(this.calendar, 'eventRemove', this.handleEventRemove);
 	},
 
 
 	unbindEventChanges: function() {
+		// can write this shorter?
 		this.stopListeningTo(this.calendar, 'eventsReset');
-	},
-
-
-	setEvents: function(eventsPayload) {
-		this.set('currentEvents', eventsPayload);
-		this.set('hasEvents', true);
-	},
-
-
-	unsetEvents: function() {
-		this.unset('currentEvents');
-		this.unset('hasEvents');
-	},
-
-
-	resetEvents: function(eventsPayload) {
-		this.startBatchRender();
-		this.unsetEvents();
-		this.setEvents(eventsPayload);
-		this.stopBatchRender();
+		//this.stopListeningTo(this.calendar, 'eventAdd');
+		//this.stopListeningTo(this.calendar, 'eventUpdate');
+		//this.stopListeningTo(this.calendar, 'eventRemove');
 	},
 
 
@@ -1009,32 +997,7 @@ var View = FC.View = InteractiveDateComponent.extend({
 });
 
 
-View.watch('dateProfileMisc', [ 'dateProfile' ], function(deps) {
-	var calendar = this.calendar;
-	var dateProfile = deps.dateProfile;
-	var children = this.children;
-	var i;
-
-	// DEPRECATED, but we need to keep it updated...
-	this.start = calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, dateProfile.isRangeAllDay);
-	this.end = calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, dateProfile.isRangeAllDay);
-	this.intervalStart = calendar.msToMoment(dateProfile.currentUnzonedRange.startMs, dateProfile.isRangeAllDay);
-	this.intervalEnd = calendar.msToMoment(dateProfile.currentUnzonedRange.endMs, dateProfile.isRangeAllDay);
-
-	this.title = this.computeTitle(dateProfile);
-	this.calendar.reportViewDatesChanged(this, dateProfile); // TODO: reverse pubsub
-
-	for (i = 0; i < children.length; i++) {
-		children[i].set('dateProfile', dateProfile);
-	}
-});
-
-
-View.watch('displayingDates', [ 'dateProfile' ], function(deps) {
-	this.requestRender('date', 'init', this.executeDateRender, [ deps.dateProfile ]);
-}, function() {
-	this.requestRender('date', 'destroy', this.executeDateUnrender);
-});
+// responsible for populating data that DateComponent relies on
 
 
 View.watch('businessHours', [ 'rawBusinessHours', 'dateProfile' ], function(deps) {
@@ -1046,32 +1009,35 @@ View.watch('businessHours', [ 'rawBusinessHours', 'dateProfile' ], function(deps
 });
 
 
-View.watch('displayingBusinessHours', [ 'displayingDates', 'businessHours' ], function(deps) {
-	this.requestRender('businessHours', 'init', this.renderBusinessHours, [ deps.businessHours ]);
-}, function() {
-	this.requestRender('businessHours', 'destroy', this.unrenderBusinessHours);
-});
-
-
 View.watch('initialEvents', [ 'dateProfile' ], function(deps) {
 	return this.fetchInitialEvents(deps.dateProfile);
 });
 
 
 View.watch('bindingEvents', [ 'initialEvents' ], function(deps) {
-	this.setEvents(deps.initialEvents);
+	this.handleEventsSet(deps.initialEvents);
 	this.bindEventChanges();
 }, function() {
 	this.unbindEventChanges();
-	this.unsetEvents();
+	this.handleEventsUnset();
 });
 
 
-View.watch('displayingEvents', [ 'displayingDates', 'hasEvents' ], function() {
-	// pass currentEvents in case there were event mutations after initialEvents
-	this.requestRender('event', 'init', this.executeEventsRender, [ this.get('currentEvents') ]);
-}, function() {
-	this.requestRender('event', 'destroy', this.executeEventsUnrender);
+// misc & legacy conversion
+
+
+View.watch('dateProfileMisc', [ 'dateProfile' ], function(deps) {
+	var calendar = this.calendar;
+	var dateProfile = deps.dateProfile;
+
+	// DEPRECATED, but we need to keep it updated...
+	this.start = calendar.msToMoment(dateProfile.activeUnzonedRange.startMs, dateProfile.isRangeAllDay);
+	this.end = calendar.msToMoment(dateProfile.activeUnzonedRange.endMs, dateProfile.isRangeAllDay);
+	this.intervalStart = calendar.msToMoment(dateProfile.currentUnzonedRange.startMs, dateProfile.isRangeAllDay);
+	this.intervalEnd = calendar.msToMoment(dateProfile.currentUnzonedRange.endMs, dateProfile.isRangeAllDay);
+
+	this.title = this.computeTitle(dateProfile);
+	calendar.reportViewDatesChanged(this, dateProfile); // TODO: reverse the pubsub
 });
 
 

+ 33 - 34
src/agenda/AgendaView.js

@@ -299,33 +299,51 @@ var AgendaView = FC.AgendaView = View.extend({
 	------------------------------------------------------------------------------------------------------------------*/
 
 
-	renderEventsPayload: function(eventsPayload) {
-		View.prototype.renderEventsPayload.apply(this, arguments);
+	// routing
 
-		// the all-day area is flexible and might have a lot of events, so shift the height
-		this.updateHeight();
-	},
 
+	setEventsInChildren: function(eventsPayload) {
+		var allDayPayload = {};
+		var timedPayload = {};
+		var id, eventInstanceGroup;
+
+		for (id in eventsPayload) {
+			eventInstanceGroup = eventsPayload[id];
 
-	renderFgEventFootprints: function(eventFootprints) {
-		var res = sortEventFootprintsByAllDay(eventFootprints);
+			if (eventInstanceGroup.getEventDef().isAllDay()) {
+				allDayPayload[id] = eventInstanceGroup;
+			}
+			else {
+				timedPayload[id] = eventInstanceGroup;
+			}
+		}
 
-		this.timeGrid.renderFgEventFootprints(res.timed);
+		this.timeGrid.handleEventsSet(timedPayload);
 
 		if (this.dayGrid) {
-			this.dayGrid.renderFgEventFootprints(res.allDay);
+			this.dayGrid.handleEventsSet(allDayPayload);
 		}
 	},
 
 
-	renderBgEventFootprints: function(eventFootprints) {
-		var res = sortEventFootprintsByAllDay(eventFootprints);
+	addOrUpdateEventInChildren: function(id, eventInstanceGroup) {
+		if (!eventInstanceGroup.getEventDef().isAllDay()) {
+			this.timeGrid.handleEventAddOrUpdate(id, eventInstanceGroup);
+		}
+		else if (this.dayGrid) {
+			this.dayGrid.handleEventAddOrUpdate(id, eventInstanceGroup);
+		}
+	},
+
 
-		this.timeGrid.renderBgEventFootprints(res.timed);
+	// rendering
 
-		if (this.dayGrid) {
-			this.dayGrid.renderBgEventFootprints(res.allDay);
-		}
+
+	renderEventsPayload: function(eventsPayload) {
+		View.prototype.renderEventsPayload.apply(this, arguments);
+
+		// the all-day area is flexible and might have a lot of events, so shift the height
+		this.updateHeight();
 	},
 
 
@@ -438,22 +456,3 @@ var agendaDayGridMethods = {
 	}
 
 };
-
-
-function sortEventFootprintsByAllDay(eventFootprints) {
-	var allDay = [];
-	var timed = [];
-	var i;
-
-	for (i = 0; i < eventFootprints.length; i++) {
-
-		if (eventFootprints[i].componentFootprint.isAllDay) {
-			allDay.push(eventFootprints[i]);
-		}
-		else {
-			timed.push(eventFootprints[i]);
-		}
-	}
-
-	return { allDay: allDay, timed: timed };
-}

+ 199 - 14
src/component/DateComponent.js

@@ -72,10 +72,30 @@ var DateComponent = Component.extend({
 	},
 
 
-	// Date Low-level Rendering
+	// Date
 	// -----------------------------------------------------------------------------------------------------------------
 
 
+	setDateProfileInChildren: function(dateProfile) {
+		this.setInChildren('dateProfile', dateProfile);
+	},
+
+
+	unsetDateProfileInChildren: function() {
+		this.unsetInChildren('dateProfile');
+	},
+
+
+	executeDateRender: function(dateProfile, skipScroll) { // wrapper
+		this.renderDates();
+	},
+
+
+	executeDateUnrender: function() { // wrapper
+		this.unrenderDates();
+	},
+
+
 	// date-cell content only
 	renderDates: function() {
 		// subclasses should implement
@@ -115,13 +135,21 @@ var DateComponent = Component.extend({
 	// ---------------------------------------------------------------------------------------------------------------
 
 
+	setBusinessHoursInChildren: function(businessHours) {
+		this.setInChildren('businessHours', businessHours);
+	},
+
+
+	unsetBusinessHoursInChildren: function() {
+		this.unsetInChildren('businessHours');
+	},
+
+
 	// Renders business-hours onto the view. Assumes updateSize has already been called.
 	renderBusinessHours: function(businessHours) {
 		if (this.businessHourRenderer) {
 			this.businessHourRenderer.render(businessHours);
 		}
-
-		this.callChildren('renderBusinessHours', arguments);
 	},
 
 
@@ -130,15 +158,105 @@ var DateComponent = Component.extend({
 		if (this.businessHourRenderer) {
 			this.businessHourRenderer.unrender();
 		}
-
-		this.callChildren('unrenderBusinessHours', arguments);
 	},
 
 
-	// Event Rendering
+	// Events
 	// -----------------------------------------------------------------------------------------------------------------
 
 
+	// initial handling (to be called by initial data receipt)
+
+
+	handleEventsSet: function(eventsPayload) {
+		this.set('currentEvents', eventsPayload);
+		this.set('hasEvents', true);
+		this.setEventsInChildren(eventsPayload);
+	},
+
+
+	handleEventsUnset: function() {
+		this.unset('hasEvents');
+		this.unset('currentEvents');
+		this.unsetEventsInChildren();
+	},
+
+
+	// dynamic handling (to be called by post-binding updates)
+
+
+	handleEventsReset: function(eventsPayload) {
+		this.startBatchRender();
+		this.handleEventsUnset();
+		this.handleEventsSet(eventsPayload);
+		this.stopBatchRender();
+	},
+
+
+	handleEventAddOrUpdate: function(id, eventInstanceGroup) {
+		var currentEvents = this.get('currentEvents');
+
+		currentEvents[id] = eventInstanceGroup;
+		this.set('currentEvents', currentEvents);
+		this.addOrUpdateEventInChildren(id, eventInstanceGroup);
+
+		if (this.get('displayingEvents')) {
+			this.requestRender('event', 'add', this.renderEventAddOrUpdate, arguments);
+		}
+	},
+
+
+	handleEventRemove: function(id) {
+		var currentEvents = this.get('currentEvents');
+
+		if (id in currentEvents) {
+			delete currentEvents[id];
+			this.set('currentEvents', currentEvents);
+			this.removeEventInChildren(id);
+		}
+
+		if (this.get('displayingEvents')) {
+			this.requestRender('event', 'remove', this.renderEventRemove, arguments);
+		}
+	},
+
+
+	// for children
+
+
+	setEventsInChildren: function(eventsPayload) {
+		this.callChildren('handleEventsSet', arguments);
+	},
+
+
+	unsetEventsInChildren: function() {
+		this.callChildren('handleEventsUnset', arguments);
+	},
+
+
+	addOrUpdateEventInChildren: function(id, eventInstanceGroup) {
+		this.callChildren('handleEventAddOrUpdate', arguments);
+	},
+
+
+	removeEventInChildren: function(id) {
+		this.callChildren('handleEventRemove', arguments);
+	},
+
+
+	// rendering
+
+
+	executeEventsRender: function(eventsPayload) { // wrapper
+		this.renderEventsPayload(eventsPayload);
+	},
+
+
+	executeEventsUnrender: function() { // wrapper
+		this.unrenderEvents();
+	},
+
+
 	// TODO: eventually rename to `renderEvents` once legacy is gone.
 	renderEventsPayload: function(eventsPayload) {
 		var dateProfile = this.get('dateProfile');
@@ -177,12 +295,29 @@ var DateComponent = Component.extend({
 	},
 
 
+	renderEventAddOrUpdate: function(id, eventsPayload) {
+		// by default, rerender all
+		this.unrenderEvents();
+		this.renderEventsPayload(this.get('currentEvents'));
+	},
+
+
+	renderEventRemove: function() {
+		// by default, rerender all
+		this.unrenderEvents();
+		this.renderEventsPayload(this.get('currentEvents'));
+	},
+
+
+	// fg & bg delegation
+	// NOTE: parents should never call these
+	// TODO: make EventRenderer responsible for routing FG vs BG?
+
+
 	renderFgEventFootprints: function(eventFootprints) {
 		if (this.eventRenderer) {
 			this.eventRenderer.renderFgFootprints(eventFootprints);
 		}
-
-		this.callChildren('renderFgEventFootprints', arguments);
 	},
 
 
@@ -190,8 +325,6 @@ var DateComponent = Component.extend({
 		if (this.eventRenderer) {
 			this.eventRenderer.renderBgFootprints(eventFootprints);
 		}
-
-		this.callChildren('renderBgEventFootprints', arguments);
 	},
 
 
@@ -202,8 +335,6 @@ var DateComponent = Component.extend({
 		if (this.eventRenderer) {
 			this.eventRenderer.unrenderFgFootprints();
 		}
-
-		this.callChildren('unrenderFgEventFootprints', arguments);
 	},
 
 
@@ -214,8 +345,6 @@ var DateComponent = Component.extend({
 		if (this.eventRenderer) {
 			this.eventRenderer.unrenderBgFootprints();
 		}
-
-		this.callChildren('unrenderBgEventFootprints', arguments);
 	},
 
 
@@ -509,6 +638,26 @@ var DateComponent = Component.extend({
 	},
 
 
+	setInChildren: function(propName, propValue) {
+		var children = this.children;
+		var i;
+
+		for (i = 0; i < children.length; i++) {
+			children[i].set(propName, propValue);
+		}
+	},
+
+
+	unsetInChildren: function(propName) {
+		var children = this.children;
+		var i;
+
+		for (i = 0; i < children.length; i++) {
+			children[i].unset(propName);
+		}
+	},
+
+
 	_getCalendar: function() { // TODO: strip out. move to generic parent.
 		return this.calendar || this.view.calendar;
 	},
@@ -519,3 +668,39 @@ var DateComponent = Component.extend({
 	}
 
 });
+
+
+DateComponent.watch('dateProfileInChildren', [ 'dateProfile' ], function(deps) {
+	this.setDateProfileInChildren(deps.dateProfile);
+}, function() {
+	this.unsetDateProfileInChildren();
+});
+
+
+DateComponent.watch('businessHoursInChildren', [ 'businessHours' ], function(deps) {
+	this.setBusinessHoursInChildren(deps.businessHours);
+}, function() {
+	this.unsetBusinessHoursInChildren();
+});
+
+
+DateComponent.watch('displayingDates', [ 'dateProfile' ], function(deps) {
+	this.requestRender('date', 'init', this.executeDateRender, [ deps.dateProfile ]);
+}, function() {
+	this.requestRender('date', 'destroy', this.executeDateUnrender);
+});
+
+
+DateComponent.watch('displayingBusinessHours', [ 'displayingDates', 'businessHours' ], function(deps) {
+	this.requestRender('businessHours', 'init', this.renderBusinessHours, [ deps.businessHours ]);
+}, function() {
+	this.requestRender('businessHours', 'destroy', this.unrenderBusinessHours);
+});
+
+
+DateComponent.watch('displayingEvents', [ 'displayingDates', 'hasEvents' ], function() {
+	// pass currentEvents in case there were event mutations after initialEvents
+	this.requestRender('event', 'init', this.executeEventsRender, [ this.get('currentEvents') ]);
+}, function() {
+	this.requestRender('event', 'destroy', this.executeEventsUnrender);
+});