如何从一开始就使datalist匹配结果

时间:2017-03-04 06:38:16

标签: javascript jquery html html5

我想在html中使用datalist这里是示例

<h1>Datalist Demo</h1>
<label for="default">Pick a programming language</label>
<input type="text" id="default" list="languages">
<datalist id="languages">
    <option value="HTML">
    <option value="CSS">
    <option value="JavaScript">
    <option value="Java">
    <option value="Ruby And Go">
    <option value="PHP And HTML">
    <option value="Go">
    <option value="Erlang">
    <option value="Python And C++">
    <option value="C">
    <option value="C#">
    <option value="C++">
</datalist>

但是当我搜索&#39;去&#39;它向我展示了2个结果

  • Ruby And Go
  • Go

Result When i Search for 'go'

我希望它只显示与输入文本的开头匹配的术语,而不是来自内部的术语 就像当我搜索&#39;去&#39;只显示一个结果

  • Go

我必须在存储在MySQL中的5000多条记录上实现这一点。

2 个答案:

答案 0 :(得分:1)

对于完全匹配,您可以在pattern事件

上动态地将RegExp属性值设置为[\\w\\s+#]{${this.value.length}} input

&#13;
&#13;
<h1>Datalist Demo</h1>
<label for="default">Pick a programming language</label>
<input type="text" id="default" list="languages" pattern="">
<datalist id="languages">
    <option value="HTML">
    <option value="CSS">
    <option value="JavaScript">
    <option value="Java">
    <option value="Ruby And Go">
    <option value="PHP And HTML">
    <option value="Go">
    <option value="Erlang">
    <option value="Python And C++">
    <option value="C">
    <option value="C#">
    <option value="C++">
</datalist>
<script>
  document.querySelector("#default")
  .oninput = function() {
    this.pattern = `[\\w\\s+#]{${this.value.length}}`;
  }
</script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

对于这种情况,有一个非常合理的解决方案:在内部 html 中保留一个空的数据列表(如果为空,它将在焦点事件上填充)并在每个输入事件上使用 Javascript 动态填充它。在 JS 中,最好按字母顺序对选项数组进行排序,以便在已经找到一些巧合并且没有进一步匹配时能够停止迭代。继续这个问题的例子:

const dlOptions = ["C", "C#", "C++", "CSS", "Erlang", "Go", "HTML", "Java",
"JavaScript", "PHP And HTML", "Python And C++", "Ruby And Go"].map(o => {
    return [`<option value="${o}"></option>`, o.toLowerCase()];
});

function completeDataList(e) {
    const fill = val => document.getElementById('languages').innerHTML = val;
    if(!e.target.value) {
        fill(dlOptions.reduce((sum, [html]) => sum + html, ''));
    } else if(!(e instanceof InputEvent)) { // OR: else if(!e.inputType)
        e.target.blur();
    } else {
        const inputValue = e.target.value.toLowerCase();
        let result = '';
        for (const [html, valuePattern] of dlOptions) {
            if (!valuePattern.indexOf(inputValue)) {
                result += html;
            } else if (result) {
                break;
            }
        }
        fill(result);
    }
}

function fillDataListIfEmpty() {
    if(!document.getElementById('languages').innerHTML) {
        completeDataList({ target: {} });
    }
}
<h1>Datalist Demo</h1>
<label for="default">Pick a programming language</label>
<input type="text" id="default" list="languages" oninput="completeDataList(event)" onfocus="fillDataListIfEmpty()">
<datalist id="languages"></datalist>

附言在桌面和移动设备上都非常有用(我在我的项目中使用这种方法,在大约 80 个选项的输入上生成数据列表)。但是,正如上面已经提到的,对于大量选项,使用带有数据库查询的服务器解决方案更为合理。

UPD:在使用这种方法时,应该注意选择一个数据列表选项也会触发一个输入事件(或者,更准确地说,只是一个事件的实例,但不是InputEvent),并且,为了良好的用户体验,应该考虑到这一点(否则选择一个选项后会错误地再次弹出datalist选项); similar situation 带有 keyup 事件。我刚刚更新了代码。

UPD2:我已经根据@heretic-monkey 的建议编辑了函数 completeDataList(详细信息见这篇文章下的评论)。此外,为了性能,选项值数组被转换为另一个静态搜索和 html 模式数组并初始化为全局变量(为了在每个输入事件上使用这些模式,而不是在每个事件上多次重建它们),这在有大量选项和/或频繁调用函数的情况下至关重要。