Running javascript functions in sequence

How can I run javascript functions in sequence instead of at the same time?
LVL 1
ncwAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

garrethgCommented:
Don't understand the question, that's how processors and programs work - they process sequencially:

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
<!--

//-- defining some functions
function myFun1() {
  alert("called 1st function")
}
function myFun2() {
  alert("called 2nd function")
}
function myFun3() {
  alert("called 3rd function")
}

//-- calling some functions
myFun1();
myFun2();
myFun3();

//-->
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>

I think you need to rephrase and provide an example of what you want to achieve prehaps?
0
ncwAuthor Commented:
Yes the question was probably a bit vague. The code I am using is below. The function Slide moves two images diagonally on the 'on open' event. I did have the function split into two, because I wanted one image to slide followed by the other, but the result was that both images moved at once.

Can the script be changed so that the images move sequentially?

Nick

<HTML>
<HEAD>

<SCRIPT LANGUAGE="JavaScript">

ns4 = (document.layers)? true:false
ie4 = (document.all)? true:false


function slide() {
      if (ns4) ball1 = document.ball1div
      if (ie4) ball1 = ball1div.style
      ball1.xpos = parseInt(ball1.left)
      ball1.ypos = parseInt(ball1.top)

      if (ball1.xpos < 210) {
            ball1.xpos += 5
            ball1.ypos += 3
            ball1.left =ball1.xpos
            ball1.top = ball1.ypos
            setTimeout("slide()",30)
      }

      if (ns4) ball2 = document.ball2div
      if (ie4) ball2 = ball2div.style
      ball2.xpos = parseInt(ball2.left)
      ball2.ypos = parseInt(ball2.top)

      if (ball2.xpos < 210) {
            ball2.xpos += 5
            ball2.ypos += 5
            ball2.left =ball2.xpos
            ball2.top = ball2.ypos
            setTimeout("slide()",30)
      }
}

//-->
</SCRIPT>

</HEAD>
<BODY BGCOLOR=white TEXT=#333399 LINK="#333399" ALINK=blue VLINK=purple onLoad="slide();banner()">
<BASEFONT=3>

<DIV ID="ball1div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="ball-glass-blue.gif" BORDER="NONE"></A>
</DIV>

<DIV ID="ball2div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="ball-glass-yellow.gif" BORDER="NONE"></A>
</DIV>

</BODY>
</HTML>
0
HardawayCommented:
I have got one suggestion, see whether it works out what you wanted.

Since the slide function will make both ball one and ball two move, ball two will move immediately after ball one moved. Therefore, one possilbe way to do it is to add a delay function immediately after ball one's movement. Accroding program structure, the delay should not be larger than 30. It was because your time out time is 30.

To make it better, seperate ball one and ball two movement into two functions. Add a main function to call ball one move, then call the delay function, finally call ball two to move.
0
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

garrethgCommented:
This may be a quick fix for what you want to achieve:

<HTML>
<HEAD>

<SCRIPT LANGUAGE="JavaScript">

ns4 = (document.layers)? true:false
ie4 = (document.all)? true:false

function slide(me) {
  if (ns4) {
    ball= document.layers[me];
  }
  if (ie4) {
    ball= document.all[me].style;
  }
  if (parseInt(ball.left) < 210) {
    if (ns4) {
      ball.left+= 5;
      ball.top+=  3;
    }
    else if (ie4) {
      ball.pixelLeft+= 5;
      ball.pixelTop+= 3;
    }
    setTimeout("slide('"+me+"')",30);
  }
  else if (me != "ball2div") {
    slide("ball2div");
  }
}

//-->
</SCRIPT>

</HEAD>
<BODY BGCOLOR=white TEXT=#333399 LINK="#333399" ALINK=blue VLINK=purple onLoad="slide('ball1div')">
<BASEFONT=3>

<DIV ID="ball1div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="1.gif" BORDER="NONE"></A>
</DIV>

<DIV ID="ball2div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="2.gif" BORDER="NONE"></A>
</DIV>

</BODY>
</HTML>
0
banjonesCommented:
Err, I am not sure if I am missing something here, but if you want one function to run after another could you not simply call the second function at the end of the first?
<script>
  function doStuff () {
     if (stuff) {
         // Move things here
     }
     doMoreStuff();
  }

  function doMoreStuff () {
     if (moreStuff) {
         // Move more things here
     }
  }
</script>
<body onLoad="doStuff()">
0
garrethgCommented:
Yes, you're missing the fact the functions are called on a timeout :-)
0
ncwAuthor Commented:
banjones :
I've tried that and both images move at the same time, so as Hardaway suggests I think I need a time delay.

Hardaway:
I have setup the functions as you suggest (I originally had them separate). Can you give me some guidance on the time delay in the following function.

function slideBalls() {
slideBall1()
slideBall2()
slideBall2()
slideBall2()
}

garrethg:
Your code worked well for two images, but I had an error when I added a third: "Stack overflow at line 28". The amended code is as follows:

<HTML>
<HEAD>

<SCRIPT LANGUAGE="JavaScript">

        ns4 = (document.layers)? true:false
        ie4 = (document.all)? true:false

        function slide(me) {
        if (ns4) {
        ball= document.layers[me];
        }
        if (ie4) {
        ball= document.all[me].style;
        }
        if (parseInt(ball.left) < 210) {
        if (ns4) {
        ball.left+= 5;
        ball.top+=  3;
        }
        else if (ie4) {
        ball.pixelLeft+= 5;
        ball.pixelTop+= 3;
        }
        setTimeout("slide('"+me+"')",30);
        }
        else if (me != "ball2div") {
        slide("ball2div");
        }
      else if (me != "ball3div") {
      slide("ball3div");
      }
}

//-->
</SCRIPT>

</HEAD>
<BODY BGCOLOR=white TEXT=#333399 LINK="#333399" ALINK=blue
VLINK=purple onLoad="slide('ball1div')">
<BASEFONT=3>

<DIV ID="ball1div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball1.gif" BORDER="NONE"></A>
</DIV>

<DIV ID="ball2div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="ball2.gif" BORDER="NONE"></A>
</DIV>

<DIV ID="ball3div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball3.gif" BORDER="NONE"></A>
</DIV>

</BODY>
</HTML>

0
garrethgCommented:
You didn't reorganise the test conditions so the control flows ends at some point.

Need to use:

else if (me != "ball2div" && me != "ball3div") {
slide("ball2div");
}
else if (me != "ball3div") {
slide("ball3div");
}

Should really be using some sort of array mechanisim at this point though.
0
ncwAuthor Commented:
Hardaway:
I have tried calling sub functions from a main function as you suggest. Can you give me some guidance on how to apply the time delay in the following main function.

function slideBalls() {
slideBall1()
slideBall2()
slideBall2()
slideBall2()
}


garrethg:
As you can probably tell I'm a bit of a novice at javascript. I simply pasted in your extra script, but it gave a error.Can you tell me where I've gone wrong.

ns4 = (document.layers)? true:false
ie4 = (document.all)? true:false

        function slide(me) {
        if (ns4) {
        ball= document.layers[me];
        }
        if (ie4) {
        ball= document.all[me].style;
        }
        if (parseInt(ball.left) < 210) {
        if (ns4) {
        ball.left+= 5;
        ball.top+=  3;
        }
        else if (ie4) {
        ball.pixelLeft+= 5;
        ball.pixelTop+= 3;
        }
        setTimeout("slide('"+me+"')",30);
        }
      else if (me != "ball2div" && me != "ball3div") {
        slide("ball2div");
        }
        else if (me != "ball3div") {
        slide("ball3div");
        }

}
0
garrethgCommented:
I cut & pasted the above but it works fine, you may have missed something in your HTML prehaps? Not sure, what is the error message you get? If you open it in Netscape Navigator and type javascript: into the location bar it will bring up the JavaScript console which returns much more useful error messages than IE.
0
ncwAuthor Commented:
garrethg :

That's a useful tip about the JavaScript console.

I fixed one error which was siply that I had miss spelt the function in the onload event, but it still returns this error:

"line 42: ball has no properties."

Line 42 is:  if (parseInt(ball.left) < 210) {

The script references ball2div and ball3div but how is it referencing ball1div?

Nick
0
ncwAuthor Commented:
Hardaway:

I have tried calling sub functions from a main function as you
suggest. Can you give me some guidance on how to apply the time delay in the main function.

Nick
0
banjonesCommented:
If you want to apply a time delay just use the setTimeout() function, eg:

function mainFunction () {
  setTimeout("subFunction1()",30);
  setTimeout("subFunction2()",30);
}
0
garrethgCommented:
Sorry if you have being waiting, I've been on a short holiday.
Sounds like the the value of the argument 'me' being passed to slide() did not match the ID attribute of the layer. Here's a slightly modified version which is a bit easier to use. Sorry to clutter the thread but I'm pasting all the code so there will be no confusion.

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript1.2">
ns4 = (document.layers)? true:false
ie4 = (document.all)? true:false

totalBalls= 5;/* the total number of layers to be moved (and not a bad joke) */
currentBall= 1;/* the layer currently flagged to move */

function slide(me) {
  if (ns4) {
    ball= document.layers[me];
  }
  if (ie4) {
    ball= document.all[me].style;
  }
  if (parseInt(ball.left) < 210) {
    if (ns4) {
      ball.left+= 5;
      ball.top+=  3;
    }
    else if (ie4) {
      ball.pixelLeft+= 5;
      ball.pixelTop+= 3;
    }
    setTimeout("slide('"+me+"')",30);
  }
  else if (currentBall < totalBalls) {
    currentBall++
    slide("ball"+currentBall+"div");
  }
}
</SCRIPT>
</HEAD>
<BODY BGCOLOR=white TEXT=#333399 LINK="#333399" ALINK=blue VLINK=purple onLoad="if(document.layers||document.all){slide('ball'+currentBall+'div')}">
<BASEFONT SIZE=3>
<DIV ID="ball1div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball1.gif" BORDER="NONE"></A>
</DIV>
<DIV ID="ball2div" STYLE="position:absolute; left:100; top:190; width:30">
<A HREF="database/home.htm"><IMG SRC="ball2.gif" BORDER="NONE"></A>
</DIV>
<DIV ID="ball3div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball3.gif" BORDER="NONE"></A>
</DIV>
<DIV ID="ball4div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball4.gif" BORDER="NONE"></A>
</DIV>
<DIV ID="ball5div" STYLE="position:absolute; left:100; top:190;width:30">
<A HREF="database/home.htm"><IMG SRC="ball5.gif" BORDER="NONE"></A>
</DIV>
</BODY>
</HTML>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ncwAuthor Commented:
banjones:

I tried what you suggested before and the images still move simultaneously.

garrethg:

Yes that works well. Hardaway has not been in contact so I think its time you took the points. I would have liked to have solved the problem regarding running functions sequentially - do you have any comments?

thanks,

Nick
0
garrethgCommented:
"I would have liked to have solved the problem regarding running functions sequentially"
Are there problems or a part you wish explained?
If there are still problems I'm more than happy to address them. The function is called sequentially. That is, when the function is through being called for ball1div it is called for ball2div and so on.
If you want to use timeouts for a similar ordering of the animation you'd have to know exactly how long it's going to take for a ball to get from A to B. Given it takes a certain amount of system dependent time to execute the function (negligible really) and a certain amount of system dependent time to redraw the layer's position (not at all negligible), timeout is the least attractive way to achieve this. The chances of recursion problems are also high.
0
ncwAuthor Commented:
garrethg:

Can the second function be called after the first ball has reach a position, eg when ball.left = 210?

Nick
0
garrethgCommented:
Well there is only one function...

The else if statement below executes if parseInt(ball.left) >= 210 as the prior condition is (parseInt(ball.left) < 210)

  else if (currentBall < totalBalls) {
    currentBall++
    slide("ball"+currentBall+"div");
  }

As I think parseInt(ball.left) does equal 210 at some point this is the same as:

if (parseInt(ball.left) != 210) {
//-- code to call when ball.left
}
else if (conditon) {
//some code to call when parseInt(ball.left)==210
}

And while I'm pretty sure that will give the same results as the code in my previous comment it's not particularly safe control flow.

All the above means that the next ball in the sequence is called when the previous ball's left position equals 210.
0
ncwAuthor Commented:
garrethg,

Sorry, what I meant was if I have a number of functions, as in your very first comment, which if called each move a ball (gif) and then a main function calls each of the above functions in turn, can the second function be called by the first function only when eg the first ball has reached a position of ball.left = 210?

What I'm to establish is can you have any control over the timing of when subsequent sequential functions are called, ie on an event not a timeout (nor click of a button).

Nick
0
garrethgCommented:
If you want to split it into several functions it would be a senario like you original code above. The only real problem with that was the logic of your control flow. So if you take that, and look at the control flow I provided, you can easly split it in to several functions. All you do is call the next function in the chain when the test condition is passed (or failed depending on the logic).

e.g.

if (parseInt(ball.left) < 210) {
//-- move to the next function
    myNextFunction();
}
else {
//-- call this function again
  setTimeout("thisFunction()",50)
}
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
HTML

From novice to tech pro — start learning today.