twitter-bootstrap 如何在输入更改事件之前获得 Bootstrap 预先输入点击结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15777398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 16:48:49  来源:igfitidea点击:

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

javascripttwitter-bootstraponchangebootstrap-typeahead

提问by Dan Walmsley

I am trying to use bootstraps typeahead as a flexible select for users. So if the item is known they select it if not a dialogue opens up allowing them to enter a new item.

我正在尝试使用引导程序预先输入作为用户的灵活选择。因此,如果该项目是已知的,他们会选择它,否则会打开一个对话框,允许他们输入新项目。

I am doing this by watching for the change event on the input, if the inputs val is not in the source array (for the the typeahead) then the "add item" dialogue is shown to the user. The problem is if the user clicks one of the options a change event is sent before the typeahead has a chance to set the val. This is as the click will cause a blur on the text.

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

I wanted to check the active element to get around this, so in the change event look at document.activeElement and see if it is one of the typeahead options, this did not work and returned the entire body element.

我想检查活动元素来解决这个问题,所以在更改事件中查看 document.activeElement 并查看它是否是预先输入的选项之一,这不起作用并返回了整个 body 元素。

Here is a trimmed down version of the code:

这是代码的精简版本:

Html

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

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();
})

And a JSFiddle version http://jsfiddle.net/k39vM/

还有一个 JSFiddle 版本http://jsfiddle.net/k39vM/

Does any one know how I can test if the user has clicked a typeahead to find out if that caused the change event?

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

采纳答案by pickypg

My previous suggestion didn't actually work because, as you mentioned, there is a somewhat unexpected blurevent triggering the changebeforeevent the clickon the menu. I had assumed that it was related to the this.hide()call inside the Typeahead.prototype.selectmethod.

我之前的建议实际上并没有奏效,因为正如您所提到的,有一个有点意外的blur事件触发了菜单上的changebefore事件click。我认为它与方法this.hide()内部的调用有关Typeahead.prototype.select

However, after a bit of trial-and-error, I do think that I may have found a workaround. It's not actually the this.hide()call within the selectmethod that is causing the problem. Knowing that there are two ways that the user can trigger selection helps to understand the hopefully working workaround (I only tested in Chrome): using the keyboard, such as hitting enter, or clicking on the item. As a result, knowing that the click is the problem-child of the two, I noticed that the mousedoverevent is maintained when the user mouses over the dropdown.

但是,经过一些反复试验,我确实认为我可能已经找到了解决方法。导致问题的实际上并不是方法中的this.hide()调用select。了解用户可以通过两种方式触发选择有助于理解有希望的解决方法(我仅在 Chrome 中测试过):使用键盘,例如按 Enter,或单击项目。结果,知道点击是两者的问题,我注意到mousedover当用户将鼠标悬停在下拉菜单上时,事件会被维护。

As a result, the odd behavior can be manually ignoredwithin a changeevent. To simplify the process of determining what actually causes the nextchangeevent I used a different (custom) event called "selected" to denote the user has changed the value rather than a standard change. Unfortunately, you still must manually ignore changeevents when the mousedoverproperty is true:

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

Simplified HTML (I used the ptag because I find that Chrome has trouble with debugging JSFiddle's JavaScript, and combining with the console lead to a bad time):

简化的 HTML(我使用这个p标签是因为我发现 Chrome 在调试 JSFiddle 的 JavaScript 时有问题,并且与控制台结合会导致糟糕的时间):

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

JavaScript (text can be replaced by console.logfor the those interested comfortable):

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 />");
});

For reference, this is the default selectmethod:

作为参考,这是默认select方法:

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

回答by Daniel

A somewhat simpler solution to the problem is to include the following in your click event:

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

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

The first line will retrieve the typeahead if it is attached. The second will assure that the current value matches the selected value.

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

You can also do a check for typeahead.mousedoverwithin the if to allow invalid (meaning not a typeahead option) input to still trigger the default change behavior when the control loses focus without making a selection.

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