From 0a7895f4d4c22296ad23b2d8a7e1a4dbe231b941 Mon Sep 17 00:00:00 2001 From: Allan Chen Date: Wed, 3 Jun 2020 14:03:10 -0700 Subject: [PATCH] fix(select): Make compatible with rich list-items PiperOrigin-RevId: 314600015 --- packages/mdc-list/README.md | 1 + packages/mdc-list/component.ts | 30 +++++++++++++++--------- packages/mdc-list/test/component.test.ts | 16 +++++++++++++ packages/mdc-menu/README.md | 1 + packages/mdc-menu/component.ts | 12 ++++++++++ packages/mdc-menu/test/component.test.ts | 15 +++++++++--- packages/mdc-select/component.ts | 2 +- 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/packages/mdc-list/README.md b/packages/mdc-list/README.md index df90d39b8a9..fbf4ceeb56f 100644 --- a/packages/mdc-list/README.md +++ b/packages/mdc-list/README.md @@ -505,6 +505,7 @@ Property | Value Type | Description Method Signature | Description --- | --- `layout() => void` | Recalculates layout and orientation. +`getPrimaryText(item: Element) => string` | Fetches the primary text in the given element. `initializeListType() => void` | Initialize `selectedIndex` value based on pre-selected checkbox list items, single selection or radio. `setEnabled(itemIndex: number, isEnabled: boolean) => void` | Updates the list item at `itemIndex` to the desired `isEnabled` state. diff --git a/packages/mdc-list/component.ts b/packages/mdc-list/component.ts index 4bf84426ee3..5fb3a0005c7 100644 --- a/packages/mdc-list/component.ts +++ b/packages/mdc-list/component.ts @@ -111,6 +111,23 @@ export class MDCList extends MDCComponent { this.foundation.layout(); } + /** + * Extracts the primary text from a list item. + * @param item The list item element. + * @return The primary text in the element. + */ + getPrimaryText(item: Element): string { + const primaryText = + item.querySelector(`.${cssClasses.LIST_ITEM_PRIMARY_TEXT_CLASS}`); + if (primaryText) { + return primaryText.textContent || ''; + } + + const singleLineText = + item.querySelector(`.${cssClasses.LIST_ITEM_TEXT_CLASS}`); + return (singleLineText && singleLineText.textContent) || ''; + } + /** * Initialize selectedIndex value based on pre-selected checkbox list items, single selection or radio. */ @@ -171,17 +188,8 @@ export class MDCList extends MDCComponent { getFocusedElementIndex: () => this.listElements.indexOf(document.activeElement!), getListItemCount: () => this.listElements.length, - getPrimaryTextAtIndex: (index) => { - const primaryText = this.listElements[index].querySelector( - `.${cssClasses.LIST_ITEM_PRIMARY_TEXT_CLASS}`); - if (primaryText) { - return primaryText.textContent || ''; - } - - const singleLineText = this.listElements[index].querySelector( - `.${cssClasses.LIST_ITEM_TEXT_CLASS}`); - return (singleLineText && singleLineText.textContent) || ''; - }, + getPrimaryTextAtIndex: (index) => + this.getPrimaryText(this.listElements[index]), hasCheckboxAtIndex: (index) => { const listItem = this.listElements[index]; return !!listItem.querySelector(strings.CHECKBOX_SELECTOR); diff --git a/packages/mdc-list/test/component.test.ts b/packages/mdc-list/test/component.test.ts index 6bece240a34..063058a0c50 100644 --- a/packages/mdc-list/test/component.test.ts +++ b/packages/mdc-list/test/component.test.ts @@ -376,6 +376,22 @@ describe('MDCList', () => { expect(0).toEqual(root.querySelectorAll('button:not([tabindex])').length); }); + it('#getPrimaryText returns the appropriate text for one line list', () => { + const {root, component} = setupTest(); + const item = root.querySelectorAll('.mdc-list-item')[2] as HTMLElement; + document.body.appendChild(root); + expect(component.getPrimaryText(item)).toEqual('Pasta'); + document.body.removeChild(root); + }); + + it('#getPrimaryText returns the appropriate text for two line list', () => { + const {root, component} = setupTest(getTwoLineFixture()); + const item = root.querySelectorAll('.mdc-list-item')[2] as HTMLElement; + document.body.appendChild(root); + expect(component.getPrimaryText(item)).toEqual('Pasta'); + document.body.removeChild(root); + }); + it('vertical calls setVerticalOrientation on foundation', () => { const {component, mockFoundation} = setupTest(); component.vertical = false; diff --git a/packages/mdc-menu/README.md b/packages/mdc-menu/README.md index 3de4b970564..c49bed09e3c 100644 --- a/packages/mdc-menu/README.md +++ b/packages/mdc-menu/README.md @@ -231,6 +231,7 @@ Method Signature | Description `setIsHoisted(isHoisted: boolean) => void` | Proxies to the menu surface's `setIsHoisted(isHoisted: boolean)` method. `setAnchorElement(element: Element) => void` | Proxies to the menu surface's `setAnchorElement(element)` method. `getOptionByIndex(index: number) => Element \| null` | Returns the list item at the `index` specified. +`getPrimaryTextAtIndex(index: number) => string` | Returns the primary text at the `index` specified. `getDefaultFoundation() => MDCMenuFoundation` | Returns the foundation. `setDefaultFocusState(focusState: DefaultFocusState) => void` | Sets default focus state where the menu should focus every time when menu is opened. Focuses the list root (`DefaultFocusState.LIST_ROOT`) element by default. `setEnabled(index: number, isEnabled: boolean) => void` | Sets the enabled state to `isEnabled` for the menu item at given `index`. diff --git a/packages/mdc-menu/component.ts b/packages/mdc-menu/component.ts index 94c2ad426fa..e4a752b0b94 100644 --- a/packages/mdc-menu/component.ts +++ b/packages/mdc-menu/component.ts @@ -200,6 +200,18 @@ export class MDCMenu extends MDCComponent { } } + /** + * @param index A menu item's index. + * @return The primary text within the menu at the index specified. + */ + getPrimaryTextAtIndex(index: number): string { + const item = this.getOptionByIndex(index); + if (item && this.list_) { + return this.list_.getPrimaryText(item) || ''; + } + return ''; + } + setFixedPosition(isFixed: boolean) { this.menuSurface_.setFixedPosition(isFixed); } diff --git a/packages/mdc-menu/test/component.test.ts b/packages/mdc-menu/test/component.test.ts index dd0b32aaed3..d34493bf7f6 100644 --- a/packages/mdc-menu/test/component.test.ts +++ b/packages/mdc-menu/test/component.test.ts @@ -83,11 +83,12 @@ function getFixtureWithMultipleSelectionGroups(open = false) { } class FakeList { - destroy: Function = jasmine.createSpy('.destroy'); - itemsContainer: Function = jasmine.createSpy('.root_'); - layout: Function = jasmine.createSpy('layout'); + destroy: jasmine.Spy = jasmine.createSpy('.destroy'); + itemsContainer: jasmine.Spy = jasmine.createSpy('.root_'); + layout: jasmine.Spy = jasmine.createSpy('layout'); wrapFocus: boolean = true; listElements: HTMLElement[]; + getPrimaryText: jasmine.Spy = jasmine.createSpy('.getPrimaryText'); constructor(root: HTMLElement) { this.listElements = [].slice.call(root.querySelectorAll('.mdc-list-item')) @@ -294,6 +295,14 @@ describe('MDCMenu', () => { expect(component.getOptionByIndex(items.length)).toBe(null); }); + it('getPrimaryTextAtIndex', () => { + const {component, list} = setupTestWithFakes(); + list.getPrimaryText.withArgs(jasmine.any(Element)) + .and.returnValue('Another Item'); + + expect(component.getPrimaryTextAtIndex(1)).toEqual('Another Item'); + }); + it('setFixedPosition', () => { const {component, menuSurface} = setupTestWithFakes(); component.setFixedPosition(true); diff --git a/packages/mdc-select/component.ts b/packages/mdc-select/component.ts index 3c5cced763c..e3faa559f94 100644 --- a/packages/mdc-select/component.ts +++ b/packages/mdc-select/component.ts @@ -393,7 +393,7 @@ export class MDCSelect extends MDCComponent { getMenuItemValues: () => this.menu.items.map( (el) => el.getAttribute(strings.VALUE_ATTR) || ''), getMenuItemTextAtIndex: (index: number) => - this.menu.items[index].textContent as string, + this.menu.getPrimaryTextAtIndex(index), addClassAtIndex: (index: number, className: string) => { this.menu.items[index].classList.add(className); },