diff --git a/etemplate/js/et2_dataview_controller.js b/etemplate/js/et2_dataview_controller.js
index a6ae9aef11..6e17fb77f1 100644
--- a/etemplate/js/et2_dataview_controller.js
+++ b/etemplate/js/et2_dataview_controller.js
@@ -51,16 +51,33 @@ var et2_dataview_controller = Class.extend({
 		// server.
 		this._lastModification = null;
 
+		// Timer used for queing fetch requests
+		this._queueTimer = null;
+
+		// Array used for queing the requests
+		this._queue = [];
+
 		// Register the dataFetch callback
 		this._grid.setDataCallback(this._gridCallback, this);
 	},
 
+	destroy: function () {
+
+		this._clearTimer();
+
+		this._super();
+	},
+
 	/**
 	 * The update function queries the server for changes in the currently
 	 * managed index range -- those changes are then merged into the current
 	 * view without a complete rebuild of every row.
 	 */
 	update: function () {
+		// Clear the fetch queue
+		this._queue = [];
+		this._clearTimer();
+
 		// Get the currently visible range from the grid
 		var range = this._grid.getIndexRange();
 
@@ -72,7 +89,7 @@ var et2_dataview_controller = Class.extend({
 
 		// Require that range from the server
 		this._queueFetch(range.top, range.bottom - range.top + 1,
-				this._lastModification !== null);
+				this._lastModification !== null, true);
 	},
 
 	/**
@@ -205,7 +222,6 @@ var et2_dataview_controller = Class.extend({
 		// Queue fetching that data range
 		if (needsData !== false)
 		{
-			console.log("<--> Calling _queueFetch: ", needsData, _idxEnd - needsData + 1);
 			this._queueFetch(needsData, _idxEnd - needsData + 1, false);
 		}
 	},
@@ -213,21 +229,139 @@ var et2_dataview_controller = Class.extend({
 	/**
 	 * 
 	 */
-	_queueFetch: function (_start, _numRows, _refresh) {
-		// Sanitize the request
-		_start = Math.max(0, _start);
-		_numRows = Math.min(this._grid.getTotalCount(), _start + _numRows)
-				- _start;
+	_queueFetch: function (_start, _numRows, _refresh, _immediate) {
 
-		// Context used in the callback function
-		var ctx = { "self": this, "start": _start, "count": _numRows };
+		// Force immediate to be false
+		_immediate = _immediate ? _immediate : false;
+//		_immediate = true;
 
-		// Build the query
-		var query = { "start": _start, "num_rows": _numRows, "refresh": _refresh };
+		// Push the request onto the request queue
+		this._queue.push({
+				"start": _start,
+				"num_rows": _numRows,
+				"refresh": _refresh
+		});
+
+		// Start the queue timer, if this has not already been done
+		if (this._queueTimer === null && !_immediate)
+		{
+			var self = this;
+			this._queueTimer = window.setTimeout(function () {
+				self._flushQueue();
+			}, ET2_DATAVIEW_FETCH_TIMEOUT);
+		}
+
+		if (_immediate)
+		{
+			this._flushQueue();
+		}
+	},
+
+	_flushQueue: function () {
+
+		function consolidateQueries(_q) {
+			var didConsolidation = false;
+
+			var _new = [];
+			var skip = {};
+
+			for (var i = 0; i < _q.length; i++)
+			{
+				var r1 = et2_range(_q[i].start, _q[i].num_rows);
+
+				var intersected = false;
+
+				for (var j = i + 1; j < _q.length; j++)
+				{
+					if (skip[j])
+					{
+						continue;
+					}
+
+					var r2 = et2_range(_q[j].start, _q[j].num_rows);
+
+					if (et2_rangeIntersect(r1, r2))
+					{
+						var n = et2_bounds(Math.min(r1.top, r2.top),
+								Math.max(r1.botom, r2.bottom));
+						_new.push({
+							"start": n.top,
+							"num_rows": n.bottom - n.top + 1,
+							"refresh": _q[i].refresh
+						});
+						skip[i] = true;
+						skip[j] = true;
+						intersected = true;
+					}
+				}
+
+				if (!intersected)
+				{
+					_new.push(_q[i]);
+					skip[i] = true;
+				}
+			}
+
+			if (didConsolidation) {
+				return consolidateQueries(_new);
+			}
+
+			return _new;
+		}
+
+		// Clear any still existing timer
+		this._clearTimer();
+
+		// Calculate the refresh flag (refresh = false is stronger)
+		var refresh = true;
+		for (var i = 0; i < this._queue.length; i++)
+		{
+			refresh = refresh && this._queue[i].refresh;
+		}
+
+		// Extend all ranges into bottom direction, initialize the queries array
+		for (var i = 0; i < this._queue.length; i++)
+		{
+			this._queue[i].num_rows += 10;
+			this._queue[i].refresh = refresh;
+		}
+
+		// Consolidate all queries
+		var queries = consolidateQueries(this._queue);
+
+		// Execute all queries
+		for (var i = 0; i < queries.length; i++)
+		{
+			// Sanitize the requests
+			queries[i].start = Math.max(0, queries[i].start);
+			queries[i].num_rows = Math.min(this._grid.getTotalCount(),
+					queries[i].start + queries[i].num_rows) - queries[i].start;
+
+			// Context used in the callback function
+			var ctx = {
+					"self": this,
+					"start": queries[i].start,
+					"count": queries[i].num_rows
+			};
+
+			// Call the callback
+			this._dataProvider.dataFetch(queries[i], this._lastModification,
+					this._fetchCallback, ctx);
+		}
+
+		// Flush the queue
+		this._queue = [];
+	},
+
+	_clearTimer: function () {
+
+		// Reset the queue timer upon destruction
+		if (this._queueTimer)
+		{
+			window.clearTimeout(this._queueTimer);
+			this._queueTimer = null;
+		}
 
-		// Call the callback
-		this._dataProvider.dataFetch(query, this._lastModification,
-				this._fetchCallback, ctx);
 	},
 
 	/**
@@ -322,7 +456,14 @@ var et2_dataview_controller = Class.extend({
 				// of that entry is unknown, simply update the entry.
 				current.uid = _order[i];
 				current.idx = idx;
-				this._insertDataRow(current, true);
+
+				// Only update the row, if it is displayed (e.g. has a "loading"
+				// row displayed) -- this is needed for prefetching
+				if (current.row)
+				{
+					this._insertDataRow(current, true);
+				}
+
 				mapIdx++;
 			}
 			else if (current.uid !== _order[i])
diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js
index 93dd0e6cce..cd5f3faf46 100644
--- a/etemplate/js/et2_extension_nextmatch.js
+++ b/etemplate/js/et2_extension_nextmatch.js
@@ -327,7 +327,9 @@ var et2_nextmatch = et2_DOMWidget.extend(et2_IResizeable, {
 				columnPreference = negated ? pref.substring(1) : pref;
 			}
 		}
-		var columnDisplay = et2_csvSplit(columnPreference,null,",");
+
+		var columnDisplay = typeof columnPreference === "string"
+				? et2_csvSplit(columnPreference,null,",") : columnPreference;
 
 		// Adjusted column sizes
 		var size = {};