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

Enable widget clipboard manipulation #3168

Merged
merged 32 commits into from
Sep 18, 2019
Merged

Enable widget clipboard manipulation #3168

merged 32 commits into from
Sep 18, 2019

Conversation

jacekbogdanski
Copy link
Member

@jacekbogdanski jacekbogdanski commented Jun 14, 2019

What is the purpose of this pull request?

Feature request

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

Proposed changelog entry

* [#3138](https://github.com/ckeditor/ckeditor-dev/issues/3138): Use [`widgetDefinition.getClipboardHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-getClipboardHtml) method to customize [Widget](https://ckeditor.com/cke4/addon/widget) HTML during copy, cut and drag operations.

What changes did you make?

Added new widget getClipboardHtml member allowing to customize HTML copied to the clipboard during copy, cut and drop operations.

Closes #3138.

@Comandeer Comandeer self-requested a review July 10, 2019 11:58
@Comandeer Comandeer self-assigned this Jul 10, 2019
@Comandeer
Copy link
Member

Rebased onto latest major.

Copy link
Member

@Comandeer Comandeer left a comment

Choose a reason for hiding this comment

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

I've found an edge case:

  1. Open manual test.
  2. Select all content inside the editor.
  3. Cut it and paste.

Expected:

Widget was replaced by prepared content.

Unexpected:

Widget was pasted as is, without any transformation.

I think it would be very counter-intuitive for users to see that widget behaves differently when pasted with some other content than when pasted alone.

Please also update version tags.

@Comandeer
Copy link
Member

I've update the implementation to use internally our toDataFormat event. It allows us to downcast widgets before copying their content.

I haven't add unit tests, because I want some early review to see if the whole approach is feasible at all.

@Comandeer Comandeer removed their assignment Aug 22, 2019
@Comandeer Comandeer requested a review from f1ames August 22, 2019 16:12
@f1ames
Copy link
Contributor

f1ames commented Aug 23, 2019

@jacekbogdanski I remember you talked about some selection blinking when trying to come up with the solution, can you just take a quick glimpse on @Comandeer proposal to see if the solution is similar and same issue may occur?

@f1ames f1ames self-assigned this Aug 23, 2019
Copy link
Contributor

@f1ames f1ames left a comment

Choose a reason for hiding this comment

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

The biggest change here as far as I understand correctly, is that previously when selection containing widget was copied, simply entire widget HTML (upcasted) was copied. Now, it's downcasted version is copied. When pasted back it needs to be upcasted (does it also happen when copying single widget now?). I'm not sure yet, if there are any cases which may be negatively affected by this 🤔


Found two issues after some brief testing:

  1. After cut/paste widget it is not possible to cut again if entire content is selected:

widget copy

And the blinking mentioned in #3168 (comment) (you may talk to @jacekbogdanski if he tried to solved this issue):

widget copy blink-blink

Also please update version tags to 4.13.0.


Overall, it looks to be a good direction 👍And the fact that it doesn't required big clipboard refactor is a plus.

plugins/widget/plugin.js Outdated Show resolved Hide resolved
plugins/widget/plugin.js Show resolved Hide resolved
@@ -2494,6 +2511,7 @@
// * FF tends to copy all blocks up to the copybin container.
// * IE tends to copy only the copybin, without its container.
// * We use spans on IE and blockless editors, but divs in other cases.
// We are really sorry for summoning Zalgo…
Copy link
Contributor

Choose a reason for hiding this comment

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

😱

Copy link
Member Author

Choose a reason for hiding this comment

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

😱

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we really need this line 😛

Copy link
Member

Choose a reason for hiding this comment

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

H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ

plugins/widget/plugin.js Show resolved Hide resolved
parserFragment = CKEDITOR.htmlParser.fragment.fromHtml( widget.getClipboardHtml() );

retElement = parserFragment.children[ 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 wonder how it will work with the code below, managing editables output 🤔 Does the fact that custom widget HTML (getClipboardHtml()) is provided means any editables will be simply replaced by this custom HTML? If so there is no need to process them in any way. WDYT?

And second thing, I wonder how it will (or should) work with nested widgets? Can you check it and also add such test (we don't have many nested widget cases but still worth checking)?

Copy link
Member

Choose a reason for hiding this comment

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

Everything seems to work correctly. Editables and nested widgets are replaced by the outermost widget's getClipboardHtml result.

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 we mentioned in the getClipboardHtml() docs that for nested widget it will overwrite/replace entire widget HTML (no matter nesting/editables content)? Or is it obvious? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

TBH it seems rather obvious, but there will be no harm mentioning it directly in docs.

plugins/widget/plugin.js Show resolved Hide resolved
@Comandeer Comandeer self-assigned this Aug 24, 2019
Copy link
Member Author

@jacekbogdanski jacekbogdanski left a comment

Choose a reason for hiding this comment

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

And the blinking mentioned in #3168 (comment) (you may talk to @jacekbogdanski if he tried to solved this issue):

Yep, I was talking about this selection blinking, unfortunately, didn't have time to work on it. As I already have taken a look at this PR, I'm providing small feedback:

Overall it looks nice, especially that widgets are now downcasted, but as already @f1ames mentioned, I'm wondering if we can go with such big change 🤔 Users may have already some integrations relaying on upcasted widget HTML, as it has been working like that from the beginning. Maybe we could provide some configuration option as a fallback in that case? I'm really for cleaning up clipboard data, not sure if it's not "too breaking" change.

plugins/widget/plugin.js Show resolved Hide resolved
plugins/widget/plugin.js Show resolved Hide resolved
@@ -2494,6 +2511,7 @@
// * FF tends to copy all blocks up to the copybin container.
// * IE tends to copy only the copybin, without its container.
// * We use spans on IE and blockless editors, but divs in other cases.
// We are really sorry for summoning Zalgo…
Copy link
Member Author

Choose a reason for hiding this comment

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

😱

@Comandeer
Copy link
Member

After cut/paste widget it is not possible to cut again if entire content is selected:

Actually the new logic is not even fired when the whole content is selected due to #3352. I found it during trying to write unit test for the new logic handling multiple widgets.

@Comandeer
Copy link
Member

Overall it looks nice, especially that widgets are now downcasted, but as already @f1ames mentioned, I'm wondering if we can go with such big change

Actually by default the upcasted HTML is returned, via default getClipboardHtml implementation. So without implementing custom getClipboardHtml everything should work the same as previously. toDataFormat is used only as a simple way to utilize our HTML parser.

I'm thinking about making getClipboardHtml compliant with downcast, so it wouldn't operate on HTML string, but rather htmlParser.nodes. WDYT of such a change?

@Comandeer
Copy link
Member

I've fixed failing tests in IE8 and Safari. Additionally I've refactored copybin to have a nicer API via CopyBin class. Enhancing it further should allow us to finally move it to clipboard (see #3358).

The only issue left is the one with selecting all content and cutting, but I'm afraid that it's connected with deeper issues with selecting widgets, as can be seen in unit tests, e.g. Safari has incorrect selection, when only two nested widgets are selected and IE8 does not select widgets if whole wrappers are not contained inside the range.

@Comandeer Comandeer requested review from Comandeer and f1ames August 27, 2019 15:07
@Comandeer Comandeer removed their assignment Aug 27, 2019
@Comandeer Comandeer removed their request for review August 27, 2019 15:26
@f1ames
Copy link
Contributor

f1ames commented Sep 4, 2019

The only issue left is the one with selecting all content and cutting, but I'm afraid that it's connected with deeper issues with selecting widgets, as can be seen in unit tests, e.g. Safari has incorrect selection, when only two nested widgets are selected and IE8 does not select widgets if whole wrappers are not contained inside the range.

Does it always happen? I recall you mentioned something about widgetselection plugin, but can't find it now 🤔 If it happens always (and not only with/without the plugin) that's pretty bad news😭 Anyway, @Comandeer would you be trying to cover this issue in this PR or prefer to extract as a follow-up (still we will need to fix it soon probably).

@Comandeer
Copy link
Member

It's already extracted as #3352. Probably it would be much more difficult to fix than the proposed refactor of clipboard handling and because of that I don't see much sense in delaying this change.

@f1ames f1ames self-assigned this Sep 6, 2019
@f1ames f1ames merged commit 1b67bc3 into major Sep 18, 2019
@CKEditorBot CKEditorBot deleted the t/3138 branch September 18, 2019 07:32
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.

Possibility to override clipboard content when widget is copied/dragged
3 participants