Search code examples
svgd3.jsonbluronfocusout

Focus, blur, focusin, focusout, don't work with D3 and SVG Elements? Is there an alternative?


I'm using the d3 library to create a widget within a SVG. Within the SVG I'm trying to do the following:

There are small rectangles that are clickable. Once clickable, they should "enlarge" and show some input fields. When I click outside the rectangles I want them to "un-enlarge" and remove the input fields again.

Small rectangle:

enter image description here

Once clicked, they enlarge (no input fields yet):

enter image description here

When I click outside of the white rectangle, I want it to revert back to picture 1:

enter image description here

I trigger the enlargement with an on click event:

let whiteRect = node.append("g")
                    .on('click', function(a) {
                         // Trigger enlarge function
                         return a;
                     })};

And I would like to trigger the "click outside" using a blur or focusout event. But this doesn't seem to work for SVG. Something like this:

let whiteRect = node.append("g")
                    .on('blur', function(a) {
                         // Trigger "un-enlarge" function
                         return a;
                     })};

I've been doing some searching, and it seems that in SVG 2 this might be supported, but this doesn't seem to be implemented by any browsers.

Anyone have an idea how I could implement this? I know I can add an onclick event listener for the whole SVG and write some logic there to identify if I'm clicking on an enlarged rectangle. But I'd prefer using something easier like blur or focusout if possible. Any ideas?


Solution

  • Shortly after posting I found this tutorial on focusing svg elements: https://allyjs.io/tutorials/focusing-in-svg.html

    Turns out if you add a focus event to an element it becomes focusable and also gets a blur event. So what I did was add an empty focus event to be able to use the blur.

    let whiteRect = node.append("g")
                    .on('click', function(a) {
                         // Trigger enlarge function
                         return a;
                     })}
                    .on('focus', function(a) {
                         // Empty focus event
                         return a;
                     })}
                    .on('blur', function(a) {
                         // Trigger un-enlarge function
                         return a;
                     })};
    

    Which worked for me.