mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
Restore default click behaviors on mousedown of a combobox
(closes #5732)
This commit is contained in:
+57
-34
@@ -18,17 +18,19 @@ import { utilGetSetValue, utilRebind, utilTriggerEvent } from '../util';
|
||||
// value: 'display text'
|
||||
// }, ...]
|
||||
|
||||
var _comboTimerID;
|
||||
var _comboHideTimerID;
|
||||
|
||||
export function uiCombobox(context, klass) {
|
||||
var dispatch = d3_dispatch('accept', 'cancel');
|
||||
var container = context.container();
|
||||
|
||||
var _suggestions = [];
|
||||
var _values = [];
|
||||
var _choice = null;
|
||||
var _canAutocomplete = true;
|
||||
var _caseSensitive = false;
|
||||
var _minItems = 2;
|
||||
var _tDown = 0;
|
||||
|
||||
var _fetcher = function(val, cb) {
|
||||
cb(_values.filter(function(d) {
|
||||
@@ -44,12 +46,12 @@ export function uiCombobox(context, klass) {
|
||||
|
||||
input
|
||||
.classed('combobox-input', true)
|
||||
.on('focus.typeahead', focus)
|
||||
.on('blur.typeahead', blur)
|
||||
.on('keydown.typeahead', keydown)
|
||||
.on('keyup.typeahead', keyup)
|
||||
.on('input.typeahead', change)
|
||||
.on('mousedown', mousedown)
|
||||
.on('focus.combobox', focus)
|
||||
.on('blur.combobox', blur)
|
||||
.on('keydown.combobox', keydown)
|
||||
.on('keyup.combobox', keyup)
|
||||
.on('input.combobox', change)
|
||||
.on('mousedown.combobox', mousedown)
|
||||
.each(addCaret);
|
||||
|
||||
function addCaret() {
|
||||
@@ -72,7 +74,7 @@ export function uiCombobox(context, klass) {
|
||||
|
||||
|
||||
function blur() {
|
||||
_comboTimerID = window.setTimeout(hide, 150);
|
||||
_comboHideTimerID = window.setTimeout(hide, 150);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +88,7 @@ export function uiCombobox(context, klass) {
|
||||
.style('position', 'absolute')
|
||||
.style('display', 'block')
|
||||
.style('left', '0px')
|
||||
.on('mousedown', function () {
|
||||
.on('mousedown.combobox', function () {
|
||||
// prevent moving focus out of the input field
|
||||
d3_event.preventDefault();
|
||||
});
|
||||
@@ -97,9 +99,9 @@ export function uiCombobox(context, klass) {
|
||||
|
||||
|
||||
function hide() {
|
||||
if (_comboTimerID) {
|
||||
window.clearTimeout(_comboTimerID);
|
||||
_comboTimerID = undefined;
|
||||
if (_comboHideTimerID) {
|
||||
window.clearTimeout(_comboHideTimerID);
|
||||
_comboHideTimerID = undefined;
|
||||
}
|
||||
|
||||
container.selectAll('.combobox')
|
||||
@@ -120,10 +122,10 @@ export function uiCombobox(context, klass) {
|
||||
d3_event.stopPropagation();
|
||||
_choice = null;
|
||||
render();
|
||||
input.on('input.typeahead', function() {
|
||||
input.on('input.combobox', function() {
|
||||
var start = input.property('selectionStart');
|
||||
input.node().setSelectionRange(start, start);
|
||||
input.on('input.typeahead', change);
|
||||
input.on('input.combobox', change);
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -187,21 +189,44 @@ export function uiCombobox(context, klass) {
|
||||
|
||||
|
||||
function mousedown() {
|
||||
// prevent the form element from blurring. it blurs on mousedown
|
||||
d3_event.stopPropagation();
|
||||
d3_event.preventDefault();
|
||||
if (d3_event.button !== 0) return; // left click only
|
||||
|
||||
var start = input.property('selectionStart');
|
||||
var end = input.property('selectionEnd');
|
||||
if (start !== end) return; // exit if user is deselecting
|
||||
|
||||
_tDown = +new Date();
|
||||
input.on('mouseup.combobox', mouseup);
|
||||
}
|
||||
|
||||
|
||||
function mouseup() {
|
||||
input.on('mouseup.combobox', null);
|
||||
|
||||
if (d3_event.button !== 0) return; // left click only
|
||||
|
||||
var start = input.property('selectionStart');
|
||||
var end = input.property('selectionEnd');
|
||||
if (start !== end) return; // exit if user is selecting
|
||||
|
||||
var combo = container.selectAll('.combobox');
|
||||
if (combo.empty()) {
|
||||
input.node().focus();
|
||||
fetch('', function() {
|
||||
show();
|
||||
render();
|
||||
});
|
||||
if (combo.empty()) { // not showing - try to show it.
|
||||
var tOrig = _tDown;
|
||||
window.setTimeout(function() {
|
||||
if (tOrig !== _tDown) return; // exit if user double clicked
|
||||
input.node().focus();
|
||||
fetch('', function() {
|
||||
show();
|
||||
render();
|
||||
});
|
||||
}, 150);
|
||||
|
||||
} else {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function nav(dir) {
|
||||
if (!_suggestions.length) return;
|
||||
|
||||
@@ -323,7 +348,7 @@ export function uiCombobox(context, klass) {
|
||||
.merge(options)
|
||||
.attr('title', function(d) { return d.title; })
|
||||
.classed('selected', function(d) { return d === _choice; })
|
||||
.on('click', accept)
|
||||
.on('click.combobox', accept)
|
||||
.order();
|
||||
|
||||
var node = attachTo ? attachTo.node() : input.node();
|
||||
@@ -394,16 +419,14 @@ export function uiCombobox(context, klass) {
|
||||
|
||||
uiCombobox.off = function(input) {
|
||||
input
|
||||
.on('focus.typeahead', null)
|
||||
.on('blur.typeahead', null)
|
||||
.on('keydown.typeahead', null)
|
||||
.on('keyup.typeahead', null)
|
||||
.on('input.typeahead', null)
|
||||
.each(function() {
|
||||
d3_select(this.parentNode).selectAll('.combobox-caret')
|
||||
.filter(function(d) { return d === input.node(); })
|
||||
.on('mousedown', null);
|
||||
});
|
||||
.on('focus.combobox', null)
|
||||
.on('blur.combobox', null)
|
||||
.on('keydown.combobox', null)
|
||||
.on('keyup.combobox', null)
|
||||
.on('input.combobox', null)
|
||||
.on('mousedown.combobox', null)
|
||||
.on('mouseup.combobox', null);
|
||||
|
||||
|
||||
d3_select('body')
|
||||
.on('scroll.combobox', null);
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('uiCombobox', function() {
|
||||
iD.d3.customEvent(happen.makeEvent({
|
||||
type: 'keydown',
|
||||
keyCode: keyCode
|
||||
}), input.on('keydown.typeahead'));
|
||||
}), input.on('keydown.combobox'));
|
||||
|
||||
switch (key) {
|
||||
case '⇥':
|
||||
@@ -80,7 +80,7 @@ describe('uiCombobox', function() {
|
||||
|
||||
function focusTypeahead(input) {
|
||||
input.node().focus();
|
||||
d3.customEvent(happen.makeEvent('focus'), input.on('focus.typeahead'));
|
||||
d3.customEvent(happen.makeEvent('focus'), input.on('focus.combobox'));
|
||||
}
|
||||
|
||||
it('adds the combobox-input class', function() {
|
||||
@@ -90,7 +90,8 @@ describe('uiCombobox', function() {
|
||||
|
||||
it('adds combobox under container', function() {
|
||||
input.call(combobox.data(data));
|
||||
body.selectAll('.combobox-input').dispatch('mousedown');
|
||||
focusTypeahead(input);
|
||||
simulateKeypress('↓');
|
||||
expect(d3.select('.id-container > div.combobox').nodes().length).to.equal(1);
|
||||
});
|
||||
|
||||
@@ -106,14 +107,16 @@ describe('uiCombobox', function() {
|
||||
|
||||
it('shows all entries when clicking on the caret', function() {
|
||||
input.property('value', 'foobar').call(combobox.data(data));
|
||||
body.selectAll('.combobox-input').dispatch('mousedown');
|
||||
focusTypeahead(input);
|
||||
simulateKeypress('↓');
|
||||
expect(body.selectAll('.combobox-option').size()).to.equal(5);
|
||||
expect(body.selectAll('.combobox-option').text()).to.equal('foobar');
|
||||
});
|
||||
|
||||
it('is initially shown with no selection', function() {
|
||||
input.call(combobox.data(data));
|
||||
body.selectAll('.combobox-input').dispatch('mousedown');
|
||||
focusTypeahead(input);
|
||||
simulateKeypress('↓');
|
||||
expect(body.selectAll('.combobox-option.selected').size()).to.equal(0);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user