【问题标题】:Twitter bootstrap typeahead multiple values?Twitter引导输入多个值?
【发布时间】:2012-09-21 16:26:50
【问题描述】:

我正在使用带有 Jquery 的 Twitter Bootstrap。 我想将 TYPEAHEAD 函数用于 textarea,我可以非常轻松地使用它。 但我也需要它来允许多选

我的意思是,在我从自动完成中选择一个单词后,它会带我回到 textarea 并有一个额外的空间,然后如果我再次开始输入,它会让我再次输入。

这是一个 JS bin:http://jsbin.com/ewubuk/1/edit (里面没什么特别的)。

是否有一个简单的解决方案可以通过预先输入来进行多项选择?如果是,如何?

提前致谢。

【问题讨论】:

    标签: twitter-bootstrap typeahead


    【解决方案1】:

    编辑已经有一个拉动:https://github.com/twitter/bootstrap/pull/2007


    您可以通过使用预先输入的代理来实现所需的行为:Demo (jsfiddle)

    var $myTextarea = $('#myTextarea');
    
    $('.typeahead').typeahead({
        source: source,
        updater: function(item) {
            $myTextarea.append(item, ' ');
            return '';
        }
    });
    

    我认为updater 方法是针对这种事情的,您只需返回将显示的内容即可。


    或者如果你真的希望所有内容都在同一个输入元素中,你将不得不重写更多的方法,以便它只匹配当前输入的元素:Demo (jsfiddle)

    function extractor(query) {
        var result = /([^,]+)$/.exec(query);
        if(result && result[1])
            return result[1].trim();
        return '';
    }
    
    $('.typeahead').typeahead({
        source: source,
        updater: function(item) {
            return this.$element.val().replace(/[^,]*$/,'')+item+',';
        },
        matcher: function (item) {
          var tquery = extractor(this.query);
          if(!tquery) return false;
          return ~item.toLowerCase().indexOf(tquery.toLowerCase())
        },
        highlighter: function (item) {
          var query = extractor(this.query).replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
          return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
            return '<strong>' + match + '</strong>'
          })
        }
    });
    

    这不是白痴证明,因为你必须在最后输入,在特殊字符之后。

    【讨论】:

    • 嗯,这似乎是一个很棒的计划,但它不再适用于 bootstrap 2.3.1。至少对我来说。 updater 方法对我没有任何作用,但字头可以单独使用。
    • 好吧,我错过了 HTML 部分。我把 而不是
    • @IvanIvković 如果您遇到问题,您应该尝试使用 jsfiddle 之类的东西并提出一个新问题(参考这个问题)。但我看到你解决了,太好了!
    • 嗯,很奇怪,即使我贡献了,我仍然无法回答任何问题。 :/ 谢谢。 :)
    • 我在 jsfiddle 和我自己的代码中都遇到了这个问题。只有当您开始输入小写时,它似乎才有效。如果您先键入大写字母,则不会返回任何内容。
    【解决方案2】:

    这是选择框的绝佳替代品:

    http://ivaynberg.github.io/select2/

    (如果您使用多值版本。)

    【讨论】:

    【解决方案3】:

    最佳答案似乎不再适用于最新的typeahead,因此我提供以下内容。

    FIDDLE

    function MultiTypeahead(id, data, trigger, vertAdjustMenu)
    {
        trigger = (undefined !== trigger) ? trigger : '';
        var validChars = /^[a-zA-Z]+$/;
    
    
        function extractor(query)
        {
            var result = (new RegExp('([^,; \r\n]+)$')).exec(query);
            if(result && result[1])
                return result[1].trim();
            return '';
        }
    
        var lastUpper = false;
        function strMatcher(id, strs) 
        {
            return function findMatches(q, sync, async) 
            {
                var pos = $(id).caret('pos');
                q = (0 < pos) ? extractor(q.substring(0, pos)) : '';
    
                if (q.length <= trigger.length)
                    return;
    
                if (trigger.length)
                {
                    if(trigger != q.substr(0, trigger.length))
                        return;
    
                    q = q.substr(trigger.length);
                }
    
                if (!q.match(validChars))
                    return;
    
                var firstChar = q.substr(0, 1);
                lastUpper = (firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase());
    
                var cpos = $(id).caret('position');
                $(id).parent().find('.tt-menu').css('left', cpos.left + 'px');
                if (vertAdjustMenu)
                    $(id).parent().find('.tt-menu').css('top', (cpos.top + cpos.height) + 'px');
    
                var matches = [];
                var matches = [], substrRegex = new RegExp(q, 'i');
                $.each(strs, function(i, str) 
                {
                    if (str.length > q.length && substrRegex.test(str))
                        matches.push(str);
                });
    
                if (!matches.length)
                    return;
    
                sync(matches);
            };
        };
    
        var lastVal = '';
        var lastPos = 0;
        function beforeReplace(event, data)
        {
            lastVal = $(id).val();
            lastPos = $(id).caret('pos');
            return true;
        }
    
        function onReplace(event, data)
        {            
            if (!data || !data.length)
                return;
    
            if (!lastVal.length)
                return;
    
            var root = lastVal.substr(0, lastPos);
            var post = lastVal.substr(lastPos);
    
            var typed = extractor(root);
            if (!lastUpper && typed.length >= root.length && 0 >= post.length)
                return;
    
            var str = root.substr(0, root.length - typed.length);
    
            str += lastUpper ? (data.substr(0, 1).toUpperCase() + data.substr(1)) : data;
            var cursorPos = str.length;
    
            str += post;
    
            $(id).val(str);
            $(id).caret('pos', cursorPos);      
        }
    
        this.typeahead = 
            $(id).typeahead({hint: false, highlight: false}, {'limit': 5, 'source': strMatcher(id, data)})
                    .on('typeahead:beforeselect', beforeReplace)
                    .on('typeahead:beforeautocomplete', beforeReplace)
                    .on('typeahead:beforecursorchange', beforeReplace)
                    .on('typeahead:selected', function(event,data){setTimeout(function(){ onReplace(event, data); }, 0);})
                    .on('typeahead:autocompleted', onReplace)
                    .on('typeahead:cursorchange', onReplace)
                    ;
    }
    

    编辑:意识到前面的代码有太多额外的东西,我将其缩小到一个最小的工作示例。

    This 是之前发布的内容..

    【讨论】:

    • +1 用于更新旧代码,虽然这很容易做到。我知道您为什么使用正则表达式,但它确实混淆了为他人编辑您的代码。唯一的其他事情 - 在我看来会改善你的答案 - 是新行而不是同一行并且不使用@。
    【解决方案4】:

    我想您可以编辑插件以允许多项选择(只是不要关闭下拉菜单)并添加以逗号分隔的选定值。我看到的唯一问题是您不知道何时关闭下拉菜单。

    【讨论】:

      【解决方案5】:

      我迟到了,但这是我为 Bootstrap v4 提出的。 它还需要 d3(因为我对 jQuery 不太熟悉)。

      您可以在http://sumneuron.gitlab.io/multitags/ 看到一个运行示例

      它有一些有用的功能,写得很清楚,应该让任何发现它的人有个好的开始。特别是如果您对如何实现标记感到好奇。

      代码可在https://gitlab.com/SumNeuron/multitags/pipelines获取

      逻辑大致如下:

      if keydown in [enter, ","]:
          // logic of function "doneTyping" 
          text = parse(text) // get text from textarea and grab latest value
          if text is valid:
              renderTag(text) // put the text in a tag element
              updateHiddenForm(text) // update the hidden form to include the tag
          else:
              notifyUserOfInvalidTag(text) // alert user
      else:
          // logic of function "stillTyping" 
          suggest = bloodhoundSearch(text) // use twitter typeahead
          updateSuggestionBox(suggest) // display results from typeahead
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-27
        • 2013-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多