datahub/test/view.map.test.js
amercader 50b33f3ccf Change default tiles for map view, allow customization
After the MapQuest debacle, there was a patch merged that replaced the
MapQuest tiles with the OpenStreetMap ones (#501). IMO these are not a
good default choice because while they might be fine for a small Recline
project, heavy usage of them goes against their Terms of Use:

http://wiki.openstreetmap.org/wiki/Tile_usage_policy

More specifically:

> Heavy use (e.g. distributing an app that uses tiles from openstreetmap.org)
> is forbidden without prior permission from the System Administrators

Popular CKAN instances that use Recline are likely to fall in this
category.

And also:

> Highly Recommended: Do not hardcode any URL at tile.openstreetmap.org
> into an app.

This patch replaces the tiles with the Terrain tileset from Stamen
(http://maps.stamen.com), which have more liberal terms.

But more crucially, as this is something that different people will have
different views on, it allows you to configure the tiles used by passing
custom options to the view constructor, eg:

    view = new recline.View.Map({
        model: dataset,
        mapTilesURL: '//{s}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/{z}/{x}/{y}.png?access_token=pk.XXXX',
        mapTilesAttribution: '© MapBox etc..',
        mapTilesSubdomains: 'ab'
    })

So everybody (and apps integrating Recline like CKAN) can configure the tiles
as they want.
2016-08-03 10:52:01 +01:00

285 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function ($) {
module("View - Map");
var GeoJSONFixture = {
getDataset: function() {
var fields = [
{id: 'id'},
{id: 'x'},
{id: 'y'},
{id: 'z'},
{id: 'geom'}
];
var records = [
{id: 0, x: 1, y: 2, z: 3, geom: '{"type":"Point","coordinates":[13.40,52.35]}'},
{id: 1, x: 2, y: 4, z: 6, geom: {type:"Point",coordinates:[13.40,52.35]}},
{id: 2, x: 3, y: 6, z: 9, geom: {type:"LineString",coordinates:[[100.0, 0.0],[101.0, 1.0]]}}
];
var dataset = new recline.Model.Dataset({
records: records,
fields: fields
});
return dataset;
}
};
test('basics', function () {
var dataset = Fixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.render();
assertPresent('.editor-field-type', view.elSidebar);
// Check that the Leaflet map was set up
assertPresent('.leaflet-container',view.el);
ok(view.map instanceof L.Map);
ok(view.features instanceof L.GeoJSON);
view.remove();
});
test('_setupGeometryField', function () {
var dataset = Fixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
view.render();
var exp = {
geomField: null,
lonField: 'lon',
latField: 'lat',
autoZoom: true,
cluster: false
};
deepEqual(view.state.toJSON(), exp);
deepEqual(view.menu.state.toJSON(), exp);
});
test('Lat/Lon geom fields', function () {
var dataset = Fixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.render();
// Not really needed but fire query to test that resetting works!
dataset.query();
// Check that all markers were created
equal(_getFeaturesCount(view.features),6);
// Delete a record
view.model.records.remove(view.model.records.get('1'));
equal(_getFeaturesCount(view.features),5);
// Add a new one
view.model.records.add({id: 7, x: 7, y: 14, z: 21, country: 'KX', label: 'seventh', lat:13.23, lon:23.56}),
equal(_getFeaturesCount(view.features),6);
view.remove();
});
test('GeoJSON geom field', function () {
var dataset = GeoJSONFixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.render();
// Check that all features were created
equal(_getFeaturesCount(view.features),3);
// Delete a record
view.model.records.remove(view.model.records.get('2'));
equal(_getFeaturesCount(view.features),2);
// Add it back
view.model.records.add({id: 2, x: 3, y: 6, z: 9, geom: {type:"LineString",coordinates:[[100.0, 0.0],[101.0, 1.0]]}}),
equal(_getFeaturesCount(view.features),3);
view.remove();
});
test('_getGeometryFromRecord non-GeoJSON', function () {
var test = [
[{ lon: 47, lat: 53}, [47,53]],
[{ lon: -47, lat: 53}, [-47,53]],
["53.3,47.32", [47.32, 53.3]],
["53.3,-47.32", [-47.32, 53.3]],
["53.3, 47.32", [47.32, 53.3]],
["-53.3, 47.32", [47.32, -53.3]],
["53.3, -47.32", [-47.32, 53.3]],
["(53.3,47.32)", [47.32, 53.3]],
[[53.3,47.32], [53.3, 47.32]],
["53.3 N, 113.5 W", [-113.5, 53.3]],
["53° 18' N, 113° 30' W", [-113.5, 53.3 ]],
["22°4590″S, 43°1545″W", [-43.2625, -22.775]]
];
var view = new recline.View.Map({
model: new recline.Model.Dataset({
records: [{a: 1}]
}),
state: {
geomField: 'location'
}
});
_.each(test, function(item) {
var record = new recline.Model.Record({location: item[0]});
var out = view._getGeometryFromRecord(record);
deepEqual(out.coordinates, item[1]);
});
});
test('many markers and clustering', function () {
var data = [];
for (var i = 0; i<1000; i++) {
data.push({ id: i, lon: 13+3*i, lat: 52+i/10});
}
var fields = [
{id: 'id'},
{id: 'lat'},
{id: 'lon'}
];
var dataset = new recline.Model.Dataset({records: data, fields: fields});
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.render();
dataset.query();
// this whole test looks a bit odd now
// we used to turn on clustering automatically at a certain level but we do not any more
equal(view.state.get('cluster'), false);
view.state.set({cluster: true});
equal(view.state.get('cluster'), true);
view.remove();
});
test('Popup', function () {
var dataset = GeoJSONFixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.render();
var marker = view.$el.find('.leaflet-marker-icon').first();
assertPresent(marker);
_.values(view.features._layers)[0].fire('click');
var popup = view.$el.find('.leaflet-popup-content');
assertPresent(popup);
var text = popup.text();
ok((text.indexOf('geom') === -1))
_.each(view.model.fields.toJSON(),function(field){
if (field.id != 'geom'){
ok((text.indexOf(field.id) !== -1))
}
});
view.remove();
});
test('Popup - Custom', function (assert) {
var dataset = GeoJSONFixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.infobox = function(record) {
var html = Mustache.render('<h3>{{x}}</h3>y: {{y}}', record.toJSON());
return html;
};
view.render();
var marker = view.$el.find('.leaflet-marker-icon').first();
_.values(view.features._layers)[0].fire('click');
var popup = view.$el.find('.leaflet-popup-content');
assertPresent(popup);
var text = popup.html();
assert.htmlEqual(text, '<h3>1</h3>y: 2');
view.remove();
});
test('geoJsonLayerOptions', function () {
var dataset = GeoJSONFixture.getDataset();
var view = new recline.View.Map({
model: dataset
});
$('.fixtures').append(view.el);
view.geoJsonLayerOptions.point
view.geoJsonLayerOptions.pointToLayer = function(feature, latlng) {
var marker = new L.CircleMarker(latlng, { radius: 8 } );
marker.bindPopup(feature.properties.popupContent);
return marker;
}
view.render();
// TODO: test it somehow?
expect(0);
view.remove();
});
test('MapMenu', function () {
var dataset = Fixture.getDataset();
var controls = new recline.View.MapMenu({
model: dataset,
state: {}
});
assertPresent('.editor-field-type', controls.el);
});
test('Custom map options', function () {
var dataset = GeoJSONFixture.getDataset();
var view = new recline.View.Map({
model: dataset,
mapTilesURL: 'http://example.com/{z}/{y}/{x}.png',
mapTilesAttribution: '&copy; MyTiles',
mapTilesSubdomains: 'ab'
});
$('.fixtures').append(view.el);
view.render();
var tiles = view.$el.find('.leaflet-tile-pane');
assertPresent(tiles);
ok(tiles.find('.leaflet-tile')[0].src.startsWith('http://example.com'));
ok(view.$el.find('.leaflet-control-attribution').text().indexOf('MyTiles') !== -1);
view.remove();
});
var _getFeaturesCount = function(features){
var cnt = 0;
_.each(features._layers, function(layer) {
cnt++;
});
return cnt;
}
})(this.jQuery);