Search code examples
swteclipse-rap

Show local HTML file with JavaScript in SWT Browser widget in RAP


For my RAP-project I need to show some charts. Because I haven't found any widget for this purpose, my plan was to use the browser widget, so I can use JavaScript-Plugins like Highcharts or Chartsjs. But I can't get it working. If I set an HTML-File in browser.setUrl, the browser widget don't show anything, not even simple HTML. The JavaScript-Console in Chrome says

Not allowed to load local resource

If I enter the HTML-Code with the setText method it shows the HTML, but JavaScript is not working, it don't load external JS-File like the jQuery-library.

Can't this be done this way? Or where is my failure? (Sorry for my bad englisch, I'm not native speaker.)

Here's the Java-Code I tried:

browser = new Browser(composite, SWT.NONE);
browser.setTouchEnabled(true);
browser.setBounds(10, 10, 358, 200);
browser.setUrl("D:\\STATS\\statistiken.html");

Or this:

File file = new File("D:\\STATS\\statistiken.html");
browser = new Browser(composite, SWT.NONE);
browser.setTouchEnabled(true);
browser.setBounds(10, 10, 358, 200);
browser.setUrl(file.toURI().toString());

I tried also some other things, there were not working to.

With HTML in setText-method (I tried external libraries and local libraries in same folder):

browser = new Browser(composite, SWT.NONE);
browser.setBounds(10, 10, 358, 200);
browser.setText(
    "<html>" +
    "<head>" +
        "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js\"></script>" +
        "<script src=\"http://code.highcharts.com/highcharts.js\"></script>" +
        "<script src=\"http://code.highcharts.com/modules/exporting.js\"></script>" +
    "</head>" +
    "<body>" +
        "<p>Test</p>" +
        "<div id=\"container\" style=\"min-width: 400px; height: 400px; margin: 0 auto\"></div>" +
    "</body>" +
    "</htm>");

Hope someone can help me with this problem.


Solution

  • Local links will not be resolved and external links will not be loaded(Cross Domain problem) in your case.

    I could suggest you 2 Solutions.

    Solution 1:

    This is useful when you have very few resources(html, javascript, css) to render on Browser and no Hyperlinks(which when cliked will load a different page).

    You can use Velocity. Read this to start using Velocity.

    You can have all the static content in Velocity Template and inject Dynamic content into it at Runtime.

    Here is the excerpt from one of my Projects.

    init.vm

     <html dir="ltr">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style type="text/css">
    .transcript {
        background-color: #d2d2d2;
    }
    
    .messageBlock {
        margin-left: 4px;
        margin-bottom: -15px;
    }
    
    .message {
        margin-left: 115px;
        word-wrap: break-word;
        white-space: -moz-pre-wrap;
        _white-space: pre;
        white-space: pre-wrap;
    }
    </style>
    
    </head>
    <script type="text/javascript">
    function resizeChatWindow() { var divT = document.getElementById("divTranscript"); divT.style.height = (document.body.clientHeight - getTopAreaHeight()) + "px"; divT.style.width = (document.body.clientWidth) + "px"; divT.style.overflow = "auto"; divT.style.position = "absolute"; divT.style.left = "0px"; divT.style.top = getTopAreaHeight() + "px";}
     function getTopAreaHeight() { var chatAlert = document.getElementById("chatAlert"); if (chatAlert) { return chatAlert.clientHeight; } return document.getElementById("divBody").clientHeight;}
     isChat=false; window.onresize=resizeChatWindow;
    </script>
    <script type="text/javascript">
    $scriptText
    </script>
    
    <script type="text/javascript">
    function addChat(chatText){
        $("#divTranscript").append(chatText);
    
        $("#divTranscript").animate({ scrollTop: $("#divTranscript")[0].scrollHeight }, "slow");
    
    }
    
    </script>
        <body onload="resizeChatWindow();">
            <div id="divBody"></div>
            <div id="divTranscript">$history</div>
        </body>
    </html>
    

    VelocityUtils

    private void init() throws Exception {
        ve = new VelocityEngine();
            Properties velocityProperties = new Properties();
            velocityProperties.put("resource.loader", "class");
            velocityProperties.put("class.resource.loader.description", "Velocity Classpath Resource Loader");
            velocityProperties.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            ve.init(velocityProperties);
            //ve.init();
    }
    
    
    public String getInitHtml(String history) throws ResourceNotFoundException, ParseErrorException, Exception {
        /* now render the template into a StringWriter */
        StringWriter writer = null;
        /* next, get the Template */
            Template t = ve.getTemplate("templates/init.vm","UTF-8");
            /* create a context and add data */
            VelocityContext context = new VelocityContext();
            String script = IOUtils.toString(VelocityUtils.class.getResourceAsStream("script/jquery.min.js"), "UTF-8");
            context.put("scriptText", script); //You can even have all the script content in init.vm rather than injecting it at runtime.
            context.put("history", StringUtils.defaultIfBlank(history, StringPool.BLANK));
            writer = new StringWriter();
            t.merge(context, writer);
            /* show the World */
    
        String returnMe = writer.toString();
        return returnMe;
    }
    

    set the returned String in Browser.setText()

    Solution 2:

    I explained it here.