Skip to content

Commit

Permalink
isElementUnderPDOM can return false if the element is the PDOM root, …
Browse files Browse the repository at this point in the history
…see #1631
  • Loading branch information
jessegreenberg committed May 8, 2024
1 parent a0c37f5 commit 92e8bc6
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 7 deletions.
2 changes: 1 addition & 1 deletion js/accessibility/FocusManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export default class FocusManager {
const display = displays[ i ];

const activeElement = document.activeElement as HTMLElement;
if ( display.isElementUnderPDOM( activeElement ) ) {
if ( display.isElementUnderPDOM( activeElement, false ) ) {
const uniqueId = activeElement.getAttribute( PDOMUtils.DATA_PDOM_UNIQUE_ID )!;
assert && assert( uniqueId, 'Event target must have a unique ID on its data if it is in the PDOM.' );

Expand Down
15 changes: 13 additions & 2 deletions js/display/Display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -938,9 +938,20 @@ export default class Display {

/**
* Returns true if the element is in the PDOM. That is only possible if the display is accessible.
* @param element
* @param allowRoot - If true, the root of the PDOM is also considered to be "under" the PDOM.
*/
public isElementUnderPDOM( element: Element ): boolean {
return this._accessible && this.pdomRootElement!.contains( element );
public isElementUnderPDOM( element: Element, allowRoot: boolean ): boolean {
if ( !this._accessible ) {
return false;
}

const isElementContained = this.pdomRootElement!.contains( element );
const isNotRootElement = element !== this.pdomRootElement;

// If allowRoot is true, just return if the element is contained.
// Otherwise, also ensure it's not the root element itself.
return allowRoot ? isElementContained : ( isElementContained && isNotRootElement );
}

/**
Expand Down
8 changes: 4 additions & 4 deletions js/input/Input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ export default class Input extends PhetioObject {
public getRelatedTargetTrail( domEvent: FocusEvent | MouseEvent ): Trail | null {
const relatedTargetElement = domEvent.relatedTarget;

if ( relatedTargetElement && this.display.isElementUnderPDOM( relatedTargetElement as HTMLElement ) ) {
if ( relatedTargetElement && this.display.isElementUnderPDOM( relatedTargetElement as HTMLElement, false ) ) {

const relatedTarget = ( domEvent.relatedTarget as unknown as Element );
assert && assert( relatedTarget instanceof window.Element );
Expand Down Expand Up @@ -1154,7 +1154,7 @@ export default class Input extends PhetioObject {
}
else {
const target = domEvent.target;
if ( target && target instanceof window.Element && this.display.isElementUnderPDOM( target ) ) {
if ( target && target instanceof window.Element && this.display.isElementUnderPDOM( target, false ) ) {
const trailIndices = target.getAttribute( PDOMUtils.DATA_PDOM_UNIQUE_ID );
assert && assert( trailIndices, 'should not be null' );
return PDOMInstance.uniqueIdToTrail( this.display, trailIndices! );
Expand Down Expand Up @@ -1607,7 +1607,7 @@ export default class Input extends PhetioObject {
// if the event target is within the PDOM the AT is sending a fake pointer event to the document - do not
// dispatch this since the PDOM should only handle Input.PDOM_EVENT_TYPES, and all other pointer input should
// go through the Display div. Otherwise, activation will be duplicated when we handle pointer and PDOM events
if ( this.display.isElementUnderPDOM( context.domEvent.target as HTMLElement ) ) {
if ( this.display.isElementUnderPDOM( context.domEvent.target as HTMLElement, true ) ) {
return;
}

Expand Down Expand Up @@ -1636,7 +1636,7 @@ export default class Input extends PhetioObject {
// if the event target is within the PDOM the AT is sending a fake pointer event to the document - do not
// dispatch this since the PDOM should only handle Input.PDOM_EVENT_TYPES, and all other pointer input should
// go through the Display div. Otherwise, activation will be duplicated when we handle pointer and PDOM events
if ( this.display.isElementUnderPDOM( context.domEvent.target as HTMLElement ) ) {
if ( this.display.isElementUnderPDOM( context.domEvent.target as HTMLElement, true ) ) {
return;
}

Expand Down

0 comments on commit 92e8bc6

Please sign in to comment.