如何在输入更改事件之前获取Bootstrap typeahead click结果

时间:2013-04-03 01:35:22

标签: javascript twitter-bootstrap onchange bootstrap-typeahead

我正在尝试使用bootstraps typeahead作为用户的灵活选择。因此,如果该项目已知,则如果没有打开对话框则允许他们输入新项目。

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

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

以下是代码的精简版:

HTML     

<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/

是否有人知道我如何测试用户是否点击了预先输入以查明是否导致了更改事件?

2 个答案:

答案 0 :(得分:4)

我之前的建议并没有真正起作用,因为正如您所提到的那样,在事件{{1}之前触发blur 之前会发生一些意外的change事件在菜单上。我原以为它与click方法中的this.hide()调用有关。

然而,经过一些反复试验后,我确实认为我可能找到了workaround。它实际上并不是导致问题的Typeahead.prototype.select方法中的this.hide()调用。知道用户有两种方式可以触发选择有助于理解希望工作的解决方法(我只在Chrome中测试过):使用键盘,例如点击输入或点击项目。因此,我知道点击是两个问题的孩子,我注意到当用户将鼠标悬停在下拉列表上时,会保留select事件。

因此,可以在mousedover事件中手动忽略。为了简化确定实际导致 next change事件的原因的过程,我使用了一个名为&#34; change&#34;的另一个(自定义)事件。表示用户已更改值而不是标准selected。不幸的是,当change属性为change时,您仍必须手动忽略mousedover个事件:

简化的HTML(我使用了true代码,因为我发现Chrome在调试JSFiddle的JavaScript方面遇到了问题,并且与控制台结合导致了糟糕的时间):

p

JavaScript(感兴趣的人可以用<input class="typeahead " type="text" placeholder="contact" value="Peter skillet"></input> <input type="text"></input> <p id="text" /> 替换文字):

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

答案 1 :(得分:3)

问题的一个稍微简单的解决方案是在点击事件中包含以下内容:

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

如果附加了第一行将检索预先输出。第二个将确保当前值与所选值匹配。

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