Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed autocomplete view positioning #1732

Merged
merged 26 commits into from
Apr 25, 2018
Merged

Fixed autocomplete view positioning #1732

merged 26 commits into from
Apr 25, 2018

Conversation

jacekbogdanski
Copy link
Member

What is the purpose of this pull request?

Bug fix

Does your PR contain necessary tests?

All patches which change the editor code must include tests. You can always read more
on PR testing,
how to set the testing environment and
how to create tests
in the official CKEditor documentation.

This PR contains

  • Unit tests
  • Manual tests

What changes did you make?

View positioning was based on window pane size and scroll position. Now it depends on absolute rectangle of the editor frame.

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

Two things needs to be addressed before going into review:

https://github.com/ckeditor/ckeditor-dev/blob/13d35dcb74ba0412d2ae2cb2c08f66e3a06ff196/tests/plugins/autocomplete/view.js#L222 - Wouldn't a better name for it be caretRect rather than just rect?
https://github.com/ckeditor/ckeditor-dev/blob/13d35dcb74ba0412d2ae2cb2c08f66e3a06ff196/tests/plugins/autocomplete/view.js#L216 - this is absolute rectangle of what? The purpose of that option should be clear. It's hard to understand it otherwise.

## Unexpected

The view is not changing its position depending on space below and above a caret.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please put just a single line ending here.

@jacekbogdanski
Copy link
Member Author

jacekbogdanski commented Mar 9, 2018

I refactored some missing semicolons etc from test file (looks like my linter wasn't working). There may be changes not related to this issue but I think it's good idea to just fix it now so we don't forgot about it in other PRs.

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

Generally looks OK, I'm missing divarea and inline editor instances in the manual test.

My point about that line has not been addressed.

editable = this.editor.editable(),
var editor = this.editor,
viewPanelHeight = this.element.getSize( 'height' ),
windowFrame = editor.window.getFrame(),
Copy link
Contributor

Choose a reason for hiding this comment

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

This variable is used only once. I think it can be safely inlined, without sacrificing the readability.

editorViewportRect = editable.isInline() ? editable.getAbsoluteClientRect( editor ) : windowFrame.getAbsoluteClientRect( editor ),
// How much space is there for the panel above and below the specified rect.
spaceAbove = rect.top - editorViewportRect.top,
spaceBelow = rect.bottom - editorViewportRect.bottom,
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't the space below be computed by editorViewportRect.bottom - rect.bottom? Surprisingly I don't see any visible issues related to this value being computed incorrectly.

@jacekbogdanski
Copy link
Member Author

About not addressed line here: https://github.com/ckeditor/ckeditor-dev/blob/3e782b9/tests/plugins/autocomplete/view.js#L226 (see #1732 (review))

I'm not sure what more could I change here? I already changed config.absoluteRect into config.editorViewportRect and renamed elementStub into getClientRectStub. Do you see any improvements which can I apply here?

@mlewand
Copy link
Contributor

mlewand commented Apr 4, 2018

There's a bit of mess in commit history. We need to wait till #1727 lands in the major.

@jacekbogdanski
Copy link
Member Author

I rebased it into the latest t/1703 so it contains #1727 changes.

@jacekbogdanski
Copy link
Member Author

I changed the manual test for inline editor - it has long content but I wanted to make sure that the editor is at the end of the browser viewport so it could be property tested.

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

I like the fact that with the new code base it became simpler (I mean the setPosition method).

Actually, regarding positioning I start to think that we should simply hide the autocomplite if it's outside of the viewable area (classic/divarea editor). But that should be extracted to a follow up ticket, for now it's good the way it is.

I found still three failing cases in the manual test. First one (mobile) is important and should be fixed, two others can be extracted to a separate issue.

Classic editor does not reposition autocomplete on iOS

  1. Open manual test on Firefox/Edge.
  2. Focus the classic editor.
  3. Start typing @ to begin autocomplete.
  4. Scroll the editor editable.

(Current) Expected

The autocomplete moves along.

Actual

Autocomplete remains statically.

Firefox/MSEdge edge case

  1. Open manual test on Firefox/Edge.
  2. Focus the classic editor.
  3. Press ctrl + end.
  4. Insert @ to begin autocomplete.

(Current) Expected

The autocomplete should appear within the editable.

Actual

It appears below the editable. It's enough to scroll down a bit again to make it appear correctly inside.

Additional notes

I'm saying currently expected because I think we should change/unify this behavior. But that should be done within a dedicated issue.

IE9 inline editor position fail

  1. Open manual test on Firefox/Edge.
    http://tests.ckeditor.test:1030/tests/plugins/autocomplete/manual/viewposition / Inline editor
  2. Focus (last) inline editor.
  3. Put the cared at the end of text and type @

Expected

View at the end of the text should be placed above a cursor.

(Works correctly on IE10, IE11, Edge)


Other things:

Manual test: Rather than putting wall of text in manual tests, you could just add a dummy paragraph/element with a large height.

Both tests: tests are not ignored on unsupported env (ie8).

<style>
/* Swap margin with padding to prevent moving autocomplete panel outside editor. */
body {
margin-left: 0px;
Copy link
Contributor

Choose a reason for hiding this comment

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

This hack should not be needed for a proper positioning. 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true. I will try to adjust caret position relative to the document body. I think it's an edge case where a user adds margin into body element but it could be probably fixed without huge work.

initEditor( 'inline', 'editor3' );

function initEditor( creator, name, extraPlugins ) {
var editor = CKEDITOR[ creator ]( name, {
Copy link
Contributor

Choose a reason for hiding this comment

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

This editor variable is not used anywhere.


<script>

initEditor( 'replace', 'editor1' );
Copy link
Contributor

Choose a reason for hiding this comment

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

Inconsistent indentation, see getTextTestCallback function.

Copy link
Contributor

Choose a reason for hiding this comment

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

By extracting function call to a function I don't think you saved too much here…

You'd be better with extracting common config, and making a regular CKEDITOR.replace / CKEDITOR.inline calls. For an example, check here: https://github.com/ckeditor/ckeditor-dev/blob/8182c89c2cdf55872c73ba0c834f516eb35335ca/tests/plugins/balloontoolbar/manual/focus.html#L59-L71


<h2>Classic editor</h2>
<div id="editor1" >
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque animi, iusto laudantium nobis itaque optio vitae asperiores, placeat magnam quo distinctio. Eaque fugiat quia maxime modi, quibusdam nostrum repellendus in?</p>
Copy link
Contributor

Choose a reason for hiding this comment

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

I changed the manual test for inline editor - it has long content but I wanted to make sure that the editor is at the end of the browser viewport so it could be property tested.

I see your reason, but you could achieve that in a simpler way. You could just put paragraphs that have a fixed height, say more that 1 times the height of the editable. I'll send a commit showing that in a minute.

@jacekbogdanski
Copy link
Member Author

jacekbogdanski commented Apr 20, 2018

After some time fighting with margins on host body I gave up because I couldn't find an easy way to fix it. I tried to remove preset body position from caret rect but it wasn't working well with different cases. I'm not sure if this is an important issue so I left margin hack from #1732 (comment) unchanged.

I don't see much use cases where someone would like to change body margins. I think this issue exists for balloonpanel also. WDYT @mlewand? Can we live with it or should I spend more time on fixing this issue?

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

I don't see much use cases where someone would like to change body margins.

I disagree, it's rare but it could definitely happen in the wild. Given the fact that it already occured is a pretty good tell.

I think this issue exists for balloonpanel also.

Does it? I think it was patched in #1201. Please check it and if it is still buggy then please report a bug.

I actually remembered that there was a similar issue in balloon panel however so I have checked it up how guys solved it. I saw the fix there but it didn't convincing to me (wasn't that clean) I recalled there's a offsetParent available and that's something we could use here. Hence the patch in 5ab276b.

I made a dirty commit, but that's something that should set you up. Please use it as a base for your work, ensure that it works correctly and cover this case with unit tests.

I also had some issues with TC names.

@@ -146,67 +161,52 @@
},

'test set position above inside absolute rect': function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not a fan of this naming. Since we touched it in this PR, how about adjusting it to something clearer.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have concerns regarding test case names. I'll illustrate what I see as an ASCII art:

+---------------------------------------------+
|                                             |
|       editor viewport                       |
|     +--------------+                        |
|     |              |                        |
|     |     view     |                        |
|     |              |                        |
|     +--------------+                        |
|     █                                       |
|                                             |
|                                             |
+---------------------------------------------+

The "above inside absolute rect" does not sound helpful.

"test position not enough space between the caret and bottom viewport"

Let's use ASCII art for TCs like that to make understanding it easier.

} );

assert.areEqual( '300px', view.element.getStyle( 'top' ) );
assert.areEqual( '100px', view.element.getStyle( 'left' ) );
},

'test set position below inside absolute rect': function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Name "test set position below inside absolute rect" in this TC is actually more accurate than the previous one.

+---------------------------------------------+
|                                             |
|       editor viewport                       |
|                                             |
|     █                                       |
|     +--------------+                        |
|     |              |                        |
|     |     view     |                        |
|     |              |                        |
|     +--------------+                        |
|                                             |
|                                             |
+---------------------------------------------+

I would go with something like: "test enough space under and above the caret"

And change the assertion:

assert.areEqual( '110px', view.element.getStyle( 'top' ) );

to

assert.areEqual( '110px', view.element.getStyle( 'top' ), 'View is displayed below the caret' );

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

There's a bug in a edge case related to position. Also few style changes are needed in tests.

} );

assert.areEqual( '110px', view.element.getStyle( 'top' ), 'View is displayed below the caret' );
assert.areEqual( '50px', view.element.getStyle( 'left' ) );
},

'test set position above outside absolute rect': function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

You have fixed the "absolute rect" thing in two previous tests, but left it here unchanged. For this and next TC "absolute rect" has again no meaning (or it actually misleads the reader).

Copy link
Contributor

Choose a reason for hiding this comment

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

I have fixed one name, but since I see that there are other issues that will require another review bounce, please fix the other name.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also add ASCII illustration to positioning tests that do not have it. It's really helpful for others (if done right).

} );

assert.areEqual( '300px', view.element.getStyle( 'top' ) );
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 not the expected result in case when selection is just below the bottom edge of viewport.

Please also add a case where the caret is 1px above the bottom viewport edge.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also add a TC where the caret starts at 0, and where the caret is above the viewport.

@mlewand
Copy link
Contributor

mlewand commented Apr 24, 2018

I have pushed a single commit with some changes that I have already been changing while reviewing.

@jacekbogdanski
Copy link
Member Author

I moved view positioning tests into a separate file so it could be easily tested with different editors. Also, I simplified setPosition function so it doesn't contain multiple ifs. Instead, I'm recalculating view position for different cases so it's easier to read but adds additional performance impact (position is calculated more times). I think it's not worth to preoptimize this code and add complicated if-else conditions but would like to know your opinion @mlewand.

My changes also closes #1913 and #1912.

@jacekbogdanski
Copy link
Member Author

Rebased into the latest t/1703

Copy link
Contributor

@mlewand mlewand left a comment

Choose a reason for hiding this comment

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

LGTM

@mlewand
Copy link
Contributor

mlewand commented Apr 25, 2018

The only missing part there was ignoring tests on unsupported IE.

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

Successfully merging this pull request may close these issues.

2 participants