I have a webpage that displays last 1000
lines of a logfile then updates via AJAX every x
seconds loading new content (if any) and appending to textarea with $('#log').append(new_data)
, a sort of tail -f
.
The problems come up after some time when too many lines are appended and the page becomes slow or unresponsive.
So I'd like to limit number of lines to, say, 5000 so it means I should:
- retrieve
new_data
- calculate
overflow = 5000 - lines_ in_new_data - lines_in_textarea
- if
overflow > 0
remove first overflow
lines from textarea
- append new_data to textarea
In my mind this involves one or more split('\n')
of both textarea
and new_data
values then use array lengths and slicing but I guess if there's a neater or better way to accomplish this.
You should be able to use a single split
and then join
after truncating the data, something like this:
// on data retrieved
var total = ((textarea.value
? textarea.value + "\n"
: "")
+ new_data).split("\n");
if (total.length > 10)
total = total.slice(total.length - 10);
textarea.value = total.join("\n");
Working example: http://jsfiddle.net/ArvQ7/ (cut to 10 lines for brevity)
Something like this (demo linked below is probably more useful):
HTML
<button id="clickme">More lines</button>
<br/>
<textarea id="log" rows="24" cols="80"></textarea>
<p>Lines: <span id="numLines">0</span></p>
JavaScript
var $log = $('#log'),
$button = $('#clickme'),
$numLines = $('#numLines'),
MAX_LINES = 5000,
lorem_ipsum = ' Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
lineCounter = 0;
$button.click(function()
{
$log.val($log.val() + generateMoreLines()).change();
});
$log.change(function ()
{
var text = tail(MAX_LINES, $log.val());
$log.val(text);
$numLines.text(countNewlines(text));
});
function generateMoreLines()
{
var buf = [];
for (var i = 0; i < 1000; i++)
{
buf.push(lineCounter++ + lorem_ipsum);
}
return buf.join('\n');
}
function countNewlines(haystack)
{
return count('\n', haystack);
}
function count(needle, haystack)
{
var num = 0,
len = haystack.length;
for (var i=0; i < len; i++)
{
if (haystack.charAt(i) === needle)
{
num++;
}
}
return num;
}
function tail(limit, haystack)
{
var lines = countNewlines(haystack) + 1;
if (lines > limit)
{
return haystack
.split('\n')
.slice(-limit)
.join('\n');
}
return haystack;
}
The newline handling isn't perfect (do you count all occurrences of '\n'
? What if the string starts or ends with '\n'
? etc.).
Demo: http://jsfiddle.net/mattball/3ghjm/