Adam Shaw 8 лет назад
Родитель
Сommit
7aece8b1fe

+ 2 - 3
src/Calendar.render.js

@@ -210,7 +210,7 @@ Calendar.mixin({
 		var oldView = this.view;
 		var newView;
 
-		this.startBatchRender();
+		this.freezeContentHeight();
 
 		if (oldView && viewType && oldView.type !== viewType) {
 			this.clearView();
@@ -235,7 +235,7 @@ Calendar.mixin({
 			this.view.setDate(this.currentDate);
 		}
 
-		this.stopBatchRender();
+		this.thawContentHeight();
 	},
 
 
@@ -249,7 +249,6 @@ Calendar.mixin({
 		this.unbindViewHandlers(currentView);
 
 		currentView.removeElement();
-		currentView.unsetDate(); // wish we could just leave the date
 
 		this.view = null;
 	},

+ 219 - 131
src/View.js

@@ -29,8 +29,6 @@ var View = FC.View = InteractiveDateComponent.extend({
 	nowIndicatorTimeoutID: null, // for refresh timing of now indicator
 	nowIndicatorIntervalID: null, // "
 
-	renderedEventSegs: null,
-
 
 	constructor: function(calendar, viewSpec) {
 		this.calendar = calendar;
@@ -45,6 +43,7 @@ var View = FC.View = InteractiveDateComponent.extend({
 
 		InteractiveDateComponent.call(this);
 
+		this.bindBaseRenderHandlers();
 		this.initHiddenDays();
 		this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
 
@@ -52,8 +51,6 @@ var View = FC.View = InteractiveDateComponent.extend({
 		if (this.initialize) {
 			this.initialize();
 		}
-
-		this.on('after:events:render', this.onAfterEventsRender);
 	},
 
 
@@ -68,6 +65,39 @@ var View = FC.View = InteractiveDateComponent.extend({
 	},
 
 
+	/* Render Queue
+	------------------------------------------------------------------------------------------------------------------*/
+
+
+	requestRender: function(func, namespace, actionType) {
+		var renderQueue = this.calendar.renderQueue;
+
+		renderQueue.queue(func, '', namespace, actionType); // TODO: has UID!!!???
+	},
+
+
+	whenSizeUpdated: function(func) { // TODO: use for events-after-all-render
+		var renderQueue = this.calendar.renderQueue;
+
+		if (renderQueue.getIsIdle()) {
+			func()
+		}
+		else {
+			renderQueue.one('idle', func);
+		}
+	},
+
+
+	startBatchRender: function() {
+		this.calendar.renderQueue.startBatchRender()
+	},
+
+
+	stopBatchRender: function() {
+		this.calendar.renderQueue.stopBatchRender()
+	},
+
+
 	/* Title and Date Formatting
 	------------------------------------------------------------------------------------------------------------------*/
 
@@ -116,32 +146,6 @@ var View = FC.View = InteractiveDateComponent.extend({
 	},
 
 
-	// Element
-	// -----------------------------------------------------------------------------------------------------------------
-
-
-	setElement: function(el) {
-		var _this = this;
-
-		InteractiveDateComponent.prototype.setElement.apply(this, arguments);
-
-		// TODO: not best place for this
-		// TODO: better way of forwarding options from calendar -> view
-		this.calendar.optionsModel.watch('viewRawBusinessHours' + this.uid, [ 'businessHours' ], function(deps) {
-			_this.set('rawBusinessHours', deps.businessHours);
-		}, function() {
-			_this.unset('rawBusinessHours');
-		});
-	},
-
-
-	removeElement: function() {
-		this.calendar.optionsModel.unwatch('viewRawBusinessHours' + this.uid);
-
-		InteractiveDateComponent.prototype.removeElement.apply(this, arguments);
-	},
-
-
 	// Date Setting/Unsetting
 	// -----------------------------------------------------------------------------------------------------------------
 
@@ -168,8 +172,7 @@ var View = FC.View = InteractiveDateComponent.extend({
 	// -----------------------------------------------------------------------------------------------------------------
 
 
-	// returns an EventInstanceDataSource
-	requestEvents: function(dateProfile) {
+	fetchInitialEvents: function(dateProfile) {
 		var calendar = this.calendar;
 		var forceAllDay = dateProfile.isRangeAllDay && !this.usesMinMaxTime;
 
@@ -180,6 +183,36 @@ var View = FC.View = InteractiveDateComponent.extend({
 	},
 
 
+	bindEventChanges: function() {
+		this.listenTo(this.calendar, 'eventsReset', this.resetEvents); // TODO: make this a real event
+	},
+
+
+	unbindEventChanges: function() {
+		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();
+	},
+
+
 	// Date High-level Rendering
 	// -----------------------------------------------------------------------------------------------------------------
 
@@ -192,25 +225,132 @@ var View = FC.View = InteractiveDateComponent.extend({
 			this.render(); // TODO: deprecate
 		}
 
+		// this.renderBusinessHours()
+		//// TODO: business hours
+		// new BusinessHourGenerator(
+		// 	deps.rawBusinessHours,
+		// 	this.calendar // TODO: untangle
+		// );
+
+		this.trigger('datesRendered');
 		this.addScroll({ isDateInit: true });
 		this.startNowIndicator(); // shouldn't render yet because updateSize will be called soon
 	},
 
 
 	executeDateUnrender: function() {
-		if (this.isDatesRendered) {
-			this.unselect();
-			this.stopNowIndicator();
+		this.unselect();
+		this.stopNowIndicator();
 
-			if (this.destroy) {
-				this.destroy(); // TODO: deprecate
-			}
+		this.trigger('before:datesUnrendered');
+
+		if (this.destroy) {
+			this.destroy(); // TODO: deprecate
 		}
 
 		DateComponent.prototype.executeDateUnrender.apply(this, arguments);
 	},
 
 
+	// "Base" rendering
+	// -----------------------------------------------------------------------------------------------------------------
+
+
+	bindBaseRenderHandlers: function() {
+		var _this = this;
+
+		this.on('datesRendered.baseHandler', function() {
+			_this.whenSizeUpdated(
+				_this.onBaseRender.bind(_this)
+			);
+		});
+
+		this.on('before:datesUnrendered.baseHandler', function() {
+			_this.onBeforeBaseUnrender();
+		});
+	},
+
+
+	onBaseRender: function() {
+		this.publiclyTrigger('viewRender', {
+			context: this,
+			args: [ this, this.el ]
+		});
+	},
+
+
+	onBeforeBaseUnrender: function() {
+		this.publiclyTrigger('viewDestroy', {
+			context: this,
+			args: [ this, this.el ]
+		});
+	},
+
+
+	// Event High-level Rendering
+	// -----------------------------------------------------------------------------------------------------------------
+
+
+	executeEventRender: function() {
+		DateComponent.prototype.executeEventRender.apply(this, arguments);
+
+		this.whenSizeUpdated(
+			this.triggerAfterEventsRendered.bind(this)
+		);
+	},
+
+
+	executeEventUnrender: function() {
+		this.triggerBeforeEventsDestroyed();
+
+		DateComponent.prototype.executeEventUnrender.apply(this, arguments);
+	},
+
+
+	triggerAfterEventsRendered: function() {
+		var _this = this;
+
+		// an optimization, because getEventLegacy is expensive
+		if (this.hasPublicHandlers('eventAfterRender')) {
+			this.getEventSegs().forEach(function(seg) {
+				var legacy;
+
+				if (seg.el) { // necessary?
+					legacy = seg.footprint.getEventLegacy();
+
+					_this.publiclyTrigger('eventAfterRender', {
+						context: legacy,
+						args: [ legacy, seg.el, _this ]
+					});
+				}
+			});
+		}
+
+		this.publiclyTrigger('eventAfterAllRender', {
+			context: this,
+			args: [ this ]
+		});
+	},
+
+
+	triggerBeforeEventsDestroyed: function() {
+		if (this.hasPublicHandlers('eventDestroy')) {
+			this.getEventSegs().forEach(function(seg) {
+				var legacy;
+
+				if (seg.el) { // necessary?
+					legacy = seg.footprint.getEventLegacy();
+
+					_this.publiclyTrigger('eventDestroy', {
+						context: legacy,
+						args: [ legacy, seg.el, _this ]
+					});
+				}
+			});
+		}
+	},
+
+
 	// Misc view rendering utils
 	// -----------------------------------------------------------------------------------------------------------------
 
@@ -595,7 +735,7 @@ var View = FC.View = InteractiveDateComponent.extend({
 		) {
 			this.unselectEventInstance();
 
-			this.getRecursiveEventSegs().forEach(function(seg) {
+			this.getEventSegs().forEach(function(seg) {
 				if (
 					seg.footprint.eventInstance === eventInstance &&
 					seg.el // necessary?
@@ -612,7 +752,7 @@ var View = FC.View = InteractiveDateComponent.extend({
 	unselectEventInstance: function() {
 		if (this.selectedEventInstance) {
 
-			this.getRecursiveEventSegs().forEach(function(seg) {
+			this.getEventSegs().forEach(function(seg) {
 				if (seg.el) { // necessary?
 					seg.el.removeClass('fc-selected');
 				}
@@ -676,18 +816,6 @@ var View = FC.View = InteractiveDateComponent.extend({
 	------------------------------------------------------------------------------------------------------------------*/
 
 
-	onAfterEventsRender: function(segs) {
-		var notYetQueued = !this.renderedEventSegs;
-		var renderedEventSegs = notYetQueued ? (this.renderedEventSegs = []) : this.renderedEventSegs;
-
-		renderedEventSegs.push.apply(renderedEventSegs, segs); // append
-
-		if (notYetQueued) {
-			this.whenSizeUpdated(this.triggerEventsRendered);
-		}
-	},
-
-
 	triggerBaseRendered: function() {
 		this.publiclyTrigger('viewRender', {
 			context: this,
@@ -704,39 +832,6 @@ var View = FC.View = InteractiveDateComponent.extend({
 	},
 
 
-	triggerEventsRendered: function() {
-		var _this = this;
-		var renderedEventSegs = this.renderedEventSegs;
-
-		this.renderedEventSegs = null;
-
-		// an optimization, because getEventLegacy is expensive
-		if (this.hasPublicHandlers('eventAfterRender')) {
-			renderedEventSegs.forEach(function(seg) {
-				var legacy;
-
-				if (seg.el) { // necessary?
-					legacy = seg.footprint.getEventLegacy();
-
-					_this.publiclyTrigger('eventAfterRender', {
-						context: legacy,
-						args: [ legacy, seg.el, _this ]
-					});
-				}
-			});
-		}
-
-		if (this.needsEventAfterAllRender) {
-			delete this.needsEventAfterAllRender;
-
-			this.publiclyTrigger('eventAfterAllRender', {
-				context: this,
-				args: [ this ]
-			});
-		}
-	},
-
-
 	// Triggers handlers to 'dayClick'
 	// Span has start/end of the clicked area. Only the start is useful.
 	triggerDayClick: function(footprint, dayEl, ev) {
@@ -751,69 +846,62 @@ var View = FC.View = InteractiveDateComponent.extend({
 });
 
 
-View.watch('title', [ 'dateProfile' ], function(deps) {
-	return (this.title = this.computeTitle(deps.dateProfile)); // assign to View for legacy reasons
-});
-
+View.watch('displayingDates', [ 'isInDom', 'dateProfile' ], function(deps) {
+	var _this = this;
 
-View.watch('legacyDateProps', [ 'dateProfile' ], function(deps) {
-	var calendar = this.calendar;
-	var dateProfile = deps.dateProfile;
+	this.requestRender(function() {
+		_this.executeDateRender(deps.dateProfile);
+	}, 'date', 'init');
+}, function() {
+	var _this = this;
 
-	// 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.requestRender(function() {
+		_this.executeDateUnrender();
+	}, 'date', 'destroy');
 });
 
 
-View.watch('displayingBase', [ 'isInDom', 'dateProfile' ], function(deps) {
-	// consider the base rendered when it has received the date profile and an updateSize
-	// (which happens after the rendering queue is drained) has happened.
-	// it's hard to track when every subcomponent has rendered their dates.
-	this.whenSizeUpdated(this.triggerBaseRendered);
-}, function() {
-	// as soon as the view looses it's dateComponent, we know it will soon after unrender its dates.
-	this.triggerBaseUnrendered();
+View.watch('initialEvents', [ 'dateProfile' ], function(deps) {
+	return this.fetchInitialEvents(deps.dateProfile);
 });
 
 
-View.watch('reportingEventsResolved', [ 'eventDataSource' ], function(deps) {
-	var eventDataSource = deps.eventDataSource;
-
-	if (eventDataSource.isResolved) {
-		this.reportEventsResolved();
-	}
-
-	this.listenTo(eventDataSource, 'resolved', this.reportEventsResolved);
-}, function(deps) {
-	this.stopListeningTo(deps.eventDataSource, 'resolved', this.reportEventsResolved);
+View.watch('bindingEvents', [ 'initialEvents' ], function(deps) {
+	this.setEvents(deps.initialEvents);
+	this.bindEventChanges();
+}, function() {
+	this.unbindEventChanges();
+	this.unsetEvents();
 });
 
 
-View.prototype.reportEventsResolved = function() {
-	this.set('eventsResolvedId', Math.random()); // TODO: eventually use formalized system for this
-};
+View.watch('displayingEvents', [ 'displayingDates', 'hasEvents' ], function() {
+	var _this = this;
 
+	this.requestRender(function() {
+		////_this.executeEventRender(_this.get('currentEvents')); // TODO: audit payload
+	}, 'event', 'init');
+}, function() {
+	var _this = this;
 
-View.watch('displayingBaseEvents', [ 'displayingBase', 'eventsResolvedId' ], function() {
-	this.needsEventAfterAllRender = true;
-	this.onAfterEventsRender([]);
+	this.requestRender(function() {
+		////_this.executeEventUnrender();
+	}, 'event', 'destroy');
 });
 
 
-// responsible for populating data that DateComponent relies on
-
-
-View.watch('businessHourGenerator', [ 'rawBusinessHours' ], function(deps) {
-	return new BusinessHourGenerator(
-		deps.rawBusinessHours,
-		this.calendar // TODO: untangle
-	);
+View.watch('title', [ 'dateProfile' ], function(deps) {
+	return (this.title = this.computeTitle(deps.dateProfile)); // assign to View for legacy reasons
 });
 
 
-View.watch('eventDataSource', [ 'dateProfile' ], function(deps) {
-	return this.requestEvents(deps.dateProfile);
+View.watch('legacyDateProps', [ '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);
 });

+ 6 - 20
src/agenda/AgendaView.js

@@ -14,8 +14,6 @@ var AgendaView = FC.AgendaView = View.extend({
 	dayGridClass: DayGrid, // class used to instantiate the dayGrid. subclasses can override
 	dayGrid: null, // the "all-day" subcomponent. if all-day is turned off, this will be null
 
-	eventDataSourceSplitter: null,
-
 	axisWidth: null, // the width of the time axis running down the side
 
 	// indicates that minTime/maxTime affects rendering
@@ -272,33 +270,21 @@ var AgendaView = FC.AgendaView = View.extend({
 	},
 
 
-	/* Event Routing
+	/* Event Rendering
 	------------------------------------------------------------------------------------------------------------------*/
 
 
-	setEventDataSourceInChildren: function(eventDataSource) {
-		var splitter = this.eventDataSourceSplitter =
-			new EventInstanceDataSourceSplitter(function(eventInstance) {
-				return [ eventInstance.dateProfile.isAllDay() ];
-			});
-
-		this.timeGrid.set('eventDataSource', splitter.buildSubSource(false));
-
-		if (this.dayGrid) {
-			this.dayGrid.set('eventDataSource', splitter.buildSubSource(true));
-		}
-
-		splitter.addSource(eventDataSource);
+	executeEventRender: function() {
+		// TODO: route
 	},
 
 
-	unsetEventDataSourceInChildren: function(eventDataSource) {
-		this.eventDataSourceSplitter.removeSource(eventDataSource);
-
-		View.prototype.unsetEventDataSourceInChildren.apply(this, arguments);
+	executeEventUnrender: function() {
+		// TODO: route
 	},
 
 
+
 	/* Dragging/Resizing Routing
 	------------------------------------------------------------------------------------------------------------------*/
 

+ 2 - 2
src/basic/BasicView.js

@@ -70,10 +70,10 @@ var BasicView = FC.BasicView = View.extend({
 	},
 
 
-	setDateProfileInChildren: function(dateProfile) {
+	executeDateRender: function(dateProfile) {
 		this.dayGrid.breakOnWeeks = /year|month|week/.test(dateProfile.currentRangeUnit);
 
-		View.prototype.setDateProfileInChildren.apply(this, arguments);
+		View.prototype.executeDateRender.apply(this, arguments);
 	},
 
 

+ 1 - 1
src/basic/DayGrid.js

@@ -335,7 +335,7 @@ var DayGrid = FC.DayGrid = InteractiveDateComponent.extend(StandardInteractionsM
 
 
 	// Retrieves all rendered segment objects currently rendered on the grid
-	getEventSegs: function() {
+	getOwnEventSegs: function() {
 		return InteractiveDateComponent.prototype.getEventSegs.call(this) // get the segments from the super-method
 			.concat(this.popoverSegs || []); // append the segments from the "more..." popover
 	},

+ 0 - 2
src/basic/DayGrid.limit.js

@@ -279,8 +279,6 @@ DayGrid.mixin({
 		// the popover doesn't live within the grid's container element, and thus won't get the event
 		// delegated-handlers for free. attach event-related handlers to the popover.
 		this.bindAllSegHandlersToEl(this.segPopover.el);
-
-		this.trigger('after:events:render', segs);
 	},
 
 

+ 0 - 15
src/common/ListenerMixin.js

@@ -38,21 +38,6 @@ var ListenerMixin = FC.ListenerMixin = (function() {
 			}
 		},
 
-		/*
-		Assumes this object has EmitterMixin
-		*/
-		listenToAndEmit: function(other, eventName) {
-			var _this = this;
-
-			this.listenTo(other, eventName, function() {
-				var args = Array.prototype.slice.call(arguments);
-
-				args.unshift(eventName);
-
-				_this.trigger.apply(_this, args);
-			});
-		},
-
 		/*
 		Causes the current object to stop listening to events on the `other` object.
 		`eventName` is optional. If omitted, will stop listening to ALL events on `other`.

+ 32 - 266
src/component/DateComponent.js

@@ -22,14 +22,11 @@ var DateComponent = FC.DateComponent = Component.extend({
 	hasAllDayBusinessHours: false, // TODO: unify with largeUnit and isTimeScale?
 
 	isDatesRendered: false,
-	isEventsRendered: false,
 
 
 	constructor: function() {
 		Component.call(this);
 
-		this.defineLateWatchers();
-
 		this.uid = String(DateComponent.guid++);
 		this.childrenByUid = {};
 
@@ -54,20 +51,10 @@ var DateComponent = FC.DateComponent = Component.extend({
 	},
 
 
-	defineLateWatchers: function() {
-		this.defineDisplayingBusinessHours();
-		this.defineBusinessHourGeneratorInChildren();
-		this.defineDisplayingEvents();
-		this.defineEventDataSourceInChildren();
-	},
-
-
 	addChild: function(child) {
 		if (!this.childrenByUid[child.uid]) {
 			this.childrenByUid[child.uid] = child;
 
-			this.listenToAndEmit(child, 'after:events:render');
-
 			// make new children catch up with old props
 			// TODO: what about eventDataSource? better system for this?
 			if (this.has('dateProfile')) {
@@ -107,38 +94,6 @@ var DateComponent = FC.DateComponent = Component.extend({
 	},
 
 
-	requestRender: function(method, args, namespace, actionType) {
-		var _this = this;
-		var renderQueue = this._getView().calendar.renderQueue;
-
-		renderQueue.queue(function() {
-			method.apply(_this, args);
-		}, this.uid, namespace, actionType);
-	},
-
-
-	whenSizeUpdated: function(func) {
-		var renderQueue = this._getView().calendar.renderQueue;
-
-		if (renderQueue.getIsIdle()) {
-			func.call(this);
-		}
-		else {
-			renderQueue.one('idle', func.bind(this));
-		}
-	},
-
-
-	startBatchRender: function() {
-		this._getView().calendar.startBatchRender();
-	},
-
-
-	stopBatchRender: function() {
-		this._getView().calendar.stopBatchRender();
-	},
-
-
 	// TODO: only do if isInDom?
 	// TODO: make part of Component, along with children/batch-render system?
 	updateSize: function(totalHeight, isAuto, isResize) {
@@ -173,30 +128,19 @@ var DateComponent = FC.DateComponent = Component.extend({
 	// -----------------------------------------------------------------------------------------------------------------
 
 
-	setDateProfileInChildren: function(dateProfile) {
-		this.setInChildren('dateProfile', dateProfile);
-	},
-
-
-	unsetDateProfileInChildren: function() {
-		this.unsetInChildren('dateProfile');
-	},
-
-
 	executeDateRender: function(dateProfile) {
-		this.executeDateUnrender();
 		this.dateProfile = dateProfile; // for rendering
 		this.renderDates(dateProfile);
 		this.isDatesRendered = true;
+		this.callChildren('executeDateRender', arguments)
 	},
 
 
 	executeDateUnrender: function() { // wrapper
-		if (this.isDatesRendered) {
-			this.dateProfile = null;
-			this.unrenderDates();
-			this.isDatesRendered = false;
-		}
+		this.callChildren('executeDateUnrender', arguments);
+		this.dateProfile = null;
+		this.unrenderDates();
+		this.isDatesRendered = false;
 	},
 
 
@@ -239,28 +183,8 @@ var DateComponent = FC.DateComponent = Component.extend({
 	// ---------------------------------------------------------------------------------------------------------------
 
 
-	setBusinessHourGeneratorInChildren: function(businessHourGenerator) {
-		this.iterChildren(this.setBusinessHourGeneratorInChild.bind(this, businessHourGenerator));
-	},
-
-
-	unsetBusinessHourGeneratorInChildren: function() {
-		this.iterChildren(this.unsetBusinessHourGeneratorInChild.bind(this));
-	},
-
-
-	setBusinessHourGeneratorInChild: function(businessHourGenerator, child) {
-		child.set('businessHourGenerator', businessHourGenerator);
-	},
-
-
-	unsetBusinessHourGeneratorInChild: function(child) {
-		child.unset('businessHourGenerator');
-	},
-
-
 	// Renders business-hours onto the view. Assumes updateSize has already been called.
-	renderBusinessHours: function(businessHourPayload) {
+	renderBusinessHours: function(businessHourPayload) { // TODO: review payload
 		var unzonedRange = this.dateProfile.activeUnzonedRange;
 		var eventInstanceGroup = businessHourPayload[this.hasAllDayBusinessHours ? 'allDay' : 'timed'];
 		var eventFootprints;
@@ -275,6 +199,8 @@ var DateComponent = FC.DateComponent = Component.extend({
 		}
 
 		this.renderBusinessHourEventFootprints(eventFootprints);
+
+		this.callChildren('renderBusinessHours', arguments);
 	},
 
 
@@ -287,79 +213,19 @@ var DateComponent = FC.DateComponent = Component.extend({
 
 	// Unrenders previously-rendered business-hours
 	unrenderBusinessHours: function() {
+		this.callChildren('unrenderBusinessHours', arguments);
+
 		if (this.businessHourRenderer) {
 			this.businessHourRenderer.unrender();
 		}
 	},
 
 
-	// Event Data
-	// ---------------------------------------------------------------------------------------------------------------
-
-
-	setEventDataSourceInChildren: function(eventDataSource) {
-		this.setInChildren('eventDataSource', eventDataSource);
-	},
-
-
-	unsetEventDataSourceInChildren: function() {
-		this.unsetInChildren('eventDataSource');
-	},
-
-
 	// Event Displaying
 	// -----------------------------------------------------------------------------------------------------------------
 
 
-	startDisplayingEvents: function(eventDataSource) {
-		if (eventDataSource.instanceRepo.cnt) {
-			this.requestEventRender(eventDataSource.instanceRepo);
-		}
-
-		this.listenTo(eventDataSource, 'receive', function(eventInstanceChangeset) {
-			this.requestEventRender(eventDataSource.instanceRepo);
-		});
-	},
-
-
-	stopDisplayingEvents: function(eventDataSource) {
-		this.stopListeningTo(eventDataSource);
-
-		this.requestEventUnrender();
-	},
-
-
-	requestEventRender: function(eventInstanceRepo) {
-		this.requestRender(this.executeEventRender, [ eventInstanceRepo ], 'event', 'destroy');
-	},
-
-
-	requestEventUnrender: function() {
-		this.requestRender(this.executeEventUnrender, null, 'event', 'destroy');
-	},
-
-
-	executeEventRender: function(eventInstanceRepo) {
-		this.executeEventUnrender();
-		if (this.renderEventsss(eventInstanceRepo) !== false) {
-			this.triggerAfterEventsRender();
-			this.isEventsRendered = true;
-		}
-	},
-
-
-	executeEventUnrender: function() {
-		if (this.isEventsRendered) {
-			this.triggerBeforeEventsUnrender();
-			this.unrenderEventsss();
-			this.isEventsRendered = false;
-		}
-	},
-
-
-	// TODO: rename once legacy `renderEvents` is out of the way
-	// returning `false` indicates that nothing happened
-	renderEventsss: function(eventInstanceRepo) {
+	executeEventRender: function(eventInstanceRepo) { // TODO: review paypload
 		if (this.eventRenderer) {
 			this.eventRenderer.rangeUpdated(); // poorly named now
 			this.eventRenderer.renderInstanceHash(eventInstanceRepo.byDefId);
@@ -367,14 +233,14 @@ var DateComponent = FC.DateComponent = Component.extend({
 		else if (this.renderEvents) { // legacy
 			this.renderEvents(convertEventInstanceHashToLegacyArray(eventInstanceRepo.byDefId));
 		}
-		else {
-			return false;
-		}
+
+		this.callChildren('executeEventRender', arguments);
 	},
 
 
-	// TODO: rename once legacy `renderEvents` is out of the way
-	unrenderEventsss: function() {
+	executeEventUnrender: function() {
+		this.callChildren('executeEventUnrender', arguments);
+
 		if (this.eventRenderer) {
 			this.eventRenderer.unrender();
 		}
@@ -384,59 +250,38 @@ var DateComponent = FC.DateComponent = Component.extend({
 	},
 
 
-	triggerAfterEventsRender: function() {
-		this.trigger('after:events:render', this.getEventSegs());
-	},
+	getBusinessHourSegs: function() { // recursive
+		var segs = this.getOwnBusinessHourSegs()
 
+		this.iterChildren(function(child) {
+			segs.push.apply(segs, child.getBusinessHourSegs());
+		});
 
-	triggerBeforeEventsUnrender: function() {
-		this.triggerEventDestroyForSegs(this.getEventSegs());
+		return segs;
 	},
 
 
-	triggerEventDestroyForSegs: function(segs) {
-		var _this = this;
-
-		if (this.hasPublicHandlers('eventDestroy')) {
-			segs.forEach(function(seg) {
-				var legacy;
-
-				if (seg.el) { // necessary?
-					legacy = seg.footprint.getEventLegacy();
-
-					_this.publiclyTrigger('eventDestroy', {
-						context: legacy,
-						args: [ legacy, seg.el, _this ]
-					});
-				}
-			});
+	getOwnBusinessHourSegs: function() {
+		if (this.businessHourRenderer) {
+			return this.businessHourRenderer.getSegs();
 		}
-	},
-
-
-	getRecursiveEventSegs: function() { // TODO: get rid of
-		var segs = this.getEventSegs();
 
-		this.iterChildren(function(child) {
-			segs.push.apply(segs, child.getRecursiveEventSegs());
-		});
-
-		return segs;
+		return [];
 	},
 
 
-	getRecursiveBusinessHourSegs: function() { // TODO: get rid of
-		var segs = this.businessHourRenderer ? this.businessHourRenderer.getSegs() : [];
+	getEventSegs: function() { // recursive
+		var segs = this.getOwnEventSegs();
 
 		this.iterChildren(function(child) {
-			segs.push.apply(segs, child.getRecursiveBusinessHourSegs());
+			segs.push.apply(segs, child.getEventSegs());
 		});
 
 		return segs;
 	},
 
 
-	getEventSegs: function() { // just for itself
+	getOwnEventSegs: function() { // just for itself
 		if (this.eventRenderer) {
 			return this.eventRenderer.getSegs();
 		}
@@ -452,6 +297,7 @@ var DateComponent = FC.DateComponent = Component.extend({
 	// Hides all rendered event segments linked to the given event
 	// RECURSIVE with subcomponents
 	showEventsWithId: function(eventDefId) {
+
 		this.getEventSegs().forEach(function(seg) {
 			if (
 				seg.footprint.eventDef.id === eventDefId &&
@@ -468,6 +314,7 @@ var DateComponent = FC.DateComponent = Component.extend({
 	// Shows all rendered event segments linked to the given event
 	// RECURSIVE with subcomponents
 	hideEventsWithId: function(eventDefId) {
+
 		this.getEventSegs().forEach(function(seg) {
 			if (
 				seg.footprint.eventDef.id === eventDefId &&
@@ -743,20 +590,6 @@ var DateComponent = FC.DateComponent = Component.extend({
 	},
 
 
-	setInChildren: function(propName, propValue) {
-		this.iterChildren(function(child) {
-			child.set(propName, propValue);
-		});
-	},
-
-
-	unsetInChildren: function(propName) {
-		this.iterChildren(function(child) {
-			child.unset(propName);
-		});
-	},
-
-
 	iterChildren: function(func) {
 		var childrenByUid = this.childrenByUid;
 		var uid;
@@ -782,73 +615,6 @@ var DateComponent = FC.DateComponent = Component.extend({
 DateComponent.guid = 0; // TODO: better system for this?
 
 
-// ordering matters :(
-// update children after updating self, because child rendering of dates/events/etc might rely on corresponding parent rendering.
-
-
-DateComponent.watch('displayingDates', [ 'isInDom', 'dateProfile' ], function(deps) {
-	this.requestRender(this.executeDateRender, [ deps.dateProfile ], 'date', 'destroy');
-}, function() {
-	this.requestRender(this.executeDateUnrender, null, 'date', 'destroy');
-});
-
-
-DateComponent.watch('dateProfileInChildren', [ 'dateProfile' ], function(deps) {
-	this.setDateProfileInChildren(deps.dateProfile);
-}, function() {
-	this.unsetDateProfileInChildren();
-});
-
-
-DateComponent.watch('businessHours', [ 'businessHourGenerator', 'dateProfile' ], function(deps) {
-	var businessHourGenerator = deps.businessHourGenerator;
-	var unzonedRange = deps.dateProfile.activeUnzonedRange;
-
-	return {
-		allDay: businessHourGenerator.buildEventInstanceGroup(true, unzonedRange),
-		timed: businessHourGenerator.buildEventInstanceGroup(false, unzonedRange)
-	};
-});
-
-
-DateComponent.prototype.defineDisplayingBusinessHours = function() {
-	this.watch('displayingBusinessHours', [ 'displayingDates', 'businessHours' ], function(deps) {
-		this.requestRender(this.renderBusinessHours, [ deps.businessHours ], 'businessHours', 'init');
-	}, function() {
-		this.requestRender(this.unrenderBusinessHours, null, 'businessHours', 'destroy');
-	});
-};
-
-
-DateComponent.prototype.defineBusinessHourGeneratorInChildren = function() {
-	this.watch('businessHourGeneratorInChildren', [ 'businessHourGenerator' ], function(deps) {
-		this.setBusinessHourGeneratorInChildren(deps.businessHourGenerator);
-	}, function() {
-		this.unsetBusinessHourGeneratorInChildren();
-	});
-};
-
-
-// wrapped in a function so subclasses can more easily override, considering the necessary ordering
-DateComponent.prototype.defineDisplayingEvents = function() {
-	this.watch('displayingEvents', [ 'displayingDates', 'eventDataSource' ], function(deps) {
-		this.startDisplayingEvents(deps.eventDataSource);
-	}, function(deps) {
-		this.stopDisplayingEvents(deps.eventDataSource);
-	});
-};
-
-
-// wrapped in a function so subclasses can more easily override, considering the necessary ordering
-DateComponent.prototype.defineEventDataSourceInChildren = function() {
-	this.watch('eventDataSourceInChildren', [ 'eventDataSource' ], function(deps) {
-		this.setEventDataSourceInChildren(deps.eventDataSource);
-	}, function(deps) {
-		this.unsetEventDataSourceInChildren(deps.eventDataSource);
-	});
-};
-
-
 // legacy
 
 function convertEventInstanceHashToLegacyArray(eventInstancesByDefId) {

+ 0 - 12
src/list/ListView.js

@@ -119,18 +119,6 @@ var ListView = View.extend({
 	},
 
 
-	startDisplayingEvents: function() {
-
-		// need to initially display the no-events message,
-		// because if there are no events, they will never be received.
-		// if events are received synchronously right after this,
-		// the render queue will cancel this.
-		this.requestEventRender(new EventInstanceRepo());
-
-		View.prototype.startDisplayingEvents.apply(this, arguments);
-	},
-
-
 	eventRendererClass: EventRenderer.extend({