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

I/6123: The MergeTableCells command #290

Merged
merged 17 commits into from
Apr 1, 2020
Merged

I/6123: The MergeTableCells command #290

merged 17 commits into from
Apr 1, 2020

Conversation

jodator
Copy link
Contributor

@jodator jodator commented Mar 27, 2020

Suggested merge commit message (convention)

Feature: Introduce MergeTableCellsCommand. Closes ckeditor/ckeditor5#6123.


Additional information

This should work OK now :)

@jodator
Copy link
Contributor Author

jodator commented Mar 27, 2020

Yo, @ckeditor/qa-team ! This needs some deep checks. So far I found (and fixed) some issues related to the direction of a selection (ie I had a bug when selecting from bottom right to top left).

You should not be able to merge cells from heading section (rows) with other cells.

Other than that everything should be possible, clean table should be preserved (no extra empty cells). Content (images, paragraphs) should be preserved, undo should work, etc.

The button is available for now in the merge cells menu.

@coveralls
Copy link

coveralls commented Mar 27, 2020

Coverage Status

Coverage increased (+0.002%) to 99.938% when pulling e5cb4b7 on i/6123 into e2dff56 on master.

@Mgsy
Copy link
Member

Mgsy commented Mar 30, 2020

We've tested it and everything looks good 👌

@oleq oleq self-requested a review April 1, 2020 08:34
@oleq oleq self-assigned this Apr 1, 2020
@oleq
Copy link
Member

oleq commented Apr 1, 2020

Are you sure this makes sense?

image

and some weird result

image

@jodator
Copy link
Contributor Author

jodator commented Apr 1, 2020

Are you sure this makes sense?

Oh, forgot about this. I'll create a follow for this case: ckeditor/ckeditor5#6521.

The second thing (merging more then selected) - is this a bug or different screenshot?

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 questions.

src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
Comment on lines +58 to +62
for ( const tableCell of selectedTableCells ) {
const tableRow = tableCell.parent;
mergeTableCells( tableCell, firstTableCell, writer );
removeRowIfEmpty( tableRow, writer );
}
Copy link
Member

Choose a reason for hiding this comment

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

Undoing some bigger merge takes a long time. There's a noticeable lag. Can we somehow optimize it? What is the bottleneck here?

2020-04-01 10 56 58

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into it for a quick win. If I don't manage to find any let's move it to a follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Quick wins are in API and it doesn't look good. TL;DR: follow-up and performance research. 

Fiddling with the merge cells algorithm didn't get me any noticeable performance boost (and AFAICS was adding small time). I've tried to move thing in the first step and them remove other things (cells, rows) in the next step. That didn't helped.

What did help was checking what took the most time and try to optimize those.

Original time: _undo 650ms:

The is time is from RootElement.is() - there's a .replace called on a string. I've removed that:

After removing this: _undo took 566 ms:

And self time of is dropped by ~100ms. The second one was in Position constructor. Here we do .concat() of arrays. DevTools marked that line as one that took long time. I've changed that to using spraed operator (wild guess): path = [ ...root.getPath(), ...path ]; and again perf boost, _undo took 465 ms:

and self-time of Position constructor dropped by ~100ms.

This is something in line with our performance research but I worry that here we just do a lot of stuff. Many operations that requires re-calculating positions, ranges and doing many transformations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cc @Reinmar, @mlewand ☝️

Copy link
Member

Choose a reason for hiding this comment

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

Congrats! Great findings. Completely valid changes to me. Both Position and is() appear in many cases that I've been investigating so those changes are totally worth doing. I'd be also interested in verifying how they affect some of our performance tests (see the manual tests in ckeditor5). Could you do the comparison?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll create a separate ticket for them as I did not implement this yet.

src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
src/commands/mergecellscommand.js Outdated Show resolved Hide resolved
Comment on lines 146 to 155
// Collapsed selection or selection only one range can't contain mergeable table cells.
if ( selection.isCollapsed || selection.rangeCount < 2 ) {
return false;
}

const selectedTableCells = getSelectionAffectedTableCells( selection );

if ( !areCellInTheSameTableSection( selectedTableCells ) ) {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't simple

const selectedTableCells = getSelectedTableCells( ... );

if ( selectedTableCells.length < 2 ) {
    return;
} 

be enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would be enough but checking selection without calculating stuff is IMO a bit faster. The getSelectedTableCells() will do all sort of things and here I didn't wanted to calculate all those things.

Probably.

This code is old and I've done some refactoring here already. So WDYT about leaving this as is?

Copy link
Member

Choose a reason for hiding this comment

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

  1. getSelectionAffectedTableCells() executes getSelectedTableCells() anyway (see the code).
  2. But getSelectionAffectedTableCells() also returns cells that have a selection inside of them (see getTableCellsContainingSelection()), which, if not for the initial condition (selection.isCollapsed || selection.rangeCount < 2), would yield invalid cells from the perspective of multi-cell merge.
  3. So considering ☝️ , there's no point in using getSelectionAffectedTableCells. getSelectedTableCells is enough.

  1. As for the initial condition: I understand that it spares us some unnecessary execution of getSelectedTableCells().
  2. But the condition is weak. For instance, you can have a selection with selection.rangeCount === 3 in FF, each range spanning over some text in a cell, and that condition will pass.
    2.1. It will also pass if anyone create such selection from code.
    2.2. (referring to the previous section of this comment): in conjunction with getSelectionAffectedTableCells() (instead of getSelectedTableCells()) this will cause bugs
  3. I think it would be better if this condition was moved to getSelectedTableCells() as an initial filter to speed things up everywhere, not only here.

To sum up:

  • the condition should land at the beginning of getSelectedTableCells() (return an empty array if false) as a speed benefit for all the sub-features,
  • then it's enough to check if getSelectedTableCells() has length greater than 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure fair enough. I've forgot about Firefox.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the code.

@jodator jodator requested a review from oleq April 1, 2020 10:48
@oleq oleq merged commit a5a7d3e into master Apr 1, 2020
@oleq oleq deleted the i/6123 branch April 1, 2020 13:00
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.

Table selection handling: Merge cell split command
5 participants