Bladeren bron

View, scroll state refactor

Adam Shaw 11 jaren geleden
bovenliggende
commit
0039e9a656
3 gewijzigde bestanden met toevoegingen van 46 en 33 verwijderingen
  1. 3 15
      src/agenda/AgendaView.js
  2. 0 3
      src/basic/BasicView.js
  3. 43 15
      src/common/View.js

+ 3 - 15
src/agenda/AgendaView.js

@@ -266,8 +266,6 @@ var AgendaView = fcViews.agenda = View.extend({
 				// and reapply the desired height to the scroller.
 				scrollerHeight = this.computeScrollerHeight(totalHeight);
 				this.scrollerEl.height(scrollerHeight);
-
-				this.restoreScroll();
 			}
 			else { // no scrollbars
 				// still, force a height and display the bottom rule (marks the end of day)
@@ -278,9 +276,8 @@ var AgendaView = fcViews.agenda = View.extend({
 	},
 
 
-	// Sets the scroll value of the scroller to the initial pre-configured state prior to allowing the user to change it
-	initializeScroll: function() {
-		var _this = this;
+	// Computes the initial pre-configured scroll state prior to allowing the user to change it
+	computeInitialScroll: function() {
 		var scrollTime = moment.duration(this.opt('scrollTime'));
 		var top = this.timeGrid.computeTimeTop(scrollTime);
 
@@ -291,12 +288,7 @@ var AgendaView = fcViews.agenda = View.extend({
 			top++; // to overcome top border that slots beyond the first have. looks better
 		}
 
-		function scroll() {
-			_this.scrollerEl.scrollTop(top);
-		}
-
-		scroll();
-		setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
+		return top;
 	},
 
 
@@ -344,10 +336,6 @@ var AgendaView = fcViews.agenda = View.extend({
 	// Unrenders all event elements and clears internal segment data
 	destroyEvents: function() {
 
-		// if destroyEvents is being called as part of an event rerender, renderEvents will be called shortly
-		// after, so remember what the scroll value was so we can restore it.
-		this.recordScroll();
-
 		// destroy the events in the subcomponents
 		this.timeGrid.destroyEvents();
 		if (this.dayGrid) {

+ 0 - 3
src/basic/BasicView.js

@@ -233,8 +233,6 @@ var BasicView = fcViews.basic = View.extend({
 			// doing the scrollbar compensation might have created text overflow which created more height. redo
 			scrollerHeight = this.computeScrollerHeight(totalHeight);
 			this.scrollerEl.height(scrollerHeight);
-
-			this.restoreScroll();
 		}
 	},
 
@@ -270,7 +268,6 @@ var BasicView = fcViews.basic = View.extend({
 
 	// Unrenders all event elements and clears internal segment data
 	destroyEvents: function() {
-		this.recordScroll(); // removing events will reduce height and mess with the scroll, so record beforehand
 		this.dayGrid.destroyEvents();
 
 		// we DON'T need to call updateHeight() because:

+ 43 - 15
src/common/View.js

@@ -262,13 +262,22 @@ var View = fc.View = Class.extend({
 	// Does everything necessary to display the view centered around the given date.
 	// Does every type of rendering EXCEPT rendering events.
 	display: function(date) {
+		var scrollState = null;
+
+		if (this.isDisplayed) {
+			scrollState = this.queryScroll();
+		}
+
 		this.clear(); // clear the old content
 		this.setDate(date);
 		this.render();
 		this.updateSize();
 		this.renderBusinessHours(); // might need coordinates, so should go after updateSize()
-		this.initializeScroll();
 		this.isDisplayed = true;
+
+		scrollState = this.computeInitialScroll(scrollState);
+		this.forceScroll(scrollState);
+
 		this.triggerRender();
 	},
 
@@ -382,11 +391,18 @@ var View = fc.View = Class.extend({
 
 	// Refreshes anything dependant upon sizing of the container element of the grid
 	updateSize: function(isResize) {
+		var scrollState;
+
 		if (isResize) {
-			this.recordScroll();
+			scrollState = this.queryScroll();
 		}
+
 		this.updateHeight();
 		this.updateWidth();
+
+		if (isResize) {
+			this.setScroll(scrollState);
+		}
 	},
 
 
@@ -440,40 +456,52 @@ var View = fc.View = Class.extend({
 	},
 
 
-	// Sets the scroll value of the scroller to the initial pre-configured state prior to allowing the user to change it
-	initializeScroll: function() {
+	// Computes the initial pre-configured scroll state prior to allowing the user to change it.
+	// Given the scroll state from the previous rendering. If first time rendering, given null.
+	computeInitialScroll: function(previousScrollState) {
+		return 0;
 	},
 
 
-	// Called for remembering the current scroll value of the scroller.
-	// Should be called before there is a destructive operation (like removing DOM elements) that might inadvertently
-	// change the scroll of the container.
-	recordScroll: function() {
+	// Retrieves the view's current natural scroll state. Can return an arbitrary format.
+	queryScroll: function() {
 		if (this.scrollerEl) {
-			this.scrollTop = this.scrollerEl.scrollTop();
+			return this.scrollerEl.scrollTop(); // operates on scrollerEl by default
 		}
 	},
 
 
-	// Set the scroll value of the scroller to the previously recorded value.
-	// Should be called after we know the view's dimensions have been restored following some type of destructive
-	// operation (like temporarily removing DOM elements).
-	restoreScroll: function() {
-		if (this.scrollTop !== null) {
-			this.scrollerEl.scrollTop(this.scrollTop);
+	// Sets the view's scroll state. Will accept the same format computeInitialScroll and queryScroll produce.
+	setScroll: function(scrollState) {
+		if (this.scrollerEl) {
+			return this.scrollerEl.scrollTop(scrollState); // operates on scrollerEl by default
 		}
 	},
 
 
+	// Sets the scroll state, making sure to overcome any predefined scroll value the browser has in mind
+	forceScroll: function(scrollState) {
+		var _this = this;
+
+		this.setScroll(scrollState);
+		setTimeout(function() {
+			_this.setScroll(scrollState);
+		}, 0);
+	},
+
+
 	/* Event Elements / Segments
 	------------------------------------------------------------------------------------------------------------------*/
 
 
 	// Does everything necessary to display the given events onto the current view
 	displayEvents: function(events) {
+		var scrollState = this.queryScroll();
+
 		this.clearEvents();
 		this.renderEvents(events);
 		this.isEventsRendered = true;
+		this.setScroll(scrollState);
 		this.triggerEventRender();
 	},