d3.typeahead = function() { var data, hidden; var typeahead = function(selection) { var container; function setup() { var rect = selection.node().getBoundingClientRect(); container = d3.select(document.body) .append('div').attr('class', 'typeahead') .style({ position: 'absolute', left: rect.left + 'px', top: rect.bottom + 'px' }); selection .on('keyup.typeahead', update); hidden = false; } function hide() { window.setTimeout(function() { container.remove(); idx = 0; hidden = true; }, 500); } selection .on('focus.typeahead', setup) .on('blur.typeahead', hide); var idx = 0; function update() { 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.selected').datum().value); hide(); } container .selectAll('a') .classed('selected', 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(); }); } }; typeahead.data = function(_) { if (!arguments.length) return data; data = _; return typeahead; }; return typeahead; };