mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-18 14:45:12 +02:00
Move the data layers section to its own object (re: #7368)
This commit is contained in:
+28
-509
@@ -1,522 +1,18 @@
|
||||
import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
event as d3_event
|
||||
} from 'd3-selection';
|
||||
|
||||
import { svgIcon } from '../../svg/icon';
|
||||
import { t, textDirection } from '../../util/locale';
|
||||
import { tooltip } from '../../util/tooltip';
|
||||
import { geoExtent } from '../../geo';
|
||||
import { t } from '../../util/locale';
|
||||
import { modeBrowse } from '../../modes/browse';
|
||||
import { uiDisclosure } from '../disclosure';
|
||||
import { uiSettingsCustomData } from '../settings/custom_data';
|
||||
import { uiTooltipHtml } from '../tooltipHtml';
|
||||
import { uiCmd } from '../cmd';
|
||||
import { uiPane } from '../pane';
|
||||
|
||||
import { uiSectionDataLayers } from '../sections/data_layers';
|
||||
import { uiSectionMapFeatures } from '../sections/map_features';
|
||||
import { uiSectionMapStyleOptions } from '../sections/map_style_options';
|
||||
import { uiSectionPhotoOverlays } from '../sections/photo_overlays';
|
||||
|
||||
export function uiPaneMapData(context) {
|
||||
var osmDataToggleKey = uiCmd('⌥' + t('area_fill.wireframe.key'));
|
||||
var layers = context.layers();
|
||||
|
||||
var settingsCustomData = uiSettingsCustomData(context)
|
||||
.on('change', customChanged);
|
||||
|
||||
var _dataLayerContainer = d3_select(null);
|
||||
var _QAList = d3_select(null);
|
||||
|
||||
var _photoOverlaysSection = uiSectionPhotoOverlays(context);
|
||||
var _mapStyleOptionsSection = uiSectionMapStyleOptions(context);
|
||||
var _mapFeaturesSection = uiSectionMapFeatures(context);
|
||||
|
||||
|
||||
function showsQA(d) {
|
||||
var QAKeys = [d];
|
||||
var QALayers = layers.all().filter(function(obj) { return QAKeys.indexOf(obj.id) !== -1; });
|
||||
var data = QALayers.filter(function(obj) { return obj.layer.supported(); });
|
||||
|
||||
function layerSupported(d) {
|
||||
return d.layer && d.layer.supported();
|
||||
}
|
||||
function layerEnabled(d) {
|
||||
return layerSupported(d) && d.layer.enabled();
|
||||
}
|
||||
|
||||
return layerEnabled(data[0]);
|
||||
}
|
||||
|
||||
|
||||
function showsLayer(which) {
|
||||
var layer = layers.layer(which);
|
||||
if (layer) {
|
||||
return layer.enabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function setLayer(which, enabled) {
|
||||
// Don't allow layer changes while drawing - #6584
|
||||
var mode = context.mode();
|
||||
if (mode && /^draw/.test(mode.id)) return;
|
||||
|
||||
var layer = layers.layer(which);
|
||||
if (layer) {
|
||||
layer.enabled(enabled);
|
||||
|
||||
if (!enabled && (which === 'osm' || which === 'notes')) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function toggleLayer(which) {
|
||||
setLayer(which, !showsLayer(which));
|
||||
}
|
||||
|
||||
|
||||
function drawOsmItems(selection) {
|
||||
var osmKeys = ['osm', 'notes'];
|
||||
var osmLayers = layers.all().filter(function(obj) { return osmKeys.indexOf(obj.id) !== -1; });
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-osm')
|
||||
.data([0]);
|
||||
|
||||
ul = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-osm')
|
||||
.merge(ul);
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(osmLayers);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.id; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
if (d.id === 'osm') {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.html(true)
|
||||
.title(uiTooltipHtml(t('map_data.layers.' + d.id + '.tooltip'), osmDataToggleKey))
|
||||
.placement('bottom')
|
||||
);
|
||||
} else {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.' + d.id + '.tooltip'))
|
||||
.placement('bottom')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function(d) { toggleLayer(d.id); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return t('map_data.layers.' + d.id + '.title'); });
|
||||
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', function (d) { return d.layer.enabled(); })
|
||||
.selectAll('input')
|
||||
.property('checked', function (d) { return d.layer.enabled(); });
|
||||
}
|
||||
|
||||
|
||||
function drawQAItems(selection) {
|
||||
var qaKeys = ['keepRight', 'improveOSM', 'osmose'];
|
||||
var qaLayers = layers.all().filter(function(obj) { return qaKeys.indexOf(obj.id) !== -1; });
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-qa')
|
||||
.data([0]);
|
||||
|
||||
ul = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-qa')
|
||||
.merge(ul);
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(qaLayers);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.id; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.' + d.id + '.tooltip'))
|
||||
.placement('bottom')
|
||||
);
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function(d) { toggleLayer(d.id); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return t('map_data.layers.' + d.id + '.title'); });
|
||||
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', function (d) { return d.layer.enabled(); })
|
||||
.selectAll('input')
|
||||
.property('checked', function (d) { return d.layer.enabled(); });
|
||||
}
|
||||
|
||||
|
||||
// Beta feature - sample vector layers to support Detroit Mapping Challenge
|
||||
// https://github.com/osmus/detroit-mapping-challenge
|
||||
function drawVectorItems(selection) {
|
||||
var dataLayer = layers.layer('data');
|
||||
var vtData = [
|
||||
{
|
||||
name: 'Detroit Neighborhoods/Parks',
|
||||
src: 'neighborhoods-parks',
|
||||
tooltip: 'Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmur6x34562qp9iv1u3ksf-54hev,jonahadkins.cjksmqxdx33jj2wp90xd9x2md-4e5y2/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}, {
|
||||
name: 'Detroit Composite POIs',
|
||||
src: 'composite-poi',
|
||||
tooltip: 'Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmm6a02sli31myxhsr7zf3-2sw8h/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}, {
|
||||
name: 'Detroit All-The-Places POIs',
|
||||
src: 'alltheplaces-poi',
|
||||
tooltip: 'Public domain business location data created by web scrapers.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmswgk340g2vo06p1w9w0j-8fjjc/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}
|
||||
];
|
||||
|
||||
// Only show this if the map is around Detroit..
|
||||
var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
|
||||
var showVectorItems = (context.map().zoom() > 9 && detroit.contains(context.map().center()));
|
||||
|
||||
var container = selection.selectAll('.vectortile-container')
|
||||
.data(showVectorItems ? [0] : []);
|
||||
|
||||
container.exit()
|
||||
.remove();
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'vectortile-container');
|
||||
|
||||
containerEnter
|
||||
.append('h4')
|
||||
.attr('class', 'vectortile-header')
|
||||
.text('Detroit Vector Tiles (Beta)');
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-vectortile');
|
||||
|
||||
containerEnter
|
||||
.append('div')
|
||||
.attr('class', 'vectortile-footer')
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#iD-icon-out-link', 'inline'))
|
||||
.attr('href', 'https://github.com/osmus/detroit-mapping-challenge')
|
||||
.append('span')
|
||||
.text('About these layers');
|
||||
|
||||
container = container
|
||||
.merge(containerEnter);
|
||||
|
||||
|
||||
var ul = container.selectAll('.layer-list-vectortile');
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(vtData);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.src; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
d3_select(this).call(
|
||||
tooltip().title(d.tooltip).placement('top')
|
||||
);
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'radio')
|
||||
.attr('name', 'vectortile')
|
||||
.on('change', selectVTLayer);
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return d.name; });
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', isVTLayerSelected)
|
||||
.selectAll('input')
|
||||
.property('checked', isVTLayerSelected);
|
||||
|
||||
|
||||
function isVTLayerSelected(d) {
|
||||
return dataLayer && dataLayer.template() === d.template;
|
||||
}
|
||||
|
||||
function selectVTLayer(d) {
|
||||
context.storage('settings-custom-data-url', d.template);
|
||||
if (dataLayer) {
|
||||
dataLayer.template(d.template, d.src);
|
||||
dataLayer.enabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function drawCustomDataItems(selection) {
|
||||
var dataLayer = layers.layer('data');
|
||||
var hasData = dataLayer && dataLayer.hasData();
|
||||
var showsData = hasData && dataLayer.enabled();
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-data')
|
||||
.data(dataLayer ? [0] : []);
|
||||
|
||||
// Exit
|
||||
ul.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var ulEnter = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-data');
|
||||
|
||||
var liEnter = ulEnter
|
||||
.append('li')
|
||||
.attr('class', 'list-item-data');
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.custom.tooltip'))
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function() { toggleLayer('data'); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(t('map_data.layers.custom.title'));
|
||||
|
||||
liEnter
|
||||
.append('button')
|
||||
.call(tooltip()
|
||||
.title(t('settings.custom_data.tooltip'))
|
||||
.placement((textDirection === 'rtl') ? 'right' : 'left')
|
||||
)
|
||||
.on('click', editCustom)
|
||||
.call(svgIcon('#iD-icon-more'));
|
||||
|
||||
liEnter
|
||||
.append('button')
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.custom.zoom'))
|
||||
.placement((textDirection === 'rtl') ? 'right' : 'left')
|
||||
)
|
||||
.on('click', function() {
|
||||
d3_event.preventDefault();
|
||||
d3_event.stopPropagation();
|
||||
dataLayer.fitZoom();
|
||||
})
|
||||
.call(svgIcon('#iD-icon-search'));
|
||||
|
||||
// Update
|
||||
ul = ul
|
||||
.merge(ulEnter);
|
||||
|
||||
ul.selectAll('.list-item-data')
|
||||
.classed('active', showsData)
|
||||
.selectAll('label')
|
||||
.classed('deemphasize', !hasData)
|
||||
.selectAll('input')
|
||||
.property('disabled', !hasData)
|
||||
.property('checked', showsData);
|
||||
}
|
||||
|
||||
|
||||
function editCustom() {
|
||||
d3_event.preventDefault();
|
||||
context.container()
|
||||
.call(settingsCustomData);
|
||||
}
|
||||
|
||||
|
||||
function customChanged(d) {
|
||||
var dataLayer = layers.layer('data');
|
||||
|
||||
if (d && d.url) {
|
||||
dataLayer.url(d.url);
|
||||
} else if (d && d.fileList) {
|
||||
dataLayer.fileList(d.fileList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function drawListItems(selection, data, type, name, change, active) {
|
||||
var items = selection.selectAll('li')
|
||||
.data(data);
|
||||
|
||||
// Exit
|
||||
items.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var enter = items.enter()
|
||||
.append('li')
|
||||
.call(tooltip()
|
||||
.html(true)
|
||||
.title(function(d) {
|
||||
var tip = t(name + '.' + d + '.tooltip');
|
||||
return uiTooltipHtml(tip);
|
||||
})
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
var label = enter
|
||||
.append('label');
|
||||
|
||||
label
|
||||
.append('input')
|
||||
.attr('type', type)
|
||||
.attr('name', name)
|
||||
.on('change', change);
|
||||
|
||||
label
|
||||
.append('span')
|
||||
.text(function(d) { return t(name + '.' + d + '.description'); });
|
||||
|
||||
// Update
|
||||
items = items
|
||||
.merge(enter);
|
||||
|
||||
items
|
||||
.classed('active', active)
|
||||
.selectAll('input')
|
||||
.property('checked', active)
|
||||
.property('indeterminate', false);
|
||||
}
|
||||
|
||||
|
||||
function renderDataLayers(selection) {
|
||||
var container = selection.selectAll('.data-layer-container')
|
||||
.data([0]);
|
||||
|
||||
_dataLayerContainer = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'data-layer-container')
|
||||
.merge(container);
|
||||
|
||||
updateDataLayers();
|
||||
}
|
||||
|
||||
function updateDataLayers() {
|
||||
_dataLayerContainer
|
||||
.call(drawOsmItems)
|
||||
.call(drawQAItems)
|
||||
.call(drawCustomDataItems)
|
||||
.call(drawVectorItems); // Beta - Detroit mapping challenge
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
if (!mapDataPane.selection().select('.disclosure-wrap-data_layers').classed('hide')) {
|
||||
updateDataLayers();
|
||||
|
||||
_QAList
|
||||
.call(drawListItems, ['keep-right'], 'checkbox', 'QA', function(d) { toggleLayer(d); }, showsQA);
|
||||
}
|
||||
|
||||
mapDataPane.selection().select('.map-data-photo-overlays')
|
||||
.call(_photoOverlaysSection.render);
|
||||
|
||||
mapDataPane.selection().select('.map-data-area-fills')
|
||||
.call(_mapStyleOptionsSection.render);
|
||||
|
||||
mapDataPane.selection().select('.map-data-feature-filters')
|
||||
.call(_mapFeaturesSection.render);
|
||||
}
|
||||
|
||||
var mapDataPane = uiPane('map-data', context)
|
||||
.key(t('map_data.key'))
|
||||
.title(t('map_data.title'))
|
||||
.description(t('map_data.description'))
|
||||
.iconName('iD-icon-data');
|
||||
|
||||
mapDataPane.renderContent = function(content) {
|
||||
|
||||
// data layers
|
||||
content
|
||||
.append('div')
|
||||
.attr('class', 'map-data-data-layers')
|
||||
.call(uiDisclosure(context, 'data_layers', true)
|
||||
.title(t('map_data.data_layers'))
|
||||
.content(renderDataLayers)
|
||||
);
|
||||
|
||||
// photo overlays
|
||||
content
|
||||
.append('div')
|
||||
.attr('class', 'map-data-photo-overlays');
|
||||
|
||||
// area fills
|
||||
content
|
||||
.append('div')
|
||||
.attr('class', 'map-data-area-fills');
|
||||
|
||||
// feature filters
|
||||
content
|
||||
.append('div')
|
||||
.attr('class', 'map-data-feature-filters');
|
||||
|
||||
update();
|
||||
};
|
||||
|
||||
context.keybinding()
|
||||
.on(t('area_fill.wireframe.key'), function toggleWireframe() {
|
||||
@@ -524,15 +20,38 @@ export function uiPaneMapData(context) {
|
||||
d3_event.stopPropagation();
|
||||
context.map().toggleWireframe();
|
||||
})
|
||||
.on(osmDataToggleKey, function() {
|
||||
.on(uiCmd('⌥' + t('area_fill.wireframe.key')), function toggleOsmData() {
|
||||
d3_event.preventDefault();
|
||||
d3_event.stopPropagation();
|
||||
toggleLayer('osm');
|
||||
|
||||
// Don't allow layer changes while drawing - #6584
|
||||
var mode = context.mode();
|
||||
if (mode && /^draw/.test(mode.id)) return;
|
||||
|
||||
var layer = context.layers().layer('osm');
|
||||
if (layer) {
|
||||
layer.enabled(!layer.enabled());
|
||||
if (!layer.enabled()) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
}
|
||||
})
|
||||
.on(t('map_data.highlight_edits.key'), function toggleHighlightEdited() {
|
||||
d3_event.preventDefault();
|
||||
context.map().toggleHighlightEdited();
|
||||
});
|
||||
|
||||
var mapDataPane = uiPane('map-data', context)
|
||||
.key(t('map_data.key'))
|
||||
.title(t('map_data.title'))
|
||||
.description(t('map_data.description'))
|
||||
.iconName('iD-icon-data')
|
||||
.sections([
|
||||
uiSectionDataLayers(context),
|
||||
uiSectionPhotoOverlays(context),
|
||||
uiSectionMapStyleOptions(context),
|
||||
uiSectionMapFeatures(context)
|
||||
]);
|
||||
|
||||
return mapDataPane;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
import _debounce from 'lodash-es/debounce';
|
||||
import {
|
||||
event as d3_event,
|
||||
select as d3_select
|
||||
} from 'd3-selection';
|
||||
|
||||
import { t, textDirection } from '../../util/locale';
|
||||
import { tooltip } from '../../util/tooltip';
|
||||
import { svgIcon } from '../../svg/icon';
|
||||
import { geoExtent } from '../../geo';
|
||||
import { modeBrowse } from '../../modes/browse';
|
||||
import { uiCmd } from '../cmd';
|
||||
import { uiSection } from '../section';
|
||||
import { uiSettingsCustomData } from '../settings/custom_data';
|
||||
import { uiTooltipHtml } from '../tooltipHtml';
|
||||
|
||||
export function uiSectionDataLayers(context) {
|
||||
|
||||
var settingsCustomData = uiSettingsCustomData(context)
|
||||
.on('change', customChanged);
|
||||
|
||||
var layers = context.layers();
|
||||
|
||||
var section = uiSection('data-layers', context)
|
||||
.title(t('map_data.data_layers'));
|
||||
|
||||
section.renderDisclosureContent = function(selection) {
|
||||
var container = selection.selectAll('.data-layer-container')
|
||||
.data([0]);
|
||||
|
||||
container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'data-layer-container')
|
||||
.merge(container)
|
||||
.call(drawOsmItems)
|
||||
.call(drawQAItems)
|
||||
.call(drawCustomDataItems)
|
||||
.call(drawVectorItems); // Beta - Detroit mapping challenge
|
||||
};
|
||||
|
||||
function showsLayer(which) {
|
||||
var layer = layers.layer(which);
|
||||
if (layer) {
|
||||
return layer.enabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setLayer(which, enabled) {
|
||||
// Don't allow layer changes while drawing - #6584
|
||||
var mode = context.mode();
|
||||
if (mode && /^draw/.test(mode.id)) return;
|
||||
|
||||
var layer = layers.layer(which);
|
||||
if (layer) {
|
||||
layer.enabled(enabled);
|
||||
|
||||
if (!enabled && (which === 'osm' || which === 'notes')) {
|
||||
context.enter(modeBrowse(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLayer(which) {
|
||||
setLayer(which, !showsLayer(which));
|
||||
}
|
||||
|
||||
function drawOsmItems(selection) {
|
||||
var osmKeys = ['osm', 'notes'];
|
||||
var osmLayers = layers.all().filter(function(obj) { return osmKeys.indexOf(obj.id) !== -1; });
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-osm')
|
||||
.data([0]);
|
||||
|
||||
ul = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-osm')
|
||||
.merge(ul);
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(osmLayers);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.id; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
if (d.id === 'osm') {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.html(true)
|
||||
.title(uiTooltipHtml(t('map_data.layers.' + d.id + '.tooltip'), uiCmd('⌥' + t('area_fill.wireframe.key'))))
|
||||
.placement('bottom')
|
||||
);
|
||||
} else {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.' + d.id + '.tooltip'))
|
||||
.placement('bottom')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function(d) { toggleLayer(d.id); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return t('map_data.layers.' + d.id + '.title'); });
|
||||
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', function (d) { return d.layer.enabled(); })
|
||||
.selectAll('input')
|
||||
.property('checked', function (d) { return d.layer.enabled(); });
|
||||
}
|
||||
|
||||
function drawQAItems(selection) {
|
||||
var qaKeys = ['keepRight', 'improveOSM', 'osmose'];
|
||||
var qaLayers = layers.all().filter(function(obj) { return qaKeys.indexOf(obj.id) !== -1; });
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-qa')
|
||||
.data([0]);
|
||||
|
||||
ul = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-qa')
|
||||
.merge(ul);
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(qaLayers);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.id; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
d3_select(this)
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.' + d.id + '.tooltip'))
|
||||
.placement('bottom')
|
||||
);
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function(d) { toggleLayer(d.id); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return t('map_data.layers.' + d.id + '.title'); });
|
||||
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', function (d) { return d.layer.enabled(); })
|
||||
.selectAll('input')
|
||||
.property('checked', function (d) { return d.layer.enabled(); });
|
||||
}
|
||||
|
||||
// Beta feature - sample vector layers to support Detroit Mapping Challenge
|
||||
// https://github.com/osmus/detroit-mapping-challenge
|
||||
function drawVectorItems(selection) {
|
||||
var dataLayer = layers.layer('data');
|
||||
var vtData = [
|
||||
{
|
||||
name: 'Detroit Neighborhoods/Parks',
|
||||
src: 'neighborhoods-parks',
|
||||
tooltip: 'Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmur6x34562qp9iv1u3ksf-54hev,jonahadkins.cjksmqxdx33jj2wp90xd9x2md-4e5y2/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}, {
|
||||
name: 'Detroit Composite POIs',
|
||||
src: 'composite-poi',
|
||||
tooltip: 'Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmm6a02sli31myxhsr7zf3-2sw8h/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}, {
|
||||
name: 'Detroit All-The-Places POIs',
|
||||
src: 'alltheplaces-poi',
|
||||
tooltip: 'Public domain business location data created by web scrapers.',
|
||||
template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmswgk340g2vo06p1w9w0j-8fjjc/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
|
||||
}
|
||||
];
|
||||
|
||||
// Only show this if the map is around Detroit..
|
||||
var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
|
||||
var showVectorItems = (context.map().zoom() > 9 && detroit.contains(context.map().center()));
|
||||
|
||||
var container = selection.selectAll('.vectortile-container')
|
||||
.data(showVectorItems ? [0] : []);
|
||||
|
||||
container.exit()
|
||||
.remove();
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'vectortile-container');
|
||||
|
||||
containerEnter
|
||||
.append('h4')
|
||||
.attr('class', 'vectortile-header')
|
||||
.text('Detroit Vector Tiles (Beta)');
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-vectortile');
|
||||
|
||||
containerEnter
|
||||
.append('div')
|
||||
.attr('class', 'vectortile-footer')
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#iD-icon-out-link', 'inline'))
|
||||
.attr('href', 'https://github.com/osmus/detroit-mapping-challenge')
|
||||
.append('span')
|
||||
.text('About these layers');
|
||||
|
||||
container = container
|
||||
.merge(containerEnter);
|
||||
|
||||
|
||||
var ul = container.selectAll('.layer-list-vectortile');
|
||||
|
||||
var li = ul.selectAll('.list-item')
|
||||
.data(vtData);
|
||||
|
||||
li.exit()
|
||||
.remove();
|
||||
|
||||
var liEnter = li.enter()
|
||||
.append('li')
|
||||
.attr('class', function(d) { return 'list-item list-item-' + d.src; });
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.each(function(d) {
|
||||
d3_select(this).call(
|
||||
tooltip().title(d.tooltip).placement('top')
|
||||
);
|
||||
});
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'radio')
|
||||
.attr('name', 'vectortile')
|
||||
.on('change', selectVTLayer);
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(function(d) { return d.name; });
|
||||
|
||||
// Update
|
||||
li
|
||||
.merge(liEnter)
|
||||
.classed('active', isVTLayerSelected)
|
||||
.selectAll('input')
|
||||
.property('checked', isVTLayerSelected);
|
||||
|
||||
|
||||
function isVTLayerSelected(d) {
|
||||
return dataLayer && dataLayer.template() === d.template;
|
||||
}
|
||||
|
||||
function selectVTLayer(d) {
|
||||
context.storage('settings-custom-data-url', d.template);
|
||||
if (dataLayer) {
|
||||
dataLayer.template(d.template, d.src);
|
||||
dataLayer.enabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawCustomDataItems(selection) {
|
||||
var dataLayer = layers.layer('data');
|
||||
var hasData = dataLayer && dataLayer.hasData();
|
||||
var showsData = hasData && dataLayer.enabled();
|
||||
|
||||
var ul = selection
|
||||
.selectAll('.layer-list-data')
|
||||
.data(dataLayer ? [0] : []);
|
||||
|
||||
// Exit
|
||||
ul.exit()
|
||||
.remove();
|
||||
|
||||
// Enter
|
||||
var ulEnter = ul.enter()
|
||||
.append('ul')
|
||||
.attr('class', 'layer-list layer-list-data');
|
||||
|
||||
var liEnter = ulEnter
|
||||
.append('li')
|
||||
.attr('class', 'list-item-data');
|
||||
|
||||
var labelEnter = liEnter
|
||||
.append('label')
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.custom.tooltip'))
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
labelEnter
|
||||
.append('input')
|
||||
.attr('type', 'checkbox')
|
||||
.on('change', function() { toggleLayer('data'); });
|
||||
|
||||
labelEnter
|
||||
.append('span')
|
||||
.text(t('map_data.layers.custom.title'));
|
||||
|
||||
liEnter
|
||||
.append('button')
|
||||
.call(tooltip()
|
||||
.title(t('settings.custom_data.tooltip'))
|
||||
.placement((textDirection === 'rtl') ? 'right' : 'left')
|
||||
)
|
||||
.on('click', editCustom)
|
||||
.call(svgIcon('#iD-icon-more'));
|
||||
|
||||
liEnter
|
||||
.append('button')
|
||||
.call(tooltip()
|
||||
.title(t('map_data.layers.custom.zoom'))
|
||||
.placement((textDirection === 'rtl') ? 'right' : 'left')
|
||||
)
|
||||
.on('click', function() {
|
||||
d3_event.preventDefault();
|
||||
d3_event.stopPropagation();
|
||||
dataLayer.fitZoom();
|
||||
})
|
||||
.call(svgIcon('#iD-icon-search'));
|
||||
|
||||
// Update
|
||||
ul = ul
|
||||
.merge(ulEnter);
|
||||
|
||||
ul.selectAll('.list-item-data')
|
||||
.classed('active', showsData)
|
||||
.selectAll('label')
|
||||
.classed('deemphasize', !hasData)
|
||||
.selectAll('input')
|
||||
.property('disabled', !hasData)
|
||||
.property('checked', showsData);
|
||||
}
|
||||
|
||||
function editCustom() {
|
||||
d3_event.preventDefault();
|
||||
context.container()
|
||||
.call(settingsCustomData);
|
||||
}
|
||||
|
||||
function customChanged(d) {
|
||||
var dataLayer = layers.layer('data');
|
||||
|
||||
if (d && d.url) {
|
||||
dataLayer.url(d.url);
|
||||
} else if (d && d.fileList) {
|
||||
dataLayer.fileList(d.fileList);
|
||||
}
|
||||
}
|
||||
|
||||
context.layers().on('change.uiSectionDataLayers', section.rerenderContent);
|
||||
|
||||
context.map()
|
||||
.on('move.uiSectionDataLayers',
|
||||
_debounce(function() {
|
||||
// Detroit layers may have moved in or out of view
|
||||
window.requestIdleCallback(section.rerenderContent);
|
||||
}, 1000)
|
||||
);
|
||||
|
||||
return section;
|
||||
}
|
||||
Reference in New Issue
Block a user