2013-07-08 13 views
8

clickfocusの両方で発生するイベントを取得しようとしています。入力をクリックすると、2回(クリックとフォーカス)起動します。どうすればこれを防ぐことができますか?フォーカスを入力してクリックすると機能が2回発射しないようにします

$('input').on('focus click', function(){ 
    console.log('fired'); 
}); 
+0

FWIW、私は汎用目的のデバウザーでオリジナルの回答を更新しました。 –

答えて

10

代わりに.oneを使用できます。それは唯一のイベントは一度発動することができますが、それは解雇された後も、バインドを削除します:

$('input').one('focus click', function(){ 
    console.log('fired'); 
}); 

バインドを維持する必要がある場合は、マウスボタンの状態を追跡する必要がありますし、 mousedownをトリガし、現在の目標:

var mouseDown, currentTarget; 
$('input').on({ 
    "mousedown mouseup": function (e) { 
     mouseDown = e.type === "mousedown"; 
     currentTarget = e.target; 
    }, 
    "focus click": function (e) { 
     if (mouseDown && currentTarget === e.target) return; 
     console.log('fired'); 
    } 
}); 

test case on jsFiddleを参照してください。

+1

しかしそれはバインディングを取り除きます...私が望むものではありません。 – kylex

+0

@kylex 'stopImmediatePropagation'メソッドも追加されました。これはうまくいくはずです...私はそれはそうではないバグだと言います。 T.Jのソリューションが嫌いなので、もう少し調べてみましょう。 – mekwall

+1

e.stopImmediatePropagationは動作していません。http://jsfiddle.net/6Vm2r/1/ – kylex

8

少しヒステリシスがオプションになる場合があります。いずれかのイベントに最後に応答した時間を記録し、ガード時間内に後続のイベントを無視します。

あなた(答えの終わりに一例)jQueryのdataこのために使用しますが、私はこれを好むことができます:汎用デバウンサを:

Live Example using click and focus | Live Source

$("#field").on("click focus", debounce(100, function(e) { 
    // Event occurred, but not with 100ms of the previous one 
})); 

debouncer機能:。

// debounce - debounces a function call 
// 
// Usage: var f = debounce([guardTime, ] func); 
// 
// Where `guardTime` is the interval during which to suppress 
// repeated calls, and `func` in the function to call. 
// You use the returned function instead of `func` to get 
// debouncing; 
// 
// Example: Debouncing a jQuery `click` event so if it happens 
// more than once within a second (1,000ms), subsequent ones 
// are ignored: 
// 
// $("selector").on("click", debounce(1000, function(e) { 
//  // Click occurred, but not within 1000ms of previous 
// }); 
// 
// Both `this` and arguments are passed through. 
function debounce(guardTime, func) { 
    var last = 0; 

    if (typeof guardTime === "function") { 
    func = guardTime; 
    guardTime = 100; 
    } 
    if (!guardTime) { 
    throw "No function given to debounce"; 
    } 
    if (!func) { 
    throw "No func given to debounce"; 
    } 

    return function() { 
    var now = +new Date(); 
    if (!last || (now - last) > guardTime) { 
     last = now; 
     return func.apply(this, arguments); 
    } 
    }; 
} 

(名称「デバウンサは」入力制限レートにヒステリシスを使用して何かのための一般的な用語ですIIRC、それはその「スイッチデバウンサ」から来ています接点が近づくと閉じた状態になる可能性があるので機械式スロー電気スイッチが開いている状態から閉じられている状態、またはその逆に遷移する際に数百回の動作を引き起こすのを避けるために使用される(非常に) /スイッチが定常状態になる前の開/閉/開/閉/開のチャタリングこのチャッターは "bouncing、」それゆえ、 『デバウンサ』)


アプローチだけでjQueryのdataを使用して:。

$('input').on('focus click', function(){ 
    var $this = $(this); 
    var now = +new Date(); 
    var lastClicked = $this.data("lastClicked"); 
    if (lastClicked && (now - lastClicked) < 100) { 
     // Don't do anything 
     return; 
    } 
    $this.data("lastClicked", now); 

    // Do the work 
}); 
+0

+1ハッキリですが、しっかりしています。(私はまだエッジケースに気付いています) –

+0

ヒステリシスやデバウンサーを使用する際の問題は、 'input'をクリックしてボタンを100ms以上押し続けると、 'click'と' focus'の両方のために起動します。 – mekwall

+0

アンダースコアjsにはデバウンスの実装があります[こちら](http://underscorejs.org/#debounce) –

1

これは古い質問ですが、私は私を解決するもののような他の答えを見つけることができませんでした問題。だから私は、これが唯一のクリックでイベントを発生させ、2015年

$('#menu-button').on('click focus', function() { 
    if(!$(this).is(':focus')) { // 1 
    // Do stuff once 
    } 
    else { 
    $this.blur(); // 2 
    } 
}); 
  1. でこの問題に遭遇してしまっ誰のためにそれをここに掲示しています。私は裏で何が起こっているのか分からないので、誰かが私にこのことを説明できるかもしれませんが、タブとフォーカスはそのままで100%働いています。

  2. この選択したオブジェクトを解除し焦点を当てていますが、それは、文書の先頭にバックフォーカスのパスを設定します。私はこれをここに残して、選択した要素を再びクリックしてメニューを無効にすることができます。私はまだフォーカスの経路を維持するための修正を探しています。

編集:より良い方法:

$('#menu-button').on('click focus', function(event) { 
    if(event.type === 'focus') { // 1 
    // Do stuff once 
    } 
}); 
  1. クリックしてフォーカスをトリガしますが、フォーカスが今までクリックをトリガしません。フォーカスイベントでコードを実行するだけです。
+0

+1あなたの投稿をありがとうございます。私はあなたの「良い方法」が好きです。しかし、私はjQueryの1.7.2バージョンを使用しています。これは、「フォーカス」ではなく「フォーカス」を与えます。一行のソリューションをありがとうございます。 – whitesiroi

関連する問題