Skip to content

Commit

Permalink
refactor(core): Move preventDefault to Dispatcher (#55756)
Browse files Browse the repository at this point in the history
This is a simple move.

PR Close #55756
  • Loading branch information
tbondwilkinson authored and atscott committed May 14, 2024
1 parent 6850ff1 commit 3b1b4e2
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 45 deletions.
22 changes: 22 additions & 0 deletions packages/core/primitives/event-dispatch/src/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ export class Dispatcher {
*/
dispatch(eventInfo: EventInfo): void {
const eventInfoWrapper = new EventInfoWrapper(eventInfo);
const action = eventInfoWrapper.getAction();
if (action && shouldPreventDefaultBeforeDispatching(action.element, eventInfoWrapper)) {
eventLib.preventDefault(eventInfoWrapper.getEvent());
}
if (eventInfoWrapper.getIsReplay()) {
if (!this.eventReplayer) {
return;
Expand Down Expand Up @@ -131,6 +135,24 @@ export function stopPropagation(eventInfoWrapper: EventInfoWrapper) {
event.stopPropagation();
}

/**
* Returns true if the default action of this event should be prevented before
* this event is dispatched.
*/
function shouldPreventDefaultBeforeDispatching(
actionElement: Element,
eventInfoWrapper: EventInfoWrapper,
): boolean {
// Prevent browser from following <a> node links if a jsaction is present
// and we are dispatching the action now. Note that the targetElement may be
// a child of an anchor that has a jsaction attached. For that reason, we
// need to check the actionElement rather than the targetElement.
return (
(actionElement.tagName === 'A' && eventInfoWrapper.getEventType() === EventType.CLICK) ||
eventInfoWrapper.getEventType() === EventType.CLICKMOD
);
}

/**
* Registers deferred functionality for an EventContract and a Jsaction
* Dispatcher.
Expand Down
26 changes: 0 additions & 26 deletions packages/core/primitives/event-dispatch/src/eventcontract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,6 @@ export class EventContract implements UnrenamedEventContract {
return;
}
this.actionResolver.resolve(eventInfo);
const action = eventInfoLib.getAction(eventInfo);
if (action) {
if (shouldPreventDefaultBeforeDispatching(eventInfoLib.getActionElement(action), eventInfo)) {
eventLib.preventDefault(eventInfoLib.getEvent(eventInfo));
}
}

this.dispatcher(eventInfo);
}

Expand Down Expand Up @@ -386,22 +379,3 @@ export function addDeferredA11yClickSupport(eventContract: EventContract) {
a11yClickLib.populateClickOnlyAction,
);
}

/**
* Returns true if the default action of this event should be prevented before
* this event is dispatched.
*/
function shouldPreventDefaultBeforeDispatching(
actionElement: Element,
eventInfo: eventInfoLib.EventInfo,
): boolean {
// Prevent browser from following <a> node links if a jsaction is present
// and we are dispatching the action now. Note that the targetElement may be
// a child of an anchor that has a jsaction attached. For that reason, we
// need to check the actionElement rather than the targetElement.
return (
actionElement.tagName === 'A' &&
(eventInfoLib.getEventType(eventInfo) === EventType.CLICK ||
eventInfoLib.getEventType(eventInfo) === EventType.CLICKMOD)
);
}
46 changes: 27 additions & 19 deletions packages/core/primitives/event-dispatch/test/eventcontract_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import {OWNER} from '../src/property';
import {Restriction} from '../src/restriction';

import {safeElement, testonlyHtml} from './html';
import {
Dispatcher as LateDispatcher,
registerDispatcher as registerLateDispatcher,
} from '../src/dispatcher';

declare global {
interface Window extends EarlyJsactionDataContainer {}
Expand Down Expand Up @@ -849,17 +853,18 @@ describe('EventContract', () => {
const actionElement = getRequiredElementById('anchor-click-action-element');
const targetElement = getRequiredElementById('anchor-click-target-element');

const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
const eventContract = createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
const dispatch = jasmine.createSpy<(eventInfoWrapper: EventInfoWrapper) => void>('dispatch');
const dispatcher = new LateDispatcher(dispatch);
registerLateDispatcher(eventContract, dispatcher);

const clickEvent = dispatchMouseEvent(targetElement);

expect(dispatcher).toHaveBeenCalledTimes(1);
const eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(dispatch).toHaveBeenCalledTimes(1);
const eventInfoWrapper = dispatch.calls.mostRecent().args[0];
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
Expand All @@ -874,17 +879,18 @@ describe('EventContract', () => {
const actionElement = getRequiredElementById('anchor-clickmod-action-element');
const targetElement = getRequiredElementById('anchor-clickmod-target-element');

const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
const eventContract = createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
const dispatch = jasmine.createSpy<(eventInfoWrapper: EventInfoWrapper) => void>('dispatch');
const dispatcher = new LateDispatcher(dispatch);
registerLateDispatcher(eventContract, dispatcher);

const clickEvent = dispatchMouseEvent(targetElement, {shiftKey: true});

expect(dispatcher).toHaveBeenCalledTimes(1);
const eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(dispatch).toHaveBeenCalledTimes(1);
const eventInfoWrapper = dispatch.calls.mostRecent().args[0];
expect(eventInfoWrapper.getEventType()).toBe('clickmod');
expect(eventInfoWrapper.getEvent()).toBe(clickEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
Expand Down Expand Up @@ -966,17 +972,18 @@ describe('EventContract', () => {
const actionElement = getRequiredElementById('a11y-anchor-click-action-element');
const targetElement = getRequiredElementById('a11y-anchor-click-target-element');

const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
createEventContract({
const eventContract = createEventContract({
eventContractContainerManager: new EventContractContainer(container),
eventTypes: ['click'],
dispatcher,
});
const dispatch = jasmine.createSpy<(eventInfoWrapper: EventInfoWrapper) => void>('dispatch');
const dispatcher = new LateDispatcher(dispatch);
registerLateDispatcher(eventContract, dispatcher);

const keydownEvent = dispatchKeyboardEvent(targetElement, {key: 'Enter'});

expect(dispatcher).toHaveBeenCalledTimes(1);
const eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(dispatch).toHaveBeenCalledTimes(1);
const eventInfoWrapper = dispatch.calls.mostRecent().args[0];
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(keydownEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
Expand Down Expand Up @@ -1095,19 +1102,20 @@ describe('EventContract', () => {
const actionElement = getRequiredElementById('a11y-anchor-click-action-element');
const targetElement = getRequiredElementById('a11y-anchor-click-target-element');

const dispatcher = jasmine.createSpy<Dispatcher>('dispatcher');
const eventContract = createEventContract({
eventContractContainerManager: new EventContractContainer(container),
exportAddA11yClickSupport: true,
eventTypes: ['click'],
dispatcher,
});
addDeferredA11yClickSupport(eventContract);
const dispatch = jasmine.createSpy<(eventInfoWrapper: EventInfoWrapper) => void>('dispatch');
const dispatcher = new LateDispatcher(dispatch);
registerLateDispatcher(eventContract, dispatcher);

const keydownEvent = dispatchKeyboardEvent(targetElement, {key: 'Enter'});

expect(dispatcher).toHaveBeenCalledTimes(1);
const eventInfoWrapper = getLastDispatchedEventInfoWrapper(dispatcher);
expect(dispatch).toHaveBeenCalledTimes(1);
const eventInfoWrapper = dispatch.calls.mostRecent().args[0];
expect(eventInfoWrapper.getEventType()).toBe('click');
expect(eventInfoWrapper.getEvent()).toBe(keydownEvent);
expect(eventInfoWrapper.getTargetElement()).toBe(targetElement);
Expand Down

0 comments on commit 3b1b4e2

Please sign in to comment.