Strings in array are not rendered as strings in HTML
First, my HTML:
<p id="p"></p>
<input id="input" />
<button onclick="fill()">Fill</button>
Then my Javascript:
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
for (var i = 0; i < y.length; i++) {
if (i == 0) {
setTimeout(function() {
document.getElementById('p').innerHTML = y[i];
},(i * 50));
}
setTimeout(function() {
document.getElementById('p').innerHTML += y[i];
},(i * 50));
}
}
What it does is take text from the textbox, strip every character, including spaces, into an array, and then loop through the array, displaying each character at 50ms spacing. The effect should look like it is printing itself.
The effect works great, but the array values ββdon't seem to look. If I were to type "abc123" I would expect it to return, but instead I get:
undefinedundefinedundefinedundefinedundefinedundefined
Using console.log()
when I check for an array it looks ok, when I check for typeof
individual values ββof the array I get string
, but when I check typeof
for an array I get object
. Perhaps this is what destroys it ...
I tried using toString()
on y[i]
, which just spits out "[object Window]", I tried to define an array like this var y = new Array;
and then doing it split()
, nothing works. I will completely lose. Actually I would like some kind of help. Thank!
source to share
I believe the problem is with the closure. Try this js code. I wrapped everything inside the loop in IIFE functions. I think it is well explained here Please explain the use of JavaScript closures in loops
<script>
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
for (var i = 0; i < y.length; i++) {
(function(i){
if (i == 0) {
setTimeout(function() {
document.getElementById('p').innerHTML = y[i];
},(i * 50));
}
setTimeout(function() {
document.getElementById('p').innerHTML += y[i];
},(i * 50));
})(i);
}
}
</script>
source to share
By calling setTimeout, you plan for something to happen in the future. By the time the function that you delay with setTimeout
executes, the loop is completely executed, and i
now it is y.length
. So if you type test
while executing a function, it will try to add y[4]
as a letter undefined
. To fix this, you can do something like this:
function fill() {
var x = document.getElementById('input').value;
var y = x.split('');
console.log(y);
for (var i = 0; i < y.length; i++) {
timeOutAdd(y[i], i*50)
}
}
function timeOutAdd(c, delay){
setTimeout(function() {
document.getElementById('p').innerHTML += c;
}, delay);
}
<p id="p"></p>
<input id="input" />
<button onclick="fill()">Fill</button>
By adding a function timeOutAdd
that gets called immediately instead of delaying, we can hang with the parameter values ββuntil the setTimeout function is run.
Note. I also removed the second call to setTimeout, this was unnecessary and caused an error where the first character of the string was printed twice.
source to share
This solves the closure problem and also simplifies the output logic. No need to split the string into an array:
function fill() {
var x = document.getElementById('input').value,
p = document.getElementById('p');
for(var i = 0; i < x.length; i++) {
(function(i) {
setTimeout(
function() {
p.innerHTML= x.substr(0, i+1);
},
i*50
)
})(i);
}
}
<p id="p"></p>
<input id="input" value="abcde" />
<button onclick="fill()">Fill</button>
source to share