rubergly
rubergly

Reputation: 898

Update DOM Elements Immediately in Javascript

For a simple project, I'm trying to display log output in a textarea. I have a log function, and would like the textarea to always be updated immediately whenever log is called. Unfortunately, it seems to only do the update once, and push everything at the same time (I'm using JQuery to set the value of the textarea, if that possibly matters). Here's a basic example:

for (i = 0; i <= 100; i++) {
    $("textarea").html($("textarea").html() + "test" + i + "\n");
    $("textarea").scrollTop(9999999)
};

This spits out all the text into the textarea at once (note: you can see the results of these examples at this jsfiddle). This basic example is easily remedied by creating a timeout and using recursive function calls:

f = function(i) {
    if (i <= 100) {
        $("textarea").html($("textarea").html() + "test" + i + "\n");
        $("textarea").scrollTop(999999);
        setTimeout(function() { f(i+1); }, 0);
    }
};

f(1);

This version spits out the text into the textarea one line at a time, which is what I want. But using timeouts and callbacks in this manner does not seem practical in the setting of logging; every time I call log, I would have to provide a callback for all the functionality that I want to ever follow the log call.

Is there any way to achieve the desired effect without callbacks?

Upvotes: 1

Views: 5491

Answers (2)

Boris Zbarsky
Boris Zbarsky

Reputation: 35064

Browsers generally (Opera is an exception) do JS execution and rendering on the same thread, so while your JS is running there will be no rendering done by th browser, unless you explicitly yield control via a timeout or interval timer.

Upvotes: 0

dwarfy
dwarfy

Reputation: 3076

I think you might consider using :

$("textarea").val(function(index, value) {
   return value + "test" + i + "\n"
});

instead of :

$("textarea").html($("textarea").html() + "test" + i + "\n");

or in general :

$("textarea").val(NEWVAL)

Also noted in the comments of your question, if you want to be able to notice "by eye" all the messages that arrives you'll have to save them in a buffer and have something like (not tested) :

var buffer = []

function log(text) { buffer.push(text) }

setInterval(function(){
  if (len(buffer)>0) {
    $("textarea").val(function(index, value) {
      return value + "\n" + buffer.shift()
    });
  }
},500)

Upvotes: 1

Related Questions