diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index edc9bc3ba5..8d5fa2b756 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -336,6 +336,21 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments); }, + /** + * APIMethod: mergeNewParams + * Refetches tiles with new params merged, keeping a backbuffer. Each + * loading new tile will have a css class of '.olTileReplacing'. If a + * stylesheet applies a 'display: none' style to that class, any fade-in + * transition will not apply, and backbuffers for each tile will be removed + * as soon as the tile is loaded. + * + * Parameters: + * newParams - {Object} + * + * Returns: + * redrawn: {Boolean} whether the layer was actually redrawn. + */ + /** * Method: clearGrid * Go through and remove all tiles from the grid, calling @@ -489,7 +504,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { }); if(forceReTile) { - if(zoomChanged && this.transitionEffect === 'resize') { + if(zoomChanged && (this.transitionEffect === 'resize' || + this.gridResolution === resolution)) { this.applyBackBuffer(resolution); } this.initGriddedTiles(bounds); @@ -692,6 +708,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { markup._j = j; markup._w = tile.size.w; markup._h = tile.size.h; + markup.id = tile.id + '_bb'; backBuffer.appendChild(markup); } } @@ -1053,6 +1070,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { */ addTileMonitoringHooks: function(tile) { + var replacingCls = 'olTileReplacing'; + tile.onLoadStart = function() { //if that was first tile then trigger a 'loadstart' on the layer if (this.loading === false) { @@ -1061,14 +1080,27 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { } this.events.triggerEvent("tileloadstart", {tile: tile}); this.numLoadingTiles++; + if (this.backBuffer && this.gridResolution === this.backBufferResolution) { + OpenLayers.Element.addClass(tile.imgDiv, replacingCls); + } }; tile.onLoadEnd = function(evt) { this.numLoadingTiles--; + var aborted = evt.type === 'unload'; this.events.triggerEvent("tileloaded", { tile: tile, - aborted: evt.type === "unload" + aborted: aborted }); + if (!aborted && this.backBuffer && this.gridResolution === this.backBufferResolution) { + if (OpenLayers.Element.getStyle(tile.imgDiv, 'display') === 'none') { + var bufferTile = document.getElementById(tile.id + '_bb'); + if (bufferTile) { + bufferTile.parentNode.removeChild(bufferTile); + } + } + OpenLayers.Element.removeClass(tile.imgDiv, replacingCls); + } //if that was the last tile, then trigger a 'loadend' on the layer if (this.numLoadingTiles === 0) { this.loading = false; diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html index d05769ed12..ce36c72673 100644 --- a/tests/Layer/Grid.html +++ b/tests/Layer/Grid.html @@ -526,7 +526,8 @@ } } } - } + }, + imgDiv: {className: ''} } g_registered = {}; @@ -1118,6 +1119,31 @@ map.destroy(); } + + function test_backbuffer_replace(t) { + t.plan(6); + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '../../img/blank.gif'); + map.addLayer(layer); + map.zoomToMaxExtent(); + + t.delay_call(1, function() { + layer.mergeNewParams({foo: 'bar'}); + var tile = layer.grid[1][1]; + t.ok(OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile is marked for being replaced'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer created for tile'); + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(!document.getElementById(tile.id + '_bb'), 'backbuffer removed for tile'); + + layer.mergeNewParams({foo: 'baz'}); + tile = layer.grid[1][1]; + tile.imgDiv.style.display = 'block'; + tile.onImageLoad(); + t.ok(!OpenLayers.Element.hasClass(tile.imgDiv, 'olTileReplacing'), 'tile replaced, no longer marked'); + t.ok(document.getElementById(tile.id + '_bb'), 'backbuffer not removed for visible tile'); + }); + } function test_singleTile_move_and_zoom(t) { diff --git a/theme/default/style.css b/theme/default/style.css index ed8cef75ce..a3b75ba519 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -487,6 +487,11 @@ a.olControlZoomOut { transition: opacity 0.2s linear; } +/* when replacing tiles, do not show tile and backbuffer at the same time */ +.olTileImage.olTileReplacing { + display: none; +} + /* override any max-width image settings (e.g. bootstrap.css) */ img.olTileImage { max-width: none;