mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
Allow combobox to nest under id-container instead of body
(re: https://github.com/openstreetmap/iD/issues/3925#issuecomment-290718356)
This commit is contained in:
+19
-12
@@ -4,6 +4,7 @@ import { utilRebind } from '../../modules/util/rebind';
|
||||
|
||||
export function d3combobox() {
|
||||
var event = d3.dispatch('accept'),
|
||||
container = d3.select(document.body),
|
||||
data = [],
|
||||
suggestions = [],
|
||||
minItems = 2,
|
||||
@@ -20,10 +21,10 @@ export function d3combobox() {
|
||||
|
||||
var combobox = function(input, attachTo) {
|
||||
var idx = -1,
|
||||
container = d3.select(document.body)
|
||||
wrapper = container
|
||||
.selectAll('div.combobox')
|
||||
.filter(function(d) { return d === input.node(); }),
|
||||
shown = !container.empty();
|
||||
shown = !wrapper.empty();
|
||||
|
||||
input
|
||||
.classed('combobox-input', true)
|
||||
@@ -70,7 +71,7 @@ export function d3combobox() {
|
||||
|
||||
function show() {
|
||||
if (!shown) {
|
||||
container = d3.select(document.body)
|
||||
wrapper = container
|
||||
.insert('div', ':first-child')
|
||||
.datum(input.node())
|
||||
.attr('class', 'combobox')
|
||||
@@ -82,7 +83,7 @@ export function d3combobox() {
|
||||
d3.event.preventDefault();
|
||||
});
|
||||
|
||||
d3.select(document.body)
|
||||
d3.select('body')
|
||||
.on('scroll.combobox', render, true);
|
||||
|
||||
shown = true;
|
||||
@@ -92,9 +93,9 @@ export function d3combobox() {
|
||||
function hide() {
|
||||
if (shown) {
|
||||
idx = -1;
|
||||
container.remove();
|
||||
wrapper.remove();
|
||||
|
||||
d3.select(document.body)
|
||||
d3.select('body')
|
||||
.on('scroll.combobox', null);
|
||||
|
||||
shown = false;
|
||||
@@ -116,7 +117,7 @@ export function d3combobox() {
|
||||
break;
|
||||
// tab
|
||||
case 9:
|
||||
container.selectAll('a.selected').each(function (d) {
|
||||
wrapper.selectAll('a.selected').each(function (d) {
|
||||
event.call('accept', this, d);
|
||||
});
|
||||
hide();
|
||||
@@ -147,7 +148,7 @@ export function d3combobox() {
|
||||
break;
|
||||
// return
|
||||
case 13:
|
||||
container.selectAll('a.selected').each(function (d) {
|
||||
wrapper.selectAll('a.selected').each(function (d) {
|
||||
event.call('accept', this, d);
|
||||
});
|
||||
hide();
|
||||
@@ -217,7 +218,7 @@ export function d3combobox() {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = container
|
||||
var options = wrapper
|
||||
.selectAll('a.combobox-option')
|
||||
.data(suggestions, function(d) { return d.value; });
|
||||
|
||||
@@ -239,7 +240,7 @@ export function d3combobox() {
|
||||
var node = attachTo ? attachTo.node() : input.node(),
|
||||
rect = node.getBoundingClientRect();
|
||||
|
||||
container
|
||||
wrapper
|
||||
.style('left', rect.left + 'px')
|
||||
.style('width', rect.width + 'px')
|
||||
.style('top', rect.height + rect.top + 'px');
|
||||
@@ -251,7 +252,7 @@ export function d3combobox() {
|
||||
}
|
||||
|
||||
function ensureVisible() {
|
||||
var node = container.selectAll('a.selected').node();
|
||||
var node = wrapper.selectAll('a.selected').node();
|
||||
if (node) node.scrollIntoView();
|
||||
}
|
||||
|
||||
@@ -289,6 +290,12 @@ export function d3combobox() {
|
||||
return combobox;
|
||||
};
|
||||
|
||||
combobox.container = function(_) {
|
||||
if (!arguments.length) return container;
|
||||
container = _;
|
||||
return combobox;
|
||||
};
|
||||
|
||||
return utilRebind(combobox, event, 'on');
|
||||
}
|
||||
|
||||
@@ -306,6 +313,6 @@ d3combobox.off = function(input) {
|
||||
.on('mousedown', null);
|
||||
});
|
||||
|
||||
d3.select(document.body)
|
||||
d3.select('body')
|
||||
.on('scroll.combobox', null);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
describe('d3.combobox', function() {
|
||||
var body, content, input, combobox;
|
||||
var body, container, content, input, combobox;
|
||||
|
||||
var data = [
|
||||
{title: 'foo', value: 'foo'},
|
||||
@@ -62,14 +62,16 @@ describe('d3.combobox', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
body = d3.select('body');
|
||||
content = body.append('div');
|
||||
container = body.append('div').attr('class', 'id-container');
|
||||
content = container.append('div');
|
||||
input = content.append('input');
|
||||
combobox = iD.lib.d3combobox();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
content.remove();
|
||||
body.selectAll('.combobox').remove();
|
||||
content.remove();
|
||||
container.remove();
|
||||
});
|
||||
|
||||
function focusTypeahead(input) {
|
||||
@@ -82,6 +84,20 @@ describe('d3.combobox', function() {
|
||||
expect(input).to.be.classed('combobox-input');
|
||||
});
|
||||
|
||||
it('adds combobox under body by default', function() {
|
||||
input.call(combobox.data(data));
|
||||
focusTypeahead(input);
|
||||
expect(d3.select('body > div.combobox').nodes().length).to.equal(1);
|
||||
expect(d3.select('.id-container > div.combobox').nodes().length).to.equal(0);
|
||||
});
|
||||
|
||||
it('adds combobox under container with container option', function() {
|
||||
input.call(combobox.container(container).data(data));
|
||||
focusTypeahead(input);
|
||||
expect(d3.select('body > div.combobox').nodes().length).to.equal(0);
|
||||
expect(d3.select('.id-container > div.combobox').nodes().length).to.equal(1);
|
||||
});
|
||||
|
||||
it('shows a menu of entries on focus', function() {
|
||||
input.call(combobox.data(data));
|
||||
focusTypeahead(input);
|
||||
|
||||
Reference in New Issue
Block a user