mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
290 lines
9.5 KiB
JavaScript
290 lines
9.5 KiB
JavaScript
import _debounce from 'lodash-es/debounce';
|
|
import { descending as d3_descending, ascending as d3_ascending } from 'd3-array';
|
|
import { select as d3_select } from 'd3-selection';
|
|
|
|
import { prefs } from '../../core/preferences';
|
|
import { t, localizer } from '../../core/localizer';
|
|
import { uiTooltip } from '../tooltip';
|
|
import { svgIcon } from '../../svg/icon';
|
|
import { uiCmd } from '../cmd';
|
|
import { uiSettingsCustomBackground } from '../settings/custom_background';
|
|
import { uiMapInMap } from '../map_in_map';
|
|
import { uiSection } from '../section';
|
|
|
|
export function uiSectionBackgroundList(context) {
|
|
|
|
var _backgroundList = d3_select(null);
|
|
|
|
var _customSource = context.background().findSource('custom');
|
|
|
|
var _settingsCustomBackground = uiSettingsCustomBackground(context)
|
|
.on('change', customChanged);
|
|
|
|
var section = uiSection('background-list', context)
|
|
.label(() => t.append('background.backgrounds'))
|
|
.disclosureContent(renderDisclosureContent);
|
|
|
|
function previousBackgroundID() {
|
|
return prefs('background-last-used-toggle');
|
|
}
|
|
|
|
function renderDisclosureContent(selection) {
|
|
|
|
// the background list
|
|
var container = selection.selectAll('.layer-background-list')
|
|
.data([0]);
|
|
|
|
_backgroundList = container.enter()
|
|
.append('ul')
|
|
.attr('class', 'layer-list layer-background-list')
|
|
.attr('dir', 'auto')
|
|
.merge(container);
|
|
|
|
|
|
// add minimap toggle below list
|
|
var bgExtrasListEnter = selection.selectAll('.bg-extras-list')
|
|
.data([0])
|
|
.enter()
|
|
.append('ul')
|
|
.attr('class', 'layer-list bg-extras-list');
|
|
|
|
var minimapLabelEnter = bgExtrasListEnter
|
|
.append('li')
|
|
.attr('class', 'minimap-toggle-item')
|
|
.append('label')
|
|
.call(uiTooltip()
|
|
.title(() => t.append('background.minimap.tooltip'))
|
|
.keys([t('background.minimap.key')])
|
|
.placement('top')
|
|
);
|
|
|
|
minimapLabelEnter
|
|
.append('input')
|
|
.attr('type', 'checkbox')
|
|
.on('change', function(d3_event) {
|
|
d3_event.preventDefault();
|
|
uiMapInMap.toggle();
|
|
});
|
|
|
|
minimapLabelEnter
|
|
.append('span')
|
|
.call(t.append('background.minimap.description'));
|
|
|
|
|
|
var panelLabelEnter = bgExtrasListEnter
|
|
.append('li')
|
|
.attr('class', 'background-panel-toggle-item')
|
|
.append('label')
|
|
.call(uiTooltip()
|
|
.title(() => t.append('background.panel.tooltip'))
|
|
.keys([uiCmd('⌘⇧' + t('info_panels.background.key'))])
|
|
.placement('top')
|
|
);
|
|
|
|
panelLabelEnter
|
|
.append('input')
|
|
.attr('type', 'checkbox')
|
|
.on('change', function(d3_event) {
|
|
d3_event.preventDefault();
|
|
context.ui().info.toggle('background');
|
|
});
|
|
|
|
panelLabelEnter
|
|
.append('span')
|
|
.call(t.append('background.panel.description'));
|
|
|
|
var locPanelLabelEnter = bgExtrasListEnter
|
|
.append('li')
|
|
.attr('class', 'location-panel-toggle-item')
|
|
.append('label')
|
|
.call(uiTooltip()
|
|
.title(() => t.append('background.location_panel.tooltip'))
|
|
.keys([uiCmd('⌘⇧' + t('info_panels.location.key'))])
|
|
.placement('top')
|
|
);
|
|
|
|
locPanelLabelEnter
|
|
.append('input')
|
|
.attr('type', 'checkbox')
|
|
.on('change', function(d3_event) {
|
|
d3_event.preventDefault();
|
|
context.ui().info.toggle('location');
|
|
});
|
|
|
|
locPanelLabelEnter
|
|
.append('span')
|
|
.call(t.append('background.location_panel.description'));
|
|
|
|
|
|
// "Info / Report a Problem" link
|
|
selection.selectAll('.imagery-faq')
|
|
.data([0])
|
|
.enter()
|
|
.append('div')
|
|
.attr('class', 'imagery-faq')
|
|
.append('a')
|
|
.attr('target', '_blank')
|
|
.call(svgIcon('#iD-icon-out-link', 'inline'))
|
|
.attr('href', 'https://github.com/openstreetmap/iD/blob/develop/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
|
|
.append('span')
|
|
.call(t.append('background.imagery_problem_faq'));
|
|
|
|
_backgroundList
|
|
.call(drawListItems, 'radio', function(d3_event, d) {
|
|
chooseBackground(d);
|
|
}, function(d) {
|
|
return !d.isHidden() && !d.overlay;
|
|
});
|
|
}
|
|
|
|
function setTooltips(selection) {
|
|
selection.each(function(d, i, nodes) {
|
|
var item = d3_select(this).select('label');
|
|
var span = item.select('span');
|
|
var placement = (i < nodes.length / 2) ? 'bottom' : 'top';
|
|
var hasDescription = d.hasDescription();
|
|
var isOverflowing = (span.property('clientWidth') !== span.property('scrollWidth'));
|
|
|
|
item.call(uiTooltip().destroyAny);
|
|
|
|
if (d.id === previousBackgroundID()) {
|
|
item.call(uiTooltip()
|
|
.placement(placement)
|
|
.title(() => t.append('background.switch'))
|
|
.keys([uiCmd('⌘' + t('background.key'))])
|
|
);
|
|
} else if (hasDescription || isOverflowing) {
|
|
item.call(uiTooltip()
|
|
.placement(placement)
|
|
.title(() => hasDescription ? d.description() : d.label())
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
function drawListItems(layerList, type, change, filter) {
|
|
var sources = context.background()
|
|
.sources(context.map().extent(), context.map().zoom(), true)
|
|
.filter(filter)
|
|
.sort(function(a, b) {
|
|
return a.best() && !b.best() ? -1
|
|
: b.best() && !a.best() ? 1
|
|
: d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
|
|
});
|
|
|
|
var layerLinks = layerList.selectAll('li')
|
|
// We have to be a bit inefficient about reordering the list since
|
|
// arrow key navigation of radio values likes to work in the order
|
|
// they were added, not the display document order.
|
|
.data(sources, function(d, i) { return d.id + '---' + i; });
|
|
|
|
layerLinks.exit()
|
|
.remove();
|
|
|
|
var enter = layerLinks.enter()
|
|
.append('li')
|
|
.classed('layer-custom', function(d) { return d.id === 'custom'; })
|
|
.classed('best', function(d) { return d.best(); });
|
|
|
|
var label = enter
|
|
.append('label');
|
|
|
|
label
|
|
.append('input')
|
|
.attr('type', type)
|
|
.attr('name', 'background-layer')
|
|
.attr('value', function(d) {
|
|
return d.id;
|
|
})
|
|
.on('change', change);
|
|
|
|
label
|
|
.append('span')
|
|
.each(function(d) { d.label()(d3_select(this)); });
|
|
|
|
enter.filter(function(d) { return d.id === 'custom'; })
|
|
.append('button')
|
|
.attr('class', 'layer-browse')
|
|
.call(uiTooltip()
|
|
.title(() => t.append('settings.custom_background.tooltip'))
|
|
.placement((localizer.textDirection() === 'rtl') ? 'right' : 'left')
|
|
)
|
|
.on('click', function(d3_event) {
|
|
d3_event.preventDefault();
|
|
editCustom();
|
|
})
|
|
.call(svgIcon('#iD-icon-more'));
|
|
|
|
enter.filter(function(d) { return d.best(); })
|
|
.append('div')
|
|
.attr('class', 'best')
|
|
.call(uiTooltip()
|
|
.title(() => t.append('background.best_imagery'))
|
|
.placement((localizer.textDirection() === 'rtl') ? 'right' : 'left')
|
|
)
|
|
.append('span')
|
|
.text('★');
|
|
|
|
layerList
|
|
.call(updateLayerSelections);
|
|
}
|
|
|
|
function updateLayerSelections(selection) {
|
|
function active(d) {
|
|
return context.background().showsLayer(d);
|
|
}
|
|
|
|
selection.selectAll('li')
|
|
.classed('active', active)
|
|
.classed('switch', function(d) { return d.id === previousBackgroundID(); })
|
|
.call(setTooltips)
|
|
.selectAll('input')
|
|
.property('checked', active);
|
|
}
|
|
|
|
|
|
function chooseBackground(d) {
|
|
if (d.id === 'custom' && !d.template()) {
|
|
return editCustom();
|
|
}
|
|
|
|
var previousBackground = context.background().baseLayerSource();
|
|
prefs('background-last-used-toggle', previousBackground.id);
|
|
prefs('background-last-used', d.id);
|
|
context.background().baseLayerSource(d);
|
|
}
|
|
|
|
|
|
function customChanged(d) {
|
|
if (d && d.template) {
|
|
_customSource.template(d.template);
|
|
chooseBackground(_customSource);
|
|
} else {
|
|
_customSource.template('');
|
|
chooseBackground(context.background().findSource('none'));
|
|
}
|
|
}
|
|
|
|
|
|
function editCustom() {
|
|
context.container()
|
|
.call(_settingsCustomBackground);
|
|
}
|
|
|
|
|
|
context.background()
|
|
.on('change.background_list', function() {
|
|
_backgroundList.call(updateLayerSelections);
|
|
});
|
|
|
|
context.map()
|
|
.on('move.background_list',
|
|
_debounce(function() {
|
|
// layers in-view may have changed due to map move
|
|
window.requestIdleCallback(section.reRender);
|
|
}, 1000)
|
|
);
|
|
|
|
return section;
|
|
}
|