使用带有'包含'方法的HTML5(datalist)自动完成功能,而不只是'开头'

Rud*_*die 28 html5 autocomplete html-datalist

(我找不到它,但我又不知道如何搜索它.)

我想使用<input list=xxx><datalist id=xxx>获得自动完成功能,但我希望浏览器通过"包含"方法匹配所有选项,而不是"开始于",这似乎是标准的.有办法吗?

如果不是简单,有没有办法强制显示我想要显示的建议,而不是浏览器匹配的建议?假设我正在键入"foo",我想显示选项"bar"和"baz".我可以强迫用户使用吗?如果我只是用那些(用JS)填充datalist,浏览器仍然会执行'start with'检查,并将其过滤掉.

我希望最终控制数据主义选项如何显示.不要超过它的UI,灵活性,可访问性等,所以我不想完全重新制作它.甚至不建议使用jQuery插件.

如果我可以最终控制表单元素验证,为什么不自动完成,对吧?

编辑:我现在看到Firefox确实使用'包含'方法......那甚至不是标准?有什么方法可以强迫这个?我可以改变Firefox的方式吗?

编辑:我这是为了说明我喜欢的内容:http://jsfiddle.net/rudiedirkx/r3jbfpxw/

Nin*_*olz 14

'包含'的方法

也许这就是你要找的东西(问题的第一部分).

它符合"开始于"的限制,并在进行选择时发生变化.

'use strict';
function updateList(that) {
    if (!that) {
        return;
    }
    var lastValue = that.lastValue,
        value = that.value,
        array = [],
        pos = value.indexOf('|'),
        start = that.selectionStart,
        end = that.selectionEnd,
        options;

    if (that.options) {
        options = that.options;
    } else {
        options = Object.keys(that.list.options).map(function (option) {
            return that.list.options[option].value;
        });
        that.options = options;
    }

    if (lastValue !== value) {
        that.list.innerHTML = options.filter(function (a) {
            return ~a.toLowerCase().indexOf(value.toLowerCase());
        }).map(function (a) {
            return '<option value="' + value + '|' + a + '">' + a + '</option>';
        }).join();
        updateInput(that);
        that.lastValue = value;
    }
}

function updateInput(that) {
    if (!that) {
        return;
    }
    var value = that.value,
        pos = value.indexOf('|'),
        start = that.selectionStart,
        end = that.selectionEnd;

    if (~pos) {
        value = value.slice(pos + 1);
    }
    that.value = value;
    that.setSelectionRange(start, end);
}

document.getElementsByTagName('input').browser.addEventListener('keyup', function (e) {
    updateList(this);
});
document.getElementsByTagName('input').browser.addEventListener('input', function (e) {
    updateInput(this);
});
Run Code Online (Sandbox Code Playgroud)
<input list="browsers" name="browser" id="browser" onkeyup="updateList();" oninput="updateInput();">
<datalist id="browsers">
    <option value="Internet Explorer">
    <option value="Firefox">
    <option value="Chrome">
    <option value="Opera">
    <option value="Safari">
</datalist>
Run Code Online (Sandbox Code Playgroud)

编辑

显示搜索内容的不同方法,以明确,发生了什么.这也适用于Chrome.受Show datalist标签的启发,但提交实际值

   'use strict';
var datalist = {
        r: ['ralph', 'ronny', 'rudie'],
        ru: ['rudie', 'rutte', 'rudiedirkx'],
        rud: ['rudie', 'rudiedirkx'],
        rudi: ['rudie'],
        rudo: ['rudolf'],
        foo: [
            { value: 42, text: 'The answer' },
            { value: 1337, text: 'Elite' },
            { value: 69, text: 'Dirty' },
            { value: 3.14, text: 'Pi' }
        ]
    },
    SEPARATOR = ' > ';

function updateList(that) {
    var lastValue = that.lastValue,
        value = that.value,
        array,
        key,
        pos = value.indexOf('|'),
        start = that.selectionStart,
        end = that.selectionEnd;

    if (lastValue !== value) {
        if (value !== '') {
            if (value in datalist) {
                key = value;
            } else {
                Object.keys(datalist).some(function (a) {
                    return ~a.toLowerCase().indexOf(value.toLowerCase()) && (key = a);
                });
            }
        }
        that.list.innerHTML = key ? datalist[key].map(function (a) {
            return '<option data-value="' + (a.value || a) + '">' + value + (value === key ? '' : SEPARATOR + key) + SEPARATOR + (a.text || a) + '</option>';
        }).join() : '';
        updateInput(that);
        that.lastValue = value;
    }
}

function updateInput(that) {
    var value = that.value,
        pos = value.lastIndexOf(SEPARATOR),
        start = that.selectionStart,
        end = that.selectionEnd;

    if (~pos) {
        value = value.slice(pos + SEPARATOR.length);
    }
    Object.keys(that.list.options).some(function (option) {
        var o = that.list.options[option],
            p = o.text.lastIndexOf(SEPARATOR);
        if (o.text.slice(p + SEPARATOR.length) === value) {
            value = o.getAttribute('data-value');
            return true;
        }
    });
    that.value = value;
    that.setSelectionRange(start, end);
}

document.getElementsByTagName('input').xx.addEventListener('keyup', function (e) {
    updateList(this);
});
document.getElementsByTagName('input').xx.addEventListener('input', function (e) {
    updateInput(this);
});
Run Code Online (Sandbox Code Playgroud)
<input list="xxx" name="xx" id="xx">
<datalist id="xxx" type="text"></datalist>
Run Code Online (Sandbox Code Playgroud)


tsh*_*tsh 5

然而这个帖子是大约两年前发布的。但如果您正在阅读此主题,您可能需要检查浏览器的较新版本:

当前规范:https://html.spec.whatwg.org/multipage/forms.html#the-list-attribute

当建议数量很大时,鼓励用户代理过滤由建议源元素表示的建议,仅包括最相关的建议(例如,基于到目前为止的用户输入)。没有定义精确的阈值,但将列表上限限制为四到七个值是合理的。如果根据用户的输入进行过滤,用户代理应该对建议的 label 和 value使用子字符串匹配

在撰写本文时,Firefox (51) 和 Chrome (56) 的行为已经更改以符合规范。

这意味着操作员想要的现在应该可以工作。