This discussion is archived
8 Replies Latest reply: Nov 27, 2013 4:43 PM by 13f5a1e5-b14a-457c-aaaa-53600fb2df9d RSS

Modify HTML of the document of the rendered page and reload

13f5a1e5-b14a-457c-aaaa-53600fb2df9d Newbie
Currently Being Moderated

Currently i am loading a url in javafx through webengine.load(url). My requirement is to keep the styling in tact with the original page. However, once the page is rendered, the fonts are not loaded and i am unable to increase the font sizes. I worked through the following steps to achieve this.

1. Add a listener through getLoadWorker method for web engine and get the document object when the state is SUCCEEDED.

2. Transform the document to a html string which gives me the whole HTML of the page in a string including the css.

3. Then i do a replace on the css part with the actual location of the font files (absolute path url) and reload the html through loadContent method.

With this, i am able to get the fonts loaded properly.

 

Problem:

1. I end up with a infinite loop when i use the "webEngine.loadContent(string, "text/html")" inside the getLoadWorker method.

2. I tried to do that outside the getLoadWorker method before the webEngine.load(url) but in this case the replace html body string is coming as null.

 

Any help on how to achieve this?? Below is my code:

      webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {

            String htmlBody = null;

            @Override

            public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State prevState, Worker.State newState) {

                //To change body of implemented methods use File | Settings | File Templates.

                //String htmlBody = null;

                int count = 0;

                if (newState == Worker.State.SUCCEEDED) {

                    browser.requestFocus();

                    // Get the document object from Engine.

                    Document doc = webEngine.getDocument();

                    try {

                        // Use Transformer to convert the HTML Object from the document top String format.

                        Transformer transformer = TransformerFactory.newInstance().newTransformer();

                        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");

                        transformer.setOutputProperty(OutputKeys.METHOD, "html");

                        transformer.setOutputProperty(OutputKeys.INDENT, "yes");

                        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

                        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

 

                        StringWriter outWriter = new StringWriter();

                        transformer.transform(new DOMSource(doc),new StreamResult(outWriter));

                        StringBuffer sb = outWriter.getBuffer();

                        htmlBody = sb.toString();

 

                        // Replace the font-family attribute in the style section to the actual URL of the font being used.

                        htmlBody = htmlBody.replace("font-family: medium", "font-family: url(http://1.10.30.45:8080/fonts/Md.ttf)");

 

                        // Load the new HTML string to the Engine.

                        //webEngine.loadContent(htmlBody, "text/html");

 

 

                    } catch (Exception ex) {

                        ex.printStackTrace();

                    }

                }

            }

        });

        webEngine.load(url);

        //add the web view to the scene

        getChildren().add(browser);

  • 1. Re: Modify HTML of the document of the rendered page and reload
    James_D Guru
    Currently Being Moderated

    Is this a one-off page load?

    If so, you should be able to fix the problem with

     

    observableValue.removeListener(this);

     

    just before you call

     

    webEngine.loadContent(htmlBody, "text/html");

     

    Otherwise, you may need to do something fairly ugly: e.g. have a flag "loadingTransformedHTML" which is initially false. Then in your changed(...) method do

     

    if (newState == WorkerState.SUCCEEDED) {
         if (loadingTransformedHTML) {
              loadingTransformedHTML = false ;
         } else {
              browser.requestFocus();
              // ... 
              loadingTransformedHTML = true ;
              webEngine.loadContent(htmlBody, "text/html");
              // ...
         }
    }
  • 2. Re: Modify HTML of the document of the rendered page and reload
    13f5a1e5-b14a-457c-aaaa-53600fb2df9d Newbie
    Currently Being Moderated

    Thanks james. The observableValue.removeListener(this);  worked for me. This is a login screen which is rendered through load(url) and from the sign in i will be routing to the other pages where i will be increasing the font sizes. I will mark this as correct.

  • 3. Re: Modify HTML of the document of the rendered page and reload
    13f5a1e5-b14a-457c-aaaa-53600fb2df9d Newbie
    Currently Being Moderated

    I ran into another problem when i implemented the above. I am not able to sign in. Nothing happens when i click on the sign in button. If i remove the below lines then it works fine.

    observableValue.removeListener(this);

    webEngine.loadContent(htmlBody, "text/html"); 


    is it related to the removelistener thing or the loadContent. I have just started with java FX last week and not able to move ahead with the flow. Any pointers will be helpful.

     

  • 4. Re: Modify HTML of the document of the rendered page and reload
    James_D Guru
    Currently Being Moderated
    is it related to the removelistener thing or the loadContent

    Most likely to the loadContent(...). My guess would be that somehow the changes you're making to the HTML are breaking the form.

  • 5. Re: Modify HTML of the document of the rendered page and reload
    13f5a1e5-b14a-457c-aaaa-53600fb2df9d Newbie
    Currently Being Moderated

    I compare the HTML string before and after making the changes. Nothing seems to be broken and also the page gets loaded fine. I am able to put data on the text box. The button is a simple submit button

     

    <BUTTON type="submit" class="btn">Sign In</BUTTON>

     

    Also don't see any error/exception in the logs as well. I am starting to think is there any other way to accomplice this rather than what i am doing (converting to string and then replacing).

  • 6. Re: Modify HTML of the document of the rendered page and reload
    James_D Guru
    Currently Being Moderated

    Not sure I can help with that. Looks like it should all work.

     

    I would try:

    1. If you can, set up a really simple HTML page with a form, and see if your technique works. Maybe put in a tiny bit of javascript to see if you can detect the submit button being pressed.

    2. Perhaps another way to do this is to manipulate the Document once the page is loaded, using the DOM API instead of by reloading the page. The Document you get back from webEngine.getDocument() is from the org.w3c.dom package; see the Javadocs to see how to manipulate the document. (It's a bit like using Javascript to manipulate an HTML document, but using a Java API.)

  • 7. Re: Modify HTML of the document of the rendered page and reload
    13f5a1e5-b14a-457c-aaaa-53600fb2df9d Newbie
    Currently Being Moderated

    James,

    I tried the document manipulation but was unable to override the css that was already applied. I downloaded and used jdk 8 which has the latest version of javaFX which fixed the font loading issue. Now i can see all the custom fonts and everything getting loaded as part of css.

     

    However, when i try to capture the state of the worker, it stays in the running and not changing to success. First few instances, the page was loaded successfully but then it stopped. Any idea if this is due to the new javaFX version of jdk8? Below is the code snippet:

     

           webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {

                @Override

                public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State prevState, Worker.State newState) {

                    //To change body of implemented methods use File | Settings | File Templates.

                    System.out.println(newState);

                    if (newState == Worker.State.SUCCEEDED) {

                        browser.requestFocus();

     

     

                        // Get the document object from Engine.

                        Document doc = webEngine.getDocument();

                        System.out.println(doc.getDocumentURI());

     

                    }

                }

            });

     

     

            webEngine.load(url);

            //add the web view to the scene

            getChildren().add(browser);

     

    The output is

    SCHEDULED

    RUNNING

     

    and nothing after that...

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points