From f381693f2b83ff2c62ec5c91d571ca162220d218 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Wed, 5 Dec 2012 11:12:56 -0500 Subject: [PATCH] Improve typeahead --- css/app.css | 6 +++- js/id/ui/inspector.js | 18 ++++++------ js/lib/d3.typeahead.js | 62 ++++++++++++++++++++++++++---------------- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/css/app.css b/css/app.css index f9034d209..72f3b8dc6 100644 --- a/css/app.css +++ b/css/app.css @@ -240,15 +240,19 @@ input#geocode-location { div.typeahead { background:#fff; - padding:2px 4px; width:148px; border:1px solid #ccc; } div.typeahead a { + padding:1px 4px; display:block; } +div.typeahead a.active { + background:#DDE4FF; +} + .modal { width:640px; height:550px; diff --git a/js/id/ui/inspector.js b/js/id/ui/inspector.js index 68db9424b..60a84819a 100644 --- a/js/id/ui/inspector.js +++ b/js/id/ui/inspector.js @@ -70,18 +70,20 @@ iD.Inspector = function() { .data(function(d) { return [d, d]; }); valuetds.enter().append('td').append('input') .property('value', function(d, i) { return d[i ? 'value' : 'key']; }) - .on('keyup', function(d, i) { + .on('keyup.update', function(d, i) { d[i ? 'value' : 'key'] = this.value; update(); }) .each(function(d, i) { - var selection = this; - if (i == 1) { - taginfo.values(d.key, function(err, data) { - d3.select(selection).call(d3.typeahead() - .data(data.data)); - }); - } + if (!i) return; + var selection = d3.select(this); + selection.call(d3.typeahead() + .data(function(selection, callback) { + update(); + taginfo.values(selection.datum().key, function(err, data) { + callback(data.data); + }); + })); }); row.append('td').attr('class', 'tag-help').append('a') diff --git a/js/lib/d3.typeahead.js b/js/lib/d3.typeahead.js index ad933b3bc..689b30925 100644 --- a/js/lib/d3.typeahead.js +++ b/js/lib/d3.typeahead.js @@ -1,11 +1,11 @@ d3.typeahead = function() { - var data; + var data, hidden; var typeahead = function(selection) { var container; function setup() { var rect = selection.node().getBoundingClientRect(); - d3.select(document.body) + container = d3.select(document.body) .append('div').attr('class', 'typeahead') .style({ position: 'absolute', @@ -13,12 +13,15 @@ d3.typeahead = function() { top: rect.bottom + 'px' }); selection - .on('keyup', update); + .on('keyup.update', update); + hidden = false; } function hide() { window.setTimeout(function() { - d3.selectAll('div.typeahead').remove(); + container.remove(); + idx = 0; + hidden = true; }, 500); } @@ -26,29 +29,42 @@ d3.typeahead = function() { .on('focus', setup) .on('blur', hide); + var idx = 0; function update() { - var val = selection.property('value'), - matches = data.filter(function(d) { - return d.value.toLowerCase().indexOf(val) === 0; - }).map(function(d) { - return { value: d.value, description: d.description }; - }), - container = d3.select('div.typeahead') - .style('display', function() { - return matches.length ? 'block' : 'none'; - }), - options = container + if (hidden) setup(); + if (d3.event.keyCode === 40) idx++; + if (d3.event.keyCode === 38) idx--; + if (d3.event.keyCode === 13) { + selection.property('value', container.select('a.active').datum().value); + hide(); + } + container + .selectAll('a') + .classed('active', function(d, i) { return i == idx; }); + // if (d3.event.keyCode === 13) // return + data(selection, function(data) { + var val = selection.property('value'), + matches = data.filter(function(d) { + return d.value.toLowerCase().indexOf(val) === 0; + }).map(function(d) { + return { value: d.value, description: d.description }; + }); + container.style('display', function() { + return matches.length ? 'block' : 'none'; + }); + var options = container .selectAll('a') .data(matches, function(d) { return d.value; }); - options.enter() - .append('a') - .text(function(d) { return d.value; }) - .attr('title', function(d) { return d.description; }) - .on('click', function(d) { - selection.property('value', d.value); - }); - options.exit().remove(); + options.enter() + .append('a') + .text(function(d) { return d.value; }) + .attr('title', function(d) { return d.description; }) + .on('click', function(d) { + selection.property('value', d.value); + }); + options.exit().remove(); + }); } };