web-dev-qa-db-ja.com

focusOutでevent.preventDefaultを使用する方法はありますか?そうでない場合、なぜですか?

デフォルトのイベントがfocusOut(またはblur)イベントから発生しないようにし、フォーカスを特定の入力フィールドに設定したままにします。

これは私がすでに試したことです:

  • 関数の最初と最後でevent.preventDefault()を使用する(スタイルではなくテスト目的で)

  • _return false;_伝播を防ぐため

  • 要素内の要素に直接フォーカスを戻す(ただし、フォーカス切り替えが実行されるため、フォーカスがまだ切り替わることがわかりましたafter.on()関数が実行されます。使用できることはわかっています。 setTimeoutですが、それを避けて問題の核心を理解したいと思います。)

  • blurの代わりにfocusOutを使用する

私のコードはこれです:

_    _triggerEventHide: function(inst, eventType) {
        inst.$target.on(eventType, function(event) {
            event.preventDefault();
            if (!$.suggestBox.$divCont.hasClass($.suggestBox.mouseOverClassName)) {
                $.suggestBox.$divCont.css({display: 'none'});   //reposition Suggestbox
            } else {
                inst.target.focus(); 
            }
            event.preventDefault();
            return false;
        });
     }
_

_$target_はjQueryでラップされた要素を表し、targetはネイティブのDOM要素を表すことに注意してください。

私はいくつかの調査を行い、私の質問に関連するいくつかの記事をすでに見つけましたが、それらのどれもこの正確な質問に答えていません。

  1. preventDefaultはフォーカスイベントでは機能しません –ここで、与えられた答えは、あらゆる種類のイベント操作を使用するための代替ルートです。

  2. 必要な値がない場合はフォーカスアウトにフォーカスバックテキストボックス –ここでの解決策は、setTimeout()を使用してフォーカスを元の要素に戻すことでしたが、これで問題ありません。問題の核心、なぜpreventDefault()がここで機能しないのかを理解したいと思います。

  3. jQuery PreventDefault()が機能しませんevent.stopImmediatePropagation()event.stop()を使用するなど、このスレッドから考えられる解決策をいくつか試しましたが、すべてがうまくいきませんでした。

私は、この問題に貢献した知識と解決策(試みを含む)に感謝します。本当に学びたい…

これがjsFiddleで、問題を示しています…気軽に試して、さまざまな解決策を試してください。

17
Klik

さらに調査した結果、特定のイベントのみが「キャンセル可能」であることがわかりました。

  • http://help.dottoro.com/ljwolcsp.php から引用

    バージョン9より前のInternetExplorerを除くすべてのブラウザーで、cancelableプロパティを使用してイベントをキャンセルできるかどうかを確認できます。cancelableプロパティはFirefoxに存在しますが、イベントのキャンセル可能な状態に関係なく、常にtrueを返します。バージョン9より前のInternetExplorerでイベントをキャンセルできるかどうかを判断する方法はありません。

    キャンセルできないイベントでpreventDefaultメソッドとreturnValueプロパティを使用しても、エラーは発生しないことに注意してください。イベントハンドラがfalseを返すと、イベントはキャンセルされます。 PreventDefaultメソッドとreturnValueプロパティの代わりに使用できます。以下の例2を参照してください。

  • Javascriptの各イベントには、イベントを防止できる場合は「true」、イベントをキャンセルできない場合は「false」として定義されるキャンセル可能なプロパティがあります。参照: http://help.dottoro.com/ljeosnqv.php

  • http://help.dottoro.com/ljeosnqv.php からのサンプルスクリプトは、このプロパティを示しています ここ jsFiddle(スペースを節約するため)。 Firefoxがイベントオブジェクトのキャンセル可能なプロパティに対して常にtrueを返す方法に関するコード内のコメントに注意してください。

一般的な原則は次のとおりです。

 $('selector').on(eventType, function (event) {
    alert(('cancelable' in event));   //will return true
    alert(event.cancelable);      //will return true if event can be cancelled
                                  //NOTE: Firefox mistakenly always returns true
});
  • イベントには、状況に応じて発生する順序が事前に設定されています。たとえば、マウスボタンがクリックされた場合、eventTriggersの順序は、mousedown、mouseup、およびclickになります。参照:www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-initMouseEvent

  • 引用元 http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-flow-cancelation

    「キャンセル可能なイベント」は、DOMイベントフロー中にキャンセルできるデフォルトのアクションに関連付けられたイベントです。イベントフロー中の任意のフェーズで、トリガーされたイベントリスナーは、デフォルトのアクションをキャンセルするか、デフォルトのアクションの続行を許可するかを選択できます。ブラウザのハイパーリンクの場合、アクションをキャンセルすると、ハイパーリンクがアクティブ化されなくなります。この仕様で定義されているすべてのイベントがキャンセル可能なイベントであるとは限りません。

  • 一連のイベントで、キャンセルしようとしているイベントが表示される前にDOMのデフォルトのアクションが発生する場合があります。この場合、デフォルトのアクションはすでに実行されているため、キャンセルできません。つまり、デフォルトのアクションが発生しますbeforeイベントのディスパッチ。


私の解決策:

そうは言っても、私は自分の問題に対する解決策を見つけることができ、多かれ少なかれこの問題を見つけることができました。基本的に、focusinの要素を持つeventListenerがすでにあり、この要素にフォーカスを維持したかったのです。

<div id='display'></div>
$('#idBox').on('focusin', function () {
  $('#div').append('focused');
  //do something
}

最初は、クリックしたときにsetTimeoutイベントを使用しようとしましたが、focusinイベントが再度トリガーされるため、これは適切ではないことがわかりました。したがって、必要なのは、ディスパッチされるイベントDOMのデフォルトアクションの前フォーカスの切り替えです。この要件を満たすイベントがあるあることがわかりましたが、IEでのみ使用できます...通常。ちなみに、"onbeforedeactivate"そしてそれはキャンセル可能です。ただし、ブラウザー間の互換性が重要であるため、このeventTriggerは使用しないでください。むしろ、DOMがフォーカスを変更する動作を開始する前に、イベントのマウスダウンが発生することがわかりました。

したがって、私たちにできることは次のとおりです。

$(document).on('mousedown', function(event) { 
       target = event.target;     // the element clicked on
       myTarget = document.getElementById("idBox");   // the element to keep focus
       if (target !== myTarget) {   
           event.preventDefault();  //prevent default DOM action
           event.stopPropagation();   //stop bubbling
           return false;   // return
       }
});

それについては他にもたくさんの方法があります。私は個人的にeventListenerをドキュメント全体に設定するのは好きではありませんが、基本を示すためにその目的を果たします。


脚注:Javascriptでのイベント処理について詳しく知るために読むべき素晴らしい記事は、 http://help.dottoro.com/ljtdqwlx.php 私が偶然見つけた素晴らしいリソースです。

21
Klik

問題の原因はクリック機能であることがわかっています。したがって、chromeのような通常のエクスプローラーでは、mousedownイベントをデタッチしてからpreventDefaultを実行できます。

ただし、これはIEでは機能しませんが、代わりにbeforedeactivateイベントを使用できます http://msdn.Microsoft.com/en-us/library/windows/apps/jj569321.aspx 。つまり、フォーカスが変化しているときに、それは検出されない可能性があります。だからそれを防いでください。

コードはこれを望みます:

       $inp.on('blur', function(){

            self.hide();
        });

        isIE && $inp.on('beforedeactivate', function(evt){
            mousedown && evt.preventDefault();
        });

        $holder.on('mousedown', function(evt){
            evt.preventDefault();
            mousedown = 1;
        });
1
Easum