每个单词下面的Jquery-ui自动完成下拉列表

时间:2013-02-03 12:23:37

标签: jquery jquery-ui autocomplete jquery-ui-autocomplete

我正在使用jquery-ui中的Autocomplete。在多个值中,您可以获得空格后每个单词的下拉列表,但下拉列表显示为输入框的大小。是否有可能使下拉列表出现在每个光标下方,其宽度等于下拉字而不是输入框的整个长度?

编辑:示例(类似Google的搜索框):

当你去谷歌并在句子继续时输入一个长句子,在每个单词之后,为光标位置下方的每个单词出现一个自动完成下拉列表。所以我需要一个类似的下拉列表,可以添加到jQuery Autocomplete

enter image description here

我的功能很大,因为它具有多个单词的功能,并按字母顺序显示数组。 这是<script代码:

    <script>

    $(function() {

            var availableTags = <?php echo json_encode($sometags); ?>;


            function split( val ) {
            return val.split( / \s*/ );
            }
            function extractLast( term ) {
            return split( term ).pop();
            }
             $( "#query" )
            // don't navigate away from the field on tab when selecting an item
            .bind( "keydown", function( event ) {
            if ( event.keyCode === $.ui.keyCode.TAB &&
            $( this ).data( "autocomplete" ).menu.active ) {
            event.preventDefault();
            }
            })
            .autocomplete({
            minLength: 1,
            source: function( request, response ) {
            // delegate back to autocomplete, but extract the last term
            response( $.ui.autocomplete.filter(
            availableTags, extractLast( request.term ) ) );
            var term = $.ui.autocomplete.escapeRegex(request.term)
            , startsWithMatcher = new RegExp("^" + term, "i")
            , startsWith = $.grep(availableTags, function(value) {
                return startsWithMatcher.test(value.label || value.value || value);
            })
            , containsMatcher = new RegExp(term, "i")
            , contains = $.grep(availableTags, function (value) {
                return $.inArray(value, startsWith) < 0 &&
                    containsMatcher.test(value.label || value.value || value);
            });

            response(startsWith.concat(contains));
            },
            focus: function() {
            // prevent value inserted on focus
            return false;
            },
            select: function( event, ui ) {
            var terms = split( this.value );
            // remove the current input
            terms.pop();
            // add the selected item
            terms.push( ui.item.value );
            // add placeholder to get the comma-and-space at the end
            terms.push( "" );
            this.value = terms.join( " " );
            return false;
            }
            });

    });
    </script>
编辑:就像google-box一样,下拉列表应该包含在输入框的宽度范围内,例如,输入框中最后一个单词的下拉框应该不是向右调整,而是向左调整。下拉框的右边缘应与输入框的右边缘对齐,下拉列表的总宽度(如果单词大于或大于输入框)不应超过输入框的宽度。

更新 以下是类似Google的自动填充的最终模式:Fiddle(2013年2月16日更新)
特点:
1)修正多个单词按字母顺序排列建议(jQuery-ui autocomplete multiple values sort results alphabetically
2)从2个阵列中检索建议,第一个建议在输入框的全宽处打开,就像谷歌一样,其余的建议在最长建议的宽度上 3)在“空格”之后输入单词之前修正下拉开放的错误(多个值) 4)防止下拉菜单在最后保持打开状态,同时在两者之间添加单词 5)16/2/2013更新:当从建议框输入的标签长度​​超过输入框的长度和输入下一个标签时,输入框显示第一个标签或者移回第一个标签位置不是从最后放置光标的位置 - http://jqueryui.com/autocomplete/#multiple。这已得到修复。

这是一个类似的小提琴,只使用了一个数组,建议总是在最长建议的宽度 - FIDDLE

感谢Jeffery To提供了问题的主要解决方案,感谢Vadim和Dom,他们的答案提供了有助于创建上述mod的想法。

3 个答案:

答案 0 :(得分:7)

正如其他答案所示,我们测量输入字段中文本的宽度(使用隐藏元素),然后偏移自动完成框。我们还可以重置自动填充框的宽度,使其仅与最长的建议(demo)一样宽:

open: function( event, ui ) {
    var input = $( event.target ),
        widget = input.autocomplete( "widget" ),
        style = $.extend( input.css( [
            "font",
            "border-left",
            "padding-left"
        ] ), {
            position: "absolute",
            visibility: "hidden",
            "padding-right": 0,
            "border-right": 0,
            "white-space": "pre"
        } ),
        div = $( "<div/>" ),
        pos = {
            my: "left top",
            collision: "none"
        },
        offset = -7; // magic number to align the first letter
                     // in the text field with the first letter
                     // of suggestions
                     // depends on how you style the autocomplete box

    widget.css( "width", "" );

    div
        .text( input.val().replace( /\S*$/, "" ) )
        .css( style )
        .insertAfter( input );
    offset = Math.min(
        Math.max( offset + div.width(), 0 ),
        input.width() - widget.width()
    );
    div.remove();

    pos.at = "left+" + offset + " bottom";
    input.autocomplete( "option", "position", pos );

    widget.position( $.extend( { of: input }, pos ) );
}

更新:修正了自动填充框定位

更新2:另一个自动填充框定位修复

答案 1 :(得分:2)

使用JQuery's multiple demo,你可以做的是创建一个隐藏的span元素

<span id="characterSpan" style="visibility: hidden;"></span>

并使用它来存储输入val()

从那里,使用.width()获取跨度的宽度并使用自动填充的open( event, ui )事件:

open: function( event, ui ) {
        var span = $('#characterSpan');
        var width = span.width();
        width > $('#query').width() ? 
        width = parseInt($('#query').position().left + $('#query').width()) : 
        width = parseInt($('#query').position().left + width);

        $('.ui-autocomplete.ui-menu').css('left', width + 'px');
    }

DEMO:http://jsfiddle.net/dirtyd77/5ySF9/8/

希望我能够解释得很清楚,如果您有任何问题,请告诉我!

答案 2 :(得分:1)

我的答案基于this question的答案。正如该答案中所提到的,IE&lt; 9将需要一些额外的代码才能使其发挥作用。

基本上,您创建一个span,您可以在其中写出input元素的内容。然后使用此跨度的宽度计算偏移量。 JqueryUI提供了一个position挂钩,您可以在其中实际抵消该值。 所以HTML

<input id="query" style="width: 300px" />
<span id="faux" style="display:none" />

和JS

    var query= $("#query");
    var faux = $("#faux");
    query.autocomplete({
        source: mySource
    }).on("keydown", function() {
        var off = query.selectionStart;
        faux.text(query.val().substring(0, off).replace(/\s/g, "\u00a0"));
        query.autocomplete("option", "position", 
              {my: "left top", at: "left+" + faux.outerWidth() + " bottom"});
    });

Working JSFiddle