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

Added autocomplete throttle feature #2001

Merged
merged 16 commits into from
Jun 8, 2018
Merged

Added autocomplete throttle feature #2001

merged 16 commits into from
Jun 8, 2018

Conversation

jacekbogdanski
Copy link
Member

What is the purpose of this pull request?

New feature

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?

Implemented throttle feature inside textwatcher / autocomplete plugins. Refactored autocomplete constructor to use CKEDITOR.plugins.autocomplete.configDefinition abstract class.

Based on #1993 (PR #1996).

Closes #1997

@mlewand
Copy link
Contributor

mlewand commented Jun 1, 2018

Please rebase the branch onto latest upstream branch.

@jacekbogdanski
Copy link
Member Author

jacekbogdanski commented Jun 1, 2018

Rebased into t/1751. I think we should refactor check for the supported environment into tests/plugins/autocomplete/manual/_helpers/utils.js but I would like to do it on t/1751 branch because this one already contains too much refactoring.

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.

Please, rebase the branch onto latest autocomplete branch. After dummy rebase, it yields errors in unit tests.

@jacekbogdanski
Copy link
Member Author

Rebased onto the latest t/1751.

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.


/**
* The editor instance to which autocomplete is attached to.
*
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like a merge artifact 🙂

*/

/**
* Indicates throttle threshold mitigating text checks.
Copy link
Contributor

Choose a reason for hiding this comment

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

First, docs for this property should clearly express that these are milliseconds given here.

I think that the second part:

Higher levels of throttle (…)

Is not really necessarry, as one should understand this consequence based on information that this is throttling expressed in milliseconds.

* Higher levels of throttle threshold will create visible delay for autocomplete view
* but also save the number of {@link #dataCallback} calls.
*
* @property {Number} [throttle=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 default value for throttling should be greater than zero. Let's make it to a small value that is barely noticable. Let's make it 20ms so that gives us 50fps.

@@ -261,6 +271,21 @@
}
};

function check( selectionRange ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that you moved it to a higher scope, this function name collides with other existing function in one scenario:

https://github.com/ckeditor/ckeditor-dev/blob/5a130a9/plugins/textwatcher/plugin.js#L202

Not a good thing, we want to avoid colliding functions. Move it instead to the closest scope where it is needed, so to the constructor where it is used and that will solve this problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also this name could be more meaningful. Since it mostly relates to calling a callback, I think that should be somehow reflected in the name.


## Expected

1. After `@` character dropdown should contain multiple items and appear immediately.
Copy link
Contributor

Choose a reason for hiding this comment

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

It won't appear immediately if you focus the editor with a tab key instead of mouse. That's because tab keyup event will trigger the initial check (that is run synchronously) and your typed @ key will get throttled.

I suggest that the first step tells explicitly to focus the editor using mouse.

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 aslo wondering whether we should put an information at the beginning asking to read expected section before starting the test, as the timing is crucial. What I mean here is that I can see someone spending 2.5 sec on performing first step, reading expected and performing 3-4. In this case result for typing "a" would appear (almost) instnatly.


Typed text should be logged:
1. Immediately after first typed character.
1. After 2000ms intervals.
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically it should be something like not more often than once every 2000ms. Or something.

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 logging the time (including millisecs) would be very helpful for this test.

* Simple usage:
*
* ```javascript
* var definition = { dataCallback: dataCallback, textTestCallback: textTestCallback, throttle: 200 };
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid putting objects in a single line. One property per line.

* @param {String} [itemTemplate] Template for list item in dropdown. See {@link CKEDITOR.plugins.autocomplete.view#itemTemplate} for more information.
* @param {String} [outputTemplate] Template for match rendering. See {@link #outputTemplate}.
* @param {CKEDITOR.plugins.autocomplete.configDefinition} config Configuration object keeping information
* how to instantiate autocomplete plugin.
Copy link
Contributor

Choose a reason for hiding this comment

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

instantiate autocomplete plugin

It's not instantiating the plugin, it's more of a component. I'd just simpify it to "Configuration object for this autocomplete instance." or something alike.

/**
* See {@link CKEDITOR.plugins.autocomplete.configDefinition#throttle}.
*
* @property {Number} [throttle=0]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd avaoid duplicating the default value here. Keep it only within configDefinition#throttle instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean code:

config.throttle || 0;

Is a good defensive way of coding, and that's fine. My concern is only related to API docs.

@property {Number} [throttle=0]

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.

Pushed some minor adjustments.

I just saw couple of minor issues in the recent code, and we're close to finish this issue.

@@ -91,7 +91,10 @@
* }
*
* // Finally, instantiate the autocomplete class.
* new CKEDITOR.plugins.autocomplete( editor, textTestCallback, dataCallback );
* new CKEDITOR.plugins.autocomplete( editor, {
* textTestCallback: textTestCallback,
Copy link
Contributor

Choose a reason for hiding this comment

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

Mixed tab and spaces, this and following lines.

var counter = 0,
counterInterval = 100,

textWatcher = new CKEDITOR.plugins.textWatcher( editor, function( selectionRange ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Formatting is pretty bad here. First, this empty line between counterInterval and textWatcher is a little misleading, but a bigger problem is missing indentation after opening the function, and wrong braces indentation (closing the function).

logger.appendChild( matchEl );

if ( counter == 0 ) {
setInterval( function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

That's a bit overcomplicated solution… use simply performance.now() and display a difference between last and current call.

However currently performance.now() has an issue that it might be off by +/- 2 ms, see mdn for more details:

The timestamp is not actually high-resolution. To mitigate security threats such as Spectre, browsers currently round the result to varying degrees. (Firefox started rounding to 2 milliseconds in Firefox 59.) Some browsers may also slightly randomize the timestamp. The precision may improve again in future releases; browser developers are still investigating these timing attacks and how best to mitigate them.

In that case I propose to set throttling in the sample to 2002 ms, and issue description should still say that the calls should be no more often than 2000 ms.

Finally make sure to put a short comment (even simply to this comment) in the code, right above the 2002 threshold value.

Copy link
Contributor

Choose a reason for hiding this comment

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

After doing that you'll be able to remove this fragment:

Other details Measured time by logger can have slight error +/- 100ms.


Typed text is logged immediately or in invalid interval times.

***Other details*** Measured time by logger can have slight error +/- 100ms.
Copy link
Contributor

Choose a reason for hiding this comment

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

For the record, use more common way to bold, which is simply double ** character.

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 have fixed mentioned review issues, and rebased onto latest upstream branch (resolved one conflict during the rebase).

@mlewand mlewand merged commit 9e711ca into t/1751 Jun 8, 2018
@mlewand mlewand deleted the t/1997 branch June 8, 2018 13:34
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.

None yet

2 participants