如何在输入更改事件之前获得Bootstrap预先输入单击结果

How to get Bootstrap typeahead click result before the input change event

本文关键字:输入 Bootstrap 单击 结果 事件      更新时间:2023-09-26

我正在尝试使用bootstrap typeahead作为用户的灵活选择。因此,如果项目是已知的,他们选择它,如果不是一个对话框打开,让他们进入一个新的项目。

我通过观察输入上的更改事件来做到这一点,如果输入val不在源数组中(对于前面的输入),那么"添加项"对话框将显示给用户。问题是,如果用户单击其中一个选项,则在typeahead有机会设置val之前发送更改事件,这是因为单击将导致文本模糊。

我想检查活动元素来解决这个问题,所以在change事件中查看document。并查看它是否是typeahead选项之一,这不起作用,返回整个body元素。

下面是代码的精简版本:

<div id="contactModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel">Unknown Contact</h3>
  </div>
  <div class="modal-body">
    <p>The contact you have entered is unknown. Press cancel to enter a different contact or fill out the details below to create a new contact</p>
    <label>Name</label>
    <input id="modal_contact"  type="text" placeholder="dealership contact" value=""/>
    <label>Email</label>
    <input id="modal_contact_email" type="text" placeholder="dealership contact" value=""/>
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <button id="save" class="btn btn-primary">Save changes</button>
  </div>
</div>
Javascript

var contacts = ['pete','geoff'];
$('.typeahead').typeahead({source:contacts, updater : function(item){
    console.log('updater fired'); //fires after first change event
    return item;
}});
$('input').change(function(ev){
    console.log($(ev.target).val());
    if ($.inArray($(ev.target).val(), contacts) < 0)
        $('#contactModal').modal();
})

和JSFiddle版本http://jsfiddle.net/k39vM/

有谁知道我如何测试用户是否点击了提前输入,以找出是否导致了更改事件?

我之前的建议实际上没有工作,因为,正如你提到的,有一个有点意想不到的blur事件触发change 事件之前的菜单上的click。我假定它与Typeahead.prototype.select方法内部的this.hide()调用有关。

然而,经过一些尝试和错误,我确实认为我可能已经找到了一个解决方案。实际上,导致问题的不是select方法中的this.hide()调用。知道有两种方法可以让用户触发选择,这有助于理解希望工作的解决方案(我只在Chrome中测试过):使用键盘,比如按回车键,或者点击项目。因此,知道单击是这两个问题的子问题后,我注意到当用户将鼠标放在下拉菜单上时维护mousedover事件。

因此,可以在change事件中手动忽略异常行为。为了简化确定导致下一个 change事件的实际原因的过程,我使用了一个名为"selected"的不同(自定义)事件来表示用户更改了值,而不是标准的change。不幸的是,当mousedover属性为true时,您仍然必须手动忽略change事件:

简化的HTML(我使用了p标签,因为我发现Chrome在调试JSFiddle的JavaScript时遇到了麻烦,并且与控制台结合会导致糟糕的时间):

<input class="typeahead " type="text" placeholder="contact" value="Peter skillet"></input>
<input type="text"></input>
<p id="text" />

JavaScript(对于感兴趣的人,可以用console.log替换文本):

var contacts = ['pete', 'geoffrey'];
var $text = $("#text");
var typeahead = $('.typeahead').typeahead({source: contacts}).data('typeahead');
typeahead.select = function () {
    var val = this.$menu.find('.active').attr('data-value');
    this.$element.val(this.updater(val))
        .trigger('selected'); // <- unique event
    return this.hide()
};
$('input.typeahead').on('change', function (e) {
    var $target = $(e.target);
    if (typeahead.mousedover) {
        $text.html($text.html() + "mousedover [ignored selection]<br />");
    }
    else if ($.inArray($target.val(), contacts) < 0) {
        $text.html($text.html() + "show add<br/>");
    }
}).on('selected', function () {
    $text.html($text.html() + "selected<br />");
});
作为参考,这是默认的select方法:

select: function () {
  var val = this.$menu.find('.active').attr('data-value')
  this.$element
    .val(this.updater(val))
    .change()
  return this.hide()
}

更简单的解决方案是在单击事件中包含以下内容:

var typeahead = $(this).data("typeahead");
if (typeahead && this.value != typeahead.$menu.find('.active').attr('data-value')) 
  return;
如果附加了

,第一行将检索提前键入的内容。第二个将确保当前值与所选值匹配。

您还可以在if中检查typeahead.mousedover,以允许无效的(意味着没有提前输入选项)输入,当控件失去焦点而不进行选择时,仍然触发默认的更改行为。