Feature List (#1545)

This commit is contained in:
John Firebaugh
2013-06-03 17:47:09 -07:00
parent a90a1a654c
commit a1d7d05155
8 changed files with 251 additions and 47 deletions

View File

@@ -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;

View File

@@ -182,6 +182,7 @@ en:
search: Search
unknown: Unknown
incomplete: <not downloaded>
feature_list: Feature List
background:
title: Background
description: Background settings

View File

@@ -223,7 +223,8 @@
"remove": "Remove",
"search": "Search",
"unknown": "Unknown",
"incomplete": "<not downloaded>"
"incomplete": "<not downloaded>",
"feature_list": "Feature List"
},
"background": {
"title": "Background",

View File

@@ -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
View 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;
};

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -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;
};