I am struggling to get copying of JSON data to work all the time. There is a browser restriction that you cannot do
event.clipboardData.setData('application/json', payload);
Unless you do it during a copy event handler against the document. This appears to be restricted for security reasons, although why it is a security risk versus copying text never seems to be explained.
Here is how I have attempted to do this in an Elm application:
const copy = new Copy(app);
app.ports.jsonToClipboard.subscribe((data) => {
copy.jsonToClipboard(data);
});
class Copy {
constructor(app) {
this.app = app;
this.copyCallback = this.copyCallback.bind(this);
document.addEventListener('copy', this.copyCallback);
}
// Gets called from the port.
jsonToClipboard(json) {
console.log("2. jsonToClipboard.");
this.jsonPayload = json;
}
copyCallback(e) {
console.log("3. Copy callback.");
if (this.jsonPayload != null) {
e.clipboardData.setData('application/json', JSON.stringify(this.jsonPayload));
console.log("4. JSON to clipboard - non null json payload.");
this.jsonPayload = null;
e.preventDefault();
return;
}
}
Then in the Elm code:
-- This gets called during a keyboard subscription handler when Ctrl+C is pressed.
-- Browser.Events.onKeyDown Keyboard.keyDownDecoder
-- |> Sub.map KeyboardShortcut
let
_ =
Debug.log "1. copyElementsFromSelection" "send json to Copy"
in
( model
, encodeElements elementsToCopy |> Ports.jsonToClipboard
)
If I then press Ctrl+C in my application, sometimes I get:
1. copyElementsFromSelection: "json to Copy"
2. jsonToClipboard.
3. Copy callback.
4. JSON to clipboard - non null json payload.
And about as often I get:
1. copyElementsFromSelection: "json to Copy"
3. Copy callback.
2. jsonToClipboard.
So you can see the problem is that the call to Ports.jsonToClipboard and the browsers document level copy event handler race against each other. If the port call completes first it works as I want it to, but if the copy event handler runs first it does not find any JSON to put in the clipboard.
Does anyone know how to make this work with Elm?
Sorry the code above is not complete, its just snippets from a larger application. However, over the next few days I will extract a runnable example so that I can share it better.