web-dev-qa-db-ja.com

「ぼかし」イベントが発生した場合、どの要素にフォーカスが移動したかをどのように確認できますか?

次のようにblur関数をHTML入力ボックスにアタッチするとします。

<input id="myInput" onblur="function() { ... }"></input>

関数内でblurイベントを発生させた要素(クリックされた要素)のIDを取得する方法はありますか?どうやって?

たとえば、次のようなスパンがあるとします。

<span id="mySpan">Hello World</span>

入力要素にフォーカスがある直後にスパンをクリックすると、入力要素のフォーカスが失われます。クリックされたのはmySpanであったことを関数はどのように知るのですか?

PS:入力要素のonblurイベントの前にスパンのonclickイベントが発生すると、特定の要素がクリックされたことを示すステータス値を設定できるため、問題が解決します。

PPS:この問題の背景は、AJAXオートコンプリーターコントロールを外部から(クリック可能な要素から)トリガーして、入力要素のblurイベントが原因で提案がすぐに消えることなく、提案を表示することです。したがって、特定の要素がクリックされたかどうかをblur関数でチェックインし、クリックした場合はblurイベントを無視します。

166
Michiel Borkent

うーん... Firefoxでは、explicitOriginalTargetを使用して、クリックされた要素をプルできます。 IEでtoElementが同じことをすると思っていましたが、動作していないようです...ただし、ドキュメントから新しくフォーカスされた要素を取得できます。

function showBlur(ev)
{
   var target = ev.explicitOriginalTarget||document.activeElement;
   document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
}

...

<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />

警告:この手法はnotキーボードのフィールドを介してtabbingによって引き起こされるフォーカス変更に対して動作します、ChromeまたはSafariではまったく機能しません。 activeElement(IEを除く)の使用に関する大きな問題は、afterblurイベントが処理されるまで一貫して更新されず、有効な値がまったくない場合があることです。処理中!これは Michielが最終的に使用する手法 :のバリエーションで軽減できます。

function showBlur(ev)
{
  // Use timeout to delay examination of activeElement until after blur/focus 
  // events have been processed.
  setTimeout(function()
  {
    var target = document.activeElement;
    document.getElementById("focused").value = 
      target ? target.id||target.tagName||target : '';
  }, 1);
}

Chromeはclicked(vs. tabed to)のボタンにフォーカスを設定しないことに注意して、ほとんどの最新ブラウザー(Chrome、IE、Firefoxでテスト済み)で動作するはずです。

82
Shog9

2015 answerI Events に従って、イベントの relatedTarget プロパティを使用できます:

イベントのタイプに応じて、Focusイベントに関連するセカンダリ EventTarget を識別するために使用されます。

blur イベントの場合、

relatedTargetイベントターゲット フォーカスを受け取ります。

例:

function blurListener(event) {
  event.target.className = 'blurred';
  if(event.relatedTarget)
    event.relatedTarget.className = 'focused';
}
[].forEach.call(document.querySelectorAll('input'), function(el) {
  el.addEventListener('blur', blurListener, false);
});
.blurred { background: orange }
.focused { background: Lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become Lime.</p>
<input /><input /><input />

Firefoxは、バージョン48までrelatedTargetをサポートしません( bug 962251MDN )。

61
Oriol

最終的にはonblurイベントのタイムアウトで解決しました(StackOverflowではない友人のアドバイスのおかげです)。

<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>

FFとIEの両方で動作します。

17
Michiel Borkent

ぼかしの代わりにドキュメントのmousedownイベントを使用することができます。

$(document).mousedown(function(){
  if ($(event.target).attr("id") == "mySpan") {
    // some process
  }
});
16
Evgeny Shmanev

タイプFocusEventインスタンスにはrelatedTarget属性がありますが、FFのバージョン47までです。具体的には、この属性はnullを返します。48はすでに機能しています。

もっと見ることができます こちら

7
rplaurindo

特定の要素がクリックされて機能するソリューションがある場合、Autocompleterがぼかしを無視するようにしようとしていますが、explicitOriginalTargetによるFirefoxのみ

Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap( 
        function(origfunc, ev) {
            if ($(this.options.ignoreBlurEventElement)) {
                var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
                if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
                    return origfunc(ev);
                }
            }
        }
    );

このコードは、AutocompleterのデフォルトのonBlurメソッドをラップし、ignoreBlurEventElementパラメーターが設定されているかどうかを確認します。設定されている場合、クリックされた要素がignoreBlurEventElementであるかどうかを毎回確認します。そうであれば、オートコンプリーターはonBlurを計算せず、そうでない場合はonBlurを呼び出します。これに関する唯一の問題は、explicitOriginalTargetプロパティがMozilla固有であるため、Firefoxでのみ機能することです。現在、explicitOriginalTargetを使用するのとは異なる方法を見つけようとしています。言及した解決策では、要素にonclick動作を手動で追加する必要があります。 explicitOriginalTargetの問題を解決できない場合は、解決策に従うと思います。

2
matte

あなたがチェックしているものを、いつ戻すことができますか?それは最後にぼやけたものを思い出す場合です:

<input id="myInput" onblur="lastBlurred=this;"></input>

そして、スパンのonClickで、両方のオブジェクトでfunction()を呼び出します。

<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>

次に、関数でAjax.AutoCompleterコントロールをトリガーするかどうかを決定できます。関数にはクリックされたオブジェクトがありますandぼやけたオブジェクト。 onBlurは既に発生しているため、提案が消えることはありません。

2
bmb

この回答 で述べたように、document.activeElementの値を確認できます。 documentはグローバル変数なので、onBlurハンドラで使用するために魔法をかける必要はありません。

function myOnBlur(e) {
  if(document.activeElement ===
       document.getElementById('elementToCheckForFocus')) {
    // Focus went where we expected!
    // ...
  }
}
1
Kevin
  • document.activeElementは親ノード(たとえば、ターゲットから別のものへの一時的なフェーズ切り替えにあるため、ボディノード)になる可能性があるため、スコープで使用できません
  • ev.explicitOriginalTargetは常に価値があるとは限りません

したがって、最良の方法は、bodyイベントでonclickを使用して、間接的にノード(event.target)がぼかしにあることを理解することです

1
user6228847

次のようなものを使用します。

var myVar = null;

そして、関数内で:

myVar = fldID;

その後:

setTimeout(setFocus,1000)

その後:

function setFocus(){ document.getElementById(fldID).focus(); }

最終コード:

<html>
<head>
    <script type="text/javascript">
        function somefunction(){
            var myVar = null;

            myVar = document.getElementById('myInput');

            if(myVar.value=='')
                setTimeout(setFocusOnJobTitle,1000);
            else
                myVar.value='Success';
        }
        function setFocusOnJobTitle(){
            document.getElementById('myInput').focus();
        }
    </script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>
1
Vikas

IEではwindow.event.toElementを使用できますが、Firefoxでは機能しません!

1
stefano m

IEを修正するには:

 event.currentTarget.firstChild.ownerDocument.activeElement

FFの場合は「explicitOriginalTarget」のように見えます。

アントワーヌとJ

0
Madbean

Javascriptをコーディングするときにタイムアウトを使用するのは好きではないので、Michiel Borkentとは逆の方法で行います。 (背後にあるコードを試していないが、あなたはアイデアを得る必要があります)。

<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>

頭の中にはこんな感じ

<head>
    <script type="text/javascript">
        function sortOfCallback(id){
            bluredElement = document.getElementById(blured);
            // Do whatever you want on the blured element with the id of the focus element


        }

    </script>
</head>
0

Google Chrome v66.x、Mozilla v59.xおよびMicrosoft Edgeで動作します... jQueryを使用したソリューション。

Internet Explorer 9でテストしましたが、サポートされていません。

$("#YourElement").blur(function(e){
     var InputTarget =  $(e.relatedTarget).attr("id"); // GET ID Element
     console.log(InputTarget);
     if(target == "YourId") { // If you want validate or make a action to specfic element
          ... // your code
     }
});

他のInternet Explorerバージョンでテストにコメントします。

0
LuisEduardox

グローバル変数blurfromとblurtoを使用することをお勧めします。次に、注目するすべての要素を構成して、DOMでの位置を変数blurfromに割り当てます。さらに、フォーカスを取得すると変数blurtoがtheir DOMの位置に設定されるように設定します。次に、別の関数を使用してblurfromデータとblurtoデータを分析できます。

0
stalepretzel

編集:それを行うためのハックな方法は、関心のあるすべての要素のフォーカスを追跡する変数を作成することです。したがって、「myInput」がフォーカスを失ったことを気にする場合は、フォーカス時に変数を設定してください。

<script type="text/javascript">
   var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />

元の回答:「this」を関数に渡すことができます。

<input id="myInput" onblur="function(this){
   var theId = this.id; // will be 'myInput'
}" />
0
brock.holum

代替ソリューション 要素をフォーカス可能かつ「ぼかし可能」にする方法を書きました。

要素をcontentEditableとして作成し、視覚的に非表示にし、編集モード自体を無効にすることに基づいています。

el.addEventListener("keydown", function(e) {
  e.preventDefault();
  e.stopPropagation();
});

el.addEventListener("blur", cbBlur);
el.contentEditable = true;

DEMO

注:Chrome、Firefox、およびSafari(OS X)でテスト済み。 IEについてはわかりません。


関連:VueJのソリューションを探していたので、Vue Focusableディレクティブを使用してそのような機能を実装する方法に興味がある/興味がある人は、 見てください をご覧ください。

0

私はこれと同じ機能で遊んでおり、FF、IE、ChromeおよびOperaにはイベントのソース要素を提供する機能があることがわかりました。私はSafariをテストしていませんが、私の推測では似たようなものがあるかもしれません。

$('#Form').keyup(function (e) {
    var ctrl = null;
    if (e.originalEvent.explicitOriginalTarget) { // FF
        ctrl = e.originalEvent.explicitOriginalTarget;
    }
    else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
        ctrl = e.originalEvent.srcElement;
    }
    //...
});
0
EricDuWeb