Issue #1797Opened February 14, 2019by arachnosoft0 reactions

Weird issue with internal drag&drop - Dropped contents === "null"

Question

Hi @artf ,

I'm facing a very strange issue related to HTML5 drag & drop.

When I select some mixed contents within grapesjs, including editable text contents and the surrounding components as a whole selection with the mouse, the dropped (copied) contents is sometimes "null" (a string carrying the "null" text value, not a JavaScript null).

I've managed to reproduce the issue with the Newsletter demo, with Chrome 71.0.3578.98. I don't know whether it happens with other browsers, or not...

grapesjs null dragend

When the issue arises, I've noticed that, when catching the canvas:dragdata event, the result.content variable is "null" (string). I looked into the call stack and found that this value comes from the dataTransfer.getData("text/html") call in grapesjs' core Droppable.getContentByData() function:

} else if ((0, _underscore.indexOf)(types, 'text/html') >= 0) { content = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g, '');

I don't know why, and in which circumstances the browser sends "null" while fetching data in text/html format. All other formats seem to carry a correct value. You'll note that I use the CKEditor plugin, hence I have some additional "formats" related to CKEditor in dataTransfer:

chrome_2019-02-14_15-57-49

Could you check whether you can reproduce this on your own side, and if you can do anything to handle this case within grapesjs? (assuming that it may be a browser-related bug).

In the meantime, I handled this on my own side by picking the value from dataTransfer.getData("text/plain") when possible, and returning empty stuff otherwise:

myGrapesJsObject.on('canvas:dragdata', function (dataTransfer, result) {
            if (result && result.content) {
                if (typeof (result.content) == "string" && result.content === "null" && dataTransfer.getData("text/html") === result.content) {
                    result.content = "";
                    if (dataTransfer.types && dataTransfer.types.length > 0) {
                        for (var i = 0; i < dataTransfer.types.length; i++) {
                            if (dataTransfer.types[i] == "text/plain") {
                                var altValue = dataTransfer.getData(dataTransfer.types[i]);
                                if (altValue && altValue != "") {
                                    result.content = altValue;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

As a side note, I sometimes found that the dataTransfer object carries some "old" dropped contents from previous drags, and not the latest stuff. But I've been unable to find when and why so far, so I'll not bother you with this for now (unless it's a known issue, and if you need additional information on this particular issue.)

Thanks for your thoughts!

Answers (3)

artfFebruary 16, 20190 reactions

Thanks for the report @arachnosoft BTW I'm able to reproduce it, but only once the first CKEditor instance is activated, can you confirm?

arachnosoftFebruary 18, 20190 reactions

Yeah @artf , seems to be the exact test case...

If I refresh the page to get a clean context, empty the canvas, drop a Grid component (quite complex one), select some of its text and surrounding cells WITHOUT activating CKEditor, and drag/drop it from the text, it's working correctly.

But as soon as I double-click on a cell to activate CKEditor, click elsewhere to disable editing, and follow the exact same steps as above (making the exact same selection and drag/drop), the dropped contents is "null".

grapesjs issue 1797 1

And, unless I refresh the page to get rid of all CKEditor instances in the DOM, the issue remains, even if I empty the canvas first:

grapesjs issue 1797 2

Glad you reproduced it as well, because it was quite a pain to find what was going wrong!

I noticed that a new CKEditor instance was being created into the DOM each time a new component is edited, even though the CKEditor plugin uses CKEditor's inline() method. I don't know if this is "by-design", or if it could explain that kind of issue.

artfFebruary 21, 20190 reactions

I noticed that a new CKEditor instance was being created into the DOM each time a new component is edited, even though the CKEditor plugin uses CKEditor's inline() method. I don't know if this is "by-design", or if it could explain that kind of issue.

Yeah this is how their inline plugins works but I don't think this somehow related

BTW definitely CKEditor adds its type to dataTransfer object and edits, for some reason (probably to handle some their edge cases), the 'text/plain' (GrapesJS relies completely on native objects without touching them).

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.