4

I've created a fiddle of this one so you can see the problem for yourselves. If you give an element focus, any associated events will fire but the focus isn't actually on the element, or at least it doesn't seem to be as tabbing takes you back through the elements. Works perfectly on Chrome.

Here's the jQuery:

$squares = $('a');

$squares.on('focus', function() {
  $(this).find('rect').attr('opacity', '.2');
}).on('blur', function() {
  $(this).find('rect').attr('opacity', '1');
});

$squares.eq(2).focus();

And here's the fiddle: http://jsfiddle.net/bigwigal/n3bf8ofe/2/

Any advice would be much appreciated. Thanks.

bigwigal
  • 95
  • 8
  • Interesting bug. You're right that the focus method isn't really setting keyboard focus, I [added different fragments to each of your links](http://jsfiddle.net/n3bf8ofe/4/) and when [viewing the result in a separate tab](http://fiddle.jshell.net/n3bf8ofe/4/show/) you can tell that hitting Enter doesn't change the page target when the "focus" is on the link you focused from the script. (If you actually tab through the cells and then activate the links the target changes as expected.) Tabbing focus also doesn't trigger a blur event on the `` that is faux-focused. – AmeliaBR Aug 08 '14 at 23:34

1 Answers1

1

The problem is that the basic DOM methods .focus() and .blur() (which are used internally by the JQuery methods) are not defined on the SVGAnchorElement interface that represents <a> elements in SVG.

The DOM Level 2 specifications only define the blur and focus methods on specific types of HTML elements (form elements and anchors).

The HTML 5 specs-in-progress define these methods for the HTMLElement interface, so any element in the HTML namespace can conceivably receive keyboard focus.

However, the SVG specs (which haven't been significantly updated since pre-HTML5 days), do not define those methods.

I personally would happily back a proposal to have the focus/blur methods defined on the general Element interface. I suspect this is how Chrome implements it internally. If that doesn't happen, hopefully there will be something specific in the SVG2 specs.

It still doesn't explain why the focus() method is triggering a focus event, and therefore a style change, in your fiddle. I suspect that JQuery is catching the no-such-function error and as a fallback creating the Focus event directly, but it's not having the proper effect on the document as a whole.

In contrast, a vanilla Javascript version of your fiddle simply errors out when trying to call (the basic DOM version of) focus() (this is how I realized that the problem was that the function didn't exist!):

http://jsfiddle.net/n3bf8ofe/5/

var squares = document.getElementsByTagName('a');

for (var i=0,max=squares.length; i<max; i++) {
    var square = squares[i];
    square.addEventListener('focus', function() {
        this.setAttribute('opacity', '.2');
    }, square);
    square.addEventListener('blur', function() {
        this.setAttribute('opacity', '1');
    }, square);
}

try {
    squares[2].focus();
}catch(e){ console.log("Error! ", e); }

Unfortunately, I haven't been able to figure out a workaround. The Document.activeElement property is read-only. (And interestingly, is not part of the W3 DOM specs, only the HTML5 specs.)

There really isn't any other standard way of controlling focus from scripts. Even the tabIndex attribute is ignored in SVG (another feature I'd like to see in the SVG 2 -- or the basic DOM -- specs!).

P.S., You might be interested in this Q&A, about similar problems with the SVGStyleElement not having all the functionality of an HTMLStyleElement.

Community
  • 1
  • 1
AmeliaBR
  • 27,344
  • 6
  • 86
  • 119