Extending drag&drop - can I create nodes?

Hi There,

I was wondering whether this might be of interest to others: being able to drag a file onto the workspace and have Node-RED create a node(s) - corresponding to the mine-type.

I've created a prototype using the serverless Node-RED and it looks like this:

draganddrop

I was playing around with the drag&drop on the workspace and noticed that if I dragged a .json Node-RED would assume it to be a flow.json and attempt to import it as such. Also if I dragged an image, I would get an exception in the browser console - because it's not a .json

This is also tested using an old version 3.1.3 and I don't know whether there are other efforts to do something similar.

I did have to make a change to the core of Node-RED to make this work, and that was to generate an extra event. Elsewhere I handle that event to create nodes.

3 Likes

Just an update, this can be done without the custom event by listening to the drag event on the #red-ui-drop-target element:

let customDropHandler = (event) => {
  ... node creation and import here ...
}
let defineCustomDropHandler = () => {
    if ($('#red-ui-drop-target').length > 0) {
        $('#red-ui-drop-target').on("drop", customDropHandler)
    } else {
        setTimeout(defineCustomDropHandler, 300)
    }
}
setTimeout(defineCustomDropHandler, 300)

(where this code runs is before the workspace initialisation, hence the setTimeout stuff.

1 Like

Having played around with this for the last couple of days, perhaps I should explain what the ultimate goal is and what are some of the drawbacks I've come across.

My ultimate aim was to store images to drive and not in the flows.json as base64 encoding. Since the drag&drop feature appeared in 3.1.0 I've been thinking about the bloat caused in flows.json files because the feature adds base64 encoded image data. There is no general solution to this since flows.json is the common denominator.

What I've been doing with my mindmap stuff (yes, I maintain my mindmap in Node-RED) is using an extra upload dashboard tab to upload image content. This upload provided me with a markdown image stanza (i.e. ![imag](url)) that I included in my mindmap nodes. So the complete workflow was: opening the dashboard, going to the upload tab, dragging (or selecting) file, copying the markdown stanze, creating a new mindmap node, pasting the markdown stanza. Workflow is far too long but I've stoically continued to use it.

This also requires having a http in node for supplying file content since I use Markdown image syntax to include images. Also I maintain images and flows.json in one git repository since this data is intimately linked. However my flows.json does not get bloated with base64 strings.

Now what I've done is intercepted the drag&drop event (only for the workspace) and upload the file contents automagically. So the nodes that I generate using the drag&drop contain a Markdown image stanza and not base64 image content. Plus I don't have to manually upload file data, it gets done automatically - much simpler all round.

This is the upside.

What I've come to realise that how I've done this is complete rubbish. The problem is that my mindmap node package defines a custom drag&drop handler and my NodeDev package defines a custom drag&drop handler and neither knows of the other. If I install both packages, this implies that when I drag certain files onto the workspace (for example image files), I get duplicate nodes - one from the mindmap package and one from the NodeDev package - not good.

Imagine if other packages begin to do the same thing - not good at all.

This is the downside.

So what to do?

I certainly believe the intercepting the drag&drop to prevent flows.json bloat is a good thing - just not in this manner. It would be nice to be able to define a backend for storing image data but what about other data? Markdown files, Javascript files, JSON files? That's what my NodeDev package does, it takes JS files and converts them to nodes that have the correct editor syntax - very convenient.

Mobile apps have solved this problem by each app registering it's own protocol, so that when a URL of the form nodered://some.thing.else?p=1 the device knows to open the Node-RED app and send it the url. But that's handling links on the web, what about random content shared between apps?

When I use the share function on my phone, I select the app that I want to have the data. This is similar to the scenario here. On the device, I do: browser open to webpage, I press share, I then have a "bookmark" type and the phone asks all apps (there is probably a registry) whether they can handle the "bookmark" type (which is text/x-moz-url on Firefox). The phone then provides me with a list of apps and I can choose.

That would be the case here: when I drag specific content onto the workspace, Node-RED provides me with a list of node packages that could handle that data because they registered themselves as handlers. If there is only one, then it would get the data without further ado.

So that's the background to the drag&drop feature.

I'm not saying no, but I don't know if the demand will be great :confused:

Agreed. Can this be done using a Node-RED plugin?

Yes, creating a new event would be the cleanest I think. And like that the plugin will be able to listen to it simply.

1 Like

Yes I set this up in a plugin, a .html plugin.

It serves me well, has greatly increased the number of images in my mindmap! Also I can drag in bookmarks and have them become reference nodes in my mindmap.

As I described, it's definitely not something that should spread because of the uncontrollable overlap between drag&drop custom handlers ... I doubt that it will catch on, so that's ok then :wink:

Feel free to publish your plugin though, that's what they are for.