Merge branch 'master' into release-v3.19.1

This commit is contained in:
Andreas Hocevar
2016-10-28 14:21:34 +02:00
13 changed files with 165 additions and 162 deletions

View File

@@ -1,7 +1,7 @@
# OpenLayers 3
[![Travis CI Status](https://secure.travis-ci.org/openlayers/ol3.svg)](http://travis-ci.org/#!/openlayers/ol3)
[![Coverage Status](https://coveralls.io/repos/openlayers/ol3/badge.svg?branch=master)](https://coveralls.io/r/openlayers/ol3?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/openlayers/ol3/badge.svg?branch=master)](https://coveralls.io/github/openlayers/ol3?branch=master)
[![OSGeo Project](https://img.shields.io/badge/OSGeo-Project-brightgreen.svg)](http://osgeo.org/)
[OpenLayers 3](https://openlayers.org/) is a high-performance, feature-packed library for creating interactive maps on the web. It can display map tiles, vector data and markers loaded from any source on any web page. OpenLayers has been developed to further the use of geographic information of all kinds. It is completely free, Open Source JavaScript, released under the 2-clause BSD License (also known as the FreeBSD).

View File

@@ -9,7 +9,7 @@ If you're eager to get your first OpenLayers 3 map on a page, dive into the [qui
For a more in-depth overview of OpenLayers 3 core concepts, check out the [tutorials](tutorials/).
Make sure to also check out the [OpenLayers 3 workshop](/workshop/en/).
Make sure to also check out the [OpenLayers 3 workshop](/workshop/).
Find additional reference material in the [API docs](../apidoc).

View File

@@ -2935,6 +2935,7 @@ olx.interaction.ModifyOptions.prototype.wrapX;
/**
* @typedef {{duration: (number|undefined),
* timeout: (number|undefined),
* useAnchor: (boolean|undefined)}}
*/
olx.interaction.MouseWheelZoomOptions;
@@ -2948,6 +2949,14 @@ olx.interaction.MouseWheelZoomOptions;
olx.interaction.MouseWheelZoomOptions.prototype.duration;
/**
* Mouse wheel timeout duration in milliseconds. Default is `80`.
* @type {number|undefined}
* @api
*/
olx.interaction.MouseWheelZoomOptions.prototype.timeout;
/**
* Enable zooming using the mouse's location as the anchor. Default is `true`.
* When set to false, zooming in and out will zoom to the center of the screen

View File

@@ -31,7 +31,7 @@
],
"dependencies": {
"async": "2.1.2",
"browserify": "13.1.0",
"browserify": "13.1.1",
"closure-util": "1.15.1",
"derequire": "2.0.3",
"fs-extra": "0.30.0",
@@ -39,7 +39,7 @@
"handlebars": "4.0.5",
"jsdoc": "3.4.2",
"marked": "0.3.6",
"metalsmith": "2.2.0",
"metalsmith": "2.2.1",
"metalsmith-layouts": "1.6.5",
"nomnom": "1.8.1",
"pbf": "3.0.2",

View File

@@ -307,18 +307,6 @@ ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
};
/**
* Empty an extent in place.
* @param {ol.Extent} extent Extent.
* @return {ol.Extent} Extent.
*/
ol.extent.empty = function(extent) {
extent[0] = extent[1] = Infinity;
extent[2] = extent[3] = -Infinity;
return extent;
};
/**
* Determine if two extents are equivalent.
* @param {ol.Extent} extent1 Extent 1.
@@ -720,29 +708,6 @@ ol.extent.isEmpty = function(extent) {
};
/**
* @param {ol.Extent} extent Extent.
* @return {boolean} Is infinite.
*/
ol.extent.isInfinite = function(extent) {
return extent[0] == -Infinity || extent[1] == -Infinity ||
extent[2] == Infinity || extent[3] == Infinity;
};
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Coordinate} coordinate Coordinate.
* @return {ol.Coordinate} Coordinate.
*/
ol.extent.normalize = function(extent, coordinate) {
return [
(coordinate[0] - extent[0]) / (extent[2] - extent[0]),
(coordinate[1] - extent[1]) / (extent[3] - extent[1])
];
};
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Extent=} opt_extent Extent.
@@ -831,19 +796,6 @@ ol.extent.intersectsSegment = function(extent, start, end) {
};
/**
* @param {ol.Extent} extent1 Extent 1.
* @param {ol.Extent} extent2 Extent 2.
* @return {boolean} Touches.
*/
ol.extent.touches = function(extent1, extent2) {
var intersects = ol.extent.intersects(extent1, extent2);
return intersects &&
(extent1[0] == extent2[2] || extent1[2] == extent2[0] ||
extent1[1] == extent2[3] || extent1[3] == extent2[1]);
};
/**
* Apply a transform function to the extent.
* @param {ol.Extent} extent Extent.

View File

@@ -142,12 +142,6 @@ ol.MAX_ATLAS_SIZE = -1;
ol.MOUSEWHEELZOOM_MAXDELTA = 1;
/**
* @define {number} Mouse wheel timeout duration.
*/
ol.MOUSEWHEELZOOM_TIMEOUT_DURATION = 80;
/**
* @define {number} Maximum width and/or height extent ratio that determines
* when the overview map should be zoomed out.

View File

@@ -36,6 +36,12 @@ ol.interaction.MouseWheelZoom = function(opt_options) {
*/
this.duration_ = options.duration !== undefined ? options.duration : 250;
/**
* @private
* @type {number}
*/
this.timeout_ = options.timeout !== undefined ? options.timeout : 80;
/**
* @private
* @type {boolean}
@@ -109,8 +115,7 @@ ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) {
this.startTime_ = Date.now();
}
var duration = ol.MOUSEWHEELZOOM_TIMEOUT_DURATION;
var timeLeft = Math.max(duration - (Date.now() - this.startTime_), 0);
var timeLeft = Math.max(this.timeout_ - (Date.now() - this.startTime_), 0);
clearTimeout(this.timeoutId_);
this.timeoutId_ = setTimeout(

View File

@@ -55,10 +55,25 @@ ol.source.TileArcGISRest = function(opt_options) {
*/
this.tmpExtent_ = ol.extent.createEmpty();
this.setKey(this.getKeyForParams_());
};
ol.inherits(ol.source.TileArcGISRest, ol.source.TileImage);
/**
* @private
* @return {string} The key for the current params.
*/
ol.source.TileArcGISRest.prototype.getKeyForParams_ = function() {
var i = 0;
var res = [];
for (var key in this.params_) {
res[i++] = key + '-' + this.params_[key];
}
return res.join('/');
};
/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
@@ -168,5 +183,5 @@ ol.source.TileArcGISRest.prototype.fixedTileUrlFunction = function(tileCoord, pi
*/
ol.source.TileArcGISRest.prototype.updateParams = function(params) {
ol.obj.assign(this.params_, params);
this.changed();
this.setKey(this.getKeyForParams_());
};

View File

@@ -20,6 +20,8 @@ var backupDir = path.join(__dirname, '../src-backup');
var instrumentedDir = path.join(__dirname, '../src-instrumented');
var coverageDir = path.join(__dirname, '../coverage');
fs.mkdirSync(coverageDir);
// The main players in the coverage generation via istanbul
var instrumenter = new istanbul.Instrumenter();
var reporter = new istanbul.Reporter(false, coverageDir);
@@ -76,16 +78,23 @@ var revertBackupAndInstrumentationDir = function() {
fs.removeSync(instrumentedDir);
};
/**
* Callback for when runTestsuite() has finished.
*/
var collectAndWriteCoverageData = function() {
log('• collect data from coverage.json');
log('• collect data from coverage *.json files');
var coverageFile = path.join(__dirname,'../coverage/coverage.json');
var coverageJson = JSON.parse(fs.readFileSync(coverageFile, 'utf8'));
collector.add(coverageJson);
var coverageFiles = [
path.join(__dirname, '..', 'coverage', 'coverage.json'),
path.join(__dirname, '..', 'coverage', 'coverage-rendering.json')
];
coverageFiles.forEach(function(coverageFile) {
if (fs.existsSync(coverageFile)) {
log(' • collect data from ' + path.basename(coverageFile));
var coverageJson = JSON.parse(fs.readFileSync(coverageFile, 'utf8'));
collector.add(coverageJson);
}
});
reporter.addAll(['lcovonly','html']);
@@ -97,6 +106,44 @@ var collectAndWriteCoverageData = function() {
});
};
/**
* Runs the rendering test by spawning a call to `make test-rendering`. The
* `make`-call sets up certain things so that the rendering tests can actually
* run, which is why we call it this way.
*
* @param {Function} callback The callback to invoke once `make` has exited.
* Will receive the exit code.
*/
var runRenderingTestsuite = function(callback) {
var spawn = require('child_process').spawn;
var child = spawn('make', ['test-rendering'], {stdio: 'inherit'});
child.on('exit', function(code) {
callback(code);
});
};
/**
* Derive output file name from input file name, by replacing the *last*
* occurence of `/src/` by `/src-instrumented/`
*
* @param {String} file The input filename.
* @return {String} file The output filename.
*/
var outputFilenameByFilename = function(file) {
var search = '/src/';
var replace = '/src-instrumented/';
var re = new RegExp(search, 'g');
var m, match;
while ((m = re.exec(file)) !== null) {
match = m;
}
var idx = match.index;
var outfile = file.substr(0, idx) + replace +
file.substr(idx + search.length);
return outfile;
};
/**
* Will instrument all JavaScript files that are passed as second parameter.
* This is the callback to the glob call.
@@ -113,15 +160,7 @@ var foundAllJavaScriptSourceFiles = function(err, files) {
files.forEach(function(file) {
cnt++;
var content = fs.readFileSync(file, 'utf-8');
// derive output file name from input file name, by replacing the *last*
// occurence of /src/ by /src-instrumented/
var re = new RegExp('/src/', 'g');
var m, match;
while ((m = re.exec(file)) !== null) {
match = m;
}
var outfile = file.substr(0, match.index) + '/src-instrumented/' +
file.substr(match.index + '/src/'.length);
var outfile = outputFilenameByFilename(file);
var instrumented = instrumenter.instrumentSync(content, file);
fs.writeFileSync(outfile, instrumented);
if (cnt % 10 === 0) {
@@ -133,8 +172,25 @@ var foundAllJavaScriptSourceFiles = function(err, files) {
fs.copySync(instrumentedDir, dir, copyOpts);
log('• run test suite on instrumented code');
runTestsuite({coverage: true, reporter: 'dot'}, collectAndWriteCoverageData);
log('• run test suites on instrumented code');
log(' • run rendering test suite');
runRenderingTestsuite(function(codeRendering) {
if (codeRendering === 0) {
log(' • run standard test suite');
runTestsuite({coverage: true, reporter: 'dot'}, function(code) {
if (code === 0) {
collectAndWriteCoverageData();
} else {
process.stderr.write('Trouble running the standard testsuite\n');
process.exit(1);
}
});
} else {
process.stderr.write('Trouble running the rendering testsuite\n');
process.exit(1);
}
});
};
/**

View File

@@ -167,24 +167,6 @@ describe('ol.extent', function() {
});
describe('empty', function() {
it('returns the empty extent', function() {
var extent = [1, 2, 3, 4];
var expected = [Infinity, Infinity, -Infinity, -Infinity];
var got = ol.extent.empty(extent);
expect(got).to.eql(expected);
});
it('empties a passed extent in place', function() {
var extent = [1, 2, 3, 4];
var expected = [Infinity, Infinity, -Infinity, -Infinity];
ol.extent.empty(extent);
expect(extent).to.eql(expected);
});
});
describe('forEachCorner', function() {
var callbackFalse;
@@ -602,73 +584,6 @@ describe('ol.extent', function() {
});
});
describe('isInfinite', function() {
it('returns true for infinite extents', function() {
var extents = [
[-Infinity, 0, 0, 0],
[0, -Infinity, 0, 0],
[0, 0, +Infinity, 0],
[0, 0, 0, +Infinity]
];
expect(ol.extent.isInfinite(extents[0])).to.be(true);
expect(ol.extent.isInfinite(extents[1])).to.be(true);
expect(ol.extent.isInfinite(extents[2])).to.be(true);
expect(ol.extent.isInfinite(extents[3])).to.be(true);
});
it('returns false for other extents', function() {
var extents = [
ol.extent.createEmpty(),
[1, 2, 3, 4]
];
expect(ol.extent.isInfinite(extents[0])).to.be(false);
expect(ol.extent.isInfinite(extents[1])).to.be(false);
});
});
describe('touches', function() {
it('returns the expected value', function() {
var touches = ol.extent.touches;
var extent = [50, 50, 100, 100];
expect(touches(extent, [20, 20, 80, 80])).to.be(false);
expect(touches(extent, [20, 20, 50, 80])).to.be(true);
expect(touches(extent, [20, 20, 50, 40])).to.be(false);
expect(touches(extent, [100, 20, 140, 80])).to.be(true);
expect(touches(extent, [100, 20, 140, 40])).to.be(false);
expect(touches(extent, [20, 20, 80, 50])).to.be(true);
expect(touches(extent, [20, 20, 40, 50])).to.be(false);
expect(touches(extent, [20, 100, 80, 140])).to.be(true);
expect(touches(extent, [20, 100, 40, 140])).to.be(false);
});
});
describe('normalize', function() {
it('returns the expected coordinate', function() {
var extent = [0, 1, 2, 3];
var coordinate;
coordinate = ol.extent.normalize(extent, [1, 2]);
expect(coordinate[0]).to.eql(0.5);
expect(coordinate[1]).to.eql(0.5);
coordinate = ol.extent.normalize(extent, [0, 3]);
expect(coordinate[0]).to.eql(0);
expect(coordinate[1]).to.eql(1);
coordinate = ol.extent.normalize(extent, [2, 1]);
expect(coordinate[0]).to.eql(1);
expect(coordinate[1]).to.eql(0);
coordinate = ol.extent.normalize(extent, [0, 0]);
expect(coordinate[0]).to.eql(0);
expect(coordinate[1]).to.eql(-0.5);
coordinate = ol.extent.normalize(extent, [-1, 1]);
expect(coordinate[0]).to.eql(-0.5);
expect(coordinate[1]).to.eql(0);
});
});
describe('scaleFromCenter', function() {
it('scales the extent from its center', function() {
var extent = [1, 1, 3, 3];

View File

@@ -27,6 +27,36 @@ describe('ol.interaction.MouseWheelZoom', function() {
disposeMap(map);
});
describe('timeout duration', function() {
var clock;
beforeEach(function() {
clock = sinon.useFakeTimers();
});
afterEach(function() {
clock.restore();
});
it('works with the defaut value', function(done) {
var spy = sinon.spy(ol.interaction.Interaction, 'zoomByDelta');
var event = new ol.MapBrowserEvent('mousewheel', map, {
type: 'mousewheel',
target: map.getViewport(),
preventDefault: ol.events.Event.prototype.preventDefault
});
map.handleMapBrowserEvent(event);
clock.tick(50);
// default timeout is 80 ms, not called yet
expect(spy.called).to.be(false);
clock.tick(30);
expect(spy.called).to.be(true);
ol.interaction.Interaction.zoomByDelta.restore();
done();
});
});
describe('handleEvent()', function() {
it('[wheel] works on Firefox in DOM_DELTA_PIXEL mode', function(done) {
var origHasFirefox = ol.has.FIREFOX;

View File

@@ -31,6 +31,18 @@ describe('ol.obj.assign()', function() {
});
it('throws a TypeError with `undefined` as target', function() {
expect(ol.obj.assign).withArgs(undefined).to.throwException(function(e) {
expect(e).to.be.a(TypeError);
});
});
it('throws a TypeError with `null` as target', function() {
expect(ol.obj.assign).withArgs(null).to.throwException(function(e) {
expect(e).to.be.a(TypeError);
});
});
});
describe('ol.obj.clear()', function() {

View File

@@ -19,8 +19,23 @@ page.open(url).then(function(status) {
}
console.error(failedTests.length + ' test(s) failed.');
} else {
// check for cov here
var coverage = page.evaluate(function() {
return window.__coverage__;
});
if (coverage) {
console.log('Writing coverage to coverage/coverage-rendering.json');
var fs = require('fs');
fs.write(
fs.workingDirectory + '/coverage/coverage-rendering.json',
JSON.stringify(coverage),
'w'
);
}
console.log('All tests passed.');
}
page.close();
phantom.exit(failedTests.length === 0 ? 0 : 1);
};