我在从查询字符串预填充的输入字段上使用 Twitter 的 typeahead.js ( https://github.com/twitter/typeahead.js/ )。加载页面后,我想以编程方式触发预输入结果的显示,而用户无需在表单字段中输入任何内容。
开箱即用,仅当用户在输入字段中手动输入内容时才会触发 typeahead.js,并且我在 typeahead.js 中找不到任何可以调用来触发结果显示的方法。
任何指针将不胜感激。
谢谢!
我在从查询字符串预填充的输入字段上使用 Twitter 的 typeahead.js ( https://github.com/twitter/typeahead.js/ )。加载页面后,我想以编程方式触发预输入结果的显示,而用户无需在表单字段中输入任何内容。
开箱即用,仅当用户在输入字段中手动输入内容时才会触发 typeahead.js,并且我在 typeahead.js 中找不到任何可以调用来触发结果显示的方法。
任何指针将不胜感激。
谢谢!
根据我的测试(见fiddle),focus() 方法是显示下拉菜单所必需的。所以:
theVal = $('.typeahead').val();
$(".typeahead").typeahead('val', '')
$(".typeahead").focus().typeahead('val',theVal).focus();
我实际上需要这个来强烈鼓励用户从来自地理编码 API 调用的 Bloodhound 建议中进行选择,这样我就可以确保在提交表单之前由客户端获取坐标。
$(".typeahead").typeahead('lookup').focus();
使用现有输入值触发。您当然可以提前更改值
对于任何在 0.11.1 版本之后发现 twitter 的 typeahead 问题的人,以下是我如何用一行来解决它:
$(".typeahead-input").typeahead('val', "cookie")
.trigger("input")
.typeahead('open');
从 Typeahead v0.10.1 开始,更改 typeahead 的值将触发另一个查询并打开下拉列表:
var val = $(".typeahead").typeahead('val');
$(".typeahead").typeahead('val', '');
$(".typeahead").typeahead('val', val);
我使用了 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="">
使用: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
查看源代码,它似乎TypeaheadView
在 key 下的元素数据中存储了一个对象typeahead
。该TypeaheadView
对象有一个内部方法 ,_showDropdown
它在内部绑定到焦点事件(以及其他一些事件)。
我不建议这样做,但您应该能够手动调用该内部方法:
$('#yourTypeaheadElement').data('typeahead')._showDropdown();
或者,您是否只是尝试在页面加载时简单地聚焦您的 typeahead 元素(当然,在将其初始化为 typeahead 元素之后):
// after page loads and yourTypeaheadElement is initialized as a typeahead
$('#yourTypeaheadElement').focus();
除非您故意将“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();
我查看了源代码,发现了这种未记录的方式:
var $myinput = $('#myinput');
$myinput.data('typeahead')._showDropdown()
这应该与“旧”引导预输入插件一起使用:
$(".typeahead").eq(0).trigger("keyup");
不幸的是,没有用 IE 测试过......不知道新的 typeahead 插件......
这是@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®ion=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()
});
对于那些正在考虑手动触发 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不会向 server 发送两个相同的请求。当用户在搜索按钮中单击两次时会发生这种情况(我的意思是,当他多次搜索他已经搜索过的相同文本时)。无论如何,如果您使用的是本地数据,则不需要这样做。
这对我有用。
$( 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
其他答案很有帮助,但没有解决我的问题。此解决方案不涉及自定义任何 angular-ui 代码本身,并且仅用于触发 typeahead 以在显式按钮单击时获取结果。
为此,我必须将一个文本字段覆盖在另一个(禁用)文本字段的顶部,该文本字段是带有预输入的实际文本字段。没有人会知道另一个在那里,但它需要在那里 angular-ui 才能在正确的位置启动菜单。您不能将其设为隐藏字段,因为它将无法在正确的位置显示菜单。
当按钮触发时(通过将触发器设置为 true) ,下面的指令将监视typeaheadText
和typeaheadTrigger
变量以填充禁用字段。该指令具有隔离范围,因此它不依赖于传入之外的任何内容。
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;
}
});
}
};
})
控制器为此设置了一些东西 - 对象内的触发器和文本范围变量。这演示了如何做到这一点 - 理想情况下,您会将整个内容包装在另一个指令中,以便可以在您的应用程序中使用它,同时隐藏细节。
这是plunk:http ://plnkr.co/edit/UYjz6F5ydkMQznkZAlfx?p=preview
当 tt-dataset 中有 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);
}
}
});
我在这里尝试了所有方法,但它不起作用,只能使用
$(".typeahead").val('hi').trigger('keyup');
$(".typeahead").val('hi').trigger('keydown');
上面的代码对我有用。不知道到底发生了什么,但使用两者都没有起作用,只有同时使用它才起作用。