web-dev-qa-db-ja.com

どこのDOM要素がフォーカスを持っているのか、どうすればわかりますか?

JavaScriptで、どの要素が現在フォーカスされているのかを調べたいと思います。私はDOMを調べていて、まだ必要なものを見つけていません。これを行う方法はありますか?

私がこれを探していた理由:

私は矢印やenterのようなキーを入力要素のテーブルをナビゲートしようとしています。タブは今動作しますが、入力し、矢印はデフォルトではないようです。キー処理部分を設定しましたが、今度はイベント処理関数でフォーカスを移動する方法を理解する必要があります。

1168
Tony Peterson

document.activeElement を使用してください。これはすべての主要ブラウザでサポートされています。

以前は、どのフォームフィールドにフォーカスがあるのか​​を調べようとしていたのではありませんでした。古いブラウザで検出をエミュレートするには、すべてのフィールドに "focus"イベントハンドラを追加し、最後にフォーカスしたフィールドを変数に記録します。最後にフォーカスされたフィールドのブラーイベントの際に変数をクリアするための「ブラー」ハンドラを追加します。

関連リンク:

1379
JW.

JWが言ったように、少なくともブラウザに依存しない方法では、現在注目している要素を見つけることはできません。しかし、あなたのアプリがIEのみの場合(いくつかは...)、次のようにして見つけることができます。

document.activeElement

編集:IEには結局問題がないわけではなく、これはHTML5ドラフトの一部であり、少なくともChrome、Safari、Firefoxの最新バージョンでサポートされているようです。

114
Wookai

あなたがjQueryを使うことができるならば、それは今サポートします:フォーカス、ちょうどあなたがバージョン1.6+を使っていることを確認してください。

このステートメントはあなたに現在焦点を当てている要素を取得します。

$(":focus")

From: jQueryを使ってフォーカスのある要素を選択する方法

78
William Denniss

document.activeElementは現在 HTML 5ワーキングドラフト の仕様の一部ですが、一部のメジャー/モバイル/古いブラウザではまだサポートされていない可能性があります。 querySelectorに戻ることができます(それがサポートされている場合)。また、ブラウザウィンドウにフォーカスがない場合でも、フォーカスされている要素がない場合、document.activeElementdocument.bodyを返します。

次のコードはこの問題を回避し、もう少し良いサポートを与えるquerySelectorに戻ります。

var focused = document.activeElement;
if (!focused || focused == document.body)
    focused = null;
else if (document.querySelector)
    focused = document.querySelector(":focus");

さらに注意すべきことは、これら2つの方法のパフォーマンスの違いです。セレクターを使用して文書を照会するのは、activeElementプロパティーにアクセスするよりもずっと遅くなります。 jsperf.com test を参照してください。

41
Andy E

文書がフォーカスされていない場合、document.activeElementはそれ自体で要素を返すことができます(したがって、ドキュメント内の何もフォーカスされていません!)

あなたはmayその振る舞いを望んでいるか、それともmayは重要ではありません(例えばkeydownイベント内)、しかし何かを知る必要があるなら実際にフォーカスされている場合は、さらに document.hasFocus() を確認できます。

以下は、ある場合はフォーカスされた要素を、そうでなければnullを提供します。

var focused_element = null;
if (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
) {
    focused_element = document.activeElement;
}

specific要素にフォーカスがあるかどうかを確認するには、より簡単です:

var input_focused = document.activeElement === input && document.hasFocus();

anythingがフォーカスされているかどうかを確認するには、さらに複雑です。

var anything_is_focused = (
    document.hasFocus() &&
    document.activeElement !== null &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
);

堅牢性注document.bodyおよびdocument.documentElementに対するチェックを行うコードでは、一部のブラウザーがこれらのいずれかを返すためです。またはnullは何もフォーカスされていない場合。

<body>(または<html>)にtabIndex属性があり、したがってが実際にフォーカスできるかどうかは考慮されません。ライブラリなどを作成していて、堅牢にしたい場合は、おそらくそれを何らかの方法で処理する必要があります。


これは(heavyairquotes)フォーカスされた要素を取得する「ワンライナー」バージョンです。これは概念的にもっと複雑です -circuiting、そしてあなたがそれを読みやすくしたいのであれば、それは明らかに1行に収まりません。
これはお勧めしません。しかし、もしあなたが1337 hax0rなら、idk ...そこにあります。
場合によってはfalseを取得しても構わないのであれば、|| null部分を削除することもできます。 (document.activeElementnullの場合、nullを取得できます):

var focused_element = (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement &&
    document.activeElement
) || null;

特定の要素がフォーカスされているかどうかを確認するには、代わりにcouldイベントを使用しますが、この方法ではセットアップ(および潜在的にティアダウン)が必要であり、重要なことに、は初期状態を想定します

var input_focused = false;
input.addEventListener("focus", function() {
    input_focused = true;
});
input.addEventListener("blur", function() {
    input_focused = false;
});

イベントなしの方法を使用して初期状態の仮定を修正できますが、代わりにそれを使用することもできます。

17
1j01

フォーカス可能な要素にフォーカスがない場合、document.activeElementはデフォルトで<body>要素になります。さらに、要素がフォーカスされていてブラウザウィンドウがぼやけている場合、activeElementはフォーカスされた要素を保持し続けます。

これら2つの動作のどちらかが望ましくない場合は、CSSベースのアプローチdocument.querySelector( ':focus' )を検討してください。

14
Nate Whittaker

私はJoel Sが使っていたアプローチが好きでしたが、document.activeElementの単純さも好きです。私はjQueryを使い、両者を組み合わせました。 document.activeElementをサポートしない古いブラウザは、 'hasFocus'の値を格納するためにjQuery.data()を使用します。最近のブラウザはdocument.activeElementを使用します。 document.activeElementのほうがパフォーマンスが良いと思います。

(function($) {
var settings;
$.fn.focusTracker = function(options) {
    settings = $.extend({}, $.focusTracker.defaults, options);

    if (!document.activeElement) {
        this.each(function() {
            var $this = $(this).data('hasFocus', false);

            $this.focus(function(event) {
                $this.data('hasFocus', true);
            });
            $this.blur(function(event) {
                $this.data('hasFocus', false);
            });
        });
    }
    return this;
};

$.fn.hasFocus = function() {
    if (this.length === 0) { return false; }
    if (document.activeElement) {
        return this.get(0) === document.activeElement;
    }
    return this.data('hasFocus');
};

$.focusTracker = {
    defaults: {
        context: 'body'
    },
    focusedElement: function(context) {
        var focused;
        if (!context) { context = settings.context; }
        if (document.activeElement) {
            if ($(document.activeElement).closest(context).length > 0) {
                focused = document.activeElement;
            }
        } else {
            $(':visible:enabled', context).each(function() {
                if ($(this).data('hasFocus')) {
                    focused = this;
                    return false;
                }
            });
        }
        return $(focused);
    }
};
})(jQuery);
10
Jason

私がMootoolsでこれらの目的のために使用した小さなヘルパー:

FocusTracker = {
    startFocusTracking: function() {
       this.store('hasFocus', false);
       this.addEvent('focus', function() { this.store('hasFocus', true); });
       this.addEvent('blur', function() { this.store('hasFocus', false); });
    },

    hasFocus: function() {
       return this.retrieve('hasFocus');
    }
}

Element.implement(FocusTracker);

このようにして、与えられた要素に対してel.hasFocus()が呼び出されていれば、要素がstartFocusTracking()でフォーカスされているかどうかをチェックできます。

9
Joel S

JQueryは現在の:focus疑似クラスをサポートしています。 JQueryのドキュメントで探しているのなら、 "="の下の "Selectors"で W3C CSSドキュメント をチェックしてください。 Chrome、FF、IE 7+でテストしました。 IEで動作するには、<!DOCTYPE...がhtmlページに存在している必要があります。これは、フォーカスがある要素にIDを割り当てたと仮定した例です。

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});
7
DeezCashews

Elementのインスタンスであるオブジェクトを取得したい場合はdocument.activeElementを使用する必要がありますが、Textのインスタンスであるオブジェクトを取得したい場合はdocument.getSelection().focusNodeを使用する必要があります。

助けていただければ幸いです。

7
rplaurindo

Document.activeElementの使用には潜在的な問題があります。検討してください:

<div contentEditable="true">
  <div>Some text</div>
  <div>Some text</div>
  <div>Some text</div>
</div>

ユーザーがinner-divに注目しても、document.activeElementは外側のdivを参照します。 document.activeElementを使って、内側のdivのどれにフォーカスがあるのか​​を判断することはできません。

次の関数はこれを回避し、フォーカスが当たっているノードを返します。

function active_node(){
  return window.getSelection().anchorNode;
}

あなたがむしろ集中した要素を手に入れたいならば、使用してください:

function active_element(){
  var anchor = window.getSelection().anchorNode;
  if(anchor.nodeType == 3){
        return anchor.parentNode;
  }else if(anchor.nodeType == 1){
        return anchor;
  }
}
6
Nathan K

他の答えを読んで、自分で試してみると、ほとんどのブラウザでdocument.activeElementが必要な要素を提供してくれるようです。

JQueryがある場合にdocument.activeElementをサポートしていないブラウザを使用している場合は、次のような非常に簡単な方法ですべてのフォーカスイベントにそれを設定できます(私はブラウザがこれらの基準を満たしていないのでテストしません)。 ):

if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
  $('*').live('focus', function () { // Attach to all focus events using .live()
    document.activeElement = this; // Set activeElement to the element that has been focussed
  });
}
5
rjmunro

JQueryを使用している場合は、これを使用して要素がアクティブかどうかを調べることができます。

$("input#id").is(":active");
5
Arne

Dojoでは、dijit.getFocus()を使用できます。

4
Daniel Hartmann

現在どの要素にフォーカスがあるのか​​を判断する際には、次のスニペットが役立つことがわかりました。以下をブラウザのコンソールにコピーすると、毎秒フォーカスが当たっている現在の要素の詳細が表示されます。

setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);

要素全体を印刷しても要素を特定できない場合は、console.logを修正して別のログアウトして正確な要素を特定できるようにしてください。

4
vegemite4me

私が最終的に思いついた解決策を与えるためにここにこれを置くだけです。

Document.activeInputAreaというプロパティを作成し、jQueryのHotKeysアドオンを使用して矢印キー、Tabキー、Enterキーのキーボードイベントをトラップし、入力要素をクリックするためのイベントハンドラを作成しました。

その後、フォーカスが変わるたびにactiveInputAreaを調整したので、そのプロパティを使用して自分がどこにいるのかを確認できます。

ただし、システムにバグがあり、意図した場所にフォーカスがない場合は、正しいフォーカスを復元するのが非常に困難です。

3
Tony Peterson