From e41ba124451a1e61523843e2a60e8d72230d14e9 Mon Sep 17 00:00:00 2001 From: Alvin Lindstam Date: Sun, 9 Aug 2015 22:09:31 +0200 Subject: [PATCH] Modify ol.featureloader (and consequently ol.source.Vector) to accept a function as a url. --- externs/olx.js | 10 ++++---- src/ol/featureloader.js | 36 ++++++++++++++++++++++++++--- test/spec/ol/featureloader.test.js | 37 +++++++++++++++++++++++++++--- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/externs/olx.js b/externs/olx.js index cf5ba38d6e..ab5a39e7c6 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -5165,7 +5165,7 @@ olx.source.TileWMSOptions.prototype.wrapX; * loader: (ol.FeatureLoader|undefined), * logo: (string|olx.LogoOptions|undefined), * strategy: (ol.LoadingStrategy|undefined), - * url: (string|undefined), + * url: (string|ol.FeatureUrlFunction|undefined), * useSpatialIndex: (boolean|undefined), * wrapX: (boolean|undefined)}} * @api @@ -5228,10 +5228,12 @@ olx.source.VectorOptions.prototype.strategy; /** * Setting this option instructs the source to use an XHR loader (see - * {@link ol.featureloader.xhr}) and an {@link ol.loadingstrategy.all} for a - * one-off download of all features from that URL. + * {@link ol.featureloader.xhr}). Use a `string` and an + * {@link ol.loadingstrategy.all} for a one-off download of all features from + * the given URL. Use a {@link ol.FeatureUrlFunction} to generate the url with + * other loading strategies. * Requires `format` to be set as well. - * @type {string|undefined} + * @type {string|ol.FeatureUrlFunction|undefined} * @api */ olx.source.VectorOptions.prototype.url; diff --git a/src/ol/featureloader.js b/src/ol/featureloader.js index f760ac4600..4dbbfec3dc 100644 --- a/src/ol/featureloader.js +++ b/src/ol/featureloader.js @@ -1,4 +1,5 @@ goog.provide('ol.FeatureLoader'); +goog.provide('ol.FeatureUrlFunction'); goog.provide('ol.featureloader'); goog.require('goog.asserts'); @@ -11,6 +12,16 @@ goog.require('ol.xml'); /** + * {@link ol.source.Vector} sources use a function of this type to load + * features. + * + * This function takes an {@link ol.Extent} representing the area to be loaded, + * a `{number}` representing the resolution (map units per pixel) and an + * {@link ol.proj.Projection} for the projection as arguments. `this` within + * the function is bound to the {@link ol.source.Vector} it's called from. + * + * The function is responsible for loading the features and adding them to the + * source. * @api * @typedef {function(this:ol.source.Vector, ol.Extent, number, * ol.proj.Projection)} @@ -19,7 +30,21 @@ ol.FeatureLoader; /** - * @param {string} url Feature URL service. + * {@link ol.source.Vector} sources use a function of this type to get the url + * to load features from. + * + * This function takes an {@link ol.Extent} representing the area to be loaded, + * a `{number}` representing the resolution (map units per pixel) and an + * {@link ol.proj.Projection} for the projection as arguments and returns a + * `{string}` representing the URL. + * @api + * @typedef {function(ol.Extent, number, ol.proj.Projection) : string} + */ +ol.FeatureUrlFunction; + + +/** + * @param {string|ol.FeatureUrlFunction} url Feature URL service. * @param {ol.format.Feature} format Feature format. * @param {function(this:ol.source.Vector, Array.)} success * Function called with the loaded features. Called with the vector @@ -77,7 +102,12 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success) { } goog.dispose(xhrIo); }, false, this); - xhrIo.send(url); + if (goog.isFunction(url)) { + xhrIo.send(url(extent, resolution, projection)); + } else { + xhrIo.send(url); + } + }); }; @@ -86,7 +116,7 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success) { * Create an XHR feature loader for a `url` and `format`. The feature loader * loads features (with XHR), parses the features, and adds them to the * vector source. - * @param {string} url Feature URL service. + * @param {string|ol.FeatureUrlFunction} url Feature URL service. * @param {ol.format.Feature} format Feature format. * @return {ol.FeatureLoader} The feature loader. * @api diff --git a/test/spec/ol/featureloader.test.js b/test/spec/ol/featureloader.test.js index 6ce714c98e..f9be87a4dc 100644 --- a/test/spec/ol/featureloader.test.js +++ b/test/spec/ol/featureloader.test.js @@ -4,16 +4,18 @@ describe('ol.featureloader', function() { describe('ol.featureloader.xhr', function() { var loader; var source; + var url; + var format; beforeEach(function() { - var url = 'spec/ol/data/point.json'; - var format = new ol.format.GeoJSON(); + url = 'spec/ol/data/point.json'; + format = new ol.format.GeoJSON(); - loader = ol.featureloader.xhr(url, format); source = new ol.source.Vector(); }); it('adds features to the source', function(done) { + loader = ol.featureloader.xhr(url, format); source.on(ol.source.VectorEventType.ADDFEATURE, function(e) { expect(source.getFeatures().length).to.be.greaterThan(0); done(); @@ -21,6 +23,35 @@ describe('ol.featureloader', function() { loader.call(source, [], 1, 'EPSG:3857'); }); + describe('when called with urlFunction', function() { + it('adds features to the source', function(done) { + url = function(extent, resolution, projection) { + return 'spec/ol/data/point.json';}; + loader = ol.featureloader.xhr(url, format); + + source.on(ol.source.VectorEventType.ADDFEATURE, function(e) { + expect(source.getFeatures().length).to.be.greaterThan(0); + done(); + }); + loader.call(source, [], 1, 'EPSG:3857'); + }); + + it('sends the correct arguments to the urlFunction', function(done) { + var extent = []; + var resolution = 1; + var projection = 'EPSG:3857'; + url = function(extent_, resolution_, projection_) { + expect(extent_).to.eql(extent); + expect(resolution_).to.eql(resolution); + expect(projection_).to.eql(projection); + done(); + return 'spec/ol/data/point.json'; + }; + loader = ol.featureloader.xhr(url, format); + loader.call(source, [], 1, 'EPSG:3857'); + }); + }); + }); });