Import from/Export to webservice end point as a specific format

501 views
Skip to first unread message

Christoph Boget

unread,
May 25, 2018, 12:39:48 PM5/25/18
to draw.io
Is it possible to bypass the initial splash screen and make it so that whenever a diagram is saved or loaded, it does so using a webservice end point?  I see with the urlParams, I can make it so that the only option on the initial splash screen is "Device".  But I want to eliminate that as an option as well.  I unsure where I can make that happen.  

In terms of saving and loading, I *think* I can override EditorUi.prototype.saveFile and make it so that it communicates with my webservice to save?  Would that be the right way?  If not, what would be a better way?  But what about loading?  Overriding EditorUi.prototype.openFile?

Finally, is there a way to always make it save (export?) as a SVG file?  I know how I can remove both the "Import from" and "Export as" menu options so the user wouldn't be able to select those, bypassing our needs.  But I'm not sure how I can make it so that the editor always "saves" or "loads" the diagram as SVG.  

So, any pointers?  Any help would be greatly appreciated!

thnx,
Christoph

Gaudenz Alder

unread,
May 25, 2018, 1:15:16 PM5/25/18
to draw.io
Are you aware our embed mode? It lets you do all this using an iframe and a simple postmessage protocol. Examples are on github.

Christoph Boget

unread,
May 25, 2018, 2:57:41 PM5/25/18
to draw.io
Are you aware our embed mode? It lets you do all this using an iframe and a simple postmessage protocol. Examples are on github.

I wasn't really aware of it.  Sounds interesting based on this

https://desk.draw.io/support/solutions/articles/16000042544-how-does-embed-mode-work-

When I went to 


I couldn't really find many examples (in github) for embedded pages.  Is this 


the only one?  I did see this


But I don't see where it is making a request from an external service to request the diagram.  I guess that one is just expecting the source to be included as part of the IMG tag?

thnx,
Christoph

Christoph Boget

unread,
May 25, 2018, 3:12:48 PM5/25/18
to draw.io
Are you aware our embed mode? It lets you do all this using an iframe and a simple postmessage protocol. Examples are on github.

Also, please forgive my ignorance, on this page


there is this code:

window.addEventListener('message', receive);
iframe.setAttribute('src', editor);
document.body.appendChild(iframe); 

What is ``editor``?  Just the same URL

'https://www.draw.io/?embed=1&ui=atlas&spin=1&modified=unsavedChanges&proto=json'

used at the top of the previous code block?

thnx,
Christoph

Gaudenz Alder

unread,
May 25, 2018, 4:41:42 PM5/25/18
to draw.io

Christoph Boget

unread,
May 30, 2018, 11:17:50 AM5/30/18
to draw.io
Ok, things have been going pretty good for me these last few days.  The above example uses a PNG.  I'm trying to get it to work using SVG.  I exported the above (using File -> Export As -> SVG).  I took the source from that file and stuck it on my page, replacing the PNG image.  It displays just fine.  But when I go to load it, I changed this line

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'load', xmlpng: source.getAttribute('src')}), '*');

to this

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'load', xmlsvg: source}), '*');

And it doesn't load.  I've tried variations of the above (e.g., source.attributes.content, et. al.) but it just isn't working.  I've tried searching around for draw.io action messages but wasn't able to really find anything.  

So how do I load a SVG source in to the editor?  Also, is there documentation on the json protocol (I think that's what it's called) or the action messages?

thnx,
Christoph

Gaudenz Alder

unread,
May 30, 2018, 11:32:39 AM5/30/18
to draw.io
Have you tried xml instead of xmlsvg, see first line in the "Description of the JSON protocol" at https://desk.draw.io/support/solutions/articles/16000042544

Christoph Boget

unread,
May 30, 2018, 11:53:15 AM5/30/18
to draw.io
Have you tried xml instead of xmlsvg, see first line in the "Description of the JSON protocol" at https://desk.draw.io/support/solutions/articles/16000042544

I didn't try it.  I guess I thought that since it used ``xmlpng`` when loading the PNG, it should be ``xmlsvg`` when loading SVG.  In any case, I just changed the line to

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'load', xml: source}), '*');

and it threw an exception saying h.xml.substring is not a function.

``source`` in this case is the entire <svg> node.  Should I use something else?

Also, I've been to the above page that describes the JSON protocol.  But it seemed like that information just scratched the surface.  Are the 7 actions listed on that page the only ones?  What about the other properties used for each of those actions?  What about the events?  Is there documentation on all of this?

thnx,
Christoph

Gaudenz Alder

unread,
May 30, 2018, 12:00:43 PM5/30/18
to draw.io
source should be a string. all actions and events should be fully specified in that page.

Gaudenz Alder

unread,
May 30, 2018, 12:07:21 PM5/30/18
to draw.io
...as you may have noticed by now, we like to keep things short ;-)

Christoph Boget

unread,
May 30, 2018, 12:23:32 PM5/30/18
to draw.io
source should be a string.

 Hmm...  ok.  So in the original code from the embed example page you linked me to, it has

var source = evt.srcElement || evt.target;

I do see in the original code, it is looking at the src attribute of the PNG.  That makes sense because the IMG tag uses the src to render the image.  SVG, however, uses the entire contents of the tag.  Please forgive my ignorance but I don't see how I can convert it to a string (using straight javascript).  I've seen some references to how it can be done using jQuery but I'm not sure exactly what draw.io is expecting to receive.

all actions and events should be fully specified in that page.

Ok.  Again, it seemed to me like it was describing a subset of what was available.

thnx,
Christoph 

Christoph Boget

unread,
May 30, 2018, 12:36:28 PM5/30/18
to draw.io
Hmm...  ok.  So in the original code from the embed example page you linked me to, it has

var source = evt.srcElement || evt.target;

I do see in the original code, it is looking at the src attribute of the PNG.  That makes sense because the IMG tag uses the src to render the image.  SVG, however, uses the entire contents of the tag.  Please forgive my ignorance but I don't see how I can convert it to a string (using straight javascript).  I've seen some references to how it can be done using jQuery but I'm not sure exactly what draw.io is expecting to receive.
 
For future reference, for anyone finding this thread in the future, this is what I found:

(new XMLSerializer()).serializeToString(source);

Passing that in as the value of the xml property of the JSON (action) message got it to load in the editor.

i.e.

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'load', xml: (new XMLSerializer()).serializeToString(source)}), '*'); 

thnx,
Christoph

Christoph Boget

unread,
May 30, 2018, 2:15:22 PM5/30/18
to draw.io
Have you tried xml instead of xmlsvg, see first line in the "Description of the JSON protocol" at https://desk.draw.io/support/solutions/articles/16000042544

Man, I keep banging my head against the wall.  Again, with the PNG, I didn't have any issue saving/exporting using the sample code on the page you suggested above --  https://github.com/jgraph/drawio-html5.  Mostly because, well, most of what I wanted was there.  I just needed to make some changes for my specific use case.  Again, everything worked.  Now I'm trying to get it so that it exports SVG instead of PNG.  As before, I was able to change the code for loading the SVG in to the editor using :

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'load', xml: (new XMLSerializer()).serializeToString(source)}), '*');

Saving/exporting on the other hand is where I'm running in to issues.  The original code had it exporting the data using xmlpng.  I changed it so that it exported xmlsvg (I also tried just svg), like so:

source.drawIoWindow.contentWindow.postMessage(JSON.stringify({action: 'export', format: 'xmlsvg'}), '*');

When the code responds to the "export" event, it alters the source attribute of the image tag like so:

source.setAttribute('src', msg.data);

Inspecting the contents of the msg object, I see two (seemingly) relevant properties -- .data and .xml.  The value of the .xml property appears to match the structure of the .content property that is part of the <svg> element I'm using in my markup (replacing the <img> used in the original example).  When trying to update that node, I'm using 

source.setAttribute('content', msg.xml);

but that doesn't seem to update the SVG the way it did the IMG when the editor flips out of embedded mode.  The value of the .data attribute doesn't look anything like the original SVG that I have in the markup.  Again, I got the full structure/contents of the SVG I am using from the file I got from draw.io when I exported as SVG.  So I'm not entirely too sure where to go from here.  How do I get the data draw.io is exporting in to the original/base (non draw.io editor version of) the page?

Thanks again for all your help.  I'm getting there! :)

thnx,
Christoph

Gaudenz Alder

unread,
May 31, 2018, 1:39:34 AM5/31/18
to dra...@googlegroups.com
msg.data is an SVG image (data URI). why are you using an SVG element and not an SVG image? basic idea to obtain the SVG and add it to the DOM:

elt.innerHTML = atob(msg.data.substring(msg.data.indexOf(',') + 1));


see http://jgraph.github.io/drawio-html5/localstorage-svg.html#default


and before you ask: keep in mind that foreignObject, which is used for labels in draw.io, is not supported in IE 11 and earlier.

Christoph Boget

unread,
May 31, 2018, 8:08:59 AM5/31/18
to draw.io
msg.data is an SVG image (data URI). why are you using an SVG element and not an SVG image?

Because our UX team wants to use the SVG element for their alchemy.  It just struck me that you could export the diagram such that it is wrapped in a SVG element but you couldn't save the diagram as an SVG element.  

I was digging through the code to see how this was done and I see that mxgraph/Graph.js has a getSvg function but I wasn't sure how I could leverage that as part of the saving.  At least, not from the receive function (in that embed.html sample page) that deals with the posted messages.  I was thinking that I might have to roll my own plugin so that I could get a handle on the editor...
  
basic idea to obtain the SVG and add it to the DOM:

elt.innerHTML = atob(msg.data.substring(msg.data.indexOf(',') + 1));


see http://jgraph.github.io/drawio-html5/localstorage-svg.html#default


and before you ask: keep in mind that foreignObject, which is used for labels in draw.io, is not supported in IE 11 and earlier.


Yeah, I know that foreignObject isn't supported in IE.  That is not a concern we have at this moment.  I'll try this and see what I can come up with.

Again, I just want to thank you for all your help.  It really has been invaluable.

thnx,
Christoph 

Christoph Boget

unread,
May 31, 2018, 11:05:08 AM5/31/18
to draw.io
Gaudenz Alder, all I have to say is that you are awesome!  Thank you very much for all your help in getting me to a place where I'll be able to import and export the diagram.  I definitely appreciate it.  I do have other questions outstanding but those are for another thread.

thnx,
Christoph

Christoph Boget

unread,
May 31, 2018, 1:16:51 PM5/31/18
to draw.io
Ok, I'm experiencing an issue with the above that I'm hoping you can help me with...

Ok, so when I do source.innerHTML (working with drawio-html5 example page), when the element is re-rendered, it does so showing the changes that I made to the diagram.  What's weird, though, is that after I set source.innerHTML, if I console.log out both source and source.innerHTML, they are two different things.  If I double click on the image again to take it back in to draw.io and allow me to modify the diagram after my changes, the original image is loaded -- not the changed one.  I'm guessing because source, the original element, is unchanged -- just the innerHTML (which the browser uses).

I've tried taking the result of 

atob(msg.data.substring(msg.data.indexOf(',') + 1))

and replacing the original element (using things like jQuery, parentNode.removeChild, parentNode.innerHTML, etc).  All of that works in terms or rendering the altered diagram.  But whenever I do any of that, I get an error saying it's not a diagram file.  

Now, doing some checking and testing from there, the only real difference, at least ostensibly, that I see between the original markup for the source and the result of the atob() function call is that the latter does not contain the content attribute for the SVG element.  Is that what is causing the error?  I believe it is because when I add that attribute, it appears to work.  But I'm not sure if I'm missing something.  Am I?

While I was able to get it to work (sort of) using jQuery, I don't know how to do this using raw javascript.  The fact that the source element is still a reference to the original node even after I changed the .innerHTML is concerning to me.  If I'm changing the .innerHTML, why is the actual node not changing?  Particularly given the fact that it appears to be working with the node and not the .innerHTML.

What am I doing wrong?

thnx,
Christoph
Reply all
Reply to author
Forward
0 new messages