4

ユーザーの柔軟な選択として、ブートストラップのタイプアヘッドを使用しようとしています。そのため、アイテムがわかっている場合はそれを選択し、そうでない場合はダイアログが開き、新しいアイテムを入力できます。

入力の変更イベントを監視することでこれを行っています。入力値がソース配列にない場合 (先行入力用)、「項目の追加」ダイアログがユーザーに表示されます。問題は、ユーザーがオプションの 1 つをクリックすると、先行入力が val を設定する前に変更イベントが送信されることです。これは、クリックするとテキストがぼやけるためです。

これを回避するためにアクティブな要素をチェックしたかったので、変更イベントで document.activeElement を見て、それが先行入力オプションの 1 つであるかどうかを確認しましたが、これは機能せず、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/

ユーザーが先行入力をクリックして変更イベントが発生したかどうかをテストする方法を知っている人はいますか?

4

2 に答える 2

4

あなたが言及したように、メニューのbeforeイベントblurをトリガーするやや予期しないイベントがあるため、私の以前の提案は実際には機能しませんでした。メソッド内の呼び出しに関連していると思い込んでいました。change clickthis.hide()Typeahead.prototype.select

ただし、試行錯誤の結果、回避策を見つけた可能性があると思います。問題を引き起こしているのは、実際にはメソッドthis.hide()内の呼び出しではありません。selectユーザーが選択をトリガーできる 2 つの方法があることを知っていると、うまく機能する回避策を理解するのに役立ちます (私は Chrome でのみテストしました): Enter キーを押すか、項目をクリックするなど、キーボードを使用します。その結果、クリックが 2 つの問題の子であることを知っていたのでmousedover、ユーザーがドロップダウンにマウスを置いたときにイベントが維持されることに気付きました。

その結果、イベント内で奇妙な動作を手動で無視できます。次のchangeイベントの実際の原因を特定するプロセスを単純化するために、" " という別の (カスタム) イベントを使用して、ユーザーが標準ではなく値を変更したことを示しました。残念ながら、プロパティが次の場合は、手動でイベントを無視する必要があります。 changeselectedchangechangemousedovertrue

簡略化された HTML (このpタグを使用したのは、Chrome で JSFiddle の JavaScript をデバッグするのに問題があり、コンソールと組み合わせるとうまくいかないことがわかったからです):

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

console.logJavaScript (興味のある方は快適にテキストを置き換えることができます):

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()
}
于 2013-04-19T02:50:29.830 に答える
3

この問題のやや簡単な解決策は、クリック イベントに以下を含めることです。

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

タイプアヘッドが添付されている場合、最初の行でタイプアヘッドが取得されます。2 つ目は、現在の値が選択した値と一致することを保証します。

if 内でチェックを実行してtypeahead.mousedover、無効な (先行入力オプションではないことを意味する) 入力を許可して、選択せずにコントロールがフォーカスを失ったときにデフォルトの変更動作を引き続きトリガーすることもできます。

于 2014-05-28T18:56:42.320 に答える