Wie kann ich einem DIV den Tastaturfokus geben und ihm Tastaturereignishandler hinzufügen?

82

Ich erstelle eine Anwendung, in der ich auf ein Rechteck klicken möchte, das von einem DIV dargestellt wird, und dann die Tastatur verwenden kann, um diesen DIV durch Auflisten von Tastaturereignissen zu verschieben.

Kann ich Tastaturereignisse auf DIV-Ebene abhören, anstatt einen Ereignis-Listener für diese Tastaturereignisse auf Dokumentebene zu verwenden, indem ich ihm möglicherweise den Tastaturfokus gebe?

Hier ist ein vereinfachtes Beispiel, um das Problem zu veranschaulichen:

<html>
<head>
</head>
<body>

<div id="outer" style="background-color:#eeeeee;padding:10px">
outer

   <div id="inner" style="background-color:#bbbbbb;width:50%;margin:10px;padding:10px;">
   want to be able to focus this element and pick up keypresses
   </div>
</div>

<script language="Javascript">

function onClick()
{
    document.getElementById('inner').innerHTML="clicked";
    document.getElementById('inner').focus();

}

//this handler is never called
function onKeypressDiv()
{
    document.getElementById('inner').innerHTML="keypress on div";
}

function onKeypressDoc()
{
    document.getElementById('inner').innerHTML="keypress on doc";
}

//install event handlers
document.getElementById('inner').addEventListener("click", onClick, false);
document.getElementById('inner').addEventListener("keypress", onKeypressDiv, false);
document.addEventListener("keypress", onKeypressDoc, false);

</script>

</body>
</html>

Beim Klicken auf das innere DIV versuche ich, es zu fokussieren, aber nachfolgende Tastaturereignisse werden immer auf Dokumentebene erfasst, nicht auf meinem Ereignis-Listener auf DIV-Ebene.

Muss ich einfach einen anwendungsspezifischen Begriff des Tastaturfokus implementieren?

Ich sollte hinzufügen, dass ich dies nur brauche, um in Firefox zu arbeiten.

Paul Dixon
quelle
1
Nicht wirklich ein Betrüger - es wurde etwa zwei Jahre zuvor gefragt, und es wird gefragt, wie Tastaturereignisse für beliebige Elemente empfangen werden sollen, anstatt die focus()Funktion zu verwenden.
Paul Dixon

Antworten:

164

Sortiert - Ich habe dem Ziel-DIV das tabindex-Attribut hinzugefügt, wodurch es beispielsweise Tastaturereignisse aufnimmt

<div id="inner" tabindex="0">
    this div can now have focus and receive keyboard events
</div>

Informationen finden Sie unter http://www.w3.org/WAI/GL/WCAG20/WD-WCAG20-TECHS/SCR29.html

Paul Dixon
quelle
6
Wenn Sie nicht möchten, dass das Div einen gepunkteten blauen Rand erhält, wenn es fokussiert ist, können Sie es auch stylen outline: 0px solid tranparent;. Siehe: stackoverflow.com/a/2260788/402807
AlcubierreDrive
4
Oder setzen Sie tabindex="-1", das verhindert auch, dass es den gepunkteten Rand bekommt.
Troglobit
Ich kann das in Chrome 60 und FF 54 überhaupt nicht zum Laufen bringen. Und IE11 macht auf magische Weise das Richtige, auch ohne das tabindex. Ist diese Antwort veraltet?
jlh
Dies funktioniert bei mir im aktuellen Firefox nicht. Der Browser übernimmt die Tastatureingabe. Gleiches gilt für die Geige.
Kwebble
1
das loszuwerden outlineist nicht zugänglich. Wenn Ihnen das Aussehen nicht gefällt, empfehle ich, einen anderen visuellen Hinweis darauf zu geben, dass das Element fokussiert ist, bevor Sie denoutline
sleeparrow
5

Pauls Antwort funktioniert gut, aber Sie könnten auch contentEditable verwenden, so ...

document.getElementById('inner').contentEditable=true;
document.getElementById('inner').focus();

Könnte in einigen Fällen vorzuziehen sein.

Peter Bagnall
quelle
6
Wenn Sie dies tun, setzt Chrome 17 einen Cursor auf das Element im Fokus und Sie können Dinge auf dem Element eingeben. Ich würde das nicht empfehlen.
Seppo Erviälä
1
@Seppo, das ist ein guter Punkt. Wenn Sie die Tastaturereignisse verbrauchen, können Sie sie nicht unbedingt bearbeiten, aber ein Cursor kann je nach dem, was Sie tun möchten, unordentlich sein. Übrigens ist es nicht nur Chrome 17, sondern so ziemlich alle neueren Browser, die sich so verhalten - sicherlich FF und Safari - IE auch, glaube ich, obwohl ich das in letzter Zeit nicht getestet habe
Peter Bagnall