James Mclaughlin
James Mclaughlin

Reputation: 702

How to properly clear and update a textarea element?

I'm having difficulties clearing and then 'redrawing' a textarea element. I have a HTML doc setup like this:

The problem seems to be occurring in the updateLog function. The numbers 0-4 are printed as they should be, but once '5' is added and the array is shifted, the textarea doesn't seem to change anymore (it should display "12345" then "23456" etc.). I have so far tested and found that the function is being called every second, the array is being properly shifted and that the textarea's value is cleared before the for loop which 'draws' to the textarea. I'm completely stumped here.

var logWidth = 60
var logHeight = 5
document.getElementById('log').setAttribute("rows", logHeight)
document.getElementById('log').setAttribute("cols", logWidth)


var canLogPrint = true
var txt = document.getElementById('log')
var x = 0
var logContents = []

setInterval(function() {
  if (canLogPrint) {
    updateLog(x.toString())
    x += 1
  }
}, 1000)

function updateLog(message) {
  logContents.push(message)
  if (logContents.length > logHeight) {
    logContents.shift()
  }
  txt.value = ''
  for (s in logContents) {
    txt.value += s + '\n'
  }
}

function pauseLog() {
  canLogPrint = !canLogPrint
}
#log {
  /*resize: none;*/
  overflow: hidden;
  margin-bottom: 5px;
}
<textarea id='log' rows=25 cols=60 autofocus readonly></textarea>
<br>
<button onclick="pauseLog()">PAUSE</button>

Upvotes: 1

Views: 79

Answers (3)

Gunther
Gunther

Reputation: 1328

The problem is that you're using for in loop, wich iterates in the object properties, in that case it is a list, so the object is like {0:'3', 1: '4', 2:'5' ... } and you're always printing the key instead of the value.

To fix that you can just use logContents[s] in your for in loop, or use for of loop.

Here's your code working.

var logWidth = 60
var logHeight = 5
document.getElementById('log').setAttribute("rows", logHeight)
document.getElementById('log').setAttribute("cols", logWidth)


var canLogPrint = true
var txt = document.getElementById('log')
var x = 0
var logContents = []

setInterval(function() {
  if (canLogPrint) {
    updateLog(x.toString())
    x += 1
  }
}, 1000)

function updateLog(message) {
  logContents.push(message)
  if (logContents.length > logHeight) {
    logContents.shift()
  }
  txt.value = ''
  for (s of logContents) {
    txt.value += s + '\n'
  }
}

function pauseLog() {
  canLogPrint = !canLogPrint
}
#log {
  /*resize: none;*/
  overflow: hidden;
  margin-bottom: 5px;
}
<textarea id='log' rows=25 cols=60 autofocus readonly></textarea>
<br>
<button onclick="pauseLog()">PAUSE</button>

Upvotes: 1

Aalexander
Aalexander

Reputation: 5004

The problem is with your for .. in. for .. in is used to iterate the keys of an object. As arrays are also Objects it will iterate the keys what means

   key value
    0    5
    1    6
    2    7
    3    8
    4    9

Now when the values changes the keys will be the same, that is the reason why your output still will be 0 1 2 3 4.

You can use forEach here as in the example below.

<html>
    <head>
        <style>
            #log {
                /*resize: none;*/
                overflow: hidden;
                margin-bottom: 5px;
            }
        </style>

    </head>
    <body>
        <textarea id='log' rows=25 cols=60 autofocus readonly></textarea>
        <br>
        <button onclick="pauseLog()">PAUSE</button>
        <script>
            var logWidth = 60
            var logHeight = 5
            document.getElementById('log').setAttribute("rows", logHeight)
            document.getElementById('log').setAttribute("cols", logWidth)


            var canLogPrint = true
            var txt = document.getElementById('log')
            var x = 0
            var logContents = []

            setInterval(function(){
                if (canLogPrint) {
                    updateLog(x.toString())
                    x += 1
                }
            },1000)

            function updateLog(message) {
                logContents.push(message)
                if (logContents.length > logHeight) {
                       logContents.shift();
                }
                txt.value = ''
                logContents.forEach((x) => {
                    txt.value += x + '\n'
                })
                    
                
            }

            function pauseLog() {
                canLogPrint = !canLogPrint
            }
        </script>
    </body>
</html>

Upvotes: 0

Harry Tom
Harry Tom

Reputation: 424

var logWidth = 60
var logHeight = 5
document.getElementById('log').setAttribute("rows", logHeight)
document.getElementById('log').setAttribute("cols", logWidth)


var canLogPrint = true
var txt = document.getElementById('log')
var x = 0
var logContents = []

setInterval(function() {
  if (canLogPrint) {
    updateLog(x.toString())
    x += 1
  }

}, 1000)

function updateLog(message) {
  logContents.push(message)
  if (logContents.length > logHeight) {
    logContents.shift();
    txt.value = logContents.join('\n');
  }
  txt.value = ''
    txt.value = logContents.join('\n');
}

function pauseLog() {
  canLogPrint = !canLogPrint
}
#log {
  /*resize: none;*/
  overflow: hidden;
  margin-bottom: 5px;
}
<textarea id='log' rows=25 cols=60 autofocus readonly></textarea>
<br>
<button onclick="pauseLog()">PAUSE</button>

Upvotes: 0

Related Questions