8

我正在尝试使用 Jquery Ui 自动完成实现 Bootstrap Tokenfield, 到目前为止,我能够做到这一点,除了我无法防止输入字段中的重复,因此,不幸的是,我的用户可以选择两次相同的值。

在我的搜索中,我发现 Bootstrap Tokenfield 有一种防止重复的方法。但是我不知道如何应用于我的代码,因为在我看来它与 Twitter typeahead 而不是 Jquery Ui 一起使用。

如何使用 Jquery Ui 自动完成来防止与 Bootstrap TokenField 重复?

这是我基于 jquery ui 自动完成的 Bootstrap TokenField 代码

$('.tokenfield').tokenfield({
  autocomplete: {
    source: [
    {
        "id": "1",
        "value": "Ferdine Faithfull" 
    },
    {
        "id": "2",
        "value": "John Carta" 
    },
    {
        "id": "3",
        "value": "Mezane Smith" 
    }
    ],

    delay: 100
  },
  showAutocompleteOnFocus: true
});

以下是我在 Github 上发现的防止重复的内容,尽管我认为它适用于 Typeahead

$('#my-tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value)
            event.preventDefault();
    });
});
4

3 回答 3

21

我想你已经做到了,你剩下要做的就是替换类

所以在第一个代码之后,而不是第二个代码写

$('.tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value)
            event.preventDefault();
    });
});

这里的区别是你的类必须被应用,它适用于 Twitter Typeahead 和 Jquery Ui

于 2015-02-24T06:12:13.913 回答
1

这可以防止列出已添加为标记的项目:

    $('.tokenfield').on('tokenfield:createdtoken tokenfield:removedtoken', function (event) {
    var field = $(this);
    var currentTokens = field.tokenfield('getTokens');
    var originalSource = field.data('bs.tokenfield').options.autocomplete.source;
    var newSource = originalSource.slice(); //clone original autocomplete source
    for (var i = newSource.length - 1; i >= 0; i--) {
      for (var j = currentTokens.length - 1; j >= 0; j--) {
        if (JSON.stringify(currentTokens[j].label) == JSON.stringify(newSource[i]) 
          || JSON.stringify(currentTokens[j]) == JSON.stringify(newSource[i]) ) {
          //remove the token from the newSource
          var index = newSource.indexOf(newSource[i]);
          if (index > -1) 
            newSource.splice(index, 1);
        };
      };
    };
    //update source
    field.data('bs.tokenfield').$input.autocomplete({source: newSource})
})

此函数在创建或删除令牌后调用以更新列表。它使用 JSON.stringify() 来比较对象,并对字符串对象和 {value: "foo", label: "bar"} 源对象进行比较。

于 2015-04-17T12:05:46.503 回答
1

@Javier您的解决方案效果很好,但有时它会出现错误并添加两倍的令牌!你对这种行为有想法吗?

PS看过文档后,我找到了解决方案。两个事件处理都是需要的。因为在创建/编辑/删除令牌之前和之后都会触发事件。

所以你需要这个来防止添加(在创建事件之前)

$('#tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    //check the capitalized version
    event.attrs.value =  capitalizeFirstLetter(event.attrs.value);
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value) {
            event.preventDefault();
            return false;
        }
    });
});

正如您所建议的,另一个也是源列表(在创建事件之后)

$('#tokenfield').on('tokenfield:createdtoken tokenfield:removedtoken', function (event) {
    var field = $(this);
    var currentTokens = field.tokenfield('getTokens').map(function(i){return i.value});
    var originalSource = field.data('bs.tokenfield').options.autocomplete.source;
    var newSource = [];
    for (var i = 0; i<originalSource.length; i++) {
      if(currentTokens.indexOf(originalSource[i])==-1){
        newSource.push(originalSource[i]);
      }
    };
    //update source
    field.data('bs.tokenfield').$input.autocomplete({source: newSource});
    //empty the input field
    $(".tokenfield.form-control").find("input.token-input").val("");
});

注意:我更改了“检查循环”,(double for 是矫枉过正),并添加了一个检查以避免“大写”匹配,以防万一你需要它。

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
于 2017-02-27T01:17:15.730 回答