diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index edf992bf7e..f6f55644b1 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -35,6 +35,16 @@ register(proj4); The map and sources no longer accept a `logo` option. Instead, if you wish to append a logo to your map, add the desired markup directly in your HTML. In addition, you can use the `attributions` property of a source to display arbitrary markup per-source with the attribution control. +#### Removal of optional this arguments. + +The following methods did get the optional this (i.e. opt_this) arguments removed. Please use closures, the es6 arrow function or the bind method to achieve this effect (Bind is explained here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). + +* Collection#forEach +* geom/LineString#forEachSegment +* Observable#on, #once, #un +* source/TileUTFGrid#forDataAtCoordinateAndResolution +* source/Vector#forEachFeature, #forEachFeatureInExtent, #forEachFeatureIntersectingExtent + ### v4.6.0 #### Renamed `exceedLength` option of `ol.style.Text` to `overflow` diff --git a/src/ol/Collection.js b/src/ol/Collection.js index a0a1d9ae95..dbbdd4c24b 100644 --- a/src/ol/Collection.js +++ b/src/ol/Collection.js @@ -101,18 +101,15 @@ _ol_Collection_.prototype.extend = function(arr) { /** * Iterate over each element, calling the provided callback. - * @param {function(this: S, T, number, Array.): *} f The function to call + * @param {function(T, number, Array.): *} f The function to call * for every element. This function takes 3 arguments (the element, the * index and the array). The return value is ignored. - * @param {S=} opt_this The object to use as `this` in `f`. - * @template S * @api */ -_ol_Collection_.prototype.forEach = function(f, opt_this) { - var fn = (opt_this) ? f.bind(opt_this) : f; +_ol_Collection_.prototype.forEach = function(f) { var array = this.array_; for (var i = 0, ii = array.length; i < ii; ++i) { - fn(array[i], i, array); + f(array[i], i, array); } }; diff --git a/src/ol/Observable.js b/src/ol/Observable.js index 785bd45036..cf69ec5123 100644 --- a/src/ol/Observable.js +++ b/src/ol/Observable.js @@ -91,23 +91,22 @@ _ol_Observable_.prototype.getRevision = function() { * Listen for a certain type of event. * @param {string|Array.} type The event type or array of event types. * @param {function(?): ?} listener The listener function. - * @param {Object=} opt_this The object to use as `this` in `listener`. * @return {ol.EventsKey|Array.} Unique key for the listener. If * called with an array of event types as the first argument, the return * will be an array of keys. * @api */ -_ol_Observable_.prototype.on = function(type, listener, opt_this) { +_ol_Observable_.prototype.on = function(type, listener) { if (Array.isArray(type)) { var len = type.length; var keys = new Array(len); for (var i = 0; i < len; ++i) { - keys[i] = _ol_events_.listen(this, type[i], listener, opt_this); + keys[i] = _ol_events_.listen(this, type[i], listener); } return keys; } else { return _ol_events_.listen( - this, /** @type {string} */ (type), listener, opt_this); + this, /** @type {string} */ (type), listener); } }; @@ -116,23 +115,22 @@ _ol_Observable_.prototype.on = function(type, listener, opt_this) { * Listen once for a certain type of event. * @param {string|Array.} type The event type or array of event types. * @param {function(?): ?} listener The listener function. - * @param {Object=} opt_this The object to use as `this` in `listener`. * @return {ol.EventsKey|Array.} Unique key for the listener. If * called with an array of event types as the first argument, the return * will be an array of keys. * @api */ -_ol_Observable_.prototype.once = function(type, listener, opt_this) { +_ol_Observable_.prototype.once = function(type, listener) { if (Array.isArray(type)) { var len = type.length; var keys = new Array(len); for (var i = 0; i < len; ++i) { - keys[i] = _ol_events_.listenOnce(this, type[i], listener, opt_this); + keys[i] = _ol_events_.listenOnce(this, type[i], listener); } return keys; } else { return _ol_events_.listenOnce( - this, /** @type {string} */ (type), listener, opt_this); + this, /** @type {string} */ (type), listener); } }; @@ -141,18 +139,16 @@ _ol_Observable_.prototype.once = function(type, listener, opt_this) { * Unlisten for a certain type of event. * @param {string|Array.} type The event type or array of event types. * @param {function(?): ?} listener The listener function. - * @param {Object=} opt_this The object which was used as `this` by the - * `listener`. * @api */ -_ol_Observable_.prototype.un = function(type, listener, opt_this) { +_ol_Observable_.prototype.un = function(type, listener) { if (Array.isArray(type)) { for (var i = 0, ii = type.length; i < ii; ++i) { - _ol_events_.unlisten(this, type[i], listener, opt_this); + _ol_events_.unlisten(this, type[i], listener); } return; } else { - _ol_events_.unlisten(this, /** @type {string} */ (type), listener, opt_this); + _ol_events_.unlisten(this, /** @type {string} */ (type), listener); } }; export default _ol_Observable_; diff --git a/src/ol/PluggableMap.js b/src/ol/PluggableMap.js index fd944f22cf..67be92077d 100644 --- a/src/ol/PluggableMap.js +++ b/src/ol/PluggableMap.js @@ -357,7 +357,7 @@ var _ol_PluggableMap_ = function(options) { */ function(control) { control.setMap(this); - }, this); + }.bind(this)); _ol_events_.listen(this.controls, CollectionEventType.ADD, /** @@ -382,7 +382,7 @@ var _ol_PluggableMap_ = function(options) { */ function(interaction) { interaction.setMap(this); - }, this); + }.bind(this)); _ol_events_.listen(this.interactions, CollectionEventType.ADD, /** @@ -400,7 +400,7 @@ var _ol_PluggableMap_ = function(options) { event.element.setMap(null); }, this); - this.overlays_.forEach(this.addOverlayInternal_, this); + this.overlays_.forEach(this.addOverlayInternal_.bind(this)); _ol_events_.listen(this.overlays_, CollectionEventType.ADD, /** diff --git a/src/ol/control/OverviewMap.js b/src/ol/control/OverviewMap.js index 4831fb7536..5936647ca4 100644 --- a/src/ol/control/OverviewMap.js +++ b/src/ol/control/OverviewMap.js @@ -129,7 +129,7 @@ var OverviewMap = function(opt_options) { */ function(layer) { ovmap.addLayer(layer); - }, this); + }.bind(this)); } var box = document.createElement('DIV'); diff --git a/src/ol/geom/LineString.js b/src/ol/geom/LineString.js index 2cf40505fd..b336a56e9c 100644 --- a/src/ol/geom/LineString.js +++ b/src/ol/geom/LineString.js @@ -114,15 +114,13 @@ LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDis * * @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function * called for each segment. - * @param {S=} opt_this The object to be used as the value of 'this' - * within callback. * @return {T|boolean} Value. * @template T,S * @api */ -LineString.prototype.forEachSegment = function(callback, opt_this) { +LineString.prototype.forEachSegment = function(callback) { return _ol_geom_flat_segments_.forEach(this.flatCoordinates, 0, - this.flatCoordinates.length, this.stride, callback, opt_this); + this.flatCoordinates.length, this.stride, callback); }; diff --git a/src/ol/interaction/Modify.js b/src/ol/interaction/Modify.js index 397ff20af6..30934f98a6 100644 --- a/src/ol/interaction/Modify.js +++ b/src/ol/interaction/Modify.js @@ -213,7 +213,7 @@ var _ol_interaction_Modify_ = function(options) { */ this.features_ = features; - this.features_.forEach(this.addFeature_, this); + this.features_.forEach(this.addFeature_.bind(this)); _ol_events_.listen(this.features_, CollectionEventType.ADD, this.handleFeatureAdd_, this); _ol_events_.listen(this.features_, CollectionEventType.REMOVE, diff --git a/src/ol/interaction/Select.js b/src/ol/interaction/Select.js index 5160d05a7d..cb4bee33ab 100644 --- a/src/ol/interaction/Select.js +++ b/src/ol/interaction/Select.js @@ -313,12 +313,12 @@ _ol_interaction_Select_.prototype.setMap = function(map) { var selectedFeatures = this.featureOverlay_.getSource().getFeaturesCollection(); if (currentMap) { - selectedFeatures.forEach(currentMap.unskipFeature, currentMap); + selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap)); } Interaction.prototype.setMap.call(this, map); this.featureOverlay_.setMap(map); if (map) { - selectedFeatures.forEach(map.skipFeature, map); + selectedFeatures.forEach(map.skipFeature.bind(map)); } }; diff --git a/src/ol/interaction/Snap.js b/src/ol/interaction/Snap.js index cf5845699e..02b39e75ee 100644 --- a/src/ol/interaction/Snap.js +++ b/src/ol/interaction/Snap.js @@ -302,7 +302,7 @@ _ol_interaction_Snap_.prototype.setMap = function(map) { if (currentMap) { keys.forEach(_ol_events_.unlistenByKey); keys.length = 0; - features.forEach(this.forEachFeatureRemove_, this); + features.forEach(this.forEachFeatureRemove_.bind(this)); } _ol_interaction_Pointer_.prototype.setMap.call(this, map); @@ -322,7 +322,7 @@ _ol_interaction_Snap_.prototype.setMap = function(map) { this.handleFeatureRemove_, this) ); } - features.forEach(this.forEachFeatureAdd_, this); + features.forEach(this.forEachFeatureAdd_.bind(this)); } }; @@ -613,7 +613,7 @@ _ol_interaction_Snap_.handleEvent_ = function(evt) { _ol_interaction_Snap_.handleUpEvent_ = function(evt) { var featuresToUpdate = _ol_obj_.getValues(this.pendingFeatures_); if (featuresToUpdate.length) { - featuresToUpdate.forEach(this.updateFeature_, this); + featuresToUpdate.forEach(this.updateFeature_.bind(this)); this.pendingFeatures_ = {}; } return false; diff --git a/src/ol/pointer/PointerEventHandler.js b/src/ol/pointer/PointerEventHandler.js index 0b08664cb0..f7dc510e9d 100644 --- a/src/ol/pointer/PointerEventHandler.js +++ b/src/ol/pointer/PointerEventHandler.js @@ -122,7 +122,7 @@ _ol_pointer_PointerEventHandler_.prototype.registerSource = function(name, sourc if (handler) { this.eventMap_[e] = handler.bind(s); } - }, this); + }.bind(this)); this.eventSourceList_.push(s); } }; @@ -178,7 +178,7 @@ _ol_pointer_PointerEventHandler_.prototype.eventHandler_ = function(inEvent) { _ol_pointer_PointerEventHandler_.prototype.addEvents_ = function(events) { events.forEach(function(eventName) { _ol_events_.listen(this.element_, eventName, this.eventHandler_, this); - }, this); + }.bind(this)); }; @@ -190,7 +190,7 @@ _ol_pointer_PointerEventHandler_.prototype.addEvents_ = function(events) { _ol_pointer_PointerEventHandler_.prototype.removeEvents_ = function(events) { events.forEach(function(e) { _ol_events_.unlisten(this.element_, e, this.eventHandler_, this); - }, this); + }.bind(this)); }; diff --git a/src/ol/renderer/webgl/VectorLayer.js b/src/ol/renderer/webgl/VectorLayer.js index cf6c6541e5..5a8ef45505 100644 --- a/src/ol/renderer/webgl/VectorLayer.js +++ b/src/ol/renderer/webgl/VectorLayer.js @@ -292,7 +292,7 @@ _ol_renderer_webgl_VectorLayer_.prototype.prepareFrame = function(frameState, la features.push(feature); }, this); features.sort(vectorLayerRenderOrder); - features.forEach(renderFeature, this); + features.forEach(renderFeature.bind(this)); } else { vectorSource.forEachFeatureInExtent(extent, renderFeature, this); } diff --git a/src/ol/reproj/Tile.js b/src/ol/reproj/Tile.js index 2e826c2438..7feecf1512 100644 --- a/src/ol/reproj/Tile.js +++ b/src/ol/reproj/Tile.js @@ -222,7 +222,7 @@ _ol_reproj_Tile_.prototype.reproject_ = function() { image: tile.getImage() }); } - }, this); + }.bind(this)); this.sourceTiles_.length = 0; if (sources.length === 0) { @@ -281,7 +281,7 @@ _ol_reproj_Tile_.prototype.load = function() { }, this); this.sourcesListenerKeys_.push(sourceListenKey); } - }, this); + }.bind(this)); this.sourceTiles_.forEach(function(tile, i, arr) { var state = tile.getState(); diff --git a/src/ol/reproj/Triangulation.js b/src/ol/reproj/Triangulation.js index 47848b9737..033b0ee8bb 100644 --- a/src/ol/reproj/Triangulation.js +++ b/src/ol/reproj/Triangulation.js @@ -172,7 +172,7 @@ var _ol_reproj_Triangulation_ = function(sourceProj, targetProj, targetExtent, triangle.source = newTriangle; } } - }, this); + }.bind(this)); } transformInvCache = {}; diff --git a/src/ol/source/TileUTFGrid.js b/src/ol/source/TileUTFGrid.js index 0c385b5242..55cca8bfbf 100644 --- a/src/ol/source/TileUTFGrid.js +++ b/src/ol/source/TileUTFGrid.js @@ -124,28 +124,26 @@ _ol_source_TileUTFGrid_.prototype.getTemplate = function() { * in case of an error). * @param {ol.Coordinate} coordinate Coordinate. * @param {number} resolution Resolution. - * @param {function(this: T, *)} callback Callback. - * @param {T=} opt_this The object to use as `this` in the callback. + * @param {function(*)} callback Callback. * @param {boolean=} opt_request If `true` the callback is always async. * The tile data is requested if not yet loaded. - * @template T * @api */ _ol_source_TileUTFGrid_.prototype.forDataAtCoordinateAndResolution = function( - coordinate, resolution, callback, opt_this, opt_request) { + coordinate, resolution, callback, opt_request) { if (this.tileGrid) { var tileCoord = this.tileGrid.getTileCoordForCoordAndResolution( coordinate, resolution); var tile = /** @type {!ol.source.TileUTFGrid.Tile_} */(this.getTile( tileCoord[0], tileCoord[1], tileCoord[2], 1, this.getProjection())); - tile.forDataAtCoordinate(coordinate, callback, opt_this, opt_request); + tile.forDataAtCoordinate(coordinate, callback, null, opt_request); } else { if (opt_request === true) { setTimeout(function() { - callback.call(opt_this, null); + callback(null); }, 0); } else { - callback.call(opt_this, null); + callback(null); } } }; diff --git a/src/ol/source/Vector.js b/src/ol/source/Vector.js index 11eb1bddb9..360451c218 100644 --- a/src/ol/source/Vector.js +++ b/src/ol/source/Vector.js @@ -379,18 +379,17 @@ _ol_source_Vector_.prototype.clear = function(opt_fast) { * with each one. If the callback returns any "truthy" value, iteration will * stop and the function will return the same value. * - * @param {function(this: T, ol.Feature): S} callback Called with each feature + * @param {function(ol.Feature): T} callback Called with each feature * on the source. Return a truthy value to stop iteration. - * @param {T=} opt_this The object to use as `this` in the callback. - * @return {S|undefined} The return value from the last call to the callback. - * @template T,S + * @return {T|undefined} The return value from the last call to the callback. + * @template T * @api */ -_ol_source_Vector_.prototype.forEachFeature = function(callback, opt_this) { +_ol_source_Vector_.prototype.forEachFeature = function(callback) { if (this.featuresRtree_) { - return this.featuresRtree_.forEach(callback, opt_this); + return this.featuresRtree_.forEach(callback); } else if (this.featuresCollection_) { - return this.featuresCollection_.forEach(callback, opt_this); + return this.featuresCollection_.forEach(callback); } }; @@ -402,18 +401,17 @@ _ol_source_Vector_.prototype.forEachFeature = function(callback, opt_this) { * value. * * @param {ol.Coordinate} coordinate Coordinate. - * @param {function(this: T, ol.Feature): S} callback Called with each feature + * @param {function(ol.Feature): T} callback Called with each feature * whose goemetry contains the provided coordinate. - * @param {T=} opt_this The object to use as `this` in the callback. - * @return {S|undefined} The return value from the last call to the callback. - * @template T,S + * @return {T|undefined} The return value from the last call to the callback. + * @template T */ -_ol_source_Vector_.prototype.forEachFeatureAtCoordinateDirect = function(coordinate, callback, opt_this) { +_ol_source_Vector_.prototype.forEachFeatureAtCoordinateDirect = function(coordinate, callback) { var extent = [coordinate[0], coordinate[1], coordinate[0], coordinate[1]]; return this.forEachFeatureInExtent(extent, function(feature) { var geometry = feature.getGeometry(); if (geometry.intersectsCoordinate(coordinate)) { - return callback.call(opt_this, feature); + return callback(feature); } else { return undefined; } @@ -435,18 +433,17 @@ _ol_source_Vector_.prototype.forEachFeatureAtCoordinateDirect = function(coordin * features, equivalent to {@link ol.source.Vector#forEachFeature}. * * @param {ol.Extent} extent Extent. - * @param {function(this: T, ol.Feature): S} callback Called with each feature + * @param {function(ol.Feature): T} callback Called with each feature * whose bounding box intersects the provided extent. - * @param {T=} opt_this The object to use as `this` in the callback. - * @return {S|undefined} The return value from the last call to the callback. - * @template T,S + * @return {T|undefined} The return value from the last call to the callback. + * @template T * @api */ -_ol_source_Vector_.prototype.forEachFeatureInExtent = function(extent, callback, opt_this) { +_ol_source_Vector_.prototype.forEachFeatureInExtent = function(extent, callback) { if (this.featuresRtree_) { - return this.featuresRtree_.forEachInExtent(extent, callback, opt_this); + return this.featuresRtree_.forEachInExtent(extent, callback); } else if (this.featuresCollection_) { - return this.featuresCollection_.forEach(callback, opt_this); + return this.featuresCollection_.forEach(callback); } }; @@ -461,24 +458,23 @@ _ol_source_Vector_.prototype.forEachFeatureInExtent = function(extent, callback, * source.forEachFeatureInExtent()} method instead. * * @param {ol.Extent} extent Extent. - * @param {function(this: T, ol.Feature): S} callback Called with each feature + * @param {function(ol.Feature): T} callback Called with each feature * whose geometry intersects the provided extent. - * @param {T=} opt_this The object to use as `this` in the callback. - * @return {S|undefined} The return value from the last call to the callback. - * @template T,S + * @return {T|undefined} The return value from the last call to the callback. + * @template T * @api */ -_ol_source_Vector_.prototype.forEachFeatureIntersectingExtent = function(extent, callback, opt_this) { +_ol_source_Vector_.prototype.forEachFeatureIntersectingExtent = function(extent, callback) { return this.forEachFeatureInExtent(extent, /** * @param {ol.Feature} feature Feature. - * @return {S|undefined} The return value from the last call to the callback. - * @template S + * @return {T|undefined} The return value from the last call to the callback. + * @template T */ function(feature) { var geometry = feature.getGeometry(); if (geometry.intersectsExtent(extent)) { - var result = callback.call(opt_this, feature); + var result = callback(feature); if (result) { return result; } diff --git a/test/spec/ol/collection.test.js b/test/spec/ol/collection.test.js index 54546a1f29..7d95628bb7 100644 --- a/test/spec/ol/collection.test.js +++ b/test/spec/ol/collection.test.js @@ -106,17 +106,6 @@ describe('ol.collection', function() { expect(cb.callCount).to.eql(2); }); }); - describe('scope', function() { - it('callbacks get the correct scope', function() { - var collection = new _ol_Collection_([0]); - var that; - var uniqueObj = {}; - collection.forEach(function(elem) { - that = this; - }, uniqueObj); - expect(that).to.be(uniqueObj); - }); - }); }); describe('remove', function() { diff --git a/test/spec/ol/observable.test.js b/test/spec/ol/observable.test.js index d3480caae4..b750cb0a24 100644 --- a/test/spec/ol/observable.test.js +++ b/test/spec/ol/observable.test.js @@ -41,15 +41,6 @@ describe('ol.Observable', function() { expect(listener.callCount).to.be(2); }); - it('accepts an optional `this` arg for the listener', function() { - var thisArg = {}; - observable.on('foo', listener, thisArg); - - observable.dispatchEvent('foo'); - expect(listener.calledOnce).to.be(true); - expect(listener.calledOn(thisArg)).to.be(true); - }); - it('returns a listener key', function() { var key = observable.on('foo', listener); @@ -106,15 +97,6 @@ describe('ol.Observable', function() { expect(listener.callCount).to.be(2); }); - it('accepts an optional `this` arg for the listener', function() { - var thisArg = {}; - observable.once('foo', listener, thisArg); - - observable.dispatchEvent('foo'); - expect(listener.calledOnce).to.be(true); - expect(listener.calledOn(thisArg)).to.be(true); - }); - it('returns a listener key', function() { var key = observable.once('foo', listener); @@ -141,24 +123,6 @@ describe('ol.Observable', function() { expect(listener.calledOnce).to.be(true); }); - it('accepts a `this` arg', function() { - var thisArg = {}; - observable.on('foo', listener, thisArg); - - observable.dispatchEvent('foo'); - expect(listener.calledOnce).to.be(true); - - // will not unregister without the same thisArg - observable.un('foo', listener); - observable.dispatchEvent('foo'); - expect(listener.callCount).to.be(2); - - // properly unregister by providing the same thisArg - observable.un('foo', listener, thisArg); - observable.dispatchEvent('foo'); - expect(listener.callCount).to.be(2); - }); - }); describe('ol.Observable.unByKey()', function() { diff --git a/test/spec/ol/source/tileutfgrid.test.js b/test/spec/ol/source/tileutfgrid.test.js index 84a3d9c31f..5e9055da98 100644 --- a/test/spec/ol/source/tileutfgrid.test.js +++ b/test/spec/ol/source/tileutfgrid.test.js @@ -253,18 +253,7 @@ describe('ol.source.TileUTFGrid', function() { done(); }; source.forDataAtCoordinateAndResolution( - bonn3857, resolutionZoom1, callback, null, true - ); - }); - - it('calls callback with correct `this` bound', function(done) { - var scope = {foo: 'bar'}; - var callback = function(data) { - expect(this).to.be(scope); - done(); - }; - source.forDataAtCoordinateAndResolution( - bonn3857, resolutionZoom1, callback, scope, true + bonn3857, resolutionZoom1, callback, true ); }); @@ -275,7 +264,7 @@ describe('ol.source.TileUTFGrid', function() { done(); }; source.forDataAtCoordinateAndResolution( - noState3857, resolutionZoom1, callback, null, true + noState3857, resolutionZoom1, callback, true ); });