JavaScript is not displaying with time delay but

Hi,

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:

http://www.notefab.com/index_test.php

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

http://www.notefab.com/index_test_wp.php

What do we need to do to fix this problem?

Just in case the JS code in question is at the bottom of the page, right above </body>

Thanks.

I don’t know. I closed browser after 8 or so alerts…

4 Likes

1st, that is NOT an answer, I dont know why post it!

So again, you can see the page without the Debug Alerts here:

http://www.notefab.com/index_test.php

And you can see it with the Debug Alerts here:

http://www.notefab.com/index_test_wp.php

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?

Chris,

Here is the JS Code:

<script>

var slogans = ['people', 'places', 'news', 'jobs', 'investments', 'travels', 'family', 'business ideas', 'home projects', 'etc.'];
var myVar;
var char_val = [];
var char_array = [];
var name = '';


for (i = 0; i < slogans.length; i++) { 

    name = slogans[i];

	// alert('name: ' + name);

	char_array = name.split('');

	for (j = 0; j < char_array.length; j++) { 

		char_val = char_array[j];

		// alert('char_val: ' + char_val);

		// setTimeout(function(){ display_char(char_val) }, 1000);

		setTimeout(display_char(char_val), 1000);
	}

	// etTimeout(function(){ clear_type() }, 3000);

	setTimeout(clear_type(), 3000);
}


function display_char(char_val) {

	document.getElementById('type_plc').innerHTML = document.getElementById('type_plc').innerHTML + char_val;
}

function clear_type () {

	document.getElementById('type_plc').innerHTML = '';
}


</script>

So the Text is to be written into DIV 'type_plc" by the above JS Code.
But it is not!

Thanks.

What the HEK! SP, does not display the JS Code inside script tags.
So here is wo the script tags:

var slogans = ['people', 'places', 'news', 'jobs', 'investments', 'travels', 'family', 'business ideas', 'home projects', 'etc.'];
var myVar;
var char_val = [];
var char_array = [];
var name = '';


for (i = 0; i < slogans.length; i++) { 
  
  name = slogans[i];
  
  // alert('name: ' + name);
  
  char_array = name.split('');
  
  for (j = 0; j < char_array.length; j++) { 
    
    char_val = char_array[j];
    
    // alert('char_val: ' + char_val);
    
    // setTimeout(function(){ display_char(char_val) }, 1000);
    
    setTimeout(display_char(char_val), 1000);
  }
  
  // etTimeout(function(){ clear_type() }, 3000);
  
  setTimeout(clear_type(), 3000);
}

function display_char(char_val) {
  document.getElementById('type_plc').innerHTML = document.getElementById('type_plc').innerHTML + char_val;
}

function clear_type () {
  document.getElementById('type_plc').innerHTML = '';
}

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.

3 Likes

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.

2 Likes

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;
}
1 Like

Chris,

I added your Code suggestion, but again NOTHING.
As you can see in the test page, here:

http://www.notefab.com/index_test.php

And how in can I "restructure how the setTimeout() function "
since that is a JS function?

Thanks

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.

Are you printing one letter at a time and then when the word is complete erasing that word and typing another word?

If so this should do the job (but not sure if this is 100% correct):

(function() {
    var slogans = ['people', 'places', 'news', 'jobs', 'investments', 'travels', 'family', 'business ideas', 'home projects', 'etc.'];
    var el = document.getElementById('type_plc');
    var counter = 0;

    function showText(string) {
        var i = 0;
        intervalId = window.setInterval(function() {
            el.innerHTML += string.charAt(i++);
            if (i > string.length) {
                window.clearInterval(intervalId);
                el.innerHTML = "";
                counter++;
                showText(slogans[counter]);
            }
        }, 2000);
    }
    showText(slogans[counter]);
})();

However, I think you may be after some other effect.

1 Like

That was how I’d interpreted it.

1 Like

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)

x-post :-)

1 Like

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.

1 Like

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.

I’m sure @Paul_Wilkins or @m3g4p0p could shorten and tidy it up loads.:slight_smile:

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.

1 Like

Thanks Paul :slight_smile: