Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Add events to el.focus() and el.blur() #533

Closed
tmpvar opened this Issue Nov 19, 2012 · 15 comments

Comments

Projects
None yet
7 participants
Owner

tmpvar commented Nov 19, 2012

Right now we are just changing the document.activeElement, but I believe we need to emit events as well.

Also, tests.

Collaborator

domenic commented Nov 20, 2012

This could help with #525's :focus failure as well.

Collaborator

domenic commented Nov 22, 2012

Actually as of HTML5 all elements have focus and blur methods:

http://dev.w3.org/html5/spec/single-page.html#focus-management

This is used in the newest Sizzle tests to focus a random div, interestingly.

Owner

tmpvar commented Nov 22, 2012

O_o .. Ok, well I guess that just makes things easier lol

On Nov 22, 2012, at 12:50 PM, Domenic Denicola notifications@github.com wrote:

Actually as of HTML5 all elements have focus and blur methods:

http://dev.w3.org/html5/spec/single-page.html#focus-management

This is used in the newest Sizzle tests to focus a random div, interestingly.


Reply to this email directly or view it on GitHub.

domenic added a commit that referenced this issue Dec 10, 2012

Blur should set `activeElement` to the body.
Thanks to @dperini for pointing this out in his comments on c78cbed.

Helps with #533, a little.

dperini commented Dec 10, 2012

Not sure this is important here for JSDOM, nor I know how much could/should be implemented.

In browsers the Activation model takes place too (DOMActivate, DOMFocusIn, DOMFocusOut).

Consider that specs says this is important only if XFORMS or Aria support is required.

Also the above events seems now deprecated, for 2 of them there are replacements: focusin, focusout.

This is a reference for event synthesis in L3:

http://www.w3.org/TR/DOM-Level-3-Events/#click-synthesis

The order in which events happen is in § 5.2.2.1

dperini commented Dec 10, 2012

The main concern that raised in me, after suggesting that patch, is if a transition through the "body" element is always required.

For example, if a text input is currently the activeElement having the keyboard focus and a click is performed on the next text input, the activeElement should transit directly to that target element instead of going through the "body" element (caused by the "blur" event).

This probably too complex for the objective but I wanted to share the doubts :)

I just ran into this. I'd managed to get a jquery.validate signup form fully tested with a manually-created JSDOM document, window etc, until I added validate-on-blur. It took me quite a while to figure out it's because these events aren't firing.

After digging around, it seems Zombie.js solves this problem by monkeypatching JSDOM: https://github.com/assaf/zombie/blob/master/src/zombie/dom_focus.coffee

Sadly there doesn't seem a way to re-use this without copypasting it into my project. (I'm extremely new to JavaScript/Node though, so maybe I've missed something.) Either way, it's a shame to have to use Zombie (or dismembered code thereof) for want of focus events in JSDOM.

Update: I decided to copypaste the Zombie monkeypatch and it works fine. Maybe it'd be possible to port this to JSDOM? I don't know if it's compliant with everything @dperini mentioned above though.

Collaborator

domenic commented Jul 15, 2013

Wow, it looks like Zombie has a lot of patches. I wish they would contribute them back to jsdom.

Just adding a 👍 as another person who could use this functionality.

Here's an approach I took to trigger the basic events. Would this kind of approach be accepted as a patch? If so, where would the tests belong?

  activeElement = document.body
  Object.defineProperty document, 'activeElement',
    get: -> activeElement
    set: (newActiveElement) ->
      blurEvent = document.createEvent("HTMLEvents")
      blurEvent.initEvent("blur", false, false)
      focusEvent = document.createEvent("HTMLEvents")
      focusEvent.initEvent("focus", false, false)
      oldActiveElement = activeElement
      activeElement = newActiveElement
      oldActiveElement.dispatchEvent(blurEvent)
      newActiveElement.dispatchEvent(focusEvent)
Collaborator

domenic commented Nov 26, 2013

No patches written in languages other than JavaScript will be accepted.

I mean the general approach, not the language.

@fatso83 fatso83 referenced this issue in assaf/zombie Dec 13, 2013

Closed

Push code back into JSDOM #622

btakita commented Dec 26, 2013

@nathansobo Nice patch! I couldn't get event bubbling to work though, even when switching the bubbles flag on the initEvent calls.

btakita commented Dec 29, 2013

Are there any attempts to get the Zombie patch into JSDOM?

btakita commented Dec 30, 2013

I tried to integrate the zombie.js patch, but in some case, the focus and blur events were not getting triggered. The fix was to remove:

  HTML.HTMLElement.prototype.focus = function() {
  };
  HTML.HTMLElement.prototype.blur = function() {
  };

Unfortunately, I was not able to isolate the issue nor able to create a simple reproduction of this error...

@craigdallimore craigdallimore referenced this issue in JedWatson/react-select Jun 11, 2015

Closed

Add Tests / Specs #240

nylen commented Jan 5, 2016

It looks like this is still an issue. I have some code that needs to read document.activeElement in a blur event handler (since nobody told IE11 about relatedTarget). In order to test this code using jsdom, we have to use an extra step:

// 1. Reset document.activeElement (pick one, these are equivalent)
myElement.blur();
document.activeElement = document.body;

// 2. Send an event to call handlers
myElement.dispatchEvent( new Event( 'blur' ) );

Context: Automattic/wp-calypso#2054

@domenic domenic closed this in 1805283 May 15, 2016

nhunzaker added a commit to nhunzaker/jsdom that referenced this issue Dec 22, 2016

Add a reasonable focus events implementation
This is clearly not a full implementation of all the focus-related complexities, but it improves over the previous naive focus() and blur() methods in the following ways:

- Only allows focusing elements that are specifically focusable
- Adds the FocusEvent class, and fires "focus" and "blur" events appropriately
- tabIndex now returns 0 by default for focusable elements

Closes #1478. Closes #533.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment