-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add functionality to cancel awaiting for delayed editor creation #5133
Conversation
It's been a while since we last heard from you. We are marking this pull request as stale due to inactivity. Please provide the requested feedback or the pull request will be closed after next 7 days. |
There was no activity regarding this pull request in the last 14 days. We're closing it for now. Still, feel free to provide us with requested feedback so that we can reopen it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was rather imagining this feature as slightly different. Currently, we have very outdated documentation for both CKEDITOR.replace
and CKEDITOR.inline
functions indicating that these always return an editor. Unfortunately, it's no longer the truth since it's possible that these methods will return null
if the integrator decided to use the delayed initialization feature.
Instead of returning null
, we could actually return a handle allowing us to clear the editor initialization.
var clearEditorInitialization = CKEDITOR.replace( 'editor' );
clearEditorInitialization();
Since it's JavaScript and type checking is a bit annoying, we could actually return an object with status
property similar to editor.status
const editor = CKEDITOR.replace( 'editor' );
if ( editor.status === 'delayed' ) {
editor.cancelInitialization();
}
WDYT @sculpt0r @Comandeer ?
See #5133 (comment). |
Well, from my understanding both approaches do basically the same, but the proposed approach in this PR introduces a more convoluted way of clearing intervals: // config option:
config.delayIfDetached_cancelInterval = function( cancel ) {
// During every interval, you have to make a decision whether you want to execute the `cancel`
// function to prevent editor initialization. It forces you to (in most cases) keeping some separate reference
// to a condition under which editor initialization should be prevented. E.g.:
if ( component.destroyed ) {
cancel();
}
};
// handle
// You just keep a reference of the specific handle that may be used to prevent editor initialization:
this.state.cancelEditor = CKEDITOR.replace( 'editor' );
// ...
onDestroy() {
this.state.cancelEditor();
} Since we already have so many config options and our documentation is outdated at the moment, the second method seems to be a more natural pick for me. Keeping both, such similar options look just redundant. From the performance side of view, the second one is also less resource-consuming as the callback is called only once, but it's rather micro-optimization than a real benefit. |
core/editor.js
Outdated
if ( CKEDITOR.config.delayIfDetached_cancelInterval ) { | ||
CKEDITOR.config.delayIfDetached_cancelInterval( clearInterval( intervalId ) ); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that we should provide a wrapper over clearInterval
method. Currently, an interval is cleared on the first code execution. This logic should be also moved inside setInterval
callback, not outside.
You're right, @jacekbogdanski. I was mistaken by the name of the config variable (I assumed that the In such a case, I'm for what @jacekbogdanski proposed. |
Actually, it was possible to get Actually, there was an idea to return the callback function when you want to use https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-delayIfDetached_callback - but we decide to config option to not break the so far behavior: only null and editor instance is returned. As for this PR - I just wanted to stick to the previous approach. What is more - changing the possible returned value also causes more work to do in integrations. However - if we are fine with this - I'll adjust this PR to @jacekbogdanski proposal :) Just to be sure @jacekbogdanski and @Comandeer you are ok with ☝️ |
I would expect an error throw in that situation, but it's not something we want to change right now. Regarding this configuration option, from what I understand it won't result in an interval so we don't need to provide any additional option to clean it up? There is one limitation to the originally proposed implementation - you can't tell which editor you are canceling. So in the case when you have multiple delayed editor instances, you will have to cancel all of them. With a handler, you can distinguish which editor gets canceled.
Do you see any potential breaking change here? The only problem I have with returning a handle is that some existing integrations could rely on checking whether creation methods returned a null - it sounds like a poor verification since you should rather check if the delayed initialization option is enabled, but there is some small risk of breaking change. |
Nope, we don't have to clean it up. I mentioned it to show that provided solution has similar logic to sth we already have done around this feature.
I think that you are able to distinguish the editor instances. Because you pass individual configuration for each var editorsCancels = [];
function trackEditorCanceling( editorId ) {
return function cancelCallback( cancelFunction ) {
editorsCancels[ editorId ] = cancelFunction;
};
}
CKEDITOR.replace( editorElem, {
delayIfDetached_cancelInterval: trackEditorCanceling( editorId )
} );
// Then when you are sure that a certain `editorId` should be canceled, you might:
editorsCancels[ editorId ](); The above code should work after corrects you mentioned in: https://github.com/ckeditor/ckeditor4/pull/5133/files#r849471320
I believe this error msg should be present in the console: https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#editor-incorrect-element ☝️ This reminds me, that we also have https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#editor-delayed-creation & https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#editor-delayed-creation-success - so probably in wrapper mentioned: https://github.com/ckeditor/ckeditor4/pull/5133/files#r849471320 we should also add another error code WDYT? |
There shouldn't be any issues with In In |
Yes, I forgot about that method.
Alright, so it looks like
That's weird that we are using warnings like that in the first place. Originally, we were using warnings to indicate some error information that is not interrupting editor functionality, like uploading a file to an invalid endpoint. A warning means that there is something requiring integrator attention - but in the case of this feature, delayed initialization is an expected outcome. But I would avoid changing it right now, so we are not introducing another confusion.
I still have a feeling that this logic is overcomplicated to what we can accomplish by returning callback directly from creation methods. Storing callbacks from another callback execution looks unpleasant and introduces unnecessary confusion. An integrator has to assume that callback will be attached synchronously (so there is no risk that |
Rebased onto the newest master. |
@jacekbogdanski - ready for another review :)
I thought about your proposal with returning editor as So to not enlarge this PR too much - I decided to only introduce the minimal changes that allow canceling editor creation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was sure that this PR is ready for a final review so I've helped a bit with some changes, but seems we are still lacking valid unit tests. Please, make sure to pull my commits before working on it.
Good documentation is essential for this feature as editor creation functions are basically the most often used public API in the whole editor codebase. Except for the missing explanation about this new return type, we were also missing information about the delayed initialization feature in docs since 4.17. I've added documentation for your changes.
Regarding replaceAll
and inlineAll
- these functions are a bit problematic, as they are not returning anything. It seems unlikely to me that someone would use the delayed initialization feature with them, so for now we can just extract a separate ticket for it and see if it gets any reactions.
Please, add the missing test case and we should be good with these changes.
@@ -42,7 +44,7 @@ var detachedTests = ( function() { | |||
delayIfDetached: true | |||
} ); | |||
|
|||
assert.isNull( editor, 'Editor should not be created on detached element, if config allows a delay. Creator function used: ' + creatorFunction ); | |||
assert.areSame( 'function', typeof editor, 'Editor should return function that allows to cancel creation. ' + assertMessage ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is not good enough. It only checks the return type of the creation method, but we are not testing the outcome of using that callback.
Done: #5167 |
It's not mutually exclusive. API docs should have enough information that integrators can work with that without reading a separate guide. Also, we were missing cross-reference links making the guide more discoverable. |
@jacekbogdanski - ready for another review.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are still lacking some changes in unit tests, although I will fix that issues in a moment.
test_delayed_editor_creation_is_cancelable: function() { | ||
var editorElement = CKEDITOR.document.getById( createHtmlForEditor() ), | ||
editorParent = editorElement.getParent(); | ||
|
||
editorElement.remove(); | ||
|
||
var cancelationCallback = CKEDITOR[ creatorFunction ]( editorElement, { | ||
delayIfDetached: true, | ||
delayIfDetached_interval: 50 | ||
} ); | ||
|
||
cancelationCallback(); | ||
|
||
// Attach the spy after cancelation to prevent unexpected invocations while test is waiting to fullfil. | ||
var spyIsDetached = sinon.spy( editorElement, 'isDetached' ); | ||
|
||
CKEDITOR.tools.setTimeout( function() { | ||
resume( function() { | ||
assert.areSame( 0, spyIsDetached.callCount, 'The isDetached method should not be called after cancelation. ' + assertMessage ); | ||
spyIsDetached.restore(); | ||
} ); | ||
}, 150 ); | ||
|
||
editorParent.append( editorElement ); | ||
|
||
wait(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's still not totally valid test case. We should make sure that the editor is not initialized. Checking internal calls is not enough in that regard and we should make sure that the creation method has not been executed. It would be best to not use spy at all, but editor initialization takes such long that simplifying it with spy on creatorFunction
should be enough.
@@ -5,6 +5,8 @@ | |||
var detachedTests = ( function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most tests that check against editor not being null are now false positive, as a function callback is also not null. Also, we are not ensuring that the delayed initialization feature has been cleaned up which impacts test isolation.
What is the purpose of this pull request?
New feature
Does your PR contain necessary tests?
All patches that 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
Did you follow the CKEditor 4 code style guide?
Your code should follow the guidelines from the CKEditor 4 code style guide which helps keep the entire codebase consistent.
What is the proposed changelog entry for this pull request?
What changes did you make?
Give an overview…
A new config function was added. It works in the same manner as the already existing callback. So the User pass a callback which will be invoked with cancelation function as an argument. It could be stored and invoked whenever convenient.
I don't want to introduce a new type that might be returned by editor creation. This requires changes in (probably all) integrations.
Which issues does your PR resolve?
Closes #4641