Making Decisions

We need one last way to control the way our code executes: we need to be able to make decisions based on something the user enters (or some value we calculate, or the time of day, or …).

As an example, let's imagine we want to present the user with a choice of which direction to move a shape in a SVG image:

<select id="direction">
<option value="up">Up</option>
<option value="down">Down</option>
</select>
<button id="move">Move</button>

We will need to do something different depending on the user's selection: either up (probably a smaller y value) or down (a larger y).

The if Statement

We can use the if statement in JavaScript to make decisions about what code to run, depending on the situation we're in. The basic decision we make with the if is “should this block of code run or not?”

Suppose we have a value count that is something the user entered (in a <input />). We want to decide if they have entered a number too large for what we're doing. The code will be something like this:

if (count > 100) {
  $('#error').html('That is too many.')
}

Here are the part of the if statement's structure:

if ( … ) { … }
This is the basic structure of the if statement. The ( … ) controls the behaviour, and the { … } is the conditional code.
( … )
This is the condition of the if. It is an expression that evaluates to either true or false.
{ … }
This is the body of the if. This code runs only when the condition evaluated to true.

Conditionals

The condition can be any expression that results in a true or false result. There are several ways to get a true/false, but we will only worry about comparisons. Here are the comparison operators that we can use:

ComparisonMeaningExample is…
23 == 3is equal tofalse
23 != 3is not equal totrue
4 < 9less thantrue
4 > 9greater thanfalse
8 <= 6less than or equalfalse
8 >= 6greater than or equaltrue
JavaScript comparison operators

As you can see, the example above used a greater-than comparison: the code in the { … } will only run if the variable count was holding a value greater than 100.

The same conditional expressions were used in the for loop to express when the loop should continue. In this example, we keep going as long as the condition n <= 6 is true:

for (n = 1; n <= 6; n += 1) {

As this loop ran, the condition would have evaluated to true for n as 1, 2, 3, 4, 5, 6, but false for 7: that is where the loop stopped.

Example

We can now return to the example with the <select> above. In this case, we know that $('#direction')​.val() will get us the string 'up' or 'down'.

We can use that string, and a comparison, to set a variable appropriately to what we want to do:

move = function() {
  dir = $('#direction').val()
  if ( dir == 'up' ) {
    trans = 't0,-20'
  }
  if ( dir == 'down' ) {
    trans = 't0,20'
  }
  
  attr = {
    'transform': trans
  }
  shape.animate(attr, 500)
}

The two if statements here check that the selected direction is 'up' and 'down', respectively. Because of the way the <select> is written, we know that one of them will run its body. In the if body, the code sets the trans variable so it can be used below.

You can try this example. When playing with it, you may notice that clicking “Move” multiple times doesn't move the circle more up or down. We can fix that and clean up our code a little more in the next topic…

Adding else

The above code was a little clumsy. We did this:

if ( dir == 'up' ) { … }
if ( dir == 'down' ) { … }

The hope was that dir would be one of 'up' or 'down'. But in that case, there wasn't any point to the second condition: if it wasn't 'up', it must have been 'down'.

We could also run into problems with this code if we added a third option to the <select>: we could fall through all of the ifs without ever setting the variable trans. That would have broken the rest of the code.

What we need is a way to express “do this if the condition is true, but that if it isn't”. The else which can be added to an if lets us do exactly that: code that will run if the condition is false.

if ( dir == 'up' ) {
  …
} else {
  …
}

The code in the second { … } will run if dir is anything besides 'up'

Example

We can return to our example to clean up the code with an else and fix the behaviour to be nicer.

The problem with the behaviour was that the Raphaël 'transform' is relative to the shape's original position, not where it is now. So, if we animate up multiple times, we ask to animate from (0,-20) to (0,-20), which has no effect.

We can instead keep track of the y value where we would like the circle to be, and adjust that accordingly. The variable y here keeps track of the desired vertical position. We change it as the user asks and animate to the new position:

y = 0
move = function() {
  dir = $('#direction').val()
  if ( dir == 'up' ) {
    y = y - 20
  } else {
    y = y + 20
  }
  
  attr = {
	'transform': 't0,' + y
  }
  shape.animate(attr, 500)
}

You can try the fixed example with this behaviour.

Another Example

In this example, our goal is to imitate the behaviour of the jQuery .toggle() function which alternately makes content appear and disappear. We will create a button: the first time it's clicked, any content with class="optional" should disappear; when it's clicked again, it should reappear.

In order to do this, we need to keep track of the current status: is the content visible or not? We will need a variable for that, and we will need to maintain its value so we know what to do next time.

visible = 'yes'
toggle = function() {
  if ( visible == 'yes' ) {
    $('.optional').css({'display': 'none'})
    visible = 'no'
  } else {
    $('.optional').css({'display': 'block'})
    visible = 'yes'
  }
}

Each path through the if/else here does two things: set the CSS display property, and set the visible variable so we know the current state of the page. This variable is used to make sure we do the opposite action next time.

As always, you can see this example working.