1

I've got some functions all set up. One's a typing effect, one is for paragraphs, other for adding " " and one for a blinking cursor like in the terminal. All these change the innerHTML of a div.

When the page loads the function Start() has about 10 functions inside it that makes up a sequence of what should happen: Text is written, cursor starts blinking, paragraph, text written again, etc, etc.

The thing is, they all execute at the same time unless I use setTimeout() for each one inside the Start() function. And that's kind of messed up given that I have to define a start time for each one of the functions.

EDIT: No JQuery here. Just javascript. This is my whole JS file:

ctrl = 0;
y=0;
block = 0;
test = "";
first_time = 1;

function typing(id, sentence){

        var index=0;
        var intObject= setInterval(function() {
               document.getElementById(id).innerHTML+=sentence[index]; 
               index++;
               if(index==sentence.length){
                     clearInterval(intObject);
                }
            }, 100);
}


function paragraph(x){
    while(x>0){
        document.getElementById("container").innerHTML+="<br>";
        x--;
    }
}

function advance(x){
    while(x>0){
        document.getElementById("container").innerHTML+="&nbsp;";
        x--;
    }
}


function blink(y){
    if(first_time == 1){ctrl = y; first_time=0;}
    if(ctrl!=0){
        if(block=='0'){
        test = document.getElementById("container").innerHTML;
            document.getElementById("container").innerHTML+="\u258B";
            block=1;
        }
        else if(block=='1'){
            document.getElementById("container").innerHTML=test;
            block=0;
        }
        ctrl--;
        setTimeout("blink(y);", 300);
    }
    if(ctrl==0){first_time=1;}
}


function start(){
    typing('container','Subject Name:');
    setTimeout("blink('4');",1700);
    setTimeout("typing('container',' Carlos Miguel Fernando');",2800);
    setTimeout("blink('6');",5600);
    setTimeout("paragraph('1');",7200);
    setTimeout("blink('8');",7400);
    setTimeout("typing('container','Age: 21');",9500);
    setTimeout("blink('4');",10800);
    setTimeout("paragraph('1');",12800);
    setTimeout("blink('4');",13200);
    setTimeout("typing('container','Location: Povoa de Varzim, Portugal');",14500);
    setTimeout("blink('14');",19000);
    setTimeout(function(){document.getElementById("more").style.display="block";}, 23000);
    setTimeout("typing('more','Find Out More');",24000);
}
4
  • 3
    Besides the fact that it's horrible to pass strings to the timeout, the solution heavily depends on your functions. They seem to be asynchronous, so you have to work with callbacks or promises. Maybe an animation queue is what you need. If you don't mind, you can have a look at jQuery where you have all these mechanics already implemented. Commented Dec 5, 2013 at 9:39
  • 3
    The problem is more complicated than it seems. I suggest you learn about callbacks and asynchronous programming in JavaScript. Look for these terms: "higher-order functions", "promises", "continuations". That should get you started. Commented Dec 5, 2013 at 9:39
  • Just edited it and added my whole javascript file. Maybe that's somewhat useful. I'll get some info on Asynchronous functions and Callbacks guys, thanks! Commented Dec 5, 2013 at 9:45
  • stackoverflow.com/questions/899102/… and stackoverflow.com/questions/17528749/… Commented Dec 5, 2013 at 9:46

2 Answers 2

2

First you need a way to find out when a function has ended. The ideal mechanism is called a promise. There's a good implementation in jQuery. Suppose in your list of activities you wanted an artificial delay:

blink(4);
sleep(1000);   // wait 1 second
blink(4);

Implement that like this:

var sleep = function(ms) {
    var result = $.Deferred();
    setTimeout(result.resolve, ms);
    return result.promise();
};

i.e. create a $.Deferred, and return its promise(), but in between, start some activity that will complete at a later time. When it does, call resolve() (here I just get setTimeout to call it directly). You can pass a value to resolve to be the logical "return value" of your function. Also you can instead call reject which is logically like throwing an exception.

Once you have a set of building block functions that return promises you can do this:

typing('container','Subject Name:').then(function() {
   return blink('4');
}).then(function() {
   return typing('container',' Test');
}).then(function() {
   return blink('4');
}).then(function() {
   // and so on
});

UPDATE:

Click here to see a quick mock-up in jsbin.

Sign up to request clarification or add additional context in comments.

8 Comments

+1 because .. promises need more exposure. (However, it should be noted that jQuery 1.8+ should probably be used for proper then support .. or maybe that was another broken-promise issue. There is also Q and whatnot.)
NB. I believe Q and jQuery differ over what should happen if resolve is called a second time on the same promise (Q throws, jQuery ignores).
Getting an "Uncaught TypeError: Cannot call method 'then' of undefined" error with that, still it solves my problem once I get it working. Thanks!
@DanielEarwicker Interesting bit of knowledge - I've never run into the case myself (yet).
@CarlosMiguelFernando - it sounds like you need to ask new questions (or find existing ones) on SO, something like "How do I reference jQuery from my HTML/JavaScript application?"
|
0

check below code

function blink(id)
{
    //Do something
    alert(id);

    if(id == 2)
    {
        //call typing with text
        blink(4);
    }
    if(id == 4)
    {
        //call typing with text
        blink(6);
    }
    if(id == 6)
    {
        //call typing with text
        blink(8);
    }
    if(id == 8)
    {
        //Complete
    }
}

And call blink(2); it will call blink function one after another.

1 Comment

The issue is that "call typing with text" is asynchronous - it returns immediately but activity continues. If blink just calls itself immediately then all the steps will run with no delay. This will be no different to the OP's original non-working code where they just called the functions sequentially.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.