使用数据列表实现多项选择

31

我正在使用 datalist 标签为搜索框创建建议列表,但是我无法从数据列表中选择多个值。目前,我的 HTML 代码如下:

<html>

  <form action="search_tags.php" method="GET"/>

  Search: <input type="text" multiple="multiple" name="search" list="tags" autocomplete="off" />

  <datalist id="tags">
    <option value="black">
    <option value="gold">
    <option value="grey">
    <option value="pink">
    <option value="turquoise">
    <option value="red">
    <option value="white">
  </datalist>

</html>

它将为一个选项提供建议,但之后建议不会为我的第二个选项提供自动完成。我以为只需要使用'multiple'标签(这也是网上建议的),但它似乎没有期望的效果。

有什么建议吗?


2
根据MDN的说法,multiple仅适用于“电子邮件”和“文件”类型。我认为对于传统的文本字段,你可能需要使用像select2.js这样的东西。 - Mike Robinson
1
很不幸 :( 有没有任何不使用jquery的javascript包可以做到这一点? - nathan lachenmyer
大多数解决方案都依赖于库,因为涉及到相当数量的DOM操作。有select2(jQuery),chosen(jQuery或Prototype),jQuery UI自动完成(jQuery)。我认为在那之后你会进入不太可靠的解决方案。为什么不能使用jQuery? - Mike Robinson
现在有没有新的选项来完成相同的任务? - pHM
5个回答

25

目前仅在Chrome和Opera浏览器中,与input type="email"一起使用时才能多重检查电子邮件地址。

看看这个极简的例子:

input{width:500px}
<input type="email" list="emails" multiple>
<datalist id="emails">
    <option value="first@example.com">
    <option value="second@example.com">
    <option value="third@example.com">
    <option value="last@example.com">
</datalist>

<br><br><br>

<input type="text" list="texts" multiple>
<datalist id="texts">
    <option value="black">
    <option value="gold">
    <option value="grey">
    <option value="pink">
    <option value="turquoise">
    <option value="red">
    <option value="white">
</datalist>

第一个输入框可用,第二个不可用。

您只需按逗号键,列表就会出现,与单击输入框时一样。

还有一个填充插件,请查看fiddle中的示例:https://jsfiddle.net/iiic/gprLnuwy/4/


17
有人知道为什么目前只支持 type="email" 吗?太奇怪了! - Nick Grealy
5
也许是因为标准文件仅在电子邮件(地址字段和附件)的上下文中展示了该属性的工作方式,浏览器厂商不愿迈出标准所明确规定的范围。 - bishop
4
@bishop - 哇,我真的希望那不是原因......因为那太可悲了。W3C提供了"一个例子",而每个人都故意忽视了意图,并实施了最低限度(只是为了打勾"支持/兼容"?)。我有什么遗漏吗? - Nick Grealy
1
我认为就是这样,@NickGrealy:在规范中,最好只实现并且仅实现规定的内容,而不管意图是否明显。实现任何隐含的内容都会冒着违反未来需求的风险,在最坏的情况下将自己限制在一个死角里,或者在最好的情况下撤销工作。 - bishop

5

超级简单的jQuery工具:Flexdatalist

我希望找到一个更简单的方式,但据我所知,“multiple”属性只适用于电子邮件和文件,因为HTML5开发人员不想打开“无底洞”,但是开发人员正在考虑修改。在搜索了所有资源之后,我唯一可以让它起作用的方法是也获得那些像许多网站上那样的漂亮、有用的列表项“#tagHere X”。它要么全部出现,要么一个也没有,它解决了我的问题。

不幸的是,我找不到如何使用 Flexdatalist 的完整说明。因此,我包含了一个超级完整的演练,并附有一个可工作的示例,如果它太多请见谅...

1.从GitHub获取Flexdatalist仅需两个文件

  • jquery.flexdatalist.min.js
  • jquery.flexdatalist.css(您也可以使用.min.css,但您可能想调整CSS)

2.将这两个文件放在正确的位置:

我使用了:

[DOMAIN]/js/jquery.flexdatalist.min.js

[DOMAIN]/css/jquery.flexdatalist.css

3. 包含CSS文件

方式一:

  • @import "jquery.flexdatalist.css"; 在你的 style.css 文件中,该文件已经在 [DOMAIN]/css/ 中存在。

或者

  • <link href="css/jquery.flexdatalist.css" rel="stylesheet" type="text/css"> 在包含 datalist 的页面的<head>标签之间。

4. 在包含 datalist<input> 元素中添加以下属性

(与其他属性一起添加)

  • <input... class="flexdatalist form-control" data-min-length="1" data-searchContain="true" multiple="multiple" ...>

5. 在 datalist 之后添加 三个 JavaScript 语句

<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="js/jquery.flexdatalist.min.js"></script>
<script>
$('.flexdatalist-json').flexdatalist({
     searchContain: false,
     valueProperty: 'iso2',
     minLength: 1,
     focusFirstResult: true,
     selectionRequired: true,
});
</script>

工作示例:

[域名]/index.html

<!DOCTYPE html>
<html>
<head>
<title>Flexdatalist Minimalist</title>
<link href="jquery.flexdatalist.css" rel="stylesheet" type="text/css">
</head>
<body>

<input type="text" placeholder="Choose a fruit"

  class="flexdatalist form-control"
  data-min-length="1"
  data-searchContain="true"
  multiple="multiple"

list="fruit" name="my-fruit">
<datalist id="fruit">
  <option value="Apples">Apples</option>
  <option value="Bananas">Bananas</option>
  <option value="Cherries">Cherries</option>
  <option value="Kiwi">Kiwi</option>
  <option value="Pineapple">Pineapple</option>
  <option value="Zucchini">Zucchini</option>
</datalist>

<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="jquery.flexdatalist.min.js"></script>
<script>
$('.flexdatalist-json').flexdatalist({
     searchContain: false,
     valueProperty: 'iso2',
     minLength: 1,
     focusFirstResult: true,
     selectionRequired: true,
});
</script>

</body>
</html>

这里有两个文件:

[DOMAIN]/js/jquery.flexdatalist.min.js

[DOMAIN]/css/jquery.flexdatalist.css

一个备选方案,有着非常好的文档,是:Awesomeplete


这对我有用,但是我遇到了一个与searchContain: true相关的问题。它需要改为search-contain: true才能正常工作。 - Peurke
@Peurke 不确定如何帮助。如果您找到了方法,可以在此处添加另一个答案。 - Jesse

3
我找到了一种不使用任何外部工具的解决方法。
HTML示例
<input type="email" class="multidatalist" multiple="multiple" name="search" list="tags" autocomplete="off" />
  <datalist id="tags">
    <option value="black">
    <option value="gold">
    <option value="grey">
  </datalist>

jQuery代码(也可以在JavaScript中完成)

$(".multidatalist").focusin ( function() { $(this).attr("type","email"); });    
$(".multidatalist").focusout( function() { $(this).attr("type","textbox"); });

当你单击输入框时,这基本上将其设置为“电子邮件”类型,因此HTML5多重数据列表正常工作。

然后当你从输入框中点击出来时,输入框会切换回“文本框”,以便你可以提交表单而不受电子邮件限制的影响。

这对我很有效,使我不必使用更复杂的jQuery / JavaScript插件。


将标题设置为“用逗号分隔的添加颜色”,这样在输入项目时,电子邮件的验证错误就不会混淆了。 - Martlark

3
根据此文,'multiple'属性仅适用于电子邮件文件输入类型。

2

自定义数据列表以接受多个值:

在每个条目后按逗号(,),然后按空格键

var datalist = jQuery('datalist');
var options = jQuery('datalist option');
var optionsarray = jQuery.map(options ,function(option) {
        return option.value;
});
var input = jQuery('input[list]');
var inputcommas = (input.val().match(/,/g)||[]).length;
var separator = ',';
        
function filldatalist(prefix) {
    if (input.val().indexOf(separator) > -1 && options.length > 0) {
        datalist.empty();
        for (i=0; i < optionsarray.length; i++ ) {
            if (prefix.indexOf(optionsarray[i]) < 0 ) {
                datalist.append('<option value="'+prefix+optionsarray[i]+'">');
            }
        }
    }
}
input.bind("change paste keyup",function() {
    var inputtrim = input.val().replace(/^\s+|\s+$/g, "");
  //console.log(inputtrim);
    var currentcommas = (input.val().match(/,/g)||[]).length;
  //console.log(currentcommas);
    if (inputtrim != input.val()) {
        if (inputcommas != currentcommas) {
            var lsIndex = inputtrim.lastIndexOf(separator);
            var str = (lsIndex != -1) ? inputtrim.substr(0, lsIndex)+", " : "";
            filldatalist(str);
            inputcommas = currentcommas;
        }
        input.val(inputtrim);
    }
});
html,
body {
  display: flex;
  align-items:center;
  flex-direction: column;
  justify-content: center;
  min-height: 100%
}

label {
  display: block;
  font-size: 15px;
  padding: 10px 0;
}
input {
  border: 2px solid #1E824C;
  color: #333;
  font-size: 12px;
  padding: 5px 3px
}
small {
  display: block;
  font-size: 11px;
  padding-top: 5px;
}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>

<label for="authors">Type authors from favorite to least favorite</label>
<input type="text" list="names-list" id="authors" value="" size="50" name="authors" placeholder="Type author names">
<small>You can type how many you want.</small>
<datalist id="names-list">
  <option value="Albert Camus">
  <option value="Alexandre Dumas">
  <option value="C. S. Lewis">
  <option value="Charles Dickens">
  <option value="Dante Alighieri">
</datalist>


1
当我按下回车键后再按空格键时,空格会立即被删除。在哪个浏览器中它能像你所描述的那样工作? - YakovL
在每次选择后按逗号和空格键。上述的jsfiddle链接在Chrome上对我来说很好用。 - Neil
1
啊,抱歉,我误读成“按回车键然后再按空格键”。不过,在按下空格键后,我确实会看到下拉菜单,但是空格键本身会被删除,因此一旦我开始输入名称,下拉菜单就会消失。不过,它可以通过“逗号-空格-第一个字母-左箭头-空格-右箭头”的方式工作(在这个顺序中,空格不会被删除)。包括在Chrome中。 - YakovL
然而,你的方法确实很有帮助和发人深省。 - YakovL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接