I am building a small web application, which includes a webpage that is updated regularly via
a websocket. Each message is a string containing many HTML tags, including LaTeX code. The
content of this string is put in a div
container. Then I use renderMathInElement
from KaTeX to interpret the LaTeX parts.
The Problem: This works fine for small messages, but for large strings, the site starts flickering, when inserting the new content. The flickering only occurs in the deployed version, which irritates me, because my Firefox should run the javascript code always with the same speed. The fact, that the loading times are slower for the deployed version, should not change the efficiency of the javascript code.
Code
// connect the websocket
if (location.protocol == 'https:') {
var socket = new WebSocket("wss://" + location.host + "/lectureserver", "lecture");
} else {
var socket = new WebSocket("ws://" + location.host + "/lectureserver", "lecture");
}
var last = ""; // last message
var content = document.getElementById("lecture"); // div displaying content
var content_hidden = document.getElementById("lecture_hidden"); // hidden element to prepare content
socket.onerror = function (error) {
console.log("unable to connect");
content.innerHTML = "<p>Error. Can't connect!</p>";
};
socket.onmessage = function (event) {
// check if data didn't change or is empty
if (event.data == last || event.data == "") {
return;
}
// save current vertical scroll position
var scrollY = window.scrollY;
// and old max height (to determine if client scrolled to the very bottom)
var oldMax = document.body.scrollHeight - document.body.clientHeight;
// save the received data
var newContent = event.data;
// fill the hidden element with the content
content_hidden.innerHTML = newContent;
// evaluate the math (KaTeX)
renderMathInElement(content_hidden, {
delimiters: [
{left: "\\[", right: "\\]", display: true},
{left: "\\(", right: "\\)", display: false},
{left: "\\begin{align\*}", right: "\\end{align\*}", display: true},
{left: "$", right: "$", display: false}
],
macros: {
"\\Q": "\\mathbb{Q}",
"\\C": "\\mathbb{C}"
},
strict: false
});
// replace old content with now rendered and prepared new content
content.innerHTML = content_hidden.innerHTML;
// reset last content
last = event.data;
// keep window in place
if (scrollY >= oldMax) {
window.scrollTo(scrollX, 100000);
} else {
window.scrollTo(scrollX, scrollY);
}
};
As you can see, I added a hidden div
, that prepares the content first before replacing the real content.innerHTML
with the new content. But this change, doesn't solve the flickering issue.
If you wonder, even removing the renderMathInElement
part doesn't resolve the issue. The
flickering is faster, but still there.
Is the javascript websocket interface in any way lazy, that might cause the difference between the deployed and the local instance? If it's strict, shouldn't make the traffic speed any difference, as the message is already completely transferred when the processing starts?
Please let me know, if you need clarification.