以编程方式触发 typeahead.js 结果显示

Posted

技术标签:

【中文标题】以编程方式触发 typeahead.js 结果显示【英文标题】:Programmatically triggering typeahead.js result display 【发布时间】:2013-02-13 10:26:49 【问题描述】:

我在从查询字符串预填充的输入字段上使用 Twitter 的 typeahead.js (https://github.com/twitter/typeahead.js/)。加载页面后,我想以编程方式触发预输入结果的显示,而用户无需在表单字段中输入任何内容。

开箱即用,仅当用户在输入字段中手动输入内容时才会触发 typeahead.js,而我在 typeahead.js 中找不到任何可以调用来触发结果显示的方法。

任何指针将不胜感激。

谢谢!

【问题讨论】:

感谢大家的精彩回答!我通过触发输入选择了一个,因为这也强制输入在显示结果之前搜索关键字(对我的要求,我意识到这不是我的问题)。再次感谢。 *** 比切片面包好得多。 可以使用prefetch功能 【参考方案1】:

触发输入似乎可以做到。

$(".typeahead").eq(0).val("Uni").trigger("input");

在example page 上对此进行了测试。

【讨论】:

嗨,除了在 IE 中(谁会猜到),它的效果很好。 IE 似乎只是返回一个 jQuery 对象,如下所示:shorttext.com/SuWiMi 我在 JS 中的调试能力不够好,所以如果有人有建议,我很想听听。谢谢! 换成"paste"而不是"input" 没有"Uni",你能做到吗? =\ 对于任何查看此内容以获取更高版本的预输入的人,您可以使用$(".typeahead").typeahead("setQuery","Uni").focus();,因为setQuery 是设置查询值的首选 API 方法。 @Pricey:我认为 setQuery 在 0.10 中已被删除。我试过了,我得到一个错误【参考方案2】:

根据我的测试(参见fiddle),为了显示下拉菜单,需要使用focus() 方法。所以:

theVal = $('.typeahead').val();
$(".typeahead").typeahead('val', '')
$(".typeahead").focus().typeahead('val',theVal).focus();
在第 1 行,我们将 Typeahead 输入的当前值分配给变量 theVal; 在第 2 行,我们简单地重置 typeahead 的计算值;和 在第 3 行,我们将原始值放回 焦点,这会导致建议下拉菜单显示为好像用户输入了某些内容。

我实际上需要这个来强烈鼓励用户从来自地理编码 API 调用的 Bloodhound 建议中进行选择,这样我就可以确保在提交表单之前由客户端获取坐标。

【讨论】:

【参考方案3】:
$(".typeahead").typeahead('lookup').focus();

使用现有输入值触发。你当然可以提前更改值

【讨论】:

【参考方案4】:

对于任何在 0.11.1 版之后使用 twitter 的 typeahead 发现这个问题的人,我是这样用一行来解决它的:

$(".typeahead-input").typeahead('val', "cookie")
                     .trigger("input")
                     .typeahead('open');

【讨论】:

【参考方案5】:

从 Typeahead v0.10.1 开始,更改 typeahead 的值将触发另一个查询并打开下拉列表:

var val = $(".typeahead").typeahead('val');
$(".typeahead").typeahead('val', '');
$(".typeahead").typeahead('val', val);

【讨论】:

这是唯一对我有用的(v0.11.1),除了我必须将第一行更改为:var val = $("#original-input-id").typeahead('val'); 其中#original-input-id 是我的输入文本字段的 id我添加了.typeahead【参考方案6】:

我使用了 twitter bootstrap typeahead,并希望在焦点上,建议列表将打开。 这里的答案不太适合我,所以我写了这个简单的指令(需要 jquery):

.directive('typeaheadFocusTrigger', function() 
        return 
            limit: 'A',
            link: function(scope, element, attrs) 
                $(element).on('focus', function(e) 
                    var $target = $(e.target);
                    var origVal = $target.eq(0).val();
                    $target.eq(0).val('').trigger('input')
                    .eq(0).val(origVal).trigger('input');
                );
            
        
    );

现在只要添加这个属性,它就会在焦点上触发

<input typeahead-focus-trigger typeahead="">

【讨论】:

trigger('input') 不在 IE 上所以只需将其更新为:trigger('change') 用于所有浏览。【参考方案7】:

使用:Typeahead v0.10.5

不要使用: $('.typeahead').typeahead('open');

这目前不起作用。来源:https://github.com/twitter/typeahead.js/issues/798。 作为临时修复,使用自定义 jQuery keydown 事件(在您实例化预输入之后):

var ttInstance = $('.typeahead').typeahead( config ); // Create Typeahead
ttInstance.typeahead('val', 'pancakes'); // Set an initial value

var evt = jQuery.Event('keydown');
evt.keyCode = evt.which = 40;
ttInstance.trigger(evt); // Opens the dropdown

【讨论】:

在这里给出的所有答案中,这是唯一对我有用的答案。【参考方案8】:

查看源代码,似乎在typeahead键下的元素数据中存储了一个TypeaheadView对象。这个TypeaheadView 对象有一个内部方法_showDropdown,它在内部绑定到焦点事件(以及其他一些事件)。

我不建议这样做,但您应该可以手动调用该内部方法:

$('#yourTypeaheadElement').data('typeahead')._showDropdown();

或者,您是否尝试过在页面加载时简单地聚焦您的 typeahead 元素(当然是在将其初始化为 typeahead 元素之后):

// after page loads and yourTypeaheadElement is initialized as a typeahead
$('#yourTypeaheadElement').focus();

【讨论】:

这似乎不适用于 typeahead*.js*。【参考方案9】:

除非您故意将“typeahead”放入输入标签的类中,否则这些都不起作用。如果你觉得不需要这样做(它没有必要工作),你最好使用 typeahead.js 写入输入标签的类。它是“.tt 输入”。这是我从 Sam_Butler 抄录的示例,为新的 CSS 类重新编码。这在最新的 typeahead 0.10.5 中适用于我:

var theVal = jQuery('.tt-input').val();
jQuery(".tt-input").typeahead('val', 're')
jQuery(".tt-input").focus().typeahead('val',theVal).focus();

【讨论】:

【参考方案10】:

查看了源码,发现了这种无证的方式:

var $myinput = $('#myinput');
$myinput.data('typeahead')._showDropdown()

【讨论】:

【参考方案11】:

这应该适用于“旧”引导预输入插件:

$(".typeahead").eq(0).trigger("keyup");

不幸的是,还没有用 IE 测试过...... 不知道新的 typeahead 插件...

【讨论】:

【参考方案12】:

这是@Sam_Butler 作品的简化版:http://jsfiddle.net/rimian/hrnf9

<button type="button" id="button">Crick</button>
<input type="text" id="text" class="typeahead">

javascript

$('#button').click(function() 
  $("#text").focus().typeahead('val', 'London');
);

// instantiate the bloodhound suggestion engine
var locations = new Bloodhound(
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: 
        url: 'https://maps.googleapis.com/maps/api/geocode/json?address=%QUERY&components=country:GB&sensor=false&region=uk', //add key
        filter: function (locations) 
            return $.map(locations.results, function (location) 
                return 
                    value: location.formatted_address
                ;
            );
        
    
);

locations.initialize();

$('#text').typeahead(null, 
    name: 'value',
    displayKey: 'value',
    source: locations.ttAdapter()
);

【讨论】:

这对我很有用。我已经在文本字段中有一个值,所以我只是将它保存在一个 var 中,在 typeahead 中清空 val,然后再次设置 prev 值并打开搜索。也许是一个 hack,但工作正常。【参考方案13】:

小心这个!

对于那些正在考虑手动触发 typeahead 行为(例如单击按钮)的人,我强烈建议您不要这样做。

我是为这个解决方案而来的,但我花了将近一整天的时间来解决它的问题(在我的例子中,这是一个按钮点击)。

对于那些真正想走这条黑暗道路的人,我与你分享我的丑陋代码,使其工作:

//Removes default features of typeahead
//This means that typeahead will not work like an "autocomplete", it only will be trigged when the user Click in #btnSearch button!
var txt = $("#typeahead");
//Save input events in variables (we'll need them)
eventInput = $._data(txt[0], "events").input[0];
eventBlur = $._data(txt[0], "events").blur[1];
//Remove input events
txt.unbind("blur");
txt.unbind("input");

//Set click event that triggers typeahead features manually
$("#btnSearch").click(function () 
    //Clears the cache of engine for it call ajax again, without it when the term was already searched the ajax is not called!
    engine.clearRemoteCache();

    txt.focus(); //When we click in a button, the focus from input is lost, so we set it again to not lose the behaviors of keyboard keys (up, down, tab, etc)
    txt.bind("input", eventInput); //Bind the event that we had saved
    txt.trigger("input"); //Trigger input (like the answer from @epascarello)
    txt.unbind("input"); //Removes it again 
);

//Set event on parent of the suggestion's div, this makes the sugestion div close when user click outside it
$("body").click(function ()             
    if (eventBlur != undefined) 
        if ($(".tt-dropdown-menu:visible").length > 0) 
            eventBlur.handler(); //This event closes the suggestion menu
        
    
);

我做的另一件事是更改 typeahead.js 上的事件 "_checkInputValue" 的代码。我改变了这个:

areEquivalent = areQueriesEquivalent(inputValue, this.query);

到这里:

areEquivalent = false;//areQueriesEquivalent(inputValue, this.query);

我将它设置为 false 因为 typeahead 不要向服务器发送两个相同的请求。当用户在搜索按钮中单击两次时会发生这种情况(我的意思是,当他多次搜索他已经搜索过的相同文本时)。无论如何,如果您使用的是本地数据,则不需要这样做。

【讨论】:

【参考方案14】:

这对我有用。

$( document ).ready(function() 
    $('#the-basics .typeahead').typeahead(
      hint: false,
      highlight: true,
      minLength: 0
    ,
    
      name: 'states',
      displayKey: 'value',
      source: substringMatcher(states)
    );

    //set a value to input to trigger opening
    $(".typeahead").eq(0).val("a").trigger("input");
    //remove value for end user
    $(".typeahead").eq(0).val("");

);

请参见此处,例如:http://joshuamaynard.com/sandbox/autocomplete

【讨论】:

【参考方案15】:

其他答案很有帮助,但没有解决我的问题。此解决方案不涉及自定义任何 angular-ui 代码本身,并且仅用于触发 typeahead 以在显式按钮单击时获取结果。

为此,我必须将一个文本字段覆盖在另一个(禁用的)文本字段之上,该文本字段是具有预输入功能的实际文本字段。没有人会知道另一个在那里,但它需要在那里 angular-ui 才能在正确的位置启动菜单。您不能将其设为隐藏字段,因为它将无法在正确的位置显示菜单。

下面的指令将监视typeaheadTexttypeaheadTrigger 变量以在按钮触发时填充禁用字段(通过将触发器设置为true)。该指令具有隔离范围,因此它不依赖于传入之外的任何内容。

directive('typeaheadTrigger', function() 
  return 
    require: ["ngModel"],
    scope: 
      typeaheadText: '=',
      triggerFlag: '='
    ,
    link: function(scope, element, attr, ctrls) 
      scope.$watch('triggerFlag', function(value) 
        if (scope.triggerFlag) 
          ctrls[0].$setViewValue(scope.typeaheadText);
          scope.typeaheadText = '';
          scope.triggerFlag = false;
        
      );
    
  ;
)

控制器为此设置了一些东西 - 对象内的触发器和文本范围变量。这演示了如何做到这一点 - 理想情况下,您会将整个内容包装在另一个指令中,以便可以在您的应用程序中使用它,同时隐藏细节。

这是笨蛋:http://plnkr.co/edit/UYjz6F5ydkMQznkZAlfx?p=preview

【讨论】:

【参考方案16】:

当 tt 数据集中有 1 个项目时,我使用它手动触发选择。添加这个很有意义。

$("#mytypeahead").keyup(function (e) 
                var charCode = (typeof e.which === "number") ? e.which : e.keyCode;
                if (charCode == 13) 
                    if ($(this).parent().find(".tt-dataset").children().length == 1) 
                        //This is how we are submitting a single selection on enter key
                        $(this).parent().find(".tt-dataset").children(0).addClass("tt-cursor");
                        var kde = jQuery.Event("keydown");
                        kde.which = 13;
                        $(this).trigger(kde);                           
                        
                                    
            );

【讨论】:

【参考方案17】:

我在这里尝试了所有方法,但它不起作用,只有使用

$(".typeahead").val('hi').trigger('keyup');
$(".typeahead").val('hi').trigger('keydown');

上面的代码对我有用。不知道到底发生了什么,但两者都不使用,只有同时使用才会奏效。

【讨论】:

以上是关于以编程方式触发 typeahead.js 结果显示的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法关闭typeahead.js的下拉菜单?

twitter typeahead ajax结果未全部显示

Typeahead.js / Bloodhound 只显示一个结果 [重复]

TypeAhead.js 和 Bloodhound 显示奇数​​个结果

typeahead.js 不返回所有结果

使用 Django 通过远程数据提高 Twitter 的 typeahead.js 性能