From ddf993f0c902b922675f8c17d225b78c7a4bea16 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 18 Feb 2013 14:18:08 -0700 Subject: [PATCH 01/16] Factor out common code and test The findInterimTiles method was used in three renderers. This change makes it available on the tile source and adds some basic tests. --- .../canvas/canvastilelayerrenderer.js | 28 +-- src/ol/renderer/dom/domtilelayerrenderer.js | 28 +-- .../renderer/webgl/webgltilelayerrenderer.js | 30 +--- src/ol/source/tilesource.js | 39 +++++ test/spec/ol/source/tilesource.test.js | 163 ++++++++++++++++++ 5 files changed, 211 insertions(+), 77 deletions(-) create mode 100644 test/spec/ol/source/tilesource.test.js diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 02e5e904ff..3917e7f3e0 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -129,30 +129,8 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var findInterimTiles = function(z, tileRange) { - // FIXME this could be more efficient about filling partial holes - var fullyCovered = true; - var tile, tileCoord, tileCoordKey, x, y; - for (x = tileRange.minX; x <= tileRange.maxX; ++x) { - for (y = tileRange.minY; y <= tileRange.maxY; ++y) { - tileCoord = new ol.TileCoord(z, x, y); - tileCoordKey = tileCoord.toString(); - if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { - return; - } - tile = tileSource.getTile(tileCoord); - if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { - if (!tilesToDrawByZ[z]) { - tilesToDrawByZ[z] = {}; - } - tilesToDrawByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; - } - } - } - return fullyCovered; - }; + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; @@ -180,7 +158,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = } allTilesLoaded = false; - tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles); + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); } } diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 094d6a3009..d6521d9386 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -93,30 +93,8 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var findInterimTiles = function(z, tileRange) { - // FIXME this could be more efficient about filling partial holes - var fullyCovered = true; - var tile, tileCoord, tileCoordKey, x, y; - for (x = tileRange.minX; x <= tileRange.maxX; ++x) { - for (y = tileRange.minY; y <= tileRange.maxY; ++y) { - tileCoord = new ol.TileCoord(z, x, y); - tileCoordKey = tileCoord.toString(); - if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { - return; - } - tile = tileSource.getTile(tileCoord); - if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { - if (!tilesToDrawByZ[z]) { - tilesToDrawByZ[z] = {}; - } - tilesToDrawByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; - } - } - } - return fullyCovered; - }; + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; @@ -144,7 +122,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = } allTilesLoaded = false; - tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles); + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); } diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 360f8f8d82..fe29c6cf00 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -365,32 +365,8 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; - var findInterimTiles = function(z, tileRange) { - // FIXME this could be more efficient about filling partial holes - var fullyCovered = true; - var tile, tileCoord, tileCoordKey, x, y; - for (x = tileRange.minX; x <= tileRange.maxX; ++x) { - for (y = tileRange.minY; y <= tileRange.maxY; ++y) { - tileCoord = new ol.TileCoord(z, x, y); - tileCoordKey = tileCoord.toString(); - if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) { - return; - } - tile = tileSource.getTile(tileCoord); - if (!goog.isNull(tile) && - tile.getState() == ol.TileState.LOADED && - mapRenderer.isTileTextureLoaded(tile)) { - if (!tilesToDrawByZ[z]) { - tilesToDrawByZ[z] = {}; - } - tilesToDrawByZ[z][tileCoordKey] = tile; - } else { - fullyCovered = false; - } - } - } - return fullyCovered; - }; + var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, + tilesToDrawByZ); var tilesToLoad = new goog.structs.PriorityQueue(); @@ -428,7 +404,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = } allTilesLoaded = false; - tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles); + tileGrid.forEachTileCoordParentTileRange(tileCoord, findLoadedTiles); } diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index 93e083eef8..bb7d3b0d96 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -8,6 +8,7 @@ goog.require('ol.Projection'); goog.require('ol.Tile'); goog.require('ol.TileCoord'); goog.require('ol.TileRange'); +goog.require('ol.TileState'); goog.require('ol.source.Source'); goog.require('ol.tilegrid.TileGrid'); @@ -58,6 +59,44 @@ ol.source.TileSource.prototype.canExpireCache = goog.functions.FALSE; ol.source.TileSource.prototype.expireCache = goog.abstractMethod; +/** + * Look for loaded tiles over a given tile range and zoom level. Adds + * properties to the provided lookup representing key/tile pairs for already + * loaded tiles. + * + * @param {Object.>} loadedTilesByZ A lookup of + * loaded tiles by zoom level. + * @param {number} z Zoom level. + * @param {ol.TileRange} tileRange Tile range. + * @return {boolean} The tile range is fully covered with loaded tiles. + */ +ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, z, + tileRange) { + // FIXME this could be more efficient about filling partial holes + var fullyCovered = true; + var tile, tileCoord, tileCoordKey, x, y; + for (x = tileRange.minX; x <= tileRange.maxX; ++x) { + for (y = tileRange.minY; y <= tileRange.maxY; ++y) { + tileCoord = new ol.TileCoord(z, x, y); + tileCoordKey = tileCoord.toString(); + if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) { + return false; // TODO: fix this + } + tile = this.getTile(tileCoord); + if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { + if (!loadedTilesByZ[z]) { + loadedTilesByZ[z] = {}; + } + loadedTilesByZ[z][tileCoordKey] = tile; + } else { + fullyCovered = false; + } + } + } + return fullyCovered; +}; + + /** * @inheritDoc */ diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js new file mode 100644 index 0000000000..9d51c59b04 --- /dev/null +++ b/test/spec/ol/source/tilesource.test.js @@ -0,0 +1,163 @@ +goog.provide('ol.test.source.TileSource'); + +describe('ol.source.TileSource', function() { + + describe('constructor', function() { + it('returns a tile source', function() { + var source = new ol.source.TileSource({ + projection: ol.Projection.getFromCode('EPSG:4326') + }); + expect(source).toBeA(ol.source.Source); + expect(source).toBeA(ol.source.TileSource); + }); + }); + + describe('#findLoadedTiles()', function() { + + it('adds no tiles if none are already loaded', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({}); + + var loadedTilesByZ = {}; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 3); + source.findLoadedTiles(loadedTilesByZ, 3, range); + + var keys = goog.object.getKeys(loadedTilesByZ); + expect(keys.length).toBe(0); + }); + + it('adds loaded tiles to the lookup (z: 0)', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({ + '0/0/-1': true, + '1/0/-1': true + }); + + var loadedTilesByZ = {}; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 0); + source.findLoadedTiles(loadedTilesByZ, 0, range); + var keys = goog.object.getKeys(loadedTilesByZ); + expect(keys.length).toBe(1); + var tile = loadedTilesByZ['0']['0/0/-1']; + expect(tile).toBeA(ol.Tile); + expect(tile.state).toBe(ol.TileState.LOADED); + }); + + it('adds loaded tiles to the lookup (z: 1)', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({ + '0/0/-1': true, + '1/0/-1': true + }); + + var loadedTilesByZ = {}; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); + source.findLoadedTiles(loadedTilesByZ, 1, range); + var keys = goog.object.getKeys(loadedTilesByZ); + expect(keys.length).toBe(1); + var tile = loadedTilesByZ['1']['1/0/-1']; + expect(tile).toBeA(ol.Tile); + expect(tile.state).toBe(ol.TileState.LOADED); + }); + + }); + +}); + +/** + * Tile source for tests that uses a EPSG:4326 based grid with 4 resolutions and + * 256x256 tiles. + * + * @constructor + * @extends {ol.source.TileSource} + * @param {Object.} loaded Lookup of already loaded tiles. + */ +ol.test.source.MockTileSource = function(loaded) { + var extent = new ol.Extent(-180, -180, 180, 180); + var tileGrid = new ol.tilegrid.TileGrid({ + resolutions: [360 / 256, 180 / 256, 90 / 256, 45 / 256], + extent: extent, + origin: new ol.Coordinate(-180, 180), + tileSize: new ol.Size(256, 256) + }); + + goog.base(this, { + extent: extent, + projection: ol.Projection.getFromCode('EPSG:4326'), + tileGrid: tileGrid + }); + + /** + * @type {Object.} + * @private + */ + this.loaded_ = loaded; + +}; +goog.inherits(ol.test.source.MockTileSource, ol.source.TileSource); + + +/** + * @inheritDoc + */ +ol.test.source.MockTileSource.prototype.getTile = function(tileCoord) { + var tile = new ol.Tile(tileCoord); + var key = tileCoord.toString(); + if (this.loaded_[key]) { + tile.state = ol.TileState.LOADED; + } + return tile; +}; + + +describe('ol.test.source.MockTileSource', function() { + + describe('constructor', function() { + it('creates a tile source', function() { + var source = new ol.test.source.MockTileSource({}); + expect(source).toBeA(ol.source.TileSource); + expect(source).toBeA(ol.test.source.MockTileSource); + }); + }); + + describe('#getTile()', function() { + it('returns a tile with state based on constructor arg', function() { + var source = new ol.test.source.MockTileSource({ + '0/0/0': true, + '1/0/-1': true + }); + var tile; + + // check a loaded tile + tile = source.getTile(new ol.TileCoord(0, 0, 0)); + expect(tile).toBeA(ol.Tile); + expect(tile.state).toBe(ol.TileState.LOADED); + + // check a tile that is not loaded + tile = source.getTile(new ol.TileCoord(1, 0, 0)); + expect(tile).toBeA(ol.Tile); + expect(tile.state).toBe(ol.TileState.IDLE); + + // check another loaded tile + tile = source.getTile(new ol.TileCoord(1, 0, -1)); + expect(tile).toBeA(ol.Tile); + expect(tile.state).toBe(ol.TileState.LOADED); + + }); + }); + +}); + +goog.require('goog.object'); + +goog.require('ol.Coordinate'); +goog.require('ol.Extent'); +goog.require('ol.Projection'); +goog.require('ol.Tile'); +goog.require('ol.TileCoord'); +goog.require('ol.TileState'); +goog.require('ol.source.TileSource'); +goog.require('ol.tilegrid.TileGrid'); From 6aa4e99fe536e50c4c2f3ed47cf930f4233bc3dd Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 18 Feb 2013 14:51:39 -0700 Subject: [PATCH 02/16] Fix return from findLoadedTiles Previously, the findInterimTiles method was returning undefined if the min x/y coord for a tile range was already in the lookup. The return says it indicates whether all tiles for the given z are loaded. This change corrects the return. This change also reveals a misunderstanding of the tile range returned by `getTileRangeForExtentAndZ`. The previous findInterimTiles method was treating max values as inclusive. This is intuitive. It looks like the method returns a range where max values are exclusive. --- src/ol/source/tilesource.js | 3 +- test/spec/ol/source/tilesource.test.js | 107 ++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index bb7d3b0d96..98e6720dc8 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -75,12 +75,13 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, z, // FIXME this could be more efficient about filling partial holes var fullyCovered = true; var tile, tileCoord, tileCoordKey, x, y; + // TODO: tile range is misunderstood (inclusive or not?) for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoord = new ol.TileCoord(z, x, y); tileCoordKey = tileCoord.toString(); if (loadedTilesByZ[z] && loadedTilesByZ[z][tileCoordKey]) { - return false; // TODO: fix this + continue; } tile = this.getTile(tileCoord); if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index 9d51c59b04..f6639eaa69 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -30,8 +30,8 @@ describe('ol.source.TileSource', function() { it('adds loaded tiles to the lookup (z: 0)', function() { // a source with no loaded tiles var source = new ol.test.source.MockTileSource({ - '0/0/-1': true, - '1/0/-1': true + '0/0/0': true, + '1/0/0': true }); var loadedTilesByZ = {}; @@ -40,7 +40,7 @@ describe('ol.source.TileSource', function() { source.findLoadedTiles(loadedTilesByZ, 0, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); - var tile = loadedTilesByZ['0']['0/0/-1']; + var tile = loadedTilesByZ['0']['0/0/0']; expect(tile).toBeA(ol.Tile); expect(tile.state).toBe(ol.TileState.LOADED); }); @@ -48,8 +48,8 @@ describe('ol.source.TileSource', function() { it('adds loaded tiles to the lookup (z: 1)', function() { // a source with no loaded tiles var source = new ol.test.source.MockTileSource({ - '0/0/-1': true, - '1/0/-1': true + '0/0/0': true, + '1/0/0': true }); var loadedTilesByZ = {}; @@ -58,11 +58,100 @@ describe('ol.source.TileSource', function() { source.findLoadedTiles(loadedTilesByZ, 1, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); - var tile = loadedTilesByZ['1']['1/0/-1']; + var tile = loadedTilesByZ['1']['1/0/0']; expect(tile).toBeA(ol.Tile); expect(tile.state).toBe(ol.TileState.LOADED); }); + it('returns true when all tiles are already loaded', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({ + // TODO: tile range is misunderstood + '1/0/0': true, + '1/0/1': true, + '1/0/2': true, + '1/1/0': true, + '1/1/1': true, + '1/1/2': true, + '1/2/0': true, + '1/2/1': true, + '1/2/2': true, + }); + + var loadedTilesByZ = {}; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); + var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); + expect(allLoaded).toBe(true); + }); + + it('returns true when all tiles are already loaded (part 2)', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({}); + + var loadedTilesByZ = { + '1': { + '1/0/0': true, + '1/0/1': true, + '1/0/2': true, + '1/1/0': true, + '1/1/1': true, + '1/1/2': true, + '1/2/0': true, + '1/2/1': true, + '1/2/2': true, + } + }; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); + var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); + expect(allLoaded).toBe(true); + }); + + it('returns false when all tiles are already loaded', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({ + '1/0/0': true, + '1/0/1': true, + '1/0/2': true, + '1/1/0': true, + '1/1/1': false, + '1/1/2': true, + '1/2/0': true, + '1/2/1': true, + '1/2/2': true, + }); + + var loadedTilesByZ = {}; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); + var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); + expect(allLoaded).toBe(false); + }); + + it('returns false when all tiles are already loaded (part 2)', function() { + // a source with no loaded tiles + var source = new ol.test.source.MockTileSource({}); + + var loadedTilesByZ = { + '1': { + '1/0/0': true, + '1/0/1': true, + '1/0/2': true, + '1/1/0': true, + '1/1/1': false, + '1/1/2': true, + '1/2/0': true, + '1/2/1': true, + '1/2/2': true, + } + }; + var grid = source.getTileGrid(); + var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); + var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); + expect(allLoaded).toBe(false); + }); + }); }); @@ -80,7 +169,7 @@ ol.test.source.MockTileSource = function(loaded) { var tileGrid = new ol.tilegrid.TileGrid({ resolutions: [360 / 256, 180 / 256, 90 / 256, 45 / 256], extent: extent, - origin: new ol.Coordinate(-180, 180), + origin: new ol.Coordinate(-180, -180), tileSize: new ol.Size(256, 256) }); @@ -127,7 +216,7 @@ describe('ol.test.source.MockTileSource', function() { it('returns a tile with state based on constructor arg', function() { var source = new ol.test.source.MockTileSource({ '0/0/0': true, - '1/0/-1': true + '1/0/0': true }); var tile; @@ -142,7 +231,7 @@ describe('ol.test.source.MockTileSource', function() { expect(tile.state).toBe(ol.TileState.IDLE); // check another loaded tile - tile = source.getTile(new ol.TileCoord(1, 0, -1)); + tile = source.getTile(new ol.TileCoord(1, 0, 0)); expect(tile).toBeA(ol.Tile); expect(tile.state).toBe(ol.TileState.LOADED); From e8c50c729009a4329caeaceef6dab9e3cbc9c610 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 18 Feb 2013 15:11:53 -0700 Subject: [PATCH 03/16] Passing tests --- test/spec/ol/source/tilesource.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index f6639eaa69..5cb401d51f 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -75,7 +75,7 @@ describe('ol.source.TileSource', function() { '1/1/2': true, '1/2/0': true, '1/2/1': true, - '1/2/2': true, + '1/2/2': true }); var loadedTilesByZ = {}; @@ -99,7 +99,7 @@ describe('ol.source.TileSource', function() { '1/1/2': true, '1/2/0': true, '1/2/1': true, - '1/2/2': true, + '1/2/2': true } }; var grid = source.getTileGrid(); @@ -119,7 +119,7 @@ describe('ol.source.TileSource', function() { '1/1/2': true, '1/2/0': true, '1/2/1': true, - '1/2/2': true, + '1/2/2': true }); var loadedTilesByZ = {}; @@ -143,7 +143,7 @@ describe('ol.source.TileSource', function() { '1/1/2': true, '1/2/0': true, '1/2/1': true, - '1/2/2': true, + '1/2/2': true } }; var grid = source.getTileGrid(); @@ -226,7 +226,7 @@ describe('ol.test.source.MockTileSource', function() { expect(tile.state).toBe(ol.TileState.LOADED); // check a tile that is not loaded - tile = source.getTile(new ol.TileCoord(1, 0, 0)); + tile = source.getTile(new ol.TileCoord(1, 0, -1)); expect(tile).toBeA(ol.Tile); expect(tile.state).toBe(ol.TileState.IDLE); From 793a956211c64c4a9e1bf56d1def9074181096e1 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 18 Feb 2013 16:34:11 +0100 Subject: [PATCH 04/16] Several fixes to the WMS Capabilities parser Make sure the object structure returned is not mangled by Closure Do not use closure XHR or JSON in the example Use Jasmine's async support in the test cases Get rid of some backwards compatibility now that we have a fresh start --- examples/wms-capabilities.html | 2 +- examples/wms-capabilities.js | 35 +- src/ol/parser/ogc/wmscapabilities_v1.js | 231 +++--- src/ol/parser/ogc/wmscapabilities_v1_1.js | 58 +- src/ol/parser/ogc/wmscapabilities_v1_1_0.js | 2 +- src/ol/parser/ogc/wmscapabilities_v1_1_1.js | 2 +- .../parser/ogc/wmscapabilities_v1_1_1_WMSC.js | 16 +- src/ol/parser/ogc/wmscapabilities_v1_3_0.js | 46 +- .../ol/parser/ogc/exceptionreport.test.js | 163 +++-- .../parser/ogc/wmscapabilities_v1_1_1.test.js | 669 +++++++----------- .../ogc/wmscapabilities_v1_1_1_WMSC.test.js | 105 ++- .../parser/ogc/wmscapabilities_v1_3_0.test.js | 417 ++++------- 12 files changed, 729 insertions(+), 1017 deletions(-) diff --git a/examples/wms-capabilities.html b/examples/wms-capabilities.html index 62e0a2e96a..c119fdc92e 100644 --- a/examples/wms-capabilities.html +++ b/examples/wms-capabilities.html @@ -13,9 +13,9 @@ height: 100%; } #log { - height: 500px; position: absolute; top: 130px; + font-size: 12px; } #text { position: absolute; diff --git a/examples/wms-capabilities.js b/examples/wms-capabilities.js index 71ba95bc33..a9c708f982 100644 --- a/examples/wms-capabilities.js +++ b/examples/wms-capabilities.js @@ -1,26 +1,19 @@ -goog.require('goog.debug.Console'); -goog.require('goog.debug.DivConsole'); -goog.require('goog.debug.Logger'); -goog.require('goog.debug.Logger.Level'); -goog.require('goog.json.Serializer'); -goog.require('goog.net.XhrIo'); goog.require('ol.parser.ogc.WMSCapabilities'); - -if (goog.DEBUG) { - goog.debug.Console.autoInstall(); - goog.debug.Logger.getLogger('ol').setLevel(goog.debug.Logger.Level.INFO); - var logconsole = new goog.debug.DivConsole(goog.dom.getElement('log')); - logconsole.setCapturing(true); -} - var parser = new ol.parser.ogc.WMSCapabilities(), result; var url = '../test/spec/ol/parser/ogc/xml/wmscapabilities_v1_3_0/ogcsample.xml'; -goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - result = parser.read(xhr.getResponseXml()); - if (goog.DEBUG) { - var output = new goog.json.Serializer().serialize(result); - goog.debug.Logger.getLogger('ol').info(output); + +var xhr = new XMLHttpRequest(); +xhr.open('GET', url, true); + + +/** + * onload handler for the XHR request. + */ +xhr.onload = function() { + if (xhr.status == 200) { + result = parser.read(xhr.responseXML); + document.getElementById('log').innerHTML = window.JSON.stringify(result); } -}); +}; +xhr.send(); diff --git a/src/ol/parser/ogc/wmscapabilities_v1.js b/src/ol/parser/ogc/wmscapabilities_v1.js index f1fe0ca815..860392da99 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1.js +++ b/src/ol/parser/ogc/wmscapabilities_v1.js @@ -19,17 +19,17 @@ ol.parser.ogc.WMSCapabilities_v1 = function() { this.readChildNodes(node, obj['service']); }, 'Name': function(node, obj) { - obj.name = this.getChildValue(node); + obj['name'] = this.getChildValue(node); }, 'Title': function(node, obj) { - obj.title = this.getChildValue(node); + obj['title'] = this.getChildValue(node); }, 'Abstract': function(node, obj) { obj['abstract'] = this.getChildValue(node); }, 'BoundingBox': function(node, obj) { var bbox = {}; - bbox.bbox = [ + bbox['bbox'] = [ parseFloat(node.getAttribute('minx')), parseFloat(node.getAttribute('miny')), parseFloat(node.getAttribute('maxx')), @@ -40,96 +40,96 @@ ol.parser.ogc.WMSCapabilities_v1 = function() { y: parseFloat(node.getAttribute('resy')) }; if (! (isNaN(res.x) && isNaN(res.y))) { - bbox.res = res; + bbox['res'] = res; } // return the bbox so that descendant classes can set the // CRS and SRS and add it to the obj return bbox; }, 'OnlineResource': function(node, obj) { - obj.href = this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', + obj['href'] = this.getAttributeNS(node, 'http://www.w3.org/1999/xlink', 'href'); }, 'ContactInformation': function(node, obj) { - obj.contactInformation = {}; - this.readChildNodes(node, obj.contactInformation); + obj['contactInformation'] = {}; + this.readChildNodes(node, obj['contactInformation']); }, 'ContactPersonPrimary': function(node, obj) { - obj.personPrimary = {}; - this.readChildNodes(node, obj.personPrimary); + obj['personPrimary'] = {}; + this.readChildNodes(node, obj['personPrimary']); }, 'ContactPerson': function(node, obj) { - obj.person = this.getChildValue(node); + obj['person'] = this.getChildValue(node); }, 'ContactOrganization': function(node, obj) { - obj.organization = this.getChildValue(node); + obj['organization'] = this.getChildValue(node); }, 'ContactPosition': function(node, obj) { - obj.position = this.getChildValue(node); + obj['position'] = this.getChildValue(node); }, 'ContactAddress': function(node, obj) { - obj.contactAddress = {}; - this.readChildNodes(node, obj.contactAddress); + obj['contactAddress'] = {}; + this.readChildNodes(node, obj['contactAddress']); }, 'AddressType': function(node, obj) { - obj.type = this.getChildValue(node); + obj['type'] = this.getChildValue(node); }, 'Address': function(node, obj) { - obj.address = this.getChildValue(node); + obj['address'] = this.getChildValue(node); }, 'City': function(node, obj) { - obj.city = this.getChildValue(node); + obj['city'] = this.getChildValue(node); }, 'StateOrProvince': function(node, obj) { - obj.stateOrProvince = this.getChildValue(node); + obj['stateOrProvince'] = this.getChildValue(node); }, 'PostCode': function(node, obj) { - obj.postcode = this.getChildValue(node); + obj['postcode'] = this.getChildValue(node); }, 'Country': function(node, obj) { - obj.country = this.getChildValue(node); + obj['country'] = this.getChildValue(node); }, 'ContactVoiceTelephone': function(node, obj) { - obj.phone = this.getChildValue(node); + obj['phone'] = this.getChildValue(node); }, 'ContactFacsimileTelephone': function(node, obj) { - obj.fax = this.getChildValue(node); + obj['fax'] = this.getChildValue(node); }, 'ContactElectronicMailAddress': function(node, obj) { - obj.email = this.getChildValue(node); + obj['email'] = this.getChildValue(node); }, 'Fees': function(node, obj) { var fees = this.getChildValue(node); if (fees && fees.toLowerCase() != 'none') { - obj.fees = fees; + obj['fees'] = fees; } }, 'AccessConstraints': function(node, obj) { var constraints = this.getChildValue(node); if (constraints && constraints.toLowerCase() != 'none') { - obj.accessConstraints = constraints; + obj['accessConstraints'] = constraints; } }, 'Capability': function(node, obj) { - obj.capability = { - nestedLayers: [], - layers: [] - }; - this.readChildNodes(node, obj.capability); + obj['capability'] = {}; + obj['capability']['nestedLayers'] = []; + obj['capability']['layers'] = []; + this.readChildNodes(node, obj['capability']); }, 'Request': function(node, obj) { - obj.request = {}; - this.readChildNodes(node, obj.request); + obj['request'] = {}; + this.readChildNodes(node, obj['request']); }, 'GetCapabilities': function(node, obj) { - obj.getcapabilities = {formats: []}; - this.readChildNodes(node, obj.getcapabilities); + obj['getcapabilities'] = {}; + obj['getcapabilities']['formats'] = []; + this.readChildNodes(node, obj['getcapabilities']); }, 'Format': function(node, obj) { - if (goog.isArray(obj.formats)) { - obj.formats.push(this.getChildValue(node)); + if (goog.isArray(obj['formats'])) { + obj['formats'].push(this.getChildValue(node)); } else { - obj.format = this.getChildValue(node); + obj['format'] = this.getChildValue(node); } }, 'DCPType': function(node, obj) { @@ -139,37 +139,32 @@ ol.parser.ogc.WMSCapabilities_v1 = function() { this.readChildNodes(node, obj); }, 'Get': function(node, obj) { - obj.get = {}; - this.readChildNodes(node, obj.get); - // backwards compatibility - if (!obj.href) { - obj.href = obj.get.href; - } + obj['get'] = {}; + this.readChildNodes(node, obj['get']); }, 'Post': function(node, obj) { - obj.post = {}; - this.readChildNodes(node, obj.post); - // backwards compatibility - if (!obj.href) { - obj.href = obj.get.href; - } + obj['post'] = {}; + this.readChildNodes(node, obj['post']); }, 'GetMap': function(node, obj) { - obj.getmap = {formats: []}; - this.readChildNodes(node, obj.getmap); + obj['getmap'] = {}; + obj['getmap']['formats'] = []; + this.readChildNodes(node, obj['getmap']); }, 'GetFeatureInfo': function(node, obj) { - obj.getfeatureinfo = {formats: []}; - this.readChildNodes(node, obj.getfeatureinfo); + obj['getfeatureinfo'] = {}; + obj['getfeatureinfo']['formats'] = []; + this.readChildNodes(node, obj['getfeatureinfo']); }, 'Exception': function(node, obj) { - obj.exception = {formats: []}; - this.readChildNodes(node, obj.exception); + obj['exception'] = {}; + obj['exception']['formats'] = []; + this.readChildNodes(node, obj['exception']); }, 'Layer': function(node, obj) { var parentLayer, capability; - if (obj.capability) { - capability = obj.capability; + if (obj['capability']) { + capability = obj['capability']; parentLayer = obj; } else { capability = obj; @@ -188,113 +183,113 @@ ol.parser.ogc.WMSCapabilities_v1 = function() { var fixedHeight = node.getAttribute('fixedHeight'); var parent = parentLayer || {}; var layer = { - nestedLayers: [], - styles: parentLayer ? [].concat(parentLayer.styles) : [], - srs: {}, - metadataURLs: [], - bbox: {}, - llbbox: parent.llbbox, - dimensions: {}, - authorityURLs: {}, - identifiers: {}, - keywords: [], - queryable: (queryable && queryable !== '') ? + 'nestedLayers': [], + 'styles': parentLayer ? [].concat(parentLayer['styles']) : [], + 'srs': {}, + 'metadataURLs': [], + 'bbox': {}, + 'llbbox': parent['llbbox'], + 'dimensions': {}, + 'authorityURLs': {}, + 'identifiers': {}, + 'keywords': [], + 'queryable': (queryable && queryable !== '') ? (queryable === '1' || queryable === 'true') : - (parent.queryable || false), - cascaded: (cascaded !== null) ? parseInt(cascaded, 10) : - (parent.cascaded || 0), - opaque: opaque ? + (parent['queryable'] || false), + 'cascaded': (cascaded !== null) ? parseInt(cascaded, 10) : + (parent['cascaded'] || 0), + 'opaque': opaque ? (opaque === '1' || opaque === 'true') : - (parent.opaque || false), - noSubsets: (noSubsets !== null) ? + (parent['opaque'] || false), + 'noSubsets': (noSubsets !== null) ? (noSubsets === '1' || noSubsets === 'true') : - (parent.noSubsets || false), - fixedWidth: (fixedWidth !== null) ? - parseInt(fixedWidth, 10) : (parent.fixedWidth || 0), - fixedHeight: (fixedHeight !== null) ? - parseInt(fixedHeight, 10) : (parent.fixedHeight || 0), - minScale: parent.minScale, - maxScale: parent.maxScale, - attribution: parent.attribution + (parent['noSubsets'] || false), + 'fixedWidth': (fixedWidth !== null) ? + parseInt(fixedWidth, 10) : (parent['fixedWidth'] || 0), + 'fixedHeight': (fixedHeight !== null) ? + parseInt(fixedHeight, 10) : (parent['fixedHeight'] || 0), + 'minScale': parent['minScale'], + 'maxScale': parent['maxScale'], + 'attribution': parent['attribution'] }; if (parentLayer) { - goog.object.extend(layer.srs, parent.srs); - goog.object.extend(layer.bbox, parent.bbox); - goog.object.extend(layer.dimensions, parent.dimensions); - goog.object.extend(layer.authorityURLs, parent.authorityURLs); + goog.object.extend(layer['srs'], parent['srs']); + goog.object.extend(layer['bbox'], parent['bbox']); + goog.object.extend(layer['dimensions'], parent['dimensions']); + goog.object.extend(layer['authorityURLs'], parent['authorityURLs']); } - obj.nestedLayers.push(layer); - layer.capability = capability; + obj['nestedLayers'].push(layer); + layer['capability'] = capability; this.readChildNodes(node, layer); - delete layer.capability; - if (layer.name) { - var parts = layer.name.split(':'), - request = capability.request, - gfi = request.getfeatureinfo; + delete layer['capability']; + if (layer['name']) { + var parts = layer['name'].split(':'), + request = capability['request'], + gfi = request['getfeatureinfo']; if (parts.length > 0) { - layer.prefix = parts[0]; + layer['prefix'] = parts[0]; } - capability.layers.push(layer); - if (layer.formats === undefined) { - layer.formats = request.getmap.formats; + capability['layers'].push(layer); + if (layer['formats'] === undefined) { + layer['formats'] = request['getmap']['formats']; } - if (layer.infoFormats === undefined && gfi) { - layer.infoFormats = gfi.formats; + if (layer['infoFormats'] === undefined && gfi) { + layer['infoFormats'] = gfi['formats']; } } }, 'Attribution': function(node, obj) { - obj.attribution = {}; - this.readChildNodes(node, obj.attribution); + obj['attribution'] = {}; + this.readChildNodes(node, obj['attribution']); }, 'LogoURL': function(node, obj) { - obj.logo = { - width: node.getAttribute('width'), - height: node.getAttribute('height') + obj['logo'] = { + 'width': node.getAttribute('width'), + 'height': node.getAttribute('height') }; - this.readChildNodes(node, obj.logo); + this.readChildNodes(node, obj['logo']); }, 'Style': function(node, obj) { var style = {}; - obj.styles.push(style); + obj['styles'].push(style); this.readChildNodes(node, style); }, 'LegendURL': function(node, obj) { var legend = { - width: node.getAttribute('width'), - height: node.getAttribute('height') + 'width': node.getAttribute('width'), + 'height': node.getAttribute('height') }; - obj.legend = legend; + obj['legend'] = legend; this.readChildNodes(node, legend); }, 'MetadataURL': function(node, obj) { - var metadataURL = {type: node.getAttribute('type')}; - obj.metadataURLs.push(metadataURL); + var metadataURL = {'type': node.getAttribute('type')}; + obj['metadataURLs'].push(metadataURL); this.readChildNodes(node, metadataURL); }, 'DataURL': function(node, obj) { - obj.dataURL = {}; - this.readChildNodes(node, obj.dataURL); + obj['dataURL'] = {}; + this.readChildNodes(node, obj['dataURL']); }, 'FeatureListURL': function(node, obj) { - obj.featureListURL = {}; - this.readChildNodes(node, obj.featureListURL); + obj['featureListURL'] = {}; + this.readChildNodes(node, obj['featureListURL']); }, 'AuthorityURL': function(node, obj) { var name = node.getAttribute('name'); var authority = {}; this.readChildNodes(node, authority); - obj.authorityURLs[name] = authority.href; + obj['authorityURLs'][name] = authority['href']; }, 'Identifier': function(node, obj) { var authority = node.getAttribute('authority'); - obj.identifiers[authority] = this.getChildValue(node); + obj['identifiers'][authority] = this.getChildValue(node); }, 'KeywordList': function(node, obj) { this.readChildNodes(node, obj); }, 'SRS': function(node, obj) { - obj.srs[this.getChildValue(node)] = true; + obj['srs'][this.getChildValue(node)] = true; } } }; diff --git a/src/ol/parser/ogc/wmscapabilities_v1_1.js b/src/ol/parser/ogc/wmscapabilities_v1_1.js index a4cb628b52..927e76b9d0 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1_1.js +++ b/src/ol/parser/ogc/wmscapabilities_v1_1.js @@ -15,37 +15,37 @@ ol.parser.ogc.WMSCapabilities_v1_1 = function() { this.readChildNodes(node, obj); }, 'Keyword': function(node, obj) { - if (obj.keywords) { - obj.keywords.push({value: this.getChildValue(node)}); + if (obj['keywords']) { + obj['keywords'].push({'value': this.getChildValue(node)}); } }, 'DescribeLayer': function(node, obj) { - obj.describelayer = {formats: []}; - this.readChildNodes(node, obj.describelayer); + obj['describelayer'] = {'formats': []}; + this.readChildNodes(node, obj['describelayer']); }, 'GetLegendGraphic': function(node, obj) { - obj.getlegendgraphic = {formats: []}; - this.readChildNodes(node, obj.getlegendgraphic); + obj['getlegendgraphic'] = {'formats': []}; + this.readChildNodes(node, obj['getlegendgraphic']); }, 'GetStyles': function(node, obj) { - obj.getstyles = {formats: []}; - this.readChildNodes(node, obj.getstyles); + obj['getstyles'] = {'formats': []}; + this.readChildNodes(node, obj['getstyles']); }, 'PutStyles': function(node, obj) { - obj.putstyles = {formats: []}; - this.readChildNodes(node, obj.putstyles); + obj['putstyles'] = {'formats': []}; + this.readChildNodes(node, obj['putstyles']); }, 'UserDefinedSymbolization': function(node, obj) { var userSymbols = { - supportSLD: parseInt(node.getAttribute('SupportSLD'), 10) == 1, - userLayer: parseInt(node.getAttribute('UserLayer'), 10) == 1, - userStyle: parseInt(node.getAttribute('UserStyle'), 10) == 1, - remoteWFS: parseInt(node.getAttribute('RemoteWFS'), 10) == 1 + 'supportSLD': parseInt(node.getAttribute('SupportSLD'), 10) == 1, + 'userLayer': parseInt(node.getAttribute('UserLayer'), 10) == 1, + 'userStyle': parseInt(node.getAttribute('UserStyle'), 10) == 1, + 'remoteWFS': parseInt(node.getAttribute('RemoteWFS'), 10) == 1 }; - obj.userSymbols = userSymbols; + obj['userSymbols'] = userSymbols; }, 'LatLonBoundingBox': function(node, obj) { - obj.llbbox = [ + obj['llbbox'] = [ parseFloat(node.getAttribute('minx')), parseFloat(node.getAttribute('miny')), parseFloat(node.getAttribute('maxx')), @@ -54,8 +54,8 @@ ol.parser.ogc.WMSCapabilities_v1_1 = function() { }, 'BoundingBox': function(node, obj) { var bbox = bboxreader.apply(this, arguments); - bbox.srs = node.getAttribute('SRS'); - obj.bbox[bbox.srs] = bbox; + bbox['srs'] = node.getAttribute('SRS'); + obj['bbox'][bbox['srs']] = bbox; }, 'ScaleHint': function(node, obj) { var min = parseFloat(node.getAttribute('min')); @@ -64,33 +64,33 @@ ol.parser.ogc.WMSCapabilities_v1_1 = function() { var dpi = (25.4 / 0.28); var ipm = 39.37; if (min !== 0) { - obj.maxScale = parseFloat((min / rad2) * ipm * dpi); + obj['maxScale'] = parseFloat((min / rad2) * ipm * dpi); } if (max != Number.POSITIVE_INFINITY) { - obj.minScale = parseFloat((max / rad2) * ipm * dpi); + obj['minScale'] = parseFloat((max / rad2) * ipm * dpi); } }, 'Dimension': function(node, obj) { var name = node.getAttribute('name').toLowerCase(); var dim = { - name: name, - units: node.getAttribute('units'), - unitsymbol: node.getAttribute('unitSymbol') + 'name': name, + 'units': node.getAttribute('units'), + 'unitsymbol': node.getAttribute('unitSymbol') }; - obj.dimensions[dim.name] = dim; + obj['dimensions'][dim.name] = dim; }, 'Extent': function(node, obj) { var name = node.getAttribute('name').toLowerCase(); if (name in obj['dimensions']) { - var extent = obj.dimensions[name]; - extent.nearestVal = + var extent = obj['dimensions'][name]; + extent['nearestVal'] = node.getAttribute('nearestValue') === '1'; - extent.multipleVal = + extent['multipleVal'] = node.getAttribute('multipleValues') === '1'; - extent.current = node.getAttribute('current') === '1'; + extent['current'] = node.getAttribute('current') === '1'; extent['default'] = node.getAttribute('default') || ''; var values = this.getChildValue(node); - extent.values = values.split(','); + extent['values'] = values.split(','); } } }); diff --git a/src/ol/parser/ogc/wmscapabilities_v1_1_0.js b/src/ol/parser/ogc/wmscapabilities_v1_1_0.js index 9aaea77ba5..e00a3da270 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1_1_0.js +++ b/src/ol/parser/ogc/wmscapabilities_v1_1_0.js @@ -15,7 +15,7 @@ ol.parser.ogc.WMSCapabilities_v1_1_0 = function() { var srs = this.getChildValue(node); var values = srs.split(/ +/); for (var i = 0, len = values.length; i < len; i++) { - obj.srs[values[i]] = true; + obj['srs'][values[i]] = true; } } }); diff --git a/src/ol/parser/ogc/wmscapabilities_v1_1_1.js b/src/ol/parser/ogc/wmscapabilities_v1_1_1.js index a8c23c2e3f..87e7ab50de 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1_1_1.js +++ b/src/ol/parser/ogc/wmscapabilities_v1_1_1.js @@ -12,7 +12,7 @@ ol.parser.ogc.WMSCapabilities_v1_1_1 = function() { this.version = '1.1.1'; goog.object.extend(this.readers['http://www.opengis.net/wms'], { 'SRS': function(node, obj) { - obj.srs[this.getChildValue(node)] = true; + obj['srs'][this.getChildValue(node)] = true; } }); }; diff --git a/src/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js b/src/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js index 246babafc3..dac01bc925 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js +++ b/src/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.js @@ -12,11 +12,11 @@ ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC = function() { this.profile = 'WMSC'; goog.object.extend(this.readers['http://www.opengis.net/wms'], { 'VendorSpecificCapabilities': function(node, obj) { - obj.vendorSpecific = {tileSets: []}; - this.readChildNodes(node, obj.vendorSpecific); + obj['vendorSpecific'] = {'tileSets': []}; + this.readChildNodes(node, obj['vendorSpecific']); }, 'TileSet': function(node, vendorSpecific) { - var tileset = {srs: {}, bbox: {}, resolutions: []}; + var tileset = {'srs': {}, 'bbox': {}, 'resolutions': []}; this.readChildNodes(node, tileset); vendorSpecific.tileSets.push(tileset); }, @@ -24,21 +24,21 @@ ol.parser.ogc.WMSCapabilities_v1_1_1_WMSC = function() { var res = this.getChildValue(node).split(' '); for (var i = 0, len = res.length; i < len; i++) { if (res[i] !== '') { - tileset.resolutions.push(parseFloat(res[i])); + tileset['resolutions'].push(parseFloat(res[i])); } } }, 'Width': function(node, tileset) { - tileset.width = parseInt(this.getChildValue(node), 10); + tileset['width'] = parseInt(this.getChildValue(node), 10); }, 'Height': function(node, tileset) { - tileset.height = parseInt(this.getChildValue(node), 10); + tileset['height'] = parseInt(this.getChildValue(node), 10); }, 'Layers': function(node, tileset) { - tileset.layers = this.getChildValue(node); + tileset['layers'] = this.getChildValue(node); }, 'Styles': function(node, tileset) { - tileset.styles = this.getChildValue(node); + tileset['styles'] = this.getChildValue(node); } }); }; diff --git a/src/ol/parser/ogc/wmscapabilities_v1_3_0.js b/src/ol/parser/ogc/wmscapabilities_v1_3_0.js index c17ab9acea..e1144bf9b0 100644 --- a/src/ol/parser/ogc/wmscapabilities_v1_3_0.js +++ b/src/ol/parser/ogc/wmscapabilities_v1_3_0.js @@ -15,18 +15,18 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { this.readChildNodes(node, obj); }, 'LayerLimit': function(node, obj) { - obj.layerLimit = parseInt(this.getChildValue(node), 10); + obj['layerLimit'] = parseInt(this.getChildValue(node), 10); }, 'MaxWidth': function(node, obj) { - obj.maxWidth = parseInt(this.getChildValue(node), 10); + obj['maxWidth'] = parseInt(this.getChildValue(node), 10); }, 'MaxHeight': function(node, obj) { - obj.maxHeight = parseInt(this.getChildValue(node), 10); + obj['maxHeight'] = parseInt(this.getChildValue(node), 10); }, 'BoundingBox': function(node, obj) { var bbox = bboxreader.apply(this, arguments); - bbox.srs = node.getAttribute('CRS'); - obj.bbox[bbox.srs] = bbox; + bbox['srs'] = node.getAttribute('CRS'); + obj['bbox'][bbox['srs']] = bbox; }, 'CRS': function(node, obj) { // CRS is the synonym of SRS @@ -34,8 +34,8 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { }, 'EX_GeographicBoundingBox': function(node, obj) { // replacement of LatLonBoundingBox - obj.llbbox = []; - this.readChildNodes(node, obj.llbbox); + obj['llbbox'] = []; + this.readChildNodes(node, obj['llbbox']); }, 'westBoundLongitude': function(node, obj) { obj[0] = this.getChildValue(node); @@ -50,10 +50,10 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { obj[3] = this.getChildValue(node); }, 'MinScaleDenominator': function(node, obj) { - obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16); + obj['maxScale'] = parseFloat(this.getChildValue(node)).toPrecision(16); }, 'MaxScaleDenominator': function(node, obj) { - obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16); + obj['minScale'] = parseFloat(this.getChildValue(node)).toPrecision(16); }, 'Dimension': function(node, obj) { // dimension has extra attributes: default, multipleValues, @@ -61,27 +61,27 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { // also contains the values. var name = node.getAttribute('name').toLowerCase(); var dim = { - name: name, - units: node.getAttribute('units'), - unitsymbol: node.getAttribute('unitSymbol'), - nearestVal: node.getAttribute('nearestValue') === '1', - multipleVal: node.getAttribute('multipleValues') === '1', + 'name': name, + 'units': node.getAttribute('units'), + 'unitsymbol': node.getAttribute('unitSymbol'), + 'nearestVal': node.getAttribute('nearestValue') === '1', + 'multipleVal': node.getAttribute('multipleValues') === '1', 'default': node.getAttribute('default') || '', - current: node.getAttribute('current') === '1', - values: this.getChildValue(node).split(',') + 'current': node.getAttribute('current') === '1', + 'values': this.getChildValue(node).split(',') }; // Theoretically there can be more dimensions with the same // name, but with a different unit. Until we meet such a case, // let's just keep the same structure as the WMS 1.1 // GetCapabilities parser uses. We will store the last // one encountered. - obj.dimensions[dim.name] = dim; + obj['dimensions'][dim['name']] = dim; }, 'Keyword': function(node, obj) { - var keyword = {value: this.getChildValue(node), - vocabulary: node.getAttribute('vocabulary')}; - if (obj.keywords) { - obj.keywords.push(keyword); + var keyword = {'value': this.getChildValue(node), + 'vocabulary': node.getAttribute('vocabulary')}; + if (obj['keywords']) { + obj['keywords'].push(keyword); } } }); @@ -91,9 +91,9 @@ ol.parser.ogc.WMSCapabilities_v1_3_0 = function() { readers.UserDefinedSymbolization.apply(this, arguments); // add the two extra attributes var value = node.getAttribute('InlineFeature'); - obj['userSymbols'].inlineFeature = parseInt(value, 10) == 1; + obj['userSymbols']['inlineFeature'] = parseInt(value, 10) == 1; value = node.getAttribute('RemoteWCS'); - obj['userSymbols'].remoteWCS = parseInt(value, 10) == 1; + obj['userSymbols']['remoteWCS'] = parseInt(value, 10) == 1; }, 'DescribeLayer': function(node, obj) { var readers = this.readers['http://www.opengis.net/wms']; diff --git a/test/spec/ol/parser/ogc/exceptionreport.test.js b/test/spec/ol/parser/ogc/exceptionreport.test.js index 069aef371c..2cb29daa0c 100644 --- a/test/spec/ol/parser/ogc/exceptionreport.test.js +++ b/test/spec/ol/parser/ogc/exceptionreport.test.js @@ -5,93 +5,88 @@ describe('ol.parser.ogc.exceptionreport', function() { var parser = new ol.parser.ogc.ExceptionReport(); describe('test read exception', function() { - var result, exceptions; - var url = 'spec/ol/parser/ogc/xml/exceptionreport/wms1_3_0.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - result = parser.read(xhr.getResponseXml()); - exceptions = result.exceptionReport.exceptions; - }); it('OCG WMS 1.3.0 exceptions', function() { - expect(exceptions.length).toBe(4); - var str = 'Plain text message about an error.'; - expect(goog.string.trim(exceptions[0].text)).toBe(str); - expect(exceptions[1].code).toBe('InvalidUpdateSequence'); - str = ' Another error message, this one with a service exception ' + - 'code supplied. '; - expect(exceptions[1].text).toBe(str); - str = 'Error in module , line 42A message that includes angle ' + - 'brackets in text must be enclosed in a Character Data Section as ' + - 'in this example. All XML-like markup is ignored except for this ' + - 'sequence of three closing characters:'; - expect(goog.string.trim(exceptions[2].text), str); - str = 'foo.c An error occurred ' + - 'Similarly, actual XML can be enclosed in a CDATA ' + - 'section. A generic parser will ignore that XML, but ' + - 'application-specific software may choose to process it.' + - ''; - expect(goog.string.trim(exceptions[3].text), str); + var result, exceptions; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/exceptionreport/wms1_3_0.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + result = parser.read(xhr.getResponseXml()); + exceptions = result.exceptionReport.exceptions; + }); + }); + waitsFor(function() { + return (result !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(exceptions.length).toBe(4); + var str = 'Plain text message about an error.'; + expect(goog.string.trim(exceptions[0].text)).toBe(str); + expect(exceptions[1].code).toBe('InvalidUpdateSequence'); + str = ' Another error message, this one with a service exception ' + + 'code supplied. '; + expect(exceptions[1].text).toBe(str); + str = 'Error in module , line 42A message that includes angle ' + + 'brackets in text must be enclosed in a Character Data Section as' + + ' in this example. All XML-like markup is ignored except for this' + + ' sequence of three closing characters:'; + expect(goog.string.trim(exceptions[2].text), str); + str = 'foo.c An error occurred ' + + 'Similarly, actual XML can be enclosed in a CDATA ' + + 'section. A generic parser will ignore that XML, but ' + + 'application-specific software may choose to process it.' + + ''; + expect(goog.string.trim(exceptions[3].text), str); + }); }); - }); - - describe('test read exception OWSCommon 1.0.0', function() { - var result, report, exception; - var url = 'spec/ol/parser/ogc/xml/exceptionreport/ows1_0_0.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - result = parser.read(xhr.getResponseXml()); - report = result.exceptionReport; - exception = report.exceptions[0]; + it('test read exception OWSCommon 1.0.0', function() { + var result, report, exception; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/exceptionreport/ows1_0_0.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + result = parser.read(xhr.getResponseXml()); + report = result.exceptionReport; + exception = report.exceptions[0]; + }); + }); + waitsFor(function() { + return (result !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(report.version).toEqual('1.0.0'); + expect(report.language).toEqual('en'); + expect(exception.code).toEqual('InvalidParameterValue'); + expect(exception.locator).toEqual('foo'); + var msg = 'Update error: Error occured updating features'; + expect(exception.texts[0]).toEqual(msg); + msg = 'Second exception line'; + expect(exception.texts[1]).toEqual(msg); + }); }); - it('Version parsed correctly', function() { - expect(report.version).toEqual('1.0.0'); - }); - it('Language parsed correctly', function() { - expect(report.language).toEqual('en'); - }); - it('exceptionCode properly parsed', function() { - expect(exception.code).toEqual('InvalidParameterValue'); - }); - it('locator properly parsed', function() { - expect(exception.locator).toEqual('foo'); - }); - it('ExceptionText correctly parsed', function() { - var msg = 'Update error: Error occured updating features'; - expect(exception.texts[0]).toEqual(msg); - }); - it('Second ExceptionText correctly parsed', function() { - var msg = 'Second exception line'; - expect(exception.texts[1]).toEqual(msg); - }); - }); - - describe('test read exception OWSCommon 1.1.0', function() { - var result, report, exception; - var url = 'spec/ol/parser/ogc/xml/exceptionreport/ows1_1_0.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - result = parser.read(xhr.getResponseXml()); - report = result.exceptionReport; - exception = report.exceptions[0]; - }); - it('Version parsed correctly', function() { - expect(report.version).toEqual('1.1.0'); - }); - it('Language parsed correctly', function() { - expect(report.language).toEqual('en'); - }); - it('exceptionCode properly parsed', function() { - expect(exception.code).toEqual('InvalidParameterValue'); - }); - it('locator properly parsed', function() { - expect(exception.locator).toEqual('foo'); - }); - it('ExceptionText correctly parsed', function() { - var msg = 'Update error: Error occured updating features'; - expect(exception.texts[0]).toEqual(msg); - }); - it('Second ExceptionText correctly parsed', function() { - expect(exception.texts[1]).toEqual('Second exception line'); + it('test read exception OWSCommon 1.1.0', function() { + var result, report, exception; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/exceptionreport/ows1_1_0.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + result = parser.read(xhr.getResponseXml()); + report = result.exceptionReport; + exception = report.exceptions[0]; + }); + }); + waitsFor(function() { + return (result !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(report.version).toEqual('1.1.0'); + expect(report.language).toEqual('en'); + expect(exception.code).toEqual('InvalidParameterValue'); + expect(exception.locator).toEqual('foo'); + var msg = 'Update error: Error occured updating features'; + expect(exception.texts[0]).toEqual(msg); + expect(exception.texts[1]).toEqual('Second exception line'); + }); }); }); }); diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js index bf453a971e..7d91002fbb 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1.test.js @@ -5,436 +5,307 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1', function() { var parser = new ol.parser.ogc.WMSCapabilities(); describe('test read exception', function() { - var obj, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/exceptionsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - }); it('Error reported correctly', function() { - expect(!!obj.error).toBeTruthy(); + var obj; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/' + + 'exceptionsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(!!obj.error).toBeTruthy(); + }); }); }); describe('test read', function() { - var obj, capability, getmap, describelayer, getfeatureinfo, layer, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - capability = obj.capability; - getmap = capability.request.getmap; - describelayer = capability.request.describelayer; - getfeatureinfo = capability.request.getfeatureinfo; - layer = capability.layers[2]; - }); - it('object contains capability property', function() { - expect(capability).toBeTruthy(); - }); - it('getmap formats parsed', function() { - expect(getmap.formats.length).toEqual(28); - }); - it('getmap href parsed', function() { - var url = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; - expect(getmap.href).toEqual(url); - }); - it('getmap.get.href parsed', function() { - expect(getmap.get.href).toEqual(getmap.href); - }); - it('getmap.post not available', function() { - expect(getmap.post).toBeUndefined(); - }); - it('describelayer href parsed', function() { - var url = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; - expect(describelayer.href).toEqual(url); - }); - it('describelayer.get.href parsed', function() { - expect(describelayer.get.href).toEqual(describelayer.href); - }); - it('describelayer.post not available', function() { - expect(describelayer.post).toBeUndefined(); - }); - it('getfeatureinfo href parsed', function() { - var url = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; - expect(getfeatureinfo.href).toEqual(url); - }); - it('getmap.get.href parsed', function() { - expect(getfeatureinfo.get.href).toEqual(getfeatureinfo.href); - }); - it('getfeatureinfo.post set correctly', function() { - var url = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; - expect(getfeatureinfo.post.href).toEqual(url); - }); - it('layers parsed', function() { - expect(capability.layers).toBeTruthy(); - }); - it('correct number of layers parsed', function() { - expect(capability.layers.length).toEqual(22); - }); - it('infoFormats set on layer', function() { - var infoFormats = ['text/plain', 'text/html', 'application/vnd.ogc.gml']; - expect(layer.infoFormats).toEqual(infoFormats); - }); - it('[2] correct layer name', function() { - expect(layer.name).toEqual('tiger:tiger_roads'); - }); - it('[2] correct layer prefix', function() { - expect(layer.prefix).toEqual('tiger'); - }); - it('[2] correct layer title', function() { - expect(layer.title).toEqual('Manhattan (NY) roads'); - }); - it('[2] correct layer abstract', function() { - var abstr = 'Highly simplified road layout of Manhattan in New York..'; - expect(layer['abstract']).toEqual(abstr); - }); - it('[2] correct layer bbox', function() { - var bbox = [-74.08769307536667, 40.660618924633326, - -73.84653192463333, 40.90178007536667]; - expect(layer.llbbox).toEqual(bbox); - }); - it('[2] correct styles length', function() { - expect(layer.styles.length).toEqual(1); - }); - it('[2] correct style name', function() { - expect(layer.styles[0].name).toEqual('tiger_roads'); - }); - it('[2] correct legend url', function() { - var url = 'http://publicus.opengeo.org:80/geoserver/wms/' + + it('Test read', function() { + var obj, capability, getmap, describelayer, getfeatureinfo, layer; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + capability = obj.capability; + getmap = capability.request.getmap; + describelayer = capability.request.describelayer; + getfeatureinfo = capability.request.getfeatureinfo; + layer = capability.layers[2]; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(capability).toBeTruthy(); + expect(getmap.formats.length).toEqual(28); + var get = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; + expect(getmap.get.href).toEqual(get); + expect(getmap.post).toBeUndefined(); + get = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; + expect(describelayer.get.href).toEqual(get); + expect(describelayer.post).toBeUndefined(); + get = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; + expect(getfeatureinfo.get.href).toEqual(get); + var post = 'http://publicus.opengeo.org:80/geoserver/wms?SERVICE=WMS&'; + expect(getfeatureinfo.post.href).toEqual(post); + expect(capability.layers).toBeTruthy(); + expect(capability.layers.length).toEqual(22); + var infoFormats = ['text/plain', 'text/html', + 'application/vnd.ogc.gml']; + expect(layer.infoFormats).toEqual(infoFormats); + expect(layer.name).toEqual('tiger:tiger_roads'); + expect(layer.prefix).toEqual('tiger'); + expect(layer.title).toEqual('Manhattan (NY) roads'); + var abstr = 'Highly simplified road layout of Manhattan in New York..'; + expect(layer['abstract']).toEqual(abstr); + var bbox = [-74.08769307536667, 40.660618924633326, + -73.84653192463333, 40.90178007536667]; + expect(layer.llbbox).toEqual(bbox); + expect(layer.styles.length).toEqual(1); + expect(layer.styles[0].name).toEqual('tiger_roads'); + var legend = 'http://publicus.opengeo.org:80/geoserver/wms/' + 'GetLegendGraphic?VERSION=1.0.0&FORMAT=image/png&WIDTH=20&' + 'HEIGHT=20&LAYER=tiger:tiger_roads'; - expect(layer.styles[0].legend.href).toEqual(url); - }); - it('[2] correct legend format', function() { - expect(layer.styles[0].legend.format).toEqual('image/png'); - }); - it('[2] correct queryable attribute', function() { - expect(layer.queryable).toBeTruthy(); + expect(layer.styles[0].legend.href).toEqual(legend); + expect(layer.styles[0].legend.format).toEqual('image/png'); + expect(layer.queryable).toBeTruthy(); + }); }); }); describe('test layers', function() { - var obj, capability, layers = {}, rootlayer, identifiers, authorities; - var featurelist, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - capability = obj.capability; - for (var i = 0, len = capability.layers.length; i < len; i++) { - if ('name' in capability.layers[i]) { - layers[capability.layers[i].name] = capability.layers[i]; - } - } - rootlayer = capability.layers[capability.layers.length - 1]; - identifiers = layers['ROADS_RIVERS'].identifiers; - authorities = layers['ROADS_RIVERS'].authorityURLs; - featurelist = layers['ROADS_RIVERS'].featureListURL; - }); - it('SRS parsed correctly for root layer', function() { - expect(rootlayer.srs).toEqual({'EPSG:4326': true}); - }); - it('Inheritance of SRS handled correctly when adding SRSes', function() { - var srs = {'EPSG:4326': true, 'EPSG:26986': true}; - expect(layers['ROADS_RIVERS'].srs).toEqual(srs); - }); - var msg = 'Inheritance of SRS handled correctly when redeclaring an ' + - 'inherited SRS'; - it(msg, function() { - expect(layers['Temperature'].srs).toEqual({'EPSG:4326': true}); - }); - it('Correct bbox and res from BoundingBox', function() { - var bbox = layers['ROADS_RIVERS'].bbox['EPSG:26986']; - expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); - expect(bbox.res).toEqual({x: 1, y: 1}); - }); - it('Correct bbox and res from BoundingBox (override)', function() { - bbox = layers['ROADS_RIVERS'].bbox['EPSG:4326']; - expect(bbox.bbox).toEqual([-71.63, 41.75, -70.78, 42.90]); - expect(bbox.res).toEqual({x: 0.01, y: 0.01}); - }); - it('Correctly inherited bbox and resolution', function() { - bbox = layers['ROADS_1M'].bbox['EPSG:26986']; - expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); - expect(bbox.res).toEqual({x: 1, y: 1}); - }); - it('got identifiers from layer ROADS_RIVERS', function() { - expect(identifiers).toBeTruthy(); - }); - it('authority attribute from Identifiers parsed correctly', function() { - expect('DIF_ID' in identifiers).toBeTruthy(); - }); - it('Identifier value parsed correctly', function() { - expect(identifiers['DIF_ID']).toEqual('123456'); - }); - it('AuthorityURLs parsed and inherited correctly', function() { - expect('DIF_ID' in authorities).toBeTruthy(); - }); - it('OnlineResource in AuthorityURLs parsed correctly', function() { - var url = 'http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html'; - expect(authorities['DIF_ID']).toEqual(url); - }); - it('layer has FeatureListURL', function() { - expect(featurelist).toBeTruthy(); - }); - it('FeatureListURL format parsed correctly', function() { - expect(featurelist.format).toEqual('application/vnd.ogc.se_xml'); - }); - it('FeatureListURL OnlineResource parsed correctly', function() { - var url = 'http://www.university.edu/data/roads_rivers.gml'; - expect(featurelist.href).toEqual(url); - }); - it('queryable property inherited correctly', function() { - expect(layers['Pressure'].queryable).toBeTruthy(); - }); - it('queryable property has correct default value', function() { - expect(layers['ozone_image'].queryable).toBeFalsy(); - }); - it('cascaded property parsed correctly', function() { - expect(layers['population'].cascaded).toEqual(1); - }); - it('fixedWidth property correctly parsed', function() { - expect(layers['ozone_image'].fixedWidth).toEqual(512); - }); - it('fixedHeight property correctly parsed', function() { - expect(layers['ozone_image'].fixedHeight).toEqual(256); - }); - it('opaque property parsed correctly', function() { - expect(layers['ozone_image'].opaque).toBeTruthy(); - }); - it('noSubsets property parsed correctly', function() { - expect(layers['ozone_image'].noSubsets).toBeTruthy(); + it('Test layers', function() { + var obj, capability, layers = {}, rootlayer, identifiers, authorities; + var featurelist; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + capability = obj.capability; + for (var i = 0, len = capability.layers.length; i < len; i++) { + if ('name' in capability.layers[i]) { + layers[capability.layers[i].name] = capability.layers[i]; + } + } + rootlayer = capability.layers[capability.layers.length - 1]; + identifiers = layers['ROADS_RIVERS'].identifiers; + authorities = layers['ROADS_RIVERS'].authorityURLs; + featurelist = layers['ROADS_RIVERS'].featureListURL; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(rootlayer.srs).toEqual({'EPSG:4326': true}); + var srs = {'EPSG:4326': true, 'EPSG:26986': true}; + expect(layers['ROADS_RIVERS'].srs).toEqual(srs); + expect(layers['Temperature'].srs).toEqual({'EPSG:4326': true}); + var bbox = layers['ROADS_RIVERS'].bbox['EPSG:26986']; + expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); + expect(bbox.res).toEqual({x: 1, y: 1}); + bbox = layers['ROADS_RIVERS'].bbox['EPSG:4326']; + expect(bbox.bbox).toEqual([-71.63, 41.75, -70.78, 42.90]); + expect(bbox.res).toEqual({x: 0.01, y: 0.01}); + bbox = layers['ROADS_1M'].bbox['EPSG:26986']; + expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); + expect(bbox.res).toEqual({x: 1, y: 1}); + expect(identifiers).toBeTruthy(); + expect('DIF_ID' in identifiers).toBeTruthy(); + expect(identifiers['DIF_ID']).toEqual('123456'); + expect('DIF_ID' in authorities).toBeTruthy(); + var url = 'http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html'; + expect(authorities['DIF_ID']).toEqual(url); + expect(featurelist).toBeTruthy(); + expect(featurelist.format).toEqual('application/vnd.ogc.se_xml'); + url = 'http://www.university.edu/data/roads_rivers.gml'; + expect(featurelist.href).toEqual(url); + expect(layers['Pressure'].queryable).toBeTruthy(); + expect(layers['ozone_image'].queryable).toBeFalsy(); + expect(layers['population'].cascaded).toEqual(1); + expect(layers['ozone_image'].fixedWidth).toEqual(512); + expect(layers['ozone_image'].fixedHeight).toEqual(256); + expect(layers['ozone_image'].opaque).toBeTruthy(); + expect(layers['ozone_image'].noSubsets).toBeTruthy(); + }); }); }); describe('test dimensions', function() { - var obj, capability, layers = {}, time, elevation, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - capability = obj.capability; - for (var i = 0, len = capability.layers.length; i < len; i++) { - if ('name' in capability.layers[i]) { - layers[capability.layers[i].name] = capability.layers[i]; - } - } - time = layers['Clouds'].dimensions.time; - elevation = layers['Pressure'].dimensions.elevation; - }); - it('Default time value parsed correctly', function() { - expect(time['default']).toEqual('2000-08-22'); - }); - it('Currect number of time extent values/periods', function() { - expect(time.values.length).toEqual(1); - }); - it('Time extent values parsed correctly', function() { - expect(time.values[0]).toEqual('1999-01-01/2000-08-22/P1D'); - }); - it('Dimension units parsed correctly', function() { - expect(elevation.units).toEqual('EPSG:5030'); - }); - it('Default elevation value parsed correctly', function() { - expect(elevation['default']).toEqual('0'); - }); - it('NearestValue parsed correctly', function() { - expect(elevation.nearestVal).toBeTruthy(); - }); - it('Absense of MultipleValues handled correctly', function() { - expect(elevation.multipleVal).toBeFalsy(); - }); - it('Parsing of comma-separated values done correctly', function() { - expect(elevation.values).toEqual(['0', '1000', '3000', '5000', '10000']); + it('Test dimensions', function() { + var obj, capability, layers = {}, time, elevation; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + capability = obj.capability; + for (var i = 0, len = capability.layers.length; i < len; i++) { + if ('name' in capability.layers[i]) { + layers[capability.layers[i].name] = capability.layers[i]; + } + } + time = layers['Clouds'].dimensions.time; + elevation = layers['Pressure'].dimensions.elevation; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(time['default']).toEqual('2000-08-22'); + expect(time.values.length).toEqual(1); + expect(time.values[0]).toEqual('1999-01-01/2000-08-22/P1D'); + expect(elevation.units).toEqual('EPSG:5030'); + expect(elevation['default']).toEqual('0'); + expect(elevation.nearestVal).toBeTruthy(); + expect(elevation.multipleVal).toBeFalsy(); + expect(elevation.values).toEqual(['0', '1000', '3000', '5000', + '10000']); + }); }); }); describe('test contact info', function() { - var obj, service, contactinfo, personPrimary, addr, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - service = obj.service; - contactinfo = service.contactInformation; - personPrimary = contactinfo.personPrimary; - addr = contactinfo.contactAddress; - }); - it('object contains contactInformation property', function() { - expect(contactinfo).toBeTruthy(); - }); - it('object contains personPrimary property', function() { - expect(personPrimary).toBeTruthy(); - }); - it('ContactPerson parsed correctly', function() { - expect(personPrimary.person).toEqual('Jeff deLaBeaujardiere'); - }); - it('ContactOrganization parsed correctly', function() { - expect(personPrimary.organization).toEqual('NASA'); - }); - it('ContactPosition parsed correctly', function() { - expect(contactinfo.position).toEqual('Computer Scientist'); - }); - it('object contains contactAddress property', function() { - expect(addr).toBeTruthy(); - }); - it('AddressType parsed correctly', function() { - expect(addr.type).toEqual('postal'); - }); - it('Address parsed correctly', function() { - var address = 'NASA Goddard Space Flight Center, Code 933'; - expect(addr.address).toEqual(address); - }); - it('City parsed correctly', function() { - expect(addr.city).toEqual('Greenbelt'); - }); - it('StateOrProvince parsed correctly', function() { - expect(addr.stateOrProvince).toEqual('MD'); - }); - it('PostCode parsed correctly', function() { - expect(addr.postcode).toEqual('20771'); - }); - it('Country parsed correctly', function() { - expect(addr.country).toEqual('USA'); - }); - it('ContactVoiceTelephone parsed correctly', function() { - expect(contactinfo.phone).toEqual('+1 301 286-1569'); - }); - it('ContactFacsimileTelephone parsed correctly', function() { - expect(contactinfo.fax).toEqual('+1 301 286-1777'); - }); - it('ContactElectronicMailAddress parsed correctly', function() { - expect(contactinfo.email).toEqual('delabeau@iniki.gsfc.nasa.gov'); + it('Test contact info', function() { + var obj, service, contactinfo, personPrimary, addr; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/' + + 'ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + service = obj.service; + contactinfo = service.contactInformation; + personPrimary = contactinfo.personPrimary; + addr = contactinfo.contactAddress; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(contactinfo).toBeTruthy(); + expect(personPrimary).toBeTruthy(); + expect(personPrimary.person).toEqual('Jeff deLaBeaujardiere'); + expect(personPrimary.organization).toEqual('NASA'); + expect(contactinfo.position).toEqual('Computer Scientist'); + expect(addr).toBeTruthy(); + expect(addr.type).toEqual('postal'); + var address = 'NASA Goddard Space Flight Center, Code 933'; + expect(addr.address).toEqual(address); + expect(addr.city).toEqual('Greenbelt'); + expect(addr.stateOrProvince).toEqual('MD'); + expect(addr.postcode).toEqual('20771'); + expect(addr.country).toEqual('USA'); + expect(contactinfo.phone).toEqual('+1 301 286-1569'); + expect(contactinfo.fax).toEqual('+1 301 286-1777'); + expect(contactinfo.email).toEqual('delabeau@iniki.gsfc.nasa.gov'); + }); }); }); describe('Test fees and constraints', function() { - var obj, service, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - service = obj.service; - }); - it('Fees=none handled correctly', function() { - expect('fees' in service).toBeFalsy(); - }); - it('AccessConstraints=none handled correctly', function() { - expect('accessConstraints' in service).toBeFalsy(); + it('Test fees and constraints', function() { + var obj, service; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + service = obj.service; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect('fees' in service).toBeFalsy(); + expect('accessConstraints' in service).toBeFalsy(); + }); }); }); describe('Test requests', function() { - var obj, request, exception, userSymbols, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - request = obj.capability.request; - exception = obj.capability.exception; - userSymbols = obj.capability.userSymbols; - }); - it('request property exists', function() { - expect(request).toBeTruthy(); - }); - it('got GetMap request', function() { - expect('getmap' in request).toBeTruthy(); - }); - it('got GetFeatureInfo request', function() { - expect('getfeatureinfo' in request).toBeTruthy(); - }); - it('GetFeatureInfo formats correctly parsed', function() { - var formats = ['text/plain', 'text/html', 'application/vnd.ogc.gml']; - expect(request.getfeatureinfo.formats).toEqual(formats); - }); - it('got DescribeLayer request', function() { - expect('describelayer' in request).toBeTruthy(); - }); - it('got GetLegendGraphic request', function() { - expect('getlegendgraphic' in request).toBeTruthy(); - }); - it('exception property exists', function() { - expect(exception).toBeTruthy(); - }); - it('Exception Format parsed', function() { - expect(exception.formats).toEqual(['application/vnd.ogc.se_xml']); - }); - it('userSymbols property exists', function() { - expect(userSymbols).toBeTruthy(); - }); - it('supportSLD parsed', function() { - expect(userSymbols.supportSLD).toBeTruthy(); - }); - it('userLayer parsed', function() { - expect(userSymbols.userLayer).toBeTruthy(); - }); - it('userStyle parsed', function() { - expect(userSymbols.userStyle).toBeTruthy(); - }); - it('remoteWFS parsed', function() { - expect(userSymbols.remoteWFS).toBeTruthy(); + it('Test requests', function() { + var obj, request, exception, userSymbols; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/gssample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + request = obj.capability.request; + exception = obj.capability.exception; + userSymbols = obj.capability.userSymbols; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(request).toBeTruthy(); + expect('getmap' in request).toBeTruthy(); + expect('getfeatureinfo' in request).toBeTruthy(); + var formats = ['text/plain', 'text/html', 'application/vnd.ogc.gml']; + expect(request.getfeatureinfo.formats).toEqual(formats); + expect('describelayer' in request).toBeTruthy(); + expect('getlegendgraphic' in request).toBeTruthy(); + expect(exception).toBeTruthy(); + expect(exception.formats).toEqual(['application/vnd.ogc.se_xml']); + expect(userSymbols).toBeTruthy(); + expect(userSymbols.supportSLD).toBeTruthy(); + expect(userSymbols.userLayer).toBeTruthy(); + expect(userSymbols.userStyle).toBeTruthy(); + expect(userSymbols.remoteWFS).toBeTruthy(); + }); }); }); describe('test ogc', function() { - var obj, capability, attribution, keywords, metadataURLs, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - capability = obj.capability; - attribution = capability.layers[2].attribution; - keywords = capability.layers[0].keywords; - metadataURLs = capability.layers[0].metadataURLs; - }); - it('attribution title parsed correctly.', function() { - expect(attribution.title).toEqual('State College University'); - }); - it('attribution href parsed correctly.', function() { - expect(attribution.href).toEqual('http://www.university.edu/'); - }); - it('attribution logo url parsed correctly.', function() { - var url = 'http://www.university.edu/icons/logo.gif'; - expect(attribution.logo.href).toEqual(url); - }); - it('attribution logo format parsed correctly.', function() { - expect(attribution.logo.format).toEqual('image/gif'); - }); - it('attribution logo width parsed correctly.', function() { - expect(attribution.logo.width).toEqual('100'); - }); - it('attribution logo height parsed correctly.', function() { - expect(attribution.logo.height).toEqual('100'); - }); - it('layer has 3 keywords.', function() { - expect(keywords.length).toEqual(3); - }); - it('1st keyword parsed correctly.', function() { - expect(keywords[0].value).toEqual('road'); - }); - it('layer has 2 metadata urls.', function() { - expect(metadataURLs.length).toEqual(2); - }); - it('type parsed correctly.', function() { - expect(metadataURLs[0].type).toEqual('FGDC'); - }); - it('format parsed correctly.', function() { - expect(metadataURLs[0].format).toEqual('text/plain'); - }); - it('href parsed correctly.', function() { - var href = 'http://www.university.edu/metadata/roads.txt'; - expect(metadataURLs[0].href).toEqual(href); - }); - it('layer.minScale is correct', function() { - expect(Math.round(capability.layers[0].minScale)).toEqual(250000); - }); - it('layer.maxScale is correct', function() { - expect(Math.round(capability.layers[0].maxScale)).toEqual(1000); - }); - it('layer.minScale for max="Infinity" is correct', function() { - expect(capability.layers[1].minScale).toBeUndefined(); - }); - it('layer.maxScale for min="0" is correct', function() { - expect(capability.layers[1].maxScale).toBeUndefined(); + it('Test ogc', function() { + var obj, capability, attribution, keywords, metadataURLs; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1/ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + capability = obj.capability; + attribution = capability.layers[2].attribution; + keywords = capability.layers[0].keywords; + metadataURLs = capability.layers[0].metadataURLs; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(attribution.title).toEqual('State College University'); + expect(attribution.href).toEqual('http://www.university.edu/'); + var url = 'http://www.university.edu/icons/logo.gif'; + expect(attribution.logo.href).toEqual(url); + expect(attribution.logo.format).toEqual('image/gif'); + expect(attribution.logo.width).toEqual('100'); + expect(attribution.logo.height).toEqual('100'); + expect(keywords.length).toEqual(3); + expect(keywords[0].value).toEqual('road'); + expect(metadataURLs.length).toEqual(2); + expect(metadataURLs[0].type).toEqual('FGDC'); + expect(metadataURLs[0].format).toEqual('text/plain'); + var href = 'http://www.university.edu/metadata/roads.txt'; + expect(metadataURLs[0].href).toEqual(href); + expect(Math.round(capability.layers[0].minScale)).toEqual(250000); + expect(Math.round(capability.layers[0].maxScale)).toEqual(1000); + expect(capability.layers[1].minScale).toBeUndefined(); + expect(capability.layers[1].maxScale).toBeUndefined(); + }); }); }); diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js index 38146d6edc..517daa762c 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_1_1_WMSC.test.js @@ -8,63 +8,62 @@ describe('ol.parser.ogc.wmscapabilities_v1_1_1_wmsc', function() { }); describe('test read', function() { - var obj, tilesets, tileset, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1_WMSC/wmsc.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - tilesets = obj.capability.vendorSpecific.tileSets; - tileset = tilesets[0]; - }); - it('We expect 2 tilesets to be parsed', function() { - expect(tilesets.length).toEqual(2); - }); - it('BBOX correctly parsed', function() { - var bbox = [-13697515.466796875, 5165920.118906248, - -13619243.94984375, 5244191.635859374]; - expect(tileset.bbox['EPSG:900913'].bbox).toEqual(bbox); - }); - it('Format correctly parsed', function() { - expect(tileset.format).toEqual('image/png'); - }); - it('Height correctly parsed', function() { - expect(tileset.height).toEqual(256); - }); - it('Width correctly parsed', function() { - expect(tileset.width).toEqual(256); - }); - it('Layers correctly parsed', function() { - expect(tileset.layers).toEqual('medford:hydro'); - }); - it('SRS correctly parsed', function() { - expect(tileset.srs['EPSG:900913']).toBeTruthy(); - }); - it('Resolutions correctly parsed', function() { - var resolutions = [156543.03390625, 78271.516953125, 39135.7584765625, - 19567.87923828125, 9783.939619140625, 4891.9698095703125, - 2445.9849047851562, 1222.9924523925781, 611.4962261962891, - 305.74811309814453, 152.87405654907226, 76.43702827453613, - 38.218514137268066, 19.109257068634033, 9.554628534317017, - 4.777314267158508, 2.388657133579254, 1.194328566789627, - 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, - 0.07464553542435169, 0.037322767712175846, 0.018661383856087923, - 0.009330691928043961, 0.004665345964021981]; - expect(tileset.resolutions).toEqual(resolutions); - }); - it('Styles correctly parsed', function() { - expect(tileset.styles).toEqual(''); + it('Test read', function() { + var obj, tilesets, tileset; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1_WMSC/wmsc.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + tilesets = obj.capability.vendorSpecific.tileSets; + tileset = tilesets[0]; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(tilesets.length).toEqual(2); + var bbox = [-13697515.466796875, 5165920.118906248, + -13619243.94984375, 5244191.635859374]; + expect(tileset.bbox['EPSG:900913'].bbox).toEqual(bbox); + expect(tileset.format).toEqual('image/png'); + expect(tileset.height).toEqual(256); + expect(tileset.width).toEqual(256); + expect(tileset.layers).toEqual('medford:hydro'); + expect(tileset.srs['EPSG:900913']).toBeTruthy(); + var resolutions = [156543.03390625, 78271.516953125, 39135.7584765625, + 19567.87923828125, 9783.939619140625, 4891.9698095703125, + 2445.9849047851562, 1222.9924523925781, 611.4962261962891, + 305.74811309814453, 152.87405654907226, 76.43702827453613, + 38.218514137268066, 19.109257068634033, 9.554628534317017, + 4.777314267158508, 2.388657133579254, 1.194328566789627, + 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, + 0.07464553542435169, 0.037322767712175846, 0.018661383856087923, + 0.009330691928043961, 0.004665345964021981]; + expect(tileset.resolutions).toEqual(resolutions); + expect(tileset.styles).toEqual(''); + }); }); }); describe('test fallback', function() { - var obj, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1_WMSC/fallback.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - }); - it('layers parsed with allowFallback true', function() { - expect(obj.capability.layers.length).toEqual(2); + it('Test fallback', function() { + var obj; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_1_1_WMSC/' + + 'fallback.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(obj.capability.layers.length).toEqual(2); + }); }); }); diff --git a/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js b/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js index 2aab980278..8ddac8875a 100644 --- a/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js +++ b/test/spec/ol/parser/ogc/wmscapabilities_v1_3_0.test.js @@ -4,293 +4,152 @@ describe('ol.parser.ogc.wmscapabilities_v1_3_0', function() { var parser = new ol.parser.ogc.WMSCapabilities(); - var obj, capability, layers = {}, rootlayer, identifiers, authorities; - var featurelist, time, elevation, service, contactinfo, personPrimary, addr; - var request, exception, attribution, keywords, metadataURLs, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_3_0/ogcsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - obj = parser.read(xhr.getResponseXml()); - capability = obj.capability; - for (var i = 0, len = capability.layers.length; i < len; i++) { - if ('name' in capability.layers[i]) { - layers[capability.layers[i].name] = capability.layers[i]; - } - } - rootlayer = capability.layers[capability.layers.length - 1]; - identifiers = layers['ROADS_RIVERS'].identifiers; - authorities = layers['ROADS_RIVERS'].authorityURLs; - featurelist = layers['ROADS_RIVERS'].featureListURL; - time = layers['Clouds'].dimensions.time; - elevation = layers['Pressure'].dimensions.elevation; - service = obj.service; - contactinfo = service.contactInformation; - personPrimary = contactinfo.personPrimary; - addr = contactinfo.contactAddress; - request = obj.capability.request; - exception = obj.capability.exception; - attribution = capability.layers[2].attribution; - keywords = capability.layers[0].keywords; - metadataURLs = capability.layers[0].metadataURLs; - }); - describe('test read exception', function() { - var result, url; - url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_3_0/exceptionsample.xml'; - goog.net.XhrIo.send(url, function(e) { - var xhr = e.target; - result = parser.read(xhr.getResponseXml()); - }); it('Error reported correctly', function() { - expect(!!result.error).toBe(true); + var result; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_3_0/' + + 'exceptionsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + result = parser.read(xhr.getResponseXml()); + }); + }); + waitsFor(function() { + return (result !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(!!result.error).toBe(true); + }); }); }); - describe('test layers', function() { - it('SRS parsed correctly for root layer', function() { - expect(rootlayer.srs).toEqual({'CRS:84': true}); - }); - it('Inheritance of SRS handled correctly when adding SRSes', function() { - var srs = {'CRS:84': true, 'EPSG:26986': true}; - expect(layers['ROADS_RIVERS'].srs).toEqual(srs); - }); - it('Inheritance of SRS handled correctly when redeclaring an' + - ' inherited SRS', function() { + describe('test read', function() { + it('Test read', function() { + var obj, capability, layers = {}, rootlayer, identifiers, authorities; + var featurelist, time, elevation, service, contactinfo, personPrimary, + addr, request, exception, attribution, keywords, metadataURLs; + runs(function() { + var url = 'spec/ol/parser/ogc/xml/wmscapabilities_v1_3_0/ogcsample.xml'; + goog.net.XhrIo.send(url, function(e) { + var xhr = e.target; + obj = parser.read(xhr.getResponseXml()); + capability = obj.capability; + for (var i = 0, len = capability.layers.length; i < len; i++) { + if ('name' in capability.layers[i]) { + layers[capability.layers[i].name] = capability.layers[i]; + } + } + rootlayer = capability.layers[capability.layers.length - 1]; + identifiers = layers['ROADS_RIVERS'].identifiers; + authorities = layers['ROADS_RIVERS'].authorityURLs; + featurelist = layers['ROADS_RIVERS'].featureListURL; + time = layers['Clouds'].dimensions.time; + elevation = layers['Pressure'].dimensions.elevation; + service = obj.service; + contactinfo = service.contactInformation; + personPrimary = contactinfo.personPrimary; + addr = contactinfo.contactAddress; + request = obj.capability.request; + exception = obj.capability.exception; + attribution = capability.layers[2].attribution; + keywords = capability.layers[0].keywords; + metadataURLs = capability.layers[0].metadataURLs; + }); + }); + waitsFor(function() { + return (obj !== undefined); + }, 'XHR timeout', 1000); + runs(function() { + expect(rootlayer.srs).toEqual({'CRS:84': true}); + var srs = {'CRS:84': true, 'EPSG:26986': true}; + expect(layers['ROADS_RIVERS'].srs).toEqual(srs); expect(layers['Temperature'].srs).toEqual({'CRS:84': true}); - }); - it('infoFormats set correctly on layer', function() { - var infoFormats = ['text/xml', 'text/plain', 'text/html']; - expect(layers['Temperature'].infoFormats).toEqual(infoFormats); - }); - it('Correct resolution and bbox from BoundingBox', function() { - var bbox = layers['ROADS_RIVERS'].bbox['EPSG:26986']; - expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); - expect(bbox.res).toEqual({x: 1, y: 1}); - }); - it('Correct resolution and bbox from BoundingBox (override)', function() { - var bbox = layers['ROADS_RIVERS'].bbox['CRS:84']; - expect(bbox.bbox).toEqual([-71.63, 41.75, -70.78, 42.90]); - expect(bbox.res).toEqual({x: 0.01, y: 0.01}); - }); - it('Correctly inherited bbox and resolution', function() { - var bbox = layers['ROADS_1M'].bbox['EPSG:26986']; - expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); - expect(bbox.res).toEqual({x: 1, y: 1}); - }); - it('got identifiers from layer ROADS_RIVERS', function() { - expect(identifiers).toBeTruthy(); - }); - it('authority attribute from Identifiers parsed correctly', function() { - expect('DIF_ID' in identifiers).toBeTruthy(); - }); - it('Identifier value parsed correctly', function() { - expect(identifiers['DIF_ID']).toEqual('123456'); - }); - it('AuthorityURLs parsed and inherited correctly', function() { - expect('DIF_ID' in authorities).toBeTruthy(); - }); - it('OnlineResource in AuthorityURLs parsed correctly', function() { - var url = 'http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html'; - expect(authorities['DIF_ID']).toEqual(url); - }); - it('layer has FeatureListURL', function() { - expect(featurelist).toBeTruthy(); - }); - it('FeatureListURL format parsed correctly', function() { - expect(featurelist.format).toEqual('XML'); - }); - it('FeatureListURL OnlineResource parsed correctly', function() { - var url = 'http://www.university.edu/data/roads_rivers.gml'; - expect(featurelist.href).toEqual(url); - }); - it('queryable property inherited correctly', function() { - expect(layers['Pressure'].queryable).toBeTruthy(); - }); - it('queryable property has correct default value', function() { - expect(layers['ozone_image'].queryable).toBeFalsy(); - }); - it('cascaded property parsed correctly', function() { - expect(layers['population'].cascaded).toEqual(1); - }); - it('fixedWidth property correctly parsed', function() { - expect(layers['ozone_image'].fixedWidth).toEqual(512); - }); - it('fixedHeight property correctly parsed', function() { - expect(layers['ozone_image'].fixedHeight).toEqual(256); - }); - it('opaque property parsed correctly', function() { - expect(layers['ozone_image'].opaque).toBeTruthy(); - }); - it('noSubsets property parsed correctly', function() { - expect(layers['ozone_image'].noSubsets).toBeTruthy(); + var infoFormats = ['text/xml', 'text/plain', 'text/html']; + expect(layers['Temperature'].infoFormats).toEqual(infoFormats); + var bbox = layers['ROADS_RIVERS'].bbox['EPSG:26986']; + expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); + expect(bbox.res).toEqual({x: 1, y: 1}); + bbox = layers['ROADS_RIVERS'].bbox['CRS:84']; + expect(bbox.bbox).toEqual([-71.63, 41.75, -70.78, 42.90]); + expect(bbox.res).toEqual({x: 0.01, y: 0.01}); + bbox = layers['ROADS_1M'].bbox['EPSG:26986']; + expect(bbox.bbox).toEqual([189000, 834000, 285000, 962000]); + expect(bbox.res).toEqual({x: 1, y: 1}); + expect(identifiers).toBeTruthy(); + expect('DIF_ID' in identifiers).toBeTruthy(); + expect(identifiers['DIF_ID']).toEqual('123456'); + expect('DIF_ID' in authorities).toBeTruthy(); + var url = 'http://gcmd.gsfc.nasa.gov/difguide/whatisadif.html'; + expect(authorities['DIF_ID']).toEqual(url); + expect(featurelist).toBeTruthy(); + expect(featurelist.format).toEqual('XML'); + url = 'http://www.university.edu/data/roads_rivers.gml'; + expect(featurelist.href).toEqual(url); + expect(layers['Pressure'].queryable).toBeTruthy(); + expect(layers['ozone_image'].queryable).toBeFalsy(); + expect(layers['population'].cascaded).toEqual(1); + expect(layers['ozone_image'].fixedWidth).toEqual(512); + expect(layers['ozone_image'].fixedHeight).toEqual(256); + expect(layers['ozone_image'].opaque).toBeTruthy(); + expect(layers['ozone_image'].noSubsets).toBeTruthy(); + expect(time['default']).toEqual('2000-08-22'); + expect(time.values.length).toEqual(1); + expect(time.values[0]).toEqual('1999-01-01/2000-08-22/P1D'); + expect(elevation.units).toEqual('CRS:88'); + expect(elevation['default']).toEqual('0'); + expect(elevation.nearestVal).toBeTruthy(); + expect(elevation.multipleVal).toBeFalsy(); + expect(elevation.values).toEqual(['0', '1000', '3000', '5000', + '10000']); + expect(contactinfo).toBeTruthy(); + expect(personPrimary).toBeTruthy(); + expect(personPrimary.person).toEqual('Jeff Smith'); + expect(personPrimary.organization).toEqual('NASA'); + expect(contactinfo.position).toEqual('Computer Scientist'); + expect(addr).toBeTruthy(); + expect(addr.type).toEqual('postal'); + expect(addr.address).toEqual('NASA Goddard Space Flight Center'); + expect(addr.city).toEqual('Greenbelt'); + expect(addr.stateOrProvince).toEqual('MD'); + expect(addr.postcode).toEqual('20771'); + expect(addr.country).toEqual('USA'); + expect(contactinfo.phone).toEqual('+1 301 555-1212'); + expect(contactinfo.email).toEqual('user@host.com'); + expect('fees' in service).toBeFalsy(); + expect('accessConstraints' in service).toBeFalsy(); + expect(request).toBeTruthy(); + expect('getmap' in request).toBeTruthy(); + expect('getfeatureinfo' in request).toBeTruthy(); + var formats = ['text/xml', 'text/plain', 'text/html']; + expect(request.getfeatureinfo.formats).toEqual(formats); + expect(exception).toBeTruthy(); + formats = ['XML', 'INIMAGE', 'BLANK']; + expect(exception.formats).toEqual(formats); + expect(attribution.title).toEqual('State College University'); + expect(attribution.href).toEqual('http://www.university.edu/'); + url = 'http://www.university.edu/icons/logo.gif'; + expect(attribution.logo.href).toEqual(url); + expect(attribution.logo.format).toEqual('image/gif'); + expect(attribution.logo.width).toEqual('100'); + expect(attribution.logo.height).toEqual('100'); + expect(keywords.length).toEqual(3); + expect(keywords[0].value).toEqual('road'); + expect(metadataURLs.length).toEqual(2); + expect(metadataURLs[0].type).toEqual('FGDC:1998'); + expect(metadataURLs[0].format).toEqual('text/plain'); + url = 'http://www.university.edu/metadata/roads.txt'; + expect(metadataURLs[0].href).toEqual(url); + var minScale = 250000; + expect(capability.layers[0].minScale).toEqual(minScale.toPrecision(16)); + var maxScale = 1000; + expect(capability.layers[0].maxScale).toEqual(maxScale.toPrecision(16)); + expect(obj.service.layerLimit).toEqual(16); + expect(obj.service.maxHeight).toEqual(2048); + expect(obj.service.maxWidth).toEqual(2048); + }); }); }); - - describe('test dimensions', function() { - it('Default time value parsed correctly', function() { - expect(time['default']).toEqual('2000-08-22'); - }); - it('Currect number of time extent values/periods', function() { - expect(time.values.length).toEqual(1); - }); - it('Time extent values parsed correctly', function() { - expect(time.values[0]).toEqual('1999-01-01/2000-08-22/P1D'); - }); - it('Dimension units parsed correctly', function() { - expect(elevation.units).toEqual('CRS:88'); - }); - it('Default elevation value parsed correctly', function() { - expect(elevation['default']).toEqual('0'); - }); - it('NearestValue parsed correctly', function() { - expect(elevation.nearestVal).toBeTruthy(); - }); - it('Absense of MultipleValues handled correctly', function() { - expect(elevation.multipleVal).toBeFalsy(); - }); - it('Parsing of comma-separated values done correctly', function() { - expect(elevation.values).toEqual(['0', '1000', '3000', '5000', '10000']); - }); - }); - - describe('test contact info', function() { - it('object contains contactInformation property', function() { - expect(contactinfo).toBeTruthy(); - }); - it('object contains personPrimary property', function() { - expect(personPrimary).toBeTruthy(); - }); - it('ContactPerson parsed correctly', function() { - expect(personPrimary.person).toEqual('Jeff Smith'); - }); - it('ContactOrganization parsed correctly', function() { - expect(personPrimary.organization).toEqual('NASA'); - }); - it('ContactPosition parsed correctly', function() { - expect(contactinfo.position).toEqual('Computer Scientist'); - }); - it('object contains contactAddress property', function() { - expect(addr).toBeTruthy(); - }); - it('AddressType parsed correctly', function() { - expect(addr.type).toEqual('postal'); - }); - it('Address parsed correctly', function() { - expect(addr.address).toEqual('NASA Goddard Space Flight Center'); - }); - it('City parsed correctly', function() { - expect(addr.city).toEqual('Greenbelt'); - }); - it('StateOrProvince parsed correctly', function() { - expect(addr.stateOrProvince).toEqual('MD'); - }); - it('PostCode parsed correctly', function() { - expect(addr.postcode).toEqual('20771'); - }); - it('Country parsed correctly', function() { - expect(addr.country).toEqual('USA'); - }); - it('ContactVoiceTelephone parsed correctly', function() { - expect(contactinfo.phone).toEqual('+1 301 555-1212'); - }); - it('ContactElectronicMailAddress parsed correctly', function() { - expect(contactinfo.email).toEqual('user@host.com'); - }); - }); - - describe('test fees and constraints', function() { - it('Fees=none handled correctly', function() { - expect('fees' in service).toBeFalsy(); - }); - it('AccessConstraints=none handled correctly', function() { - expect('accessConstraints' in service).toBeFalsy(); - }); - }); - - describe('test requests', function() { - it('request property exists', function() { - expect(request).toBeTruthy(); - }); - it('got GetMap request', function() { - expect('getmap' in request).toBeTruthy(); - }); - it('got GetFeatureInfo request', function() { - expect('getfeatureinfo' in request).toBeTruthy(); - }); - it('GetFeatureInfo formats correctly parsed', function() { - var formats = ['text/xml', 'text/plain', 'text/html']; - expect(request.getfeatureinfo.formats).toEqual(formats); - }); - it('exception property exists', function() { - expect(exception).toBeTruthy(); - }); - it('Exception Format parsed', function() { - var formats = ['XML', 'INIMAGE', 'BLANK']; - expect(exception.formats).toEqual(formats); - }); - }); - - describe('test ogc', function() { - it('attribution title parsed correctly.', function() { - expect(attribution.title).toEqual('State College University'); - }); - it('attribution href parsed correctly.', function() { - expect(attribution.href).toEqual('http://www.university.edu/'); - }); - it('attribution logo url parsed correctly.', function() { - var url = 'http://www.university.edu/icons/logo.gif'; - expect(attribution.logo.href).toEqual(url); - }); - it('attribution logo format parsed correctly.', function() { - expect(attribution.logo.format).toEqual('image/gif'); - }); - it('attribution logo width parsed correctly.', function() { - expect(attribution.logo.width).toEqual('100'); - }); - it('attribution logo height parsed correctly.', function() { - expect(attribution.logo.height).toEqual('100'); - }); - it('layer has 3 keywords.', function() { - expect(keywords.length).toEqual(3); - }); - it('1st keyword parsed correctly.', function() { - expect(keywords[0].value).toEqual('road'); - }); - it('layer has 2 metadata urls.', function() { - expect(metadataURLs.length).toEqual(2); - }); - it('type parsed correctly.', function() { - expect(metadataURLs[0].type).toEqual('FGDC:1998'); - }); - it('format parsed correctly.', function() { - expect(metadataURLs[0].format).toEqual('text/plain'); - }); - it('href parsed correctly.', function() { - var url = 'http://www.university.edu/metadata/roads.txt'; - expect(metadataURLs[0].href).toEqual(url); - }); - it('layer.minScale is correct', function() { - var minScale = 250000; - expect(capability.layers[0].minScale).toEqual(minScale.toPrecision(16)); - }); - it('layer.maxScale is correct', function() { - var maxScale = 1000; - expect(capability.layers[0].maxScale).toEqual(maxScale.toPrecision(16)); - }); - }); - - describe('test WMS 1.3 specials', function() { - it('LayerLimit parsed correctly', function() { - expect(obj.service.layerLimit).toEqual(16); - }); - it('MaxHeight parsed correctly', function() { - expect(obj.service.maxHeight).toEqual(2048); - }); - it('MaxWidth parsed correctly', function() { - expect(obj.service.maxWidth).toEqual(2048); - }); - }); - }); goog.require('goog.net.XhrIo'); From 1b984ac06c9d97893c400d03f66a260d1aa64a7a Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 09:54:41 -0700 Subject: [PATCH 05/16] Fewer tiles to be considered fully loaded With 797dba2cdbabd8fa0a78c32a7b3bfcdbff29eea8 we no longer have to load excess tiles to consider an extent fully loaded. --- test/spec/ol/source/tilesource.test.js | 30 ++++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index 5cb401d51f..a02603a9ae 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -66,16 +66,10 @@ describe('ol.source.TileSource', function() { it('returns true when all tiles are already loaded', function() { // a source with no loaded tiles var source = new ol.test.source.MockTileSource({ - // TODO: tile range is misunderstood '1/0/0': true, '1/0/1': true, - '1/0/2': true, '1/1/0': true, - '1/1/1': true, - '1/1/2': true, - '1/2/0': true, - '1/2/1': true, - '1/2/2': true + '1/1/1': true }); var loadedTilesByZ = {}; @@ -93,13 +87,9 @@ describe('ol.source.TileSource', function() { '1': { '1/0/0': true, '1/0/1': true, - '1/0/2': true, '1/1/0': true, '1/1/1': true, - '1/1/2': true, - '1/2/0': true, - '1/2/1': true, - '1/2/2': true + '1/1/2': true } }; var grid = source.getTileGrid(); @@ -113,13 +103,8 @@ describe('ol.source.TileSource', function() { var source = new ol.test.source.MockTileSource({ '1/0/0': true, '1/0/1': true, - '1/0/2': true, '1/1/0': true, - '1/1/1': false, - '1/1/2': true, - '1/2/0': true, - '1/2/1': true, - '1/2/2': true + '1/1/1': false }); var loadedTilesByZ = {}; @@ -137,13 +122,8 @@ describe('ol.source.TileSource', function() { '1': { '1/0/0': true, '1/0/1': true, - '1/0/2': true, '1/1/0': true, - '1/1/1': false, - '1/1/2': true, - '1/2/0': true, - '1/2/1': true, - '1/2/2': true + '1/1/1': false } }; var grid = source.getTileGrid(); @@ -156,6 +136,8 @@ describe('ol.source.TileSource', function() { }); + + /** * Tile source for tests that uses a EPSG:4326 based grid with 4 resolutions and * 256x256 tiles. From 80dc7b5bf7980ca211b617cf9e84cd1a913baf9a Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 12:13:58 -0700 Subject: [PATCH 06/16] Accept custom isLoaded method in findLoadedTiles method --- .../canvas/canvastilelayerrenderer.js | 5 +++- src/ol/renderer/dom/domtilelayerrenderer.js | 5 +++- .../renderer/webgl/webgltilelayerrenderer.js | 6 ++++- src/ol/source/tilesource.js | 10 +++---- test/spec/ol/source/tilesource.test.js | 26 +++++++++++-------- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 3917e7f3e0..e7c48f044c 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -129,8 +129,11 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; + function isLoaded(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; + } var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ); + tilesToDrawByZ, isLoaded); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index d6521d9386..faeb67d47d 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -93,8 +93,11 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; + function isLoaded(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED; + } var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ); + tilesToDrawByZ, isLoaded); var allTilesLoaded = true; var tile, tileCenter, tileCoord, tileState, x, y; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index fe29c6cf00..53405ca10a 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -365,8 +365,12 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; + function isLoaded(tile) { + return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED && + mapRenderer.isTileTextureLoaded(tile); + } var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource, - tilesToDrawByZ); + tilesToDrawByZ, isLoaded); var tilesToLoad = new goog.structs.PriorityQueue(); diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index 98e6720dc8..e9666dada6 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -8,7 +8,6 @@ goog.require('ol.Projection'); goog.require('ol.Tile'); goog.require('ol.TileCoord'); goog.require('ol.TileRange'); -goog.require('ol.TileState'); goog.require('ol.source.Source'); goog.require('ol.tilegrid.TileGrid'); @@ -66,16 +65,17 @@ ol.source.TileSource.prototype.expireCache = goog.abstractMethod; * * @param {Object.>} loadedTilesByZ A lookup of * loaded tiles by zoom level. + * @param {function(ol.Tile): boolean} isLoaded A function to determine if a + * tile is fully loaded. * @param {number} z Zoom level. * @param {ol.TileRange} tileRange Tile range. * @return {boolean} The tile range is fully covered with loaded tiles. */ -ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, z, - tileRange) { +ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, + isLoaded, z, tileRange) { // FIXME this could be more efficient about filling partial holes var fullyCovered = true; var tile, tileCoord, tileCoordKey, x, y; - // TODO: tile range is misunderstood (inclusive or not?) for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) { tileCoord = new ol.TileCoord(z, x, y); @@ -84,7 +84,7 @@ ol.source.TileSource.prototype.findLoadedTiles = function(loadedTilesByZ, z, continue; } tile = this.getTile(tileCoord); - if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) { + if (isLoaded(tile)) { if (!loadedTilesByZ[z]) { loadedTilesByZ[z] = {}; } diff --git a/test/spec/ol/source/tilesource.test.js b/test/spec/ol/source/tilesource.test.js index a02603a9ae..3ee01e99a6 100644 --- a/test/spec/ol/source/tilesource.test.js +++ b/test/spec/ol/source/tilesource.test.js @@ -14,6 +14,10 @@ describe('ol.source.TileSource', function() { describe('#findLoadedTiles()', function() { + function isLoaded(tile) { + return !goog.isNull(tile) && tile.getState() === ol.TileState.LOADED; + } + it('adds no tiles if none are already loaded', function() { // a source with no loaded tiles var source = new ol.test.source.MockTileSource({}); @@ -21,7 +25,7 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 3); - source.findLoadedTiles(loadedTilesByZ, 3, range); + source.findLoadedTiles(loadedTilesByZ, isLoaded, 3, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(0); @@ -37,7 +41,7 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 0); - source.findLoadedTiles(loadedTilesByZ, 0, range); + source.findLoadedTiles(loadedTilesByZ, isLoaded, 0, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); var tile = loadedTilesByZ['0']['0/0/0']; @@ -55,7 +59,7 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - source.findLoadedTiles(loadedTilesByZ, 1, range); + source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); var keys = goog.object.getKeys(loadedTilesByZ); expect(keys.length).toBe(1); var tile = loadedTilesByZ['1']['1/0/0']; @@ -75,8 +79,8 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); - expect(allLoaded).toBe(true); + var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + expect(loaded).toBe(true); }); it('returns true when all tiles are already loaded (part 2)', function() { @@ -94,8 +98,8 @@ describe('ol.source.TileSource', function() { }; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); - expect(allLoaded).toBe(true); + var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + expect(loaded).toBe(true); }); it('returns false when all tiles are already loaded', function() { @@ -110,8 +114,8 @@ describe('ol.source.TileSource', function() { var loadedTilesByZ = {}; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); - expect(allLoaded).toBe(false); + var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + expect(loaded).toBe(false); }); it('returns false when all tiles are already loaded (part 2)', function() { @@ -128,8 +132,8 @@ describe('ol.source.TileSource', function() { }; var grid = source.getTileGrid(); var range = grid.getTileRangeForExtentAndZ(source.getExtent(), 1); - var allLoaded = source.findLoadedTiles(loadedTilesByZ, 1, range); - expect(allLoaded).toBe(false); + var loaded = source.findLoadedTiles(loadedTilesByZ, isLoaded, 1, range); + expect(loaded).toBe(false); }); }); From 3698049543751e19cd944fc2e5c555b2e873c82c Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:03:48 -0700 Subject: [PATCH 07/16] View needs to call constructor on super --- src/ol/view.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ol/view.js b/src/ol/view.js index 871928073e..f9303af991 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -23,6 +23,8 @@ ol.ViewHint = { */ ol.View = function() { + goog.base(this); + /** * @private * @type {Array.} From b9507de3ea3469c8581364b1ba6c3c58334b94d7 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:14:36 -0700 Subject: [PATCH 08/16] Removing unnecessary overhead --- src/ol/object.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ol/object.js b/src/ol/object.js index dbcf0a3e4e..aff2209925 100644 --- a/src/ol/object.js +++ b/src/ol/object.js @@ -232,14 +232,16 @@ ol.Object.prototype.set = function(key, value) { * @param {Object.} options Options. */ ol.Object.prototype.setOptions = function(options) { - goog.object.forEach(options, function(value, key) { - var setterName = ol.Object.getSetterName(key); + var key, value, setterName; + for (key in options) { + value = options[key]; + setterName = ol.Object.getSetterName(key); if (this[setterName]) { this[setterName](value); } else { this.set(key, value); } - }, this); + } }; @@ -270,9 +272,7 @@ ol.Object.prototype.unbind = function(key) { * Removes all bindings. */ ol.Object.prototype.unbindAll = function() { - var listeners = ol.Object.getListeners(this); - var keys = goog.object.getKeys(listeners); - goog.array.forEach(keys, function(key) { + for (var key in ol.Object.getListeners(this)) { this.unbind(key); - }, this); + } }; From 6cfc36d8cc77e739a8d2299247db3147b6d93e6f Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:17:58 -0700 Subject: [PATCH 09/16] Using hasOwnProperty is better for user keys on objects we control --- src/ol/object.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ol/object.js b/src/ol/object.js index aff2209925..60e36e2162 100644 --- a/src/ol/object.js +++ b/src/ol/object.js @@ -91,7 +91,8 @@ ol.Object.getAccessors = function(obj) { * @return {string} Changed name. */ ol.Object.getChangedEventType = function(key) { - return ol.Object.changedEventTypeCache_[key] || + return ol.Object.changedEventTypeCache_.hasOwnProperty(key) ? + ol.Object.changedEventTypeCache_[key] : (ol.Object.changedEventTypeCache_[key] = key.toLowerCase() + '_changed'); }; @@ -101,7 +102,8 @@ ol.Object.getChangedEventType = function(key) { * @return {string} Getter name. */ ol.Object.getGetterName = function(key) { - return ol.Object.getterNameCache_[key] || + return ol.Object.getterNameCache_.hasOwnProperty(key) ? + ol.Object.getterNameCache_[key] : (ol.Object.getterNameCache_[key] = 'get' + ol.Object.capitalize(key)); }; @@ -121,7 +123,8 @@ ol.Object.getListeners = function(obj) { * @return {string} Setter name. */ ol.Object.getSetterName = function(key) { - return ol.Object.setterNameCache_[key] || + return ol.Object.setterNameCache_.hasOwnProperty(key) ? + ol.Object.setterNameCache_[key] : (ol.Object.setterNameCache_[key] = 'set' + ol.Object.capitalize(key)); }; From 052e995f2e74cf250a61033177e283a46cc58641 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:19:40 -0700 Subject: [PATCH 10/16] Key in obj check not appropriate for user supplied keys --- src/ol/object.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/object.js b/src/ol/object.js index 60e36e2162..dbb5f95aea 100644 --- a/src/ol/object.js +++ b/src/ol/object.js @@ -165,7 +165,7 @@ ol.Object.prototype.changed = goog.nullFunction; */ ol.Object.prototype.get = function(key) { var accessors = ol.Object.getAccessors(this); - if (goog.object.containsKey(accessors, key)) { + if (accessors.hasOwnProperty(key)) { var accessor = accessors[key]; var target = accessor.target; var targetKey = accessor.key; @@ -186,7 +186,7 @@ ol.Object.prototype.get = function(key) { */ ol.Object.prototype.notify = function(key) { var accessors = ol.Object.getAccessors(this); - if (goog.object.containsKey(accessors, key)) { + if (accessors.hasOwnProperty(key)) { var accessor = accessors[key]; var target = accessor.target; var targetKey = accessor.key; @@ -214,7 +214,7 @@ ol.Object.prototype.notifyInternal_ = function(key) { */ ol.Object.prototype.set = function(key, value) { var accessors = ol.Object.getAccessors(this); - if (goog.object.containsKey(accessors, key)) { + if (accessors.hasOwnProperty(key)) { var accessor = accessors[key]; var target = accessor.target; var targetKey = accessor.key; From 0707deb465a4494e40c89ee783d0ca5c20fd88e5 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:28:59 -0700 Subject: [PATCH 11/16] Properties set with set should not be accessed with bracket --- src/ol/collection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/collection.js b/src/ol/collection.js index f1de3a535e..86c331302f 100644 --- a/src/ol/collection.js +++ b/src/ol/collection.js @@ -93,7 +93,7 @@ goog.inherits(ol.Collection, ol.Object); * Remove all elements from the collection. */ ol.Collection.prototype.clear = function() { - while (this[ol.CollectionProperty.LENGTH]) { + while (this.getLength() > 0) { this.pop(); } }; @@ -187,7 +187,7 @@ ol.Collection.prototype.removeAt = function(index) { * @param {*} elem Element. */ ol.Collection.prototype.setAt = function(index, elem) { - var n = this[ol.CollectionProperty.LENGTH]; + var n = this.getLength(); if (index < n) { var prev = this.array_[index]; this.array_[index] = elem; From d6ff58305de50954fd68506f3cde4c411c0f72ac Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:35:11 -0700 Subject: [PATCH 12/16] Using a dedicated object for value storage Without this, we are limited in the key names that we can accept from users. And because of compiler renaming, we don't know ahead of time what the limitations are (e.g. the key 'a' may clobber the 'set' method). --- src/ol/object.js | 21 +++++++++++++++------ test/spec/ol/object.test.js | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/ol/object.js b/src/ol/object.js index dbb5f95aea..af7a0a9edb 100644 --- a/src/ol/object.js +++ b/src/ol/object.js @@ -39,6 +39,13 @@ ol.ObjectProperty = { */ ol.Object = function(opt_values) { goog.base(this); + + /** + * @private + * @type {Object.} + */ + this.values_ = {}; + if (goog.isDef(opt_values)) { this.setValues(opt_values); } @@ -164,6 +171,7 @@ ol.Object.prototype.changed = goog.nullFunction; * @return {*} Value. */ ol.Object.prototype.get = function(key) { + var value; var accessors = ol.Object.getAccessors(this); if (accessors.hasOwnProperty(key)) { var accessor = accessors[key]; @@ -171,13 +179,14 @@ ol.Object.prototype.get = function(key) { var targetKey = accessor.key; var getterName = ol.Object.getGetterName(targetKey); if (target[getterName]) { - return target[getterName](); + value = target[getterName](); } else { - return target.get(targetKey); + value = target.get(targetKey); } - } else { - return this[key]; + } else if (this.values_.hasOwnProperty(key)) { + value = this.values_[key]; } + return value; }; @@ -225,7 +234,7 @@ ol.Object.prototype.set = function(key, value) { target.set(targetKey, value); } } else { - this[key] = value; + this.values_[key] = value; this.notifyInternal_(key); } }; @@ -266,7 +275,7 @@ ol.Object.prototype.unbind = function(key) { var value = this.get(key); var accessors = ol.Object.getAccessors(this); delete accessors[key]; - this[key] = value; + this.values_[key] = value; } }; diff --git a/test/spec/ol/object.test.js b/test/spec/ol/object.test.js index 3dd69c04e8..bb195088dd 100644 --- a/test/spec/ol/object.test.js +++ b/test/spec/ol/object.test.js @@ -34,6 +34,37 @@ describe('ol.Object', function() { }); }); + describe('#get()', function() { + + it('does not return values that are not explicitly set', function() { + var o = new ol.Object(); + expect(o.get('constructor')).toBeUndefined(); + expect(o.get('hasOwnProperty')).toBeUndefined(); + expect(o.get('isPrototypeOf')).toBeUndefined(); + expect(o.get('propertyIsEnumerable')).toBeUndefined(); + expect(o.get('toLocaleString')).toBeUndefined(); + expect(o.get('toString')).toBeUndefined(); + expect(o.get('valueOf')).toBeUndefined(); + }); + + }); + + describe('#set()', function() { + it('can be used with arbitrary names', function() { + var o = new ol.Object(); + + o.set('set', 'sat'); + expect(o.get('set')).toBe('sat'); + + o.set('get', 'got'); + expect(o.get('get')).toBe('got'); + + o.set('toString', 'string'); + expect(o.get('toString')).toBe('string'); + expect(typeof o.toString).toBe('function'); + }); + }); + describe('setValues', function() { it('sets multiple values at once', function() { @@ -309,7 +340,7 @@ describe('ol.Object', function() { describe('setter', function() { beforeEach(function() { o.setX = function(x) { - this.x = x; + this.set('x', x); }; spyOn(o, 'setX').andCallThrough(); }); @@ -327,8 +358,8 @@ describe('ol.Object', function() { var o2 = new ol.Object(); o2.bindTo('x', o); o2.set('x', 1); - expect(o.get('x')).toEqual(1); expect(o.setX).toHaveBeenCalled(); + expect(o.get('x')).toEqual(1); }); }); }); From 2919906ba664c87a0c845af3b684622b88ba6d72 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 19 Feb 2013 14:47:49 -0700 Subject: [PATCH 13/16] Add method for getting keys --- src/ol/object.js | 12 ++++++++ test/spec/ol/object.test.js | 55 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/ol/object.js b/src/ol/object.js index af7a0a9edb..861eb651ad 100644 --- a/src/ol/object.js +++ b/src/ol/object.js @@ -190,6 +190,18 @@ ol.Object.prototype.get = function(key) { }; +/** + * Get a list of object property names. + * @return {Array.} List of property names. + */ +ol.Object.prototype.getKeys = function() { + var keys = goog.object.getKeys(ol.Object.getAccessors(this)).concat( + goog.object.getKeys(this.values_)); + goog.array.removeDuplicates(keys); + return keys; +}; + + /** * @param {string} key Key. */ diff --git a/test/spec/ol/object.test.js b/test/spec/ol/object.test.js index bb195088dd..e8d2ccfe1b 100644 --- a/test/spec/ol/object.test.js +++ b/test/spec/ol/object.test.js @@ -65,6 +65,23 @@ describe('ol.Object', function() { }); }); + describe('#getKeys()', function() { + + it('returns property names set at construction', function() { + var o = new ol.Object({ + prop1: 'val1', + prop2: 'val2', + toString: 'string', + get: 'foo' + }); + + var keys = o.getKeys(); + expect(keys.length).toBe(4); + expect(keys.sort()).toEqual(['get', 'prop1', 'prop2', 'toString']); + }); + + }); + describe('setValues', function() { it('sets multiple values at once', function() { @@ -74,6 +91,9 @@ describe('ol.Object', function() { }); expect(o.get('k1')).toEqual(1); expect(o.get('k2')).toEqual(2); + + var keys = o.getKeys().sort(); + expect(keys).toEqual(['k1', 'k2']); }); }); @@ -130,6 +150,9 @@ describe('ol.Object', function() { it('dispatches events to object', function() { o.set('k', 1); expect(listener1).toHaveBeenCalled(); + + expect(o.getKeys()).toEqual(['k']); + expect(o2.getKeys()).toEqual(['k']); }); it('dispatches generic change events to object', function() { @@ -145,6 +168,9 @@ describe('ol.Object', function() { it('dispatches events to object bound to', function() { o2.set('k', 2); expect(listener1).toHaveBeenCalled(); + + expect(o.getKeys()).toEqual(['k']); + expect(o2.getKeys()).toEqual(['k']); }); it('dispatches generic change events to object bound to', function() { @@ -168,6 +194,9 @@ describe('ol.Object', function() { o2.bindTo('k', o); expect(o.get('k')).toEqual(1); expect(o2.get('k')).toEqual(1); + + expect(o.getKeys()).toEqual(['k']); + expect(o2.getKeys()).toEqual(['k']); }); }); @@ -178,6 +207,9 @@ describe('ol.Object', function() { o.set('k', 1); expect(o.get('k')).toEqual(1); expect(o2.get('k')).toEqual(1); + + expect(o.getKeys()).toEqual(['k']); + expect(o2.getKeys()).toEqual(['k']); }); }); @@ -270,6 +302,9 @@ describe('ol.Object', function() { expect(o2.get('k1')).toBeUndefined(); expect(listener1).toHaveBeenCalled(); expect(listener2).toHaveBeenCalled(); + + expect(o.getKeys()).toEqual(['k1']); + expect(o2.getKeys()).toEqual(['k2']); }); }); @@ -288,6 +323,10 @@ describe('ol.Object', function() { expect(o.get('k1')).toEqual(1); expect(o2.get('k2')).toEqual(1); expect(o3.get('k3')).toEqual(1); + + expect(o.getKeys()).toEqual(['k1']); + expect(o2.getKeys()).toEqual(['k2']); + expect(o3.getKeys()).toEqual(['k3']); }); describe('backward', function() { @@ -297,6 +336,10 @@ describe('ol.Object', function() { expect(o.get('k1')).toEqual(1); expect(o2.get('k2')).toEqual(1); expect(o3.get('k3')).toEqual(1); + + expect(o.getKeys()).toEqual(['k1']); + expect(o2.getKeys()).toEqual(['k2']); + expect(o3.getKeys()).toEqual(['k3']); }); }); }); @@ -350,6 +393,8 @@ describe('ol.Object', function() { o.set('x', 1); expect(o.get('x')).toEqual(1); expect(o.setX).not.toHaveBeenCalled(); + + expect(o.getKeys()).toEqual(['x']); }); }); @@ -360,6 +405,9 @@ describe('ol.Object', function() { o2.set('x', 1); expect(o.setX).toHaveBeenCalled(); expect(o.get('x')).toEqual(1); + + expect(o.getKeys()).toEqual(['x']); + expect(o2.getKeys()).toEqual(['x']); }); }); }); @@ -385,6 +433,9 @@ describe('ol.Object', function() { o2.bindTo('x', o); expect(o2.get('x')).toEqual(1); expect(o.getX).toHaveBeenCalled(); + + expect(o.getKeys()).toEqual([]); + expect(o2.getKeys()).toEqual(['x']); }); }); }); @@ -399,6 +450,8 @@ describe('ol.Object', function() { it('sets the property', function() { var o = new ol.Object({k: 1}); expect(o.get('k')).toEqual(1); + + expect(o.getKeys()).toEqual(['k']); }); }); @@ -416,6 +469,8 @@ describe('ol.Object', function() { o.set('K', 1); expect(listener1).toHaveBeenCalled(); expect(listener2).not.toHaveBeenCalled(); + + expect(o.getKeys()).toEqual(['K']); }); }); }); From f24b277dde11a7ce1e3c47fe1768c5f8a066cf2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 20 Feb 2013 09:39:15 +0100 Subject: [PATCH 14/16] Update readme Add examples section --- readme.md | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 723a41881d..7e549ce4c5 100644 --- a/readme.md +++ b/readme.md @@ -56,14 +56,35 @@ Then: ## Add examples The examples are located in the `examples` directory. Adding a new example -implies creating two files in this directory, a `.html` file and `.js` file. +implies creating two files in this directory, an `.html` file and a `.js` file. See `examples/full-screen.html` and `examples/full-screen.js` for instance. The `.html` file needs to include a script tag with `loader.js?id=` as its `src`. For example, if the two files for -the examples are `myexample.js` and `myexample.html` then `id` should be set to -`myexample` in the `loader.js` URL. +the example are `myexample.js` and `myexample.html` then the script tag's `src` +should be set to `myexample`. `build.py serve` should be stopped and restarted for the -`loader.js?id=` script tag to refer to a valid URL. `build.py serve` -triggers the `examples` target which creates Plovr JSON file for each example. +`loader.js?id=` script tag to refer to a valid URL. `build.py +serve` triggers the `examples` target which creates a Plovr JSON file for each +example. + +A note on the use of the `goog` namespace in the examples: + +Short story: the OL3 examples should not use the `goog` namespace, except +for `goog.require`. + +Longer story: + +We want that the OL3 examples work in multiple modes: with the standalone lib +(which has implications of the symbols and properties we export), with Plovr in +ADVANCED mode, and with Plovr in RAW (debug) mode. + +Running the examples with Plovr makes it mandatory to declare dependencies with +`goog.require` statements. And for the examples to also run with the standalone +lib we [export](https://github.com/openlayers/ol3/blob/master/src/goog.exports) +`goog.require` as the null function. + +Exporting `goog.require` has a side effect: it adds the `goog` namespace object +to the global object. This is why we can, for example, have `if (goog.DEBUG)` +statements in the code of the examples. From da825c27dad01efc169dbbf9e75c5dd3e84d3944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 20 Feb 2013 14:22:13 +0100 Subject: [PATCH 15/16] Update Run examples locally readme section --- readme.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 7e549ce4c5..912b5b9afb 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ Run the [Plovr](http://plovr.com/) web server with: $ ./build.py serve -Windows users should run `build serve` instead. +Windows users should run `build.py serve` instead. Then, either open one of the example html files from the `examples` directory directly in your browser, or start a simple webserver, for example: @@ -31,7 +31,20 @@ and explore the `examples/` directory, for example by opening . You can turn off compilation by appending `?mode=RAW` to the URL, for example -. +. (By default mode is `ADVANCED`.) + +The examples can also be run against the `ol.js` standalone lib, without Plovr, +just like the examples [hosted](http://openlayers.github.com/ol3/master/examples/) +on GitHub. You will want to run the examples against the standalone lib to verify +that will work correctly when copied on GitHub (as GitHub pages). Start by executing +the `hostexamples` build target: + + $ ./build.py hostexamples + +This will build `ol.js` and `ol.css`, creates the examples index page, and copy everything to +`build/gh-pages//`, where `` is the name of the local checked +out Git branch. You can now open the `build/gh-pages/examples` directory +in the browser, for example: . ## Run tests From 367ea0083c3becf48cab7a0819a8b9199939d1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 20 Feb 2013 14:26:55 +0100 Subject: [PATCH 16/16] Windows users should run build serve --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 912b5b9afb..85925eddb5 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ Run the [Plovr](http://plovr.com/) web server with: $ ./build.py serve -Windows users should run `build.py serve` instead. +Windows users should run `build serve` instead. Then, either open one of the example html files from the `examples` directory directly in your browser, or start a simple webserver, for example: