Reputation: 125
Basically, the backend provides me with the content of drawio files (so we are talking xml mode) and I need to display this in our webix page.
So far, I have tried to achieve this using an iframe, following the official guidelines from https://www.drawio.com/blog/embedding-walkthrough but nothing works. If I use the usual webix.$$().getIframe().postMessage
or webix.$$().getWindow().postMessage
, the message goes through (spent a lot of time debugging to find where drawio has its counterpart listener ... it's on line 12369 of app.min), but there they check:
L.source == (window.opener || window.parent)
and this is always false:
L
is the event
L.source
is always window
window.opener
is always null
window.parent
is always the main window (not the iframe's window)
No clue how to overwrite the source property of the event while still in the parent. I mean, should this not automatically be the calling window???
When trying the whole thing using webix.$$().getIframe().contentWindow.postMessage (like in the code below), the message does not even ever reach the drawio code inside the iframe...
Anyway, here is the code:
{
view: "iframe",
id: "iframe#1",
src: 'https://embed.diagrams.net/?embed=1', //&ui=atlas&spin=1&&libraries=1&modified=unsavedChanges&proto=json&chrome=0',
style: 'border:0;position:"fixed";top:0;left:0;right:0;bottom:0;width:100%;height:100%;cursor:default;'
}
This should basically give me an iframe in webix - with all the recommended styles - the commented url params are what I tried, but none of them seem to be able to resolve it. Looking at it in the debugger, it very much looks like an iframe at least ...
const receive = (evt: MessageEvent<any>) => {
const frame = (webix.$$(this.getSubViewID("iframe")) as webix.ui.iframe).getIframe() as any;
//frame.setAttribute('frameborder', '0');
if (evt && frame.contentWindow && evt.source === frame.contentWindow) {
const msg = JSON.parse(evt.data);
if (msg.event === 'init') {
frame.contentWindow.postMessage(JSON.stringify({
action: 'load',
xml: this.xmlData,
autosave: 1
}));
}
if (msg.event === 'save' || msg.event === 'autosave') {
this.xmlData = msg.xml;
}
if (msg.event === 'exit') {
window.removeEventListener('message', receive);
frame.contentWindow.close();
}
}
};
window.addEventListener("message", receive);
No matter what I try, it always jumps to the postMessage part, xml is the 1:1 xml that you see when you open a .drawio file in an editor. It never jumps to the breakpoint in save/autosave. After the postMessage breakpoint, if the spinner is activated, the spinner keeps spinning forever, otherwise it simply stays empty in a bugged state where you cannot even add new stuff (depending on the selected ui, either everything is greyed out or things simply do not get added). Also tried the embedInline URL parameter that I found mentioned in one place of the github, but that one then made the whole thing not even load at all.
Would really appreciate any pointers as to what I might be doing wrong.
Upvotes: 0
Views: 86
Reputation: 125
Apparently, as shown in the code above, during my endless variations of trying to make this work, the "*" for target origin got lost. To make matters worse, when debugging, the the Chrome debugger apparently messes up the sent event (basically replaces the event with a generic event from the same window, but without data)
Lesson learned:
Do not try to debug cross-window communication with postMessage using the Chrome debugger. The moment you set a breakpoint within the remote code, Chrome messes up all of the events.
For reference, the correct, working code is:
const receive = (evt: MessageEvent<any>) => {
const frame = (webix.$$(this.getSubViewID("iframe")) as webix.ui.iframe).getIframe() as any;
frame.setAttribute('frameborder', '0');
if (evt && frame.contentWindow && evt.source === frame.contentWindow) {
const msg = JSON.parse(evt.data);
if (msg.event === 'init' && evt.origin === 'https://embed.diagrams.net') {
frame.contentWindow.postMessage(JSON.stringify({
action: 'load',
xml: this.xmlData,
autosave: 1
}), "https://embed.diagrams.net");
}
if (msg.event === 'save' || msg.event === 'autosave') {
this.xmlData = msg.xml;
}
if (msg.event === 'exit') {
window.removeEventListener('message', receive);
frame.contentWindow.close();
}
}
};
window.addEventListener("message", receive);
Upvotes: 0