This discussion is archived
0 Replies Latest reply: Nov 14, 2012 11:02 PM by PatrickMartin RSS

Saving WebView page source

PatrickMartin Newbie
Currently Being Moderated
This took way longer to figure out than I expected and I think I should share it.

All sorts of barriers made this harder than it should have been. I have an html document, self modifying, which contains a CodeMirror editor and a preview window in the spirit of live coding.

1st issue: WebEngine returns a w3c document via getDocument(). No big deal I thought. Being lazy, I reached for JDOM and wrote the contents out to a file.

It didn't load. I ditched jdom for w3c native and still I had issues. I then figured out that it was due to the encoding scheme. The following code worked for me:
  public static String toString(Document doc) {
    try {
      StringWriter sw = new StringWriter();
      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer transformer = tf.newTransformer();
      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
      transformer.setOutputProperty(OutputKeys.METHOD, "html");
      transformer.setOutputProperty(OutputKeys.INDENT, "no");
      //transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

      transformer.transform(new DOMSource(doc), new StreamResult(sw));
      return sw.toString();
    } catch (Exception ex) {
      throw new RuntimeException("Error converting to String", ex);
    }
  }

...

FileUtils.writeStringToFile(saveFile, toString(we.getDocument()))
Note the ever important "HTML" encoding. Took me awhile to figure that out. Also, the we object is the WebEngine and any lack of semi-colons is because this module is in Groovy.

Home free I thought. Wrong.

My dynamic document embedded CodeMirror which modifies the document at runtime. When you save and reload the document, it simply doesn't work. Even worse, it loses my editor changes.

This I overcame via some DOM manipulation. Since I had D3 (Data Driven Documents) already in my base dependency path, I simply remove the cruft if present prior to the CodeMirror editor creation.
  // Hack: CodeMirror creates this dynamically.  When I save as html and reload, I have to
  // delete the previous node in order to avoid getting duplicates.
  d3.select("div.CodeMirror.cm-s-default").remove();
Home free I thought. Wrong.

My changes were still not being found. I had to set a JavaScript event handler to update the text area with id="code" and it properly like so:
  editor.on("cursorActivity", function() {
  d3.select("#code").html(editor.getValue());
Home free I am thinking. Not quite yet... Interacting with the page so heavy with svg and javascript modifies other internals, however, the rendered page is close enough for now.

Hope this helps someone avoid the night of pain i just went through. Fun stuff :-)

The end result can be found over here:

http://www.javainc.com/projects/dex/ex/LiveCoder.html

Other fun examples showing the progress of my JavaFX visualization tool can be found here:

http://www.javainc.com/projects/dex/ex/ForceTree.html
http://www.javainc.com/projects/dex/ex/Force.html
http://www.javainc.com/projects/dex/ex/Chord.html
http://www.javainc.com/projects/dex/ex/dendogram.html
http://www.javainc.com/projects/dex/ex/HivePlot.html
http://www.javainc.com/projects/dex/ex/IndentedTree.html
http://www.javainc.com/projects/dex/ex/NodeLinkTree.html
http://www.javainc.com/projects/dex/ex/PartitionLayout.html
http://www.javainc.com/projects/dex/ex/Starburst.html
http://www.javainc.com/projects/dex/ex/TensionMap.html
http://www.javainc.com/projects/dex/ex/Treemap.html

- Pat



- Pat