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

feat(list): Toggle radio checkbox #3546

Merged
merged 25 commits into from
Sep 20, 2018
Merged

Conversation

williamernest
Copy link
Contributor

@williamernest williamernest commented Sep 11, 2018

fixes: #3510

BREAKING CHANGE: Moves the toggling of radio buttons and checkboxes to the list from the menu. Adds toggleCheckbox List adapter API.

@codecov-io
Copy link

codecov-io commented Sep 11, 2018

Codecov Report

Merging #3546 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3546      +/-   ##
==========================================
+ Coverage   98.35%   98.35%   +<.01%     
==========================================
  Files         120      120              
  Lines        5168     5175       +7     
  Branches      640      642       +2     
==========================================
+ Hits         5083     5090       +7     
  Misses         85       85
Impacted Files Coverage Δ
packages/mdc-menu/foundation.js 100% <ø> (ø) ⬆️
packages/mdc-list/constants.js 100% <ø> (ø) ⬆️
packages/mdc-menu/index.js 100% <ø> (ø) ⬆️
packages/mdc-list/foundation.js 99.16% <100%> (+0.04%) ⬆️
packages/mdc-list/index.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 26f6699...59008b7. Read the comment docs.

@mdc-web-bot
Copy link
Collaborator

All 389 screenshot tests passed for commit 73afd56 vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 389 screenshot tests passed for commit 2ec343b vs. master! 💯🎉

@kfranqueiro kfranqueiro self-requested a review September 12, 2018 01:20
@kfranqueiro kfranqueiro self-assigned this Sep 12, 2018
Copy link
Contributor

@kfranqueiro kfranqueiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline: Radio buttons have different behavior than checkboxes with regard to emitting change events (the change event only emits on the radio that becomes checked), and it might not make sense to specifically apply toggle logic to radios the same way we're handling checkboxes.

const event = document.createEvent('Event');
event.initEvent('change', false, true);

if (!element.checked) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be simplified to if (!element.checked || element.type !== 'radio') and avoid needing the else and repeating the 2 lines inside? (Move the comment up)

const listItem = this.listElements[index];
const elementsToToggle =
[].slice.call(listItem.querySelectorAll('input[type="radio"], input[type="checkbox"]'));
elementsToToggle.forEach((element) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we let a boolean outside of this loop and set it to true when this function is run, we can return it as an indicator of whether an input was found to toggle, and preventDefault on the event within the foundation if this returns true.

*/
toggleCheckbox(target) {}
toggleCheckbox(index) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still in menu's adapter... it belongs in List's now, right?

test('adapter#toggleCheckbox toggles a radio button', () => {
const {root, component} = setupTest();
document.body.appendChild(root);
const checkbox = root.querySelector('input[type="radio"]');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: checkbox -> radio

[].slice.call(listItem.querySelectorAll('input[type="radio"], input[type="checkbox"]'));
elementsToToggle.forEach((element) => {
const event = document.createEvent('Event');
event.initEvent('change', false, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are some potential issues here...

  • Why is bubbles set to false? Change events bubble by default. i.e. if I set up a document-level change listener, I will only get change events if I actually interact directly with the input right now.
  • However, right now, if I click directly on a checkbox, I get 2 change events emitted directly on the checkbox. This doesn't happen for radios, possibly because of the if below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, initEvent is apparently deprecated in favor of directly using Event constructors; see https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Event constructors are not supported in IE11.
https://developer.mozilla.org/en-US/docs/Web/API/Event/Event

td.verify(mockFoundation.handleClick(td.matchers.anything()), {times: 1});
});

test('singleSelection false removes the click handler from the root element', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI there is no equivalent test to this in the new code (i.e. no test that tests MDCListFoundation#handleClick when isSingleSelectionList_ is false)

@@ -374,3 +358,23 @@ test('keydown handler is removed from the root element on destroy', () => {
listElementItem.dispatchEvent(event);
td.verify(mockFoundation.handleKeydown(event, true, 0), {times: 0});
});

test('adapter#toggleCheckbox toggles a checkbox', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a third test with no checkbox/radio to verify it returns false

td.verify(mockAdapter.setAttributeForElementIndex(0, 'tabindex', 0), {times: 0});
});

test('#handleClick proxies to the adapter#toggleCheckbox is toggleCheckbox is true', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is toggleCheckbox -> if toggleCheckbox

@@ -481,62 +481,66 @@ test('#handleKeydown space key is triggered and focused is moved to a different
td.verify(mockAdapter.setAttributeForElementIndex(2, 'tabindex', 0), {times: 1});
});

test('#handleClick when singleSelection=true on a list item should not cause the list item to be selected', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true -> false

component.getDefaultFoundation().adapter_.setTabIndexForListItemChildren(index, 0);
assert.equal(1, listItems[index].querySelectorAll('[tabindex="0"]').length);
}
component.getDefaultFoundation().adapter_.setTabIndexForListItemChildren(0, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The descriptions of this test and in the README need updating for the new behavior.

@kfranqueiro
Copy link
Contributor

FYI there's currently no test exercising the preventDefault branch in handleKeydown.

and then tab to the first element after the list. The `Arrow`, `Home`, and `End` keys should be used for navigating
internal list elements. If `singleSelection=true`, the list will allow the user to use the `Space` or `Enter` keys to
select or deselect a list item. The MDCList will perform the following actions for each key press
As the user navigates through the list, any `button`, and `a` elements within the list will receive `tabindex="-1"` when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove comma between "button and a"

@@ -203,17 +204,31 @@ class MDCListFoundation extends MDCFoundation {
this.adapter_.followHref(currentIndex);
}
}

if (isEnter || isSpace) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be more straightforward to put this within the else if above, make that else if check only for isEnter || isSpace, then nest if (this.isSingleSelectionList_) within that? IMO it's a little hard to follow right now since there's two separate blocks with logic for enter/space, and potentially both of them can be executed.

Tangentially, I also can't remember why the preventDefault for single-selection is outside the isRootListItem check?

@@ -110,19 +110,6 @@ class MDCMenuAdapter {
* }} evtData
*/
notifySelected(evtData) {}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These also need to be removed from the menu README

Copy link
Contributor

@kfranqueiro kfranqueiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one nit and one test comment

if (isRootListItem) {
this.setSelectedIndex(currentIndex);
} else if (isEnter || isSpace) {
if (this.isSingleSelectionList_) {
Copy link
Contributor

@kfranqueiro kfranqueiro Sep 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can collapse these two nested if's (single-selection + root list item) into one if && now?

} else if (isEnter || isSpace) {
if (this.isSingleSelectionList_) {
// Check if the space key was pressed on the list item or a child element.
if (isRootListItem) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't seem to have a test for single-selection + non-root-list-item

@williamernest williamernest merged commit f59b6e6 into master Sep 20, 2018
@williamernest williamernest deleted the feat/list/toggle-radio-checbox branch September 20, 2018 00:53
@jamesmfriedman jamesmfriedman mentioned this pull request Sep 26, 2018
49 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MDCList: Move toggle of checkbox from Menu to List.
5 participants