0

I'm using a simple http server and created a context to print my logger output.

            server.createContext("/log", new HttpHandler() {

            @Override
            public void handle(final HttpExchange t) throws IOException {
                t.getResponseHeaders().set("Content-Type", "text/html; charset=UTF-8");
                t.sendResponseHeaders(200, 0);
                Writer out = new OutputStreamWriter(t.getResponseBody(), "UTF-8");
                out.write("<pre>");
                Semaphore s = new Semaphore(0);

                ExecutionContext.setLogger(new ILogger() {

                    @Override
                    public void log(String message) {
                        try {
                            out.write(message);
                            out.flush();
                        } catch (IOException e) {
                            s.release();
                        }
                    }
                });

                try {
                    s.acquire();
                } catch (InterruptedException e) {
                }

            }

The OutputStream is never closed, unless the connexion ends (for example, the user closes the browser tab). It's working as expected, except that my browser is not scrolling to the new data when available.

I know it's possible to scroll to a div using javascript but I can't find a nice method to do this (I would need to call the javascript code each time new data is available, and even if I could, the div wouldn't be at the end of the page, because the page is always updating...)

Do you have a solution?

Thanks

EDIT: Solution inspired by Sen Jacob's answer : server.createContext("/log", new HttpHandler() {

            @Override
            public void handle(final HttpExchange t) throws IOException {
                t.getResponseHeaders().set("Content-Type", "text/html; charset=UTF-8");
                t.sendResponseHeaders(200, 0);
                Writer out = new OutputStreamWriter(t.getResponseBody(), "UTF-8");
                StringBuilder sb = new StringBuilder();
                sb.append("<html>\n");
                sb.append("<body>\n");
                sb.append("<pre id='logger'></pre>\n");
                sb.append("<script>\n");
                sb.append("var logger = document.getElementById('logger');\n");
                sb.append("\n");
                sb.append("function addLog(s) {\n");
                sb.append("  // scroll only if already at the end of the page\n");
                sb.append("  var scroll = document.body.scrollTop + document.body.clientHeight == document.body.scrollHeight\n");
                sb.append("  logger.innerHTML += s;\n");
                sb.append("  if(scroll) {\n");
                sb.append("    window.scrollTo(0,document.body.scrollHeight);\n");
                sb.append("  }\n");
                sb.append("}</script>\n");

                out.write(sb.toString());

                Semaphore s = new Semaphore(0);

                ExecutionContext.setLogger(new ILogger() {

                    @Override
                    public void log(String message) {
                        try {
                            message = StringEscapeUtils.escapeEcmaScript(message);
                            out.write("\n<script>addLog('" + message + "')</script>");
                            out.flush();
                        } catch (IOException e) {
                            s.release();
                        }
                    }
                });

                try {
                    s.acquire();
                } catch (InterruptedException e) {
                }                    
            }
2
  • The page can't update faster than JavaScript can run, so you may lose true "real-time" updates, but the scrolling should work on every log received using the example Sen Jacob put in his answer. Commented Dec 12, 2016 at 17:42
  • I'm not sure to understand why I would lose updates. With the solution I added in my post, everything should be fine because I scroll only after updating the page contents Commented Dec 14, 2016 at 9:39

1 Answer 1

3

Here is an example javascript code where you can scroll to newly added log entry.

var logger = document.getElementById("logger");
function addLog() {
	// add new log entry
  var div = document.createElement("div");
  div.innerHTML = "log - " + Date.now();
  logger.appendChild(div);
  // scroll to new log
  logger.scrollTop = logger.scrollHeight;
}
// simulate http response
var timer = setInterval(addLog, 1000);
window.onbeforeunload = clearInterval.bind(window, timer);
#logger {
  height: 10em;
  overflow-y: auto;
}
<div id="logger"></div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I adapted your solution to get exactly what I wanted

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.