如何在输入更改事件之前获得 Bootstrap 预先输入点击结果 [英] How to get Bootstrap typeahead click result before the input change event

查看:60
本文介绍了如何在输入更改事件之前获得 Bootstrap 预先输入点击结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

这是代码的精简版:

HTML

<div class="modal-body"><p>您输入的联系人未知.按取消输入其他联系人或填写以下详细信息以创建新联系人

<label>名称</label><input id="modal_contact" type="text" placeholder="dealership contact" value=""/><label>电子邮件</label><input id="modal_contact_email" type="text" placeholder="dealership contact" value=""/>

<div class="modal-footer"><button class="btn" data-dismiss="modal" aria-hidden="true">关闭</button><button id="save" class="btn btn-primary">保存更改</button>

Javascript

var contacts = ['pete','geoff'];$('.typeahead').typeahead({source:contacts, updater: function(item){console.log('更新程序被触发');//在第一次更改事件后触发归还物品;}});$('input').change(function(ev){console.log($(ev.target).val());如果 ($.inArray($(ev.target).val(), 联系人) <0)$('#contactModal').modal();})

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

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

解决方案

我之前的建议实际上没有奏效,因为正如你提到的,有一个有点意外的 blur 事件触发了 更改 before 事件click 在菜单上.我假设它与 Typeahead.prototype.select 方法中的 this.hide() 调用有关.

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

因此,可以在 change 事件中手动忽略奇怪的行为.为了简化确定实际导致 next 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="文本"/>

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('选择');//<- 唯一事件返回 this.hide()};$('input.typeahead').on('change', function (e) {var $target = $(e.target);如果(typeahead.mousedover){$text.html($text.html() + "mousedover [忽略选择]
");}否则 if ($.inArray($target.val(), contacts) <0) {$text.html($text.html() + "显示添加
");}}).on('选中', function () {$text.html($text.html() + "selected
");});

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

select: function () {var val = this.$menu.find('.active').attr('data-value')this.$元素.val(this.updater(val)).改变()返回 this.hide()}

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.

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.

Here is a trimmed down version of the code:

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

And a JSFiddle version 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?

解决方案

My previous suggestion didn't actually work because, as you mentioned, there is a somewhat unexpected blur event triggering the change before event the click on the menu. I had assumed that it was related to the this.hide() call inside the Typeahead.prototype.select method.

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 select method 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 mousedover event is maintained when the user mouses over the dropdown.

As a result, the odd behavior can be manually ignored within a change event. To simplify the process of determining what actually causes the next change event 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 change events when the mousedover property is true:

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

<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.log for the those interested comfortable):

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 select method:

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

这篇关于如何在输入更改事件之前获得 Bootstrap 预先输入点击结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆