diff --git a/lib/OpenLayers/Control/CacheWrite.js b/lib/OpenLayers/Control/CacheWrite.js index 8b4e787e2f..455e5674ab 100644 --- a/lib/OpenLayers/Control/CacheWrite.js +++ b/lib/OpenLayers/Control/CacheWrite.js @@ -111,7 +111,7 @@ OpenLayers.Control.CacheWrite = OpenLayers.Class(OpenLayers.Control, { addLayer: function(evt) { evt.layer.events.on({ tileloadstart: this.makeSameOrigin, - tileloaded: this.cache, + tileloaded: this.onTileloaded, scope: this }); }, @@ -128,7 +128,7 @@ OpenLayers.Control.CacheWrite = OpenLayers.Class(OpenLayers.Control, { removeLayer: function(evt) { evt.layer.events.un({ tileloadstart: this.makeSameOrigin, - tileloaded: this.cache, + tileloaded: this.onTileloaded, scope: this }); }, @@ -156,6 +156,22 @@ OpenLayers.Control.CacheWrite = OpenLayers.Class(OpenLayers.Control, { } }, + /** + * Method: onTileloaded + * Decides whether a tile can be cached and calls the cache method. + * + * Parameters: + * evt - {Event} + */ + onTileloaded: function(evt) { + if (this.active && !evt.aborted && + evt.tile instanceof OpenLayers.Tile.Image && + evt.tile.url.substr(0, 5) !== 'data:') { + this.cache({tile: evt.tile}); + delete OpenLayers.Control.CacheWrite.urlMap[evt.tile.url]; + } + }, + /** * Method: cache * Adds a tile to the cache. When the cache is full, the "cachefull" event @@ -166,29 +182,25 @@ OpenLayers.Control.CacheWrite = OpenLayers.Class(OpenLayers.Control, { * with the data to add to the cache */ cache: function(obj) { - if (this.active && window.localStorage) { + if (window.localStorage) { var tile = obj.tile; - if (tile instanceof OpenLayers.Tile.Image && - tile.url.substr(0, 5) !== 'data:') { - try { - var canvasContext = tile.getCanvasContext(); - if (canvasContext) { - var urlMap = OpenLayers.Control.CacheWrite.urlMap; - var url = urlMap[tile.url] || tile.url; - window.localStorage.setItem( - "olCache_" + url, - canvasContext.canvas.toDataURL(this.imageFormat) - ); - delete urlMap[tile.url]; - } - } catch(e) { - // local storage full or CORS violation - var reason = e.name || e.message; - if (reason && this.quotaRegEx.test(reason)) { - this.events.triggerEvent("cachefull", {tile: tile}); - } else { - OpenLayers.Console.error(e.toString()); - } + try { + var canvasContext = tile.getCanvasContext(); + if (canvasContext) { + var urlMap = OpenLayers.Control.CacheWrite.urlMap; + var url = urlMap[tile.url] || tile.url; + window.localStorage.setItem( + "olCache_" + url, + canvasContext.canvas.toDataURL(this.imageFormat) + ); + } + } catch(e) { + // local storage full or CORS violation + var reason = e.name || e.message; + if (reason && this.quotaRegEx.test(reason)) { + this.events.triggerEvent("cachefull", {tile: tile}); + } else { + OpenLayers.Console.error(e.toString()); } } } diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index fcb2b42e64..df6535427d 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -262,8 +262,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * loaded, as a means of progress update to listeners. * listeners can access 'numLoadingTiles' if they wish to keep * track of the loading progress. Listeners are called with an object - * with a tile property as first argument, making the loded tile - * available to the listener. + * with a 'tile' property as first argument, making the loded tile + * available to the listener, and an 'aborted' property, which will be + * true when loading was aborted and no tile data is available. * tileerror - Triggered before the tileloaded event (i.e. when the tile is * still hidden) if a tile failed to load. Listeners receive an object * as first argument, which has a tile property that references the @@ -1090,9 +1091,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { this.numLoadingTiles++; }; - tile.onLoadEnd = function() { + tile.onLoadEnd = function(evt) { this.numLoadingTiles--; - this.events.triggerEvent("tileloaded", {tile: tile}); + this.events.triggerEvent("tileloaded", { + tile: tile, + aborted: evt.type === "unload" + }); //if that was the last tile, then trigger a 'loadend' on the layer if (this.tileQueue.length === 0 && this.numLoadingTiles === 0) { this.loading = false; diff --git a/tests/Control/CacheWrite.html b/tests/Control/CacheWrite.html index fdb6cabeaf..9922569332 100644 --- a/tests/Control/CacheWrite.html +++ b/tests/Control/CacheWrite.html @@ -40,7 +40,7 @@ return; } - t.plan(3); + t.plan(4); OpenLayers.Control.CacheWrite.clearCache(); var length = window.localStorage.length; @@ -68,6 +68,9 @@ // content will be null for browsers that have localStorage but no canvas support var content = canvasContext ? canvasContext.canvas.toDataURL("image/png") : null; t.eq(window.localStorage.getItem("olCache_"+url), content, "localStorage contains correct image data"); + + layer.events.triggerEvent('tileloaded', {aborted: true, tile: layer.grid[1][1]}); + t.eq(window.localStorage.length, length + (canvasContext ? tiles-1 : 0), "tile aborted during load not cached"); var key = Math.random(); window.localStorage.setItem(key, "bar");