26

I would like to respond to keystroke events directed at nodes in my force layout. I've tried adding all the variants of "keystroke", "keypress", "keyup", "keydown" that I could think of, but none of them is firing. My mouse events fire just fine. I couldn't find any keystroke events in the d3 source.... is there a way to capture key strokes?

        nodes.enter().append("circle")
            .on("click", function(d) { return d.clickHandler(self); })
            .on("mouseover", function(d) { return d.mouseOverHandler(self); })
            .on("mouseout", function(d) { return d.mouseOutHandler(self); })
            .on("keyup", function(d) { 
                console.log("keypress", d3.event); // also tried "keyup", "keydown", "key"
            })
            .classed("qNode", true)
            .call(force.drag);
VividD
  • 10,456
  • 6
  • 64
  • 111
Gene Golovchinsky
  • 6,101
  • 7
  • 53
  • 81

1 Answers1

69

I think the problem here is you are trying to add keyboard events to elements that are not focusable, try adding a keydown event to a focusable element (body in this case):

d3.select("body")
    .on("keydown", function() { ...

here you can use properties of d3.event, for instance d3.event.keyCode, or for more specialized cases, d3.event.altKey, d3.event.ctrlKey, d3.event.shiftKey, etc..

Looking at the KeyboardEvent Documentation might be helpful as well.

I've made a simple fiddle with keyboard interaction here: http://jsfiddle.net/qAHC2/292/

You can extend this to apply these keyboard interactions to svg elements by creating a variable to 'select' the current object:

var currentObject = null;

Then update this current object reference during appropriate mouse event methods:

.on("mouseover", function() {currentObject = this;})
.on("mouseout", function() {currentObject = null;});

Now you can use this current object in your keyboard interactions set up earlier.

here's a jsfiddle of this in action: http://jsfiddle.net/qAHC2/295/

Josh
  • 5,460
  • 31
  • 38
  • This works fine, but it doesn't get me at the element I want to manipulate. How do I know which SVG element was under the cursor when the keystroke event happened? – Gene Golovchinsky Mar 07 '13 at 17:36
  • 1
    for this purpose, I would suggest adding a `mouseover` event listener on your elements, then testing for keypresses in that function, though I'm not sure this is an ideal solution – Josh Mar 07 '13 at 19:00
  • so that's getting at my question: how to I test for keypresses in a `mouseover` event without rebuilding the entire event handling infrastructure? – Gene Golovchinsky Mar 07 '13 at 19:19
  • 1
    I've added to my answer what it seems you are getting at, consider revising the question if this is not the case – Josh Mar 07 '13 at 23:01
  • 4
    Clear answer, link to relevant docs, and live examples. Pity, I can only give you one up-vote. – krawyoti May 13 '13 at 10:05