Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Custom keyboard navigation through tables #304

Merged
merged 33 commits into from
Apr 23, 2020
Merged

Custom keyboard navigation through tables #304

merged 33 commits into from
Apr 23, 2020

Conversation

niegowski
Copy link
Contributor

@niegowski niegowski commented Apr 14, 2020

Suggested merge commit message (convention)

Other: Custom keyboard navigation through tables. Closes ckeditor/ckeditor5#3267. Closes ckeditor/ckeditor5#3286.


Additional information

@niegowski niegowski requested a review from oleq April 14, 2020 19:53
@coveralls
Copy link

coveralls commented Apr 14, 2020

Coverage Status

Coverage remained the same at 100.0% when pulling 92d1567 on i/3267 into 15016bf on master.

@oleq
Copy link
Member

oleq commented Apr 15, 2020

2020-04-15 12 44 30

I think the fact that I can navigate across the lines downwards using the down arrow key but using the arrow up key moves the caret to the first position in the cell is a bug.

@oleq
Copy link
Member

oleq commented Apr 15, 2020

☝️ I see that it works for multiple blocks, one after another, but in the screencast its a single block with wrapped content.

@oleq
Copy link
Member

oleq commented Apr 15, 2020

In a case where the widget is the only child of the cell, there's a lockdown. Arrow keys won't let me navigate to neighboring cells.

image

Same, if it's the first/last child (up/down arrows).

My bad, I switched to another branch in the meanwhile.

Copy link
Member

@oleq oleq left a comment

Choose a reason for hiding this comment

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

The feature looks good to me. I only had some small concerns regarding implementation. Let's move ahead with this feature.

src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
@oleq
Copy link
Member

oleq commented Apr 15, 2020

This one also looks like a bug (arrow down should always navigate to the image and the cell below):

2020-04-15 15 27 35

@niegowski
Copy link
Contributor Author

This one also looks like a bug (arrow down should always navigate to the image and the cell below):

2020-04-15 15 27 35

This should be fixed now in eebd6f2.

@niegowski
Copy link
Contributor Author

cc @ckeditor/qa-team Can you have a look at this? Navigation over table cells should be as intuitive as possible. Note that on the first/last text lines in a cell the caret is moved to first/last position in that cell (it's expected behavior). It's using DOM client rects so we should test it in different browsers.

@Mgsy
Copy link
Member

Mgsy commented Apr 17, 2020

Firefox only

If a cell contains a blockquote, pressing Arrow down makes the selection jumps to the end of the blockquote, instead of a line below.

table

@Mgsy
Copy link
Member

Mgsy commented Apr 17, 2020

We've tested it in all browsers and besides the issue above, it works fine 👍

@niegowski
Copy link
Contributor Author

Firefox only

If a cell contains a blockquote, pressing Arrow down makes the selection jumps to the end of the blockquote, instead of a line below.

table

This is how Firefox handles overflow: hidden for blockquote. It works that way even without tables. We use overflow: hidden there to trigger "Block formatting context" for blockquote to handle positioning next to floating widgets.

Copy link
Member

@oleq oleq left a comment

Choose a reason for hiding this comment

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

Some tests are failing on the CI.

Copy link
Member

@oleq oleq left a comment

Choose a reason for hiding this comment

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

Mostly concerns regarding docs.

src/table.js Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
}

/**
* Returns a range from beginning/end of range up to selection closest position.
Copy link
Member

Choose a reason for hiding this comment

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

This probably needs rephrasing ("a range from the beginning of range") because honestly I don't understand what it does without digging into the code.

src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
}

/**
* Checks if the `modelRange` renders to a single line in the DOM.
Copy link
Member

Choose a reason for hiding this comment

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

That's probably one of the key methods around here. It deserves more documentation, especially that model ranges do not work at the DOM level. You should explain that you're checking out a DOM range corresponding to the model range and then you analyze its DOMRects to figure out whether the DOM range visually wraps to the next line.

niegowski and others added 3 commits April 22, 2020 11:12
Co-Authored-By: Aleksander Nowodzinski <a.nowodzinski@cksource.com>
@niegowski niegowski requested a review from oleq April 22, 2020 09:25
Copy link
Member

@oleq oleq left a comment

Choose a reason for hiding this comment

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

Minor remarks concerning tests.

tests/tablenavigation.js Outdated Show resolved Hide resolved
@@ -0,0 +1,2277 @@
import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
Copy link
Member

@oleq oleq Apr 22, 2020

Choose a reason for hiding this comment

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

We try to follow a convention in which named imports usually land after default imports.

Also, we try (at least to some extent) to group imports (external packages in one group (image, horizontal line), in-package imports (table, table editing) in another, global helpers (global, env) in another).

This should probably be explained in https://ckeditor5.github.io/docs/nightly/ckeditor5/latest/framework/guides/contributing/code-style.html (cc @Reinmar).

} );
} );

describe( 'contains image widget with caption and selection inside the caption', () => {
Copy link
Member

Choose a reason for hiding this comment

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

What contains that image? TCs suggest this is about a cell where the initial selection is but it is not clear from the description. It could as well describe a place the selection should be anchored to after the navigation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Table cell contains image.

Copy link
Contributor

@jodator jodator left a comment

Choose a reason for hiding this comment

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

OK I'll stop here.

The feature works great and for me the issues which I'll report below are minor and can be follow ups.

As for the code:

  1. I really don't like the ck-hidden check in the view. For now I think that we could live with this but I'd rather see if we cannot detect this case differently. What if we change view class? And that kind of question - I feel that this might be a bigger issue as how to reflect such things in the model.
  2. Some if clause removals - just to have them nicer to read.
  3. I've went through the _handleArrowKeys() method - my feeling is that some checks were an outcome of a long-living code that evolved with each edge case. I found some improvements and simplifications - those might be minor things really. I only wonder if the checks shouldn't be revisited with a "fresh" eye to spot other possible cases to handle differently - especially to remove the dependency on a view (in the ck-hidden case - the calculating DOM Rects is a pretty neat idea and we don't have any other option.
  4. Don't import from model in features. We have API for that™.
  5. The _isSingleLineRange needs better comments as current one were hard to dig into. However I don't have an idea how to improve them now.
  6. I didn't read the tests so I hope @oleq found something there :D

src/table.js Show resolved Hide resolved
tests/table.js Outdated
Comment on lines 15 to 17
it( 'requires TableEditing, TableUI, TableSelection, TableClipboard, and Widget', () => {
expect( Table.requires ).to.deep.equal( [ TableEditing, TableUI, TableSelection, TableClipboard, Widget ] );
expect( Table.requires ).to.deep.equal( [ TableEditing, TableUI, TableSelection, TableClipboard, TableNavigation, Widget ] );
} );
Copy link
Contributor

Choose a reason for hiding this comment

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

Test name is wrong ;)

If you wish you could split it to 6 separate tests (each for required plugin). But changing test name is enough.

src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Show resolved Hide resolved
src/tablenavigation.js Outdated Show resolved Hide resolved
Comment on lines 510 to 513
case keyCodes.arrowleft: return isLtrContent ? 'left' : 'right';
case keyCodes.arrowright: return isLtrContent ? 'right' : 'left';
case keyCodes.arrowup: return 'up';
case keyCodes.arrowdown: return 'down';
Copy link
Contributor

Choose a reason for hiding this comment

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

Please format it so each return is in new line (code style consistency with existing code).

@jodator
Copy link
Contributor

jodator commented Apr 22, 2020

And I have and inconsistency in the behaviour. Basically the feature works like the Google docs but - I don't find it OK but maybe it's just me.

So Google docs navigating with arrow (gets "trapped"):

So Google docs navigating with TAB (as in CKEditor - navigate on the same row):

Browsers (Chrome & Firefox) with arrows (similar to TAB action):

Similarly to browser, the Libre office follows the TAB behaviour pattern for arrows:

So as long we think that having different behaviour for TAB is OK (so as in GDocs) then it is a minor issue.

cc @oleq .

Copy link
Contributor

@jodator jodator left a comment

Choose a reason for hiding this comment

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

LGTM now 👍.

The issues were addressed and the navigation itself works great.

CC @Reinmar I'd go with this in current iteration. We can also close handling shift ckeditor/ckeditor5#6641.

@jodator
Copy link
Contributor

jodator commented Apr 23, 2020

The test that fails is from Firefox. I don't see what is causing this in this PR so I'm merging it and try fix CI later.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

A way to leave a table with keyboard Implement a custom navigation through tables
6 participants