We have a JS function which is to type the Words in an Array one character at a time into selected DIV to create this cool display effect. But the JS delay function is not displaying the Words onto the screen when it is normally running, as you can see here:
so the function works completely fine regarding all aspects except for the display of the Text into the select DIV ‘type_plc’, as you can see here when we use an alert to step through the loop
So you can see the JS code works ALL OK, except it is not printing the Text into the screen, into target DIV Of ‘type_plc’ in case of the page without the Debug Alert while it is in case of the page with the Debug Alert!
Thank you all to whomever actually answers this Puzzling question!
Where on the screen is it supposed to appear? What’s the JavaScript function called? Could you provide a cut down version of the problem on Codepen or JSFiddle so that members don’t have to go digging around the page to find things?
The point is, it’s fine to use alerts if you don’t mind subjecting yourself to them. But for others they could spur them to disable JavaScript for the page
IMHO it is much better to use console.log() instead.
When you post code on the forums, you need to format it so it will display correctly. You can highlight your code, then use the </> button in the editor window, or you can place three backticks ``` (top left key on US/UK keyboards) on a line above your code, and three on a line below your code. I find this approach easier, but unfortunately some European and other keyboards don’t have that character.
I’ve had a bit of a play with it, and I’ve a feeling that it is working, but the timeout isn’t taking effect, so the entire code runs through so fast, that it never manages to display anything. If you replace your existing display_char() function as follows, then check the console, you’ll see that all of the slogans are being logged out (except the last character), they just never make it out onto the page, because the cleartype() function is getting there sooner than you need it to. I’ve a feeling you’ll need to restructure how the setTimeout() function is being applied.
function display_char(char_val) {
var current_chars = document.getElementById('type_plc').innerHTML;
console.log(current_chars);
document.getElementById('type_plc').innerHTML = current_chars + char_val;
}
That was just to show that the code is actually acquiring and updating the characters in the console. It doesn’t change the behaviour on your page.
It’s a matter of refactoring how it is used. I’ve not figured out quite where it needs applying, but it does seem that where it is currently doesn’t have the intended effect.
This line calls display_char(char_val) immediately, and passes its return value (which is undefined) to setTimeout, which again expects a function here. You want to delay the invocation of the function though; one way to do this is to pass in the function, and provide its arguments as additional parameters (check the MDN for details):
setTimeout(display_char, 1000, char_val)
Another way is to return a function that does the actual display:
function display_char(char_val) {
return function () {
document.getElementById('type_plc').innerHTML = document.getElementById('type_plc').innerHTML + char_val;
}
}
setTimeout(display_char(char_val), 1000)
But note that you’re also setting all the timeouts (almost) simultaneously in the for loop, so all characters will display after 1000ms. You’ll have to account for their index too:
var text = 'Hello WorldNews'
var display = document.getElementById('display')
var displayChar = function (char) {
display.textContent += char
}
var delayDisplay = function (char, index) {
window.setTimeout(displayChar, 1000 * index, char)
}
Array.from(text).forEach(delayDisplay)
Well after much work found out that there is a Bug in JavaScript regarding setTimeout in a Loop. It will just not work.
Now there are much write ups online as to what this Bug is and of course some explain it away as the way JS works, but whatever you want to call its setTimeout will not work as from within a JS loop. The answer is using Recursion.
After some tries we did get it working OK with Recursion as you can see in the live version here:
FYI, there are 2 recursive functions that do the Job. And actually there is a Bug regarding setTimeout and Recursion too, but with little hacking we can get around that.
[quote=“WorldNews, post:15, topic:284512, full:true”]
Well after much work found out that there is a Bug in JavaScript regarding setTimeout in a Loop. It will just not work.[/quote]
I don’t think that there is any bug. When you refer to a changing index variable inside of the setTImeout function, that function gets executed at a later time long after the loop has completed.
A good solution to that is to use a wrapper function to which you give the index as an argument, and that wrapper can then return the function that you want to use, where that index then remains available via a technique called closure.
There used to be a relatively undocumented argument that has caused problems for me. I’ve forgotten the details but IIRC it had something to do with the clock and script getting in each other’s way, (when the default was used? only when the timeout had short times?). But that was many, many years ago so I hope it’s a non-issue by now.
I gave you a working example in post #12 which should have helped with your quest as it was working properly (except that it only looped through once but that was easy to change).
I note in your example that if you go to another tab and then return to your page your routine has printed rubbish. You also spell DEVICE incorrectly in your text.
Here’s my version in a codepen which doesn’t seem to suffer from your mixed up text problem.
At a minimum, I’d run the code through jsbeautifer then JSLint which gives us the following code:
(function iife() {
"use strict";
var slogans = [
"People",
"Places",
"News Stories",
"Jobs",
"Investments",
"Travels",
"Family",
"Business Ideas",
"Projects",
"Class Notes",
"To Do Items",
"etc. etc."
];
var el = document.getElementById("type_plc");
var counter = 0;
var waitTime = 500;
var i = 0;
var intervalId;
function showText(string) {
intervalId = window.setInterval(function addChar() {
el.innerHTML += string.charAt(i);
i += 1;
if (i === string.length) {
window.clearInterval(intervalId);
waitTime = 2000;
showText(slogans[counter]);
}
if (i > string.length) {
window.clearInterval(intervalId);
el.innerHTML = "";
counter += 1;
i = 0;
waitTime = 500;
if (counter === slogans.length) {
counter = 0;
}
showText(slogans[counter]);
}
}, waitTime);
}
showText(slogans[counter]);
}());
Some of the code does need to be cleaned up, for the i=== and i> conditions do look to be a bit magical.
When reading through the code, it’s hard to understand just exactly what those sections are supposed to do, so making that more clearly understood would be of a priority.
I’ll see what I can do when I next awaken from my slumber.