mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
Feature List (#1545)
This commit is contained in:
101
css/app.css
101
css/app.css
@@ -182,14 +182,6 @@ input:focus {
|
||||
background-color: #F1F1F1;
|
||||
}
|
||||
|
||||
input.major {
|
||||
width: 100%;
|
||||
padding:5px 10px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
height:60px;
|
||||
}
|
||||
|
||||
/* remove bottom border radius when combobox is open */
|
||||
.combobox + * textarea:focus,
|
||||
.combobox + * input:focus {
|
||||
@@ -698,6 +690,10 @@ a:hover .icon.out-link { background-position: -500px -14px;}
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.feature-list-pane .inspector-body {
|
||||
top: 120px;
|
||||
}
|
||||
|
||||
.preset-list-pane .inspector-body {
|
||||
top: 120px;
|
||||
}
|
||||
@@ -711,6 +707,78 @@ a:hover .icon.out-link { background-position: -500px -14px;}
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#sidebar .search-header .icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 80px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#sidebar .search-header input {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
padding: 5px 10px;
|
||||
border-radius: 0;
|
||||
border-width: 0;
|
||||
border-bottom-width: 1px;
|
||||
text-indent: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Feature list */
|
||||
|
||||
.feature-list {
|
||||
width:100%;
|
||||
padding: 20px 20px 10px 20px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.feature-list-button-wrap {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.feature-list-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.feature-list-button .label {
|
||||
background-color: #f6f6f6;
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 5px 10px;
|
||||
left: 60px;
|
||||
line-height: 50px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
border-left: 1px solid rgba(0, 0, 0, .1);
|
||||
-moz-transition: all 100ms;
|
||||
-o-transition: all 100ms;
|
||||
transition: all 100ms;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
.feature-list-button:hover .label {
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.feature-list-button .entity-name {
|
||||
font-weight: normal;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* Presets
|
||||
------------------------------------------------------- */
|
||||
|
||||
@@ -803,23 +871,6 @@ a:hover .icon.out-link { background-position: -500px -14px;}
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.preset-list-pane .preset-search-icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 80px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.preset-list-pane .preset-search-input {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
border-radius: 0;
|
||||
border-width: 0;
|
||||
border-bottom-width: 1px;
|
||||
text-indent: 30px;
|
||||
}
|
||||
|
||||
.subgrid .preset-list {
|
||||
padding: 10px 10px 0 10px;
|
||||
border: 1px solid #CCC;
|
||||
|
||||
@@ -182,6 +182,7 @@ en:
|
||||
search: Search
|
||||
unknown: Unknown
|
||||
incomplete: <not downloaded>
|
||||
feature_list: Feature List
|
||||
background:
|
||||
title: Background
|
||||
description: Background settings
|
||||
|
||||
3
dist/locales/en.json
vendored
3
dist/locales/en.json
vendored
@@ -223,7 +223,8 @@
|
||||
"remove": "Remove",
|
||||
"search": "Search",
|
||||
"unknown": "Unknown",
|
||||
"incomplete": "<not downloaded>"
|
||||
"incomplete": "<not downloaded>",
|
||||
"feature_list": "Feature List"
|
||||
},
|
||||
"background": {
|
||||
"title": "Background",
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
<script src='js/id/ui/raw_tag_editor.js'></script>
|
||||
<script src='js/id/ui/raw_member_editor.js'></script>
|
||||
<script src='js/id/ui/raw_membership_editor.js'></script>
|
||||
<script src='js/id/ui/feature_list.js'></script>
|
||||
<script src='js/id/ui/preset_list.js'></script>
|
||||
<script src='js/id/ui/entity_editor.js'></script>
|
||||
<script src='js/id/ui/disclosure.js'></script>
|
||||
|
||||
135
js/id/ui/feature_list.js
Normal file
135
js/id/ui/feature_list.js
Normal file
@@ -0,0 +1,135 @@
|
||||
iD.ui.FeatureList = function(context) {
|
||||
function featureList(selection) {
|
||||
var header = selection.append('div')
|
||||
.attr('class', 'header fillL cf');
|
||||
|
||||
header.append('h3')
|
||||
.text(t('inspector.feature_list'));
|
||||
|
||||
function keyup() {
|
||||
var q = search.property('value');
|
||||
if (d3.event.keyCode === 13 && q.length) {
|
||||
click(list.selectAll('.feature-list-item:first-child').datum());
|
||||
} else {
|
||||
drawList();
|
||||
}
|
||||
}
|
||||
|
||||
var searchWrap = selection.append('div')
|
||||
.attr('class', 'search-header');
|
||||
|
||||
var search = searchWrap.append('input')
|
||||
.attr('placeholder', t('inspector.search'))
|
||||
.attr('type', 'search')
|
||||
.on('keyup', keyup);
|
||||
|
||||
searchWrap.append('span')
|
||||
.attr('class', 'icon search');
|
||||
|
||||
var listWrap = selection.append('div')
|
||||
.attr('class', 'inspector-body');
|
||||
|
||||
var list = listWrap.append('div')
|
||||
.attr('class', 'feature-list fillL cf');
|
||||
|
||||
drawList();
|
||||
|
||||
context.history()
|
||||
.on('change.feature-list', drawList);
|
||||
|
||||
context.map()
|
||||
.on('move', drawList);
|
||||
|
||||
function features() {
|
||||
var result = [],
|
||||
graph = context.graph(),
|
||||
q = search.property('value').toLowerCase();
|
||||
|
||||
context.intersects(context.extent()).forEach(function(entity) {
|
||||
var preset = context.presets().match(entity, context.graph()),
|
||||
name = iD.util.displayName(entity) || '';
|
||||
|
||||
if (entity.geometry(graph) === 'vertex')
|
||||
return;
|
||||
|
||||
if (q && name.toLowerCase().indexOf(q) === -1 &&
|
||||
preset.name().toLowerCase().indexOf(q) === -1)
|
||||
return;
|
||||
|
||||
result.push({
|
||||
entity: entity,
|
||||
geometry: context.geometry(entity.id),
|
||||
preset: preset,
|
||||
name: name
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function drawList() {
|
||||
list.classed('filtered', search.property('value').length);
|
||||
|
||||
var items = list.selectAll('.feature-list-item')
|
||||
.data(features(), function(d) { return d.entity.id; });
|
||||
|
||||
var enter = items.enter().append('div')
|
||||
.attr('class', 'feature-list-item');
|
||||
|
||||
var wrap = enter.append('div')
|
||||
.attr('class', 'feature-list-button-wrap col12');
|
||||
|
||||
var label = wrap.append('button')
|
||||
.attr('class', 'feature-list-button')
|
||||
.call(iD.ui.PresetIcon()
|
||||
.geometry(function(d) { return d.geometry })
|
||||
.preset(function(d) { return d.preset; }))
|
||||
.on('mouseover', function(d) { mouseover(d.entity); })
|
||||
.on('mouseout', function(d) { mouseout(); })
|
||||
.on('click', function(d) { click(d.entity); })
|
||||
.append('div')
|
||||
.attr('class', 'label');
|
||||
|
||||
label.append('span')
|
||||
.attr('class', 'entity-type')
|
||||
.text(function(d) { return d.preset.name(); });
|
||||
|
||||
label.append('span')
|
||||
.attr('class', 'entity-name')
|
||||
.text(function(d) { return d.name; });
|
||||
|
||||
enter.style('opacity', 0)
|
||||
.transition()
|
||||
.style('opacity', 1);
|
||||
|
||||
items.order();
|
||||
|
||||
items.exit()
|
||||
.remove();
|
||||
}
|
||||
|
||||
function mouseover(entity) {
|
||||
var selector = '.' + entity.id;
|
||||
|
||||
if (entity.type === 'relation') {
|
||||
entity.members.forEach(function(member) {
|
||||
selector += ', .' + member.id;
|
||||
});
|
||||
}
|
||||
|
||||
context.surface().selectAll(selector)
|
||||
.classed('hover', true);
|
||||
}
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
}
|
||||
|
||||
function click(entity) {
|
||||
context.enter(iD.modes.Select(context, [entity.id]));
|
||||
}
|
||||
}
|
||||
|
||||
return featureList;
|
||||
};
|
||||
@@ -2,33 +2,39 @@ iD.ui.PresetIcon = function() {
|
||||
var preset, geometry;
|
||||
|
||||
function presetIcon(selection) {
|
||||
selection.each(setup);
|
||||
}
|
||||
|
||||
function setup() {
|
||||
var selection = d3.select(this),
|
||||
p = preset.apply(this, arguments),
|
||||
geom = geometry.apply(this, arguments);
|
||||
|
||||
var $fill = selection.selectAll('.preset-icon-fill')
|
||||
.data([0]);
|
||||
|
||||
$fill.enter().append('div');
|
||||
|
||||
$fill.attr('class', function() {
|
||||
var s = 'preset-icon-fill icon-' + geometry;
|
||||
for (var i in preset.tags) {
|
||||
s += ' tag-' + i + ' tag-' + i + '-' + preset.tags[i];
|
||||
var s = 'preset-icon-fill icon-' + geom;
|
||||
for (var i in p.tags) {
|
||||
s += ' tag-' + i + ' tag-' + i + '-' + p.tags[i];
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
||||
var fallbackIcon = geometry === 'line' ? 'other-line' : 'marker-stroked';
|
||||
|
||||
var $icon = selection.selectAll('.preset-icon')
|
||||
.data([0]);
|
||||
|
||||
$icon.enter().append('div');
|
||||
|
||||
$icon.attr('class', function() {
|
||||
var icon = preset.icon || fallbackIcon,
|
||||
var icon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
|
||||
klass = 'feature-' + icon + ' preset-icon';
|
||||
|
||||
var featureicon = iD.data.featureIcons[icon];
|
||||
if (featureicon && featureicon[geometry]) {
|
||||
klass += ' preset-icon-' + geometry;
|
||||
if (featureicon && featureicon[geom]) {
|
||||
klass += ' preset-icon-' + geom;
|
||||
} else if (icon === 'multipolygon') {
|
||||
// Special case (geometry === 'area')
|
||||
klass += ' preset-icon-relation';
|
||||
@@ -40,13 +46,13 @@ iD.ui.PresetIcon = function() {
|
||||
|
||||
presetIcon.preset = function(_) {
|
||||
if (!arguments.length) return preset;
|
||||
preset = _;
|
||||
preset = d3.functor(_);
|
||||
return presetIcon;
|
||||
};
|
||||
|
||||
presetIcon.geometry = function(_) {
|
||||
if (!arguments.length) return geometry;
|
||||
geometry = _;
|
||||
geometry = d3.functor(_);
|
||||
return presetIcon;
|
||||
};
|
||||
|
||||
|
||||
@@ -72,17 +72,16 @@ iD.ui.PresetList = function(context) {
|
||||
}
|
||||
|
||||
var searchWrap = selection.append('div')
|
||||
.attr('class', 'preset-search');
|
||||
.attr('class', 'search-header');
|
||||
|
||||
var search = searchWrap.append('input')
|
||||
.attr('class', 'preset-search-input major')
|
||||
.attr('placeholder', t('inspector.search'))
|
||||
.attr('type', 'search')
|
||||
.on('keydown', keydown)
|
||||
.on('keyup', keyup);
|
||||
|
||||
searchWrap.append('span')
|
||||
.attr('class', 'preset-search-icon icon search');
|
||||
.attr('class', 'icon search');
|
||||
|
||||
if (autofocus) {
|
||||
search.node().focus();
|
||||
|
||||
@@ -3,12 +3,17 @@ iD.ui.Sidebar = function(context) {
|
||||
current;
|
||||
|
||||
function sidebar(selection) {
|
||||
var wrap = selection.append('div')
|
||||
var featureListWrap = selection.append('div')
|
||||
.attr('class', 'feature-list-pane')
|
||||
.call(iD.ui.FeatureList(context));
|
||||
|
||||
var inspectorWrap = selection.append('div')
|
||||
.attr('class', 'inspector-hidden inspector-wrap fr');
|
||||
|
||||
sidebar.hover = function(id) {
|
||||
if (!current && id) {
|
||||
wrap.classed('inspector-hidden', false)
|
||||
featureListWrap.classed('inspector-hidden', true);
|
||||
inspectorWrap.classed('inspector-hidden', false)
|
||||
.classed('inspector-hover', true);
|
||||
|
||||
if (inspector.entityID() !== id || inspector.state() !== 'hover') {
|
||||
@@ -16,16 +21,18 @@ iD.ui.Sidebar = function(context) {
|
||||
.state('hover')
|
||||
.entityID(id);
|
||||
|
||||
wrap.call(inspector);
|
||||
inspectorWrap.call(inspector);
|
||||
}
|
||||
} else {
|
||||
wrap.classed('inspector-hidden', true);
|
||||
featureListWrap.classed('inspector-hidden', false);
|
||||
inspectorWrap.classed('inspector-hidden', true);
|
||||
}
|
||||
};
|
||||
|
||||
sidebar.select = function(id, newFeature) {
|
||||
if (!current && id) {
|
||||
wrap.classed('inspector-hidden', false)
|
||||
featureListWrap.classed('inspector-hidden', true);
|
||||
inspectorWrap.classed('inspector-hidden', false)
|
||||
.classed('inspector-hover', false);
|
||||
|
||||
if (inspector.entityID() !== id || inspector.state() !== 'select') {
|
||||
@@ -34,21 +41,24 @@ iD.ui.Sidebar = function(context) {
|
||||
.entityID(id)
|
||||
.newFeature(newFeature);
|
||||
|
||||
wrap.call(inspector);
|
||||
inspectorWrap.call(inspector);
|
||||
}
|
||||
} else {
|
||||
wrap.classed('inspector-hidden', true);
|
||||
featureListWrap.classed('inspector-hidden', false);
|
||||
inspectorWrap.classed('inspector-hidden', true);
|
||||
}
|
||||
};
|
||||
|
||||
sidebar.show = function(component) {
|
||||
wrap.classed('inspector-hidden', true);
|
||||
featureListWrap.classed('inspector-hidden', true);
|
||||
inspectorWrap.classed('inspector-hidden', true);
|
||||
current = selection.append('div')
|
||||
.attr('class', 'sidebar-component')
|
||||
.call(component);
|
||||
};
|
||||
|
||||
sidebar.hide = function() {
|
||||
featureListWrap.classed('inspector-hidden', false);
|
||||
current.remove();
|
||||
current = null;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user