Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 3f7af7f

Browse files
committed
feat(chips): Combine event handlers
1 parent 7161170 commit 3f7af7f

File tree

2 files changed

+32
-54
lines changed

2 files changed

+32
-54
lines changed

packages/mdc-chips/chip/component.ts

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ import {MDCChipFoundation} from './foundation';
3333
import {MDCChipInteractionEventDetail, MDCChipNavigationEventDetail, MDCChipRemovalEventDetail,
3434
MDCChipSelectionEventDetail} from './types';
3535

36-
type InteractionType = 'click' | 'keydown';
37-
38-
const INTERACTION_EVENTS: InteractionType[] = ['click', 'keydown'];
39-
4036
export type MDCChipFactory = (el: Element, foundation?: MDCChipFoundation) => MDCChip;
4137

4238
export class MDCChip extends MDCComponent<MDCChipFoundation> implements MDCRippleCapableSurface {
@@ -84,20 +80,17 @@ export class MDCChip extends MDCComponent<MDCChipFoundation> implements MDCRippl
8480
root_!: HTMLElement; // assigned in MDCComponent constructor
8581

8682
private leadingIcon_!: Element | null; // assigned in initialize()
87-
private trailingIcon_!: Element | null; // assigned in initialize()
8883
private checkmark_!: Element | null; // assigned in initialize()
8984
private ripple_!: MDCRipple; // assigned in initialize()
9085
private primaryAction_!: Element | null; // assigned in initialize()
9186
private trailingAction_!: Element | null; // assigned in initialize()
9287

93-
private handleInteraction_!: SpecificEventListener<InteractionType>; // assigned in initialSyncWithDOM()
88+
private handleClick_!: SpecificEventListener<'click'>; // assigned in initialSyncWithDOM()
9489
private handleTransitionEnd_!: SpecificEventListener<'transitionend'>; // assigned in initialSyncWithDOM()
95-
private handleTrailingIconInteraction_!: SpecificEventListener<InteractionType>; // assigned in initialSyncWithDOM()
9690
private handleKeydown_!: SpecificEventListener<'keydown'>; // assigned in initialSyncWithDOM()
9791

9892
initialize(rippleFactory: MDCRippleFactory = (el, foundation) => new MDCRipple(el, foundation)) {
9993
this.leadingIcon_ = this.root_.querySelector(strings.LEADING_ICON_SELECTOR);
100-
this.trailingIcon_ = this.root_.querySelector(strings.TRAILING_ICON_SELECTOR);
10194
this.checkmark_ = this.root_.querySelector(strings.CHECKMARK_SELECTOR);
10295
this.primaryAction_ = this.root_.querySelector(strings.PRIMARY_ACTION_SELECTOR);
10396
this.trailingAction_ = this.root_.querySelector(strings.TRAILING_ACTION_SELECTOR);
@@ -112,40 +105,21 @@ export class MDCChip extends MDCComponent<MDCChipFoundation> implements MDCRippl
112105
}
113106

114107
initialSyncWithDOM() {
115-
this.handleInteraction_ = (evt: MouseEvent | KeyboardEvent) => this.foundation_.handleInteraction(evt);
108+
this.handleClick_ = (evt: MouseEvent) => this.foundation_.handleClick(evt);
116109
this.handleTransitionEnd_ = (evt: TransitionEvent) => this.foundation_.handleTransitionEnd(evt);
117-
this.handleTrailingIconInteraction_ = (evt: MouseEvent | KeyboardEvent) =>
118-
this.foundation_.handleTrailingIconInteraction(evt);
119110
this.handleKeydown_ = (evt: KeyboardEvent) => this.foundation_.handleKeydown(evt);
120111

121-
INTERACTION_EVENTS.forEach((evtType) => {
122-
this.listen(evtType, this.handleInteraction_);
123-
});
112+
this.listen('click', this.handleClick_);
124113
this.listen('transitionend', this.handleTransitionEnd_);
125114
this.listen('keydown', this.handleKeydown_);
126-
127-
if (this.trailingIcon_) {
128-
INTERACTION_EVENTS.forEach((evtType) => {
129-
this.trailingIcon_!.addEventListener(evtType, this.handleTrailingIconInteraction_ as EventListener);
130-
});
131-
}
132115
}
133116

134117
destroy() {
135118
this.ripple_.destroy();
136-
137-
INTERACTION_EVENTS.forEach((evtType) => {
138-
this.unlisten(evtType, this.handleInteraction_);
139-
});
119+
this.unlisten('click', this.handleClick_);
140120
this.unlisten('transitionend', this.handleTransitionEnd_);
141121
this.unlisten('keydown', this.handleKeydown_);
142122

143-
if (this.trailingIcon_) {
144-
INTERACTION_EVENTS.forEach((evtType) => {
145-
this.trailingIcon_!.removeEventListener(evtType, this.handleTrailingIconInteraction_ as EventListener);
146-
});
147-
}
148-
149123
super.destroy();
150124
}
151125

packages/mdc-chips/chip/foundation.ts

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ export class MDCChipFoundation extends MDCFoundation<MDCChipAdapter> {
141141
/**
142142
* Handles an interaction event on the root element.
143143
*/
144-
handleInteraction(evt: MouseEvent | KeyboardEvent) {
145-
if (this.shouldHandleInteraction_(evt)) {
146-
this.adapter_.notifyInteraction();
147-
this.focusPrimaryAction_();
144+
handleClick(evt: MouseEvent) {
145+
const trailingIconIsSource = this.adapter_.eventTargetHasClass(evt.target, cssClasses.TRAILING_ICON);
146+
if (trailingIconIsSource) {
147+
return this.notifyTrailingIconInteractionAndRemove_(evt);
148148
}
149+
150+
this.notifyInteractionAndFocus_();
149151
}
150152

151153
/**
@@ -202,28 +204,25 @@ export class MDCChipFoundation extends MDCFoundation<MDCChipAdapter> {
202204
}
203205
}
204206

205-
/**
206-
* Handles an interaction event on the trailing icon element. This is used to
207-
* prevent the ripple from activating on interaction with the trailing icon.
208-
*/
209-
handleTrailingIconInteraction(evt: MouseEvent | KeyboardEvent) {
210-
if (this.shouldHandleInteraction_(evt)) {
211-
this.adapter_.notifyTrailingIconInteraction();
212-
this.removeChip_(evt);
213-
}
214-
}
215-
216207
/**
217208
* Handles a keydown event from the root element.
218209
*/
219210
handleKeydown(evt: KeyboardEvent) {
211+
const trailingIconIsSource = this.adapter_.eventTargetHasClass(evt.target, cssClasses.TRAILING_ICON);
212+
if (trailingIconIsSource && this.shouldProcessKeydownAsClick_(evt)) {
213+
return this.notifyTrailingIconInteractionAndRemove_(evt);
214+
}
215+
216+
if (this.shouldProcessKeydownAsClick_(evt)) {
217+
return this.notifyInteractionAndFocus_();
218+
}
219+
220220
if (this.shouldRemoveChip_(evt)) {
221221
return this.removeChip_(evt);
222222
}
223223

224-
const key = evt.key;
225224
// Early exit if the key is not usable
226-
if (!navigationKeys.has(key)) {
225+
if (!navigationKeys.has(evt.key)) {
227226
return;
228227
}
229228

@@ -308,20 +307,20 @@ export class MDCChipFoundation extends MDCFoundation<MDCChipAdapter> {
308307
this.adapter_.setPrimaryActionAttr(strings.TAB_INDEX, '-1');
309308
}
310309

311-
private removeChip_(evt: MouseEvent|KeyboardEvent) {
310+
private removeChip_(evt: Event) {
312311
evt.stopPropagation();
313312
if (this.shouldRemoveOnTrailingIconClick_) {
314313
this.beginExit();
315314
}
316315
}
317316

318-
private shouldHandleInteraction_(evt: MouseEvent|KeyboardEvent): boolean {
319-
if (evt.type === 'click') {
320-
return true;
321-
}
317+
private notifyTrailingIconInteractionAndRemove_(evt: Event) {
318+
this.adapter_.notifyTrailingIconInteraction();
319+
this.removeChip_(evt);
320+
}
322321

323-
const keyEvt = evt as KeyboardEvent;
324-
return keyEvt.key === strings.ENTER_KEY || keyEvt.key === strings.SPACEBAR_KEY;
322+
private shouldProcessKeydownAsClick_(evt: KeyboardEvent): boolean {
323+
return evt.key === strings.ENTER_KEY || evt.key === strings.SPACEBAR_KEY;
325324
}
326325

327326
private shouldRemoveChip_(evt: KeyboardEvent): boolean {
@@ -346,6 +345,11 @@ export class MDCChipFoundation extends MDCFoundation<MDCChipAdapter> {
346345
private notifyIgnoredSelection_(selected: boolean) {
347346
this.adapter_.notifySelection(selected, true);
348347
}
348+
349+
private notifyInteractionAndFocus_() {
350+
this.adapter_.notifyInteraction();
351+
this.focusPrimaryAction_();
352+
}
349353
}
350354

351355
// tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.

0 commit comments

Comments
 (0)