Paste from external clipboard onto GoJS diagram

I can’t seem to trap the event associated with pasting from the external (windows) clipboard (using CTRL-v) onto a GOJS diagram. But I can seem to DROP objects onto the diagram.
Also I can paste into the document window when the diagram is not displayed (as per last example here by setting the attribute: contenteditable=“true” on the div).

var div = document.getElementById("myDiagramDiv");

div.addEventListener("paste", function(event) {

  console.log('Inside paste event');  // this message IS NOT received

}, false);

However dropping external elements DOES seem to work:

var div = document.getElementById("myDiagramDiv");

div.addEventListener("drop", function(event) {

  console.log('Inside drop event'); // this message IS received

}, false);

Also I can seem to be able to paste onto the div outside of the diagram as follows:

document.addEventListener("paste", function(event) {

  console.log('Inside paste event'); // this message IS received

}, false);

I am using the library src=“https://unpkg.com/gojs/release/go-debug.js” and I’m on windows 10 Enterprise

What am I missing?

The GoJS library does not establish any “paste” event handler.
Element: paste event - Web APIs | MDN

Have you tried setting contenteditable to true? Hopefully that won’t have any odd side-effects.

Yes. I have tried that. After setting that attribute, I was able to trap events in the div element as per the last example. But it only worked when there was no GoJS digram attached to the div element.

Once the div was connected to the GoJS diagram, I could no longer receive paste events.
And I want to be able to paste into the diagram.

GoJS allows you to Drag and Drop into the diagram using external content so why not paste?

I suspect that contentEditable won’t help get the “paste” event working.

Making content editable - Developer guides | MDN says:

For security reasons, Firefox doesn’t let JavaScript code use clipboard related features (copy, paste, etc.) by default. You can enable them by setting the preferences shown below using about:config

Also note that this functionality is not standard:
Clipboard API and events

We’ll look into this today.

Also: Copy/Paste events propagating out of canvas

You will want to stop GoJS from doing its normal paste command, and then you will want to use the document paste listener to do what you choose. Here’s an example:

myDiagram.commandHandler.doKeyDown = function() {
  const diagram = this.diagram;
  const e = diagram.lastInput;
  // The meta (Command) key substitutes for "control" for Mac commands
  const control = e.meta || e.control;
  const shift = e.shift;
  const key = e.key;
  if ((control && key === 'V') || (shift && key === 'Insert')) {
    // Do nothing
    // if (this.canPasteSelection()) this.pasteSelection();
    // but let it bubble:
    e.bubbles = true;
  } else {
    go.CommandHandler.prototype.doKeyDown.call(this, e);
  }
}

document.addEventListener('paste', function (e) {
  const paste = e.clipboardData.getData("text");
  // Decide if the clipboard should be pasted, or if we should let GoJS paste
  if (!paste.includes("XYZ")) {
    // If the clipboard does not contain XYZ, we will create a new node
    // out of the text and paste it at the mouse location
    const loc = myDiagram.lastInput.documentPoint;
    myDiagram.model.addNodeData({ text: paste, location: loc });
  } else {
    // If the clipbooard does contain XYZ, lets paste from GoJS instead
    const commandHandler = myDiagram.commandHandler;
    if (commandHandler.canPasteSelection()) commandHandler.pasteSelection();
  }
});

Here is that live: https://codepen.io/simonsarris/pen/wvrOVQW?editors=1010

Note how sometimes you may want to let the document paste command really do a GoJS paste, but when is up to you.

Note you must set e.bubbles = true;, this is an undocumented go.InputEvent property.

Hi Simon,
Thankyou. This is great.
One more problem. I still want to be able to select Nodes and do a copy and paste on them and now this is not working! It seems that the diagram paste handler is now disabled?

I guess I want to be able: to check the clipboard to see what is being pasted:
If its external data then use “document.addEventListener” as you have described, but if it’s goJS diagram nodes, I want the normal diagram paste logic to work.

Is this possible?

Yes, that is why I had the line about:

That was just to give an example of when to use the clipboard versus using the GoJS paste function. Of course you don’t want to do this conditional on the clipboard containing “XYZ”, you must substitute your own criteria.

Look at the ClipboardEvent.clipboardData, an instance of DataTransfer, and at CommandHandler.canPasteSelection. But if the user has copied some Parts and there is something in the system clipboard, you’ll need to decide which one should take precedence.
https://w3c.github.io/clipboard-apis/#dom-clipboardevent-clipboarddata
https://gojs.net/latest/api/symbols/CommandHandler.html#canPasteSelection

OK thanks Simon & Walter.

I see what you mean Simon about checking if (!paste.includes) to determine which clipboard I take.

I tried using: commandHandler.canPasteSelection() which allows use to see if there is something in the diagram clipboard.

However, ideally I would like to take the clipboard that was last copied into (I guess based on date time compare). Because normally a user will copy something into the clipboard and then after that want to paste it. This could be with the diagram or external content.

I have used other browser applications, that seem to be able to do this (paste the last copy event - either internal / or external windows clipboard). Could this be possible with GoJS?

You will need to implement your own custom CommandHandler that overrides copyToClipboard and pasteFromClipboard just like this extension does:
LocalStorageCommandHandler | GoJS API
But using that new not-yet-standard Clipboard API.

You can start with any of the three implementations that we provide, in extensions or extensionsJSM.

Thanks for your help. I will look at that down the track when I’m a bit more familiar with GoJS. For now, I have some options that I can get by with.