An introduction to JavaScript ============================= .. |05sols| replace:: :ref:`All solutions for this section ` As mentioned briefly in the first session, JavaScript is a programming language that can be used to tell the web browser to react to user input, and change the contents of a web page dynamically after it has loaded. jsPsych is written in JavaScript, and builds on it to make common functions easier (like showing an image, waiting for a keypress, and so on). Open a new file, and add this text: .. code:: html Test1 This looks similar to our first experiments with jsPsych. Save this in a file (as e.g. section05.html) so you can load it in your browser, the same way you did with experiment.html. When you first load it nothing will happen, as there's no code there yet! Now you can add some JavaScript where the .. code:: html // code goes here! line is. Add the line .. code:: javascript window.alert("hello"); Save the file and then reload the page in your browser. You'll see a message box with ``hello`` (or whatever message you typed). .. topic:: About this worksheet This is a very quick tour of some basic JavaScript. Teaching it all in depth would be a whole course to itself! The purpose of this worksheet is to give you an understanding of JavaScript to be better able to read jsPsych examples and documentation. You can work with these examples in a few ways. You could keep them all in the same file, though might get confusing (especially when you run them!) Alternatively, you can delete the code between the ```` tag each time and start again. Finally, if you want to keep all the examples, start a new file for every example. Variables --------- Try this instead -- change the code and reload the page in your web browser: .. code:: javascript var greeting = "good morning"; window.alert(greeting); The variable ``greeting`` stores the value that we want to show. This variable is given to ``window.alert()`` which then shows that value. In JavaScript (and most programming languages) a variable can be used to store information for later. Maths ----- Try this, as before, change the code and reload: .. code:: javascript var result = 123*456; window.alert(result); JavaScript makes a good calculator! It uses ``*`` to multiply numbers. Similarly you can use ``+``, ``-`` and ``/`` for add, subtract and divide. You can also add text: .. code:: javascript var result = "I wandered lonely "+"as a cloud"; window.alert(result); What do you think will happen if you run this code? .. code:: javascript var result = 123+"hi"; window.alert(result); Try it and see if you were right. Conditions ---------- Try this: .. code:: javascript var the_number = 15; if (the_number > 10) { window.alert("the number is greater than 10"); } Now change the ``15`` in the first line to ``5``. If you reload the page you'll see that no alert appears. Change it back to something higher than ``10``. Reload again, and this time the message appears. When you use ``if``, it looks like this: .. code:: javascript if (condition) { commands; } (this is just an illustration, no need to type it in!) This is made up of #. the word ``if``, #. in round brackets ``( )`` [#round]_, a condition i.e. something that can be examined to see if it's true or false, and #. in curly brackets ``{ }`` [#curly]_, a block of code, which is a series of JavaScript commands with ``;`` at the end of each command. .. topic:: An aside: JavaScript and the semicolon (;) You might notice that some code (even my code!) sometimes doesn't have a semicolon at the end of every command. This is because web browsers are built to be tolerant of some common errors, including missing semicolons. It's good to get into the habit of using the semicolon, though, as there are lots of other programming languages you might need in the future (just a few: Java, C++, PHP and C#) where a missing semicolon will mean that the program won't run. As you saw in the example, ``if`` decides whether to run some code or not depending on a condition. It's important to note that when comparing two values to see if they are equal, you must use two equals signs ``==``. A single equals sign ``=`` sets a variable. For example, this code: .. code:: javascript if (x == 3) { is testing if the value of the variable ``x`` is ``3``. This code: .. code:: javascript var x = 3; is creating a new variable ``x``, and using it to store the value ``3``. You can also provide alternative code to run if the condition is not true. Change your code to look like this: .. code:: javascript var the_number = 15; if (the_number > 10) { window.alert("the number is greater than 10"); } else { window.alert("the number is less than or equal to 10"); } Now change the number a few times. Each time, hit reload and see what happens. You'll see that now, you *always* get a message. If you use ``if`` with ``else``, exactly one of the two blocks of code will run. .. topic:: Code blocks vs. objects The curly brackets are often used to enclose blocks of code, when using ``if`` and in other contexts. But they are also used to write nodes in jsPsych: .. code:: javascript var my_node = { type: "image-keyboard-response", stimulus: "fluffydog.jpg" }; This is a completely different use of curly brackets! The easiest way to tell the difference is that the items in a code block will end with a ``;`` (semicolon). In a *JavaScript object* like a node, they will end with a ``,`` (comma). Loops ----- Try this: .. code:: javascript for (var i=1; i<6; i++) { window.alert("The number is "+i); } You'll see five alerts, with the numbers from 1 to 5. The code above is a loop, it runs the code in the code block several times. Taking a closer look at the code: * ``for`` tells the program to expect a loop * ``( )`` then there are round brackets, with some instructions on how to run the loop * ``var i=1`` runs once at the start of the loop -- create ``i`` and make it equal to 1 * ``i < 6`` means "keep running the loop while ``i`` is less than 6" * ``i++`` runs after the code every time round the loop. It means "add 1 to ``i``". (Similarly, ``i--`` means "subtract 1 from ``i``") * ``{ }`` then there are curly brackets with a code block Exercise ........ Can you change the loop so that it counts down from 5 to 1? |05sols| Arrays ------ An array in JavaScript is a list of items. For example, try: .. code:: javascript var vegetables = ["Carrot", "Cabbage", "Parsnip", "Potato"]; window.alert(vegetables[2]); What happened here? ``vegetables[2]`` selects an item from the array. It's not the second one though. This is because JavaScript (like many programming languages) starts counting from zero! Try changing the code to read ``vegetables[0]`` reload -- does this do what you expect? .. _for-of: Looping through an array ........................ What if we want to use a loop to go through these items, running some code for each item? One way is this: .. code:: javascript var vegetables = ["Carrot", "Cabbage", "Parsnip", "Potato"]; for (var veg of vegetables) { window.alert("I'm eating a "+veg); } This is a different kind of ``for`` loop, where we run the code for each item in a list. In older code you may also see this method: .. code:: javascript var vegetables = ["Carrot", "Cabbage", "Parsnip", "Potato"]; for (var i=0; i`). |05sols| Functions --------- One of the most fundamental building blocks in JavaScript is the function. A function is a block of code that is stored to be used later. Once you have stored some code, you can run it as many times as you like. Try this: .. code:: javascript function greeting() { window.alert("hello!"); } This code *defines* a function, in other words, it stores the code for later use, but doesn't run it. Now after that, add: .. code:: javascript greeting(); This *calls* the function. That means it runs the code that was stored earlier. Think of a function like a recipe for a cake. Defining the function is like writing the recipe. Calling the function is like baking the cake! You can write a recipe once, and then follow it many times. In the same way, in JavaScript you define a function once, but call it many times. Add a few more calls to your function: .. code:: javascript greeting(); greeting(); greeting(); The action in the function is repeated as many times as the function is called. Now change your function to look like this: .. code:: javascript function greeting(person) { window.alert("hello "+person+"!"); } Now the function takes a *parameter*, a piece of information that you pass to it. Change the calls to the function to give it this information: .. code:: javascript greeting('Hendrick'); greeting('Arran'); greeting('Priyangi'); A function that takes multiple parameters separates them with commas: .. code:: javascript function example_function(a,b,c) { Exercise ........ Given a list of names: .. code:: javascript var names = ['Hendrick', 'Arran', 'Kalvyn', 'Priyangi', 'Ted']; how would you call the ``greeting()`` function for each item in the list? |05sols| Return value ............ Functions can also return a value. Try this: .. code:: javascript function square(x) { return x*x; } window.alert(square(3)); window.alert(square(5)); Here the word *return* means "give this value back to where the function is called". .. _functions: Use of functions in jsPsych --------------------------- Let's look at an example we've already seen. .. code:: javascript var jsPsych = initJsPsych({ on_finish: function() { jsPsych.data.displayData(); } }); Here the ``on_finish`` field specifies an action to occur when the experiment ends. Why does this say: .. code:: javascript on_finish: function() { jsPsych.data.displayData(); } and not just this: .. code:: javascript on_finish: jsPsych.data.displayData(); The answer is that putting the call inside a function delays its action. If the code was written without ``function() { .... }``, it would run before ``initJsPsych`` ran. Written inside a function, it runs when ``on_finish`` is *used*, at the end of the experiment. If this seems confusing, don't worry -- just remember that the form above (using ``function() { .... }``) is used to delay the action of some code. .. topic:: Different ways of defining functions The examples in this section are just for illustration, so don't type them in! A function in JavaScript can be defined like this: .. code:: javascript function myfunc(x,y) { return "The input was "+x+" and "+2*y; } and called like this: .. code:: javascript var result = myfunc(4,10); or this: .. code:: javascript console.log(myfunc(4,10)); In this case the function has a name. If we want to define a function and immediately use it, we can define it like this: .. code:: javascript function(x, y) { return "The input was "+x+" and "+2*y; } You may also see another way to define functions: .. code:: (x, y) => "The input was "+x+" and "+2*y; A function without a name, like the two immediately above, is called an *anonymous function*. Code formatting in JavaScript ----------------------------- For the most part, how your code looks in JavaScript is up to you. This is mainly down to where to put spaces and line breaks! Getting this right will help you to understand the code if you ever have to come back to it. It's also important if others will need to read it. For example, let's look at the start of the table of values (to use with timeline variables) that we saw in the last section: ======== ======== image duration ======== ======== Dog2.jpg 400 Dog1.jpg 1200 Dog1.jpg 800 Dog3.jpg 800 ======== ======== In JavaScript we could represent this as: .. code:: javascript var timeline_values = [{image:"Dog2.jpg",duration:400},{image:"Dog1.jpg",duration:1200},{image:"Dog1.jpg",duration:800},{image:"Dog3.jpg",duration:800}]; Hopefully it's obvious that this is a bad idea, the line is far too long! JavaScript is happy to break lines anywhere, as long as it isn't in the middle of a variable name or string (even then, a backslash \\ will let you do this, as you may have seen). To start with, let's give each of the items in the array a line to itself: .. code:: javascript var timeline_values = [ {image:"Dog2.jpg",duration:400}, {image:"Dog1.jpg",duration:1200}, {image:"Dog1.jpg",duration:800}, {image:"Dog3.jpg",duration:800}]; The last square bracket would be easy to miss when reading the code, though! Putting it on the next line makes it easier to spot: .. code:: javascript var timeline_values = [ {image:"Dog2.jpg",duration:400}, {image:"Dog1.jpg",duration:1200}, {image:"Dog1.jpg",duration:800}, {image:"Dog3.jpg",duration:800} ]; We can also insert some spaces, to make the code even more readable: .. code:: javascript var timeline_values = [ { image: "Dog2.jpg", duration: 400 }, { image: "Dog1.jpg", duration: 1200 }, { image: "Dog1.jpg", duration: 800 }, { image: "Dog3.jpg", duration: 800 } ]; You can imagine that if there were more values in each of these objects, we might need to add more line breaks. It's not really necessary in this case, but if we wanted to do it, it would look something like: .. code:: javascript var timeline_values = [ { image: "Dog2.jpg", duration: 400 }, { image: "Dog1.jpg", duration: 1200 }, { image: "Dog1.jpg", duration: 800 }, { image: "Dog3.jpg", duration: 800 } ]; Note that I'm using indentation to show each level of brackets. This makes the structure of the code much clearer. This is one suggestion for how to format code, but any way is fine as long as it's consistent and the code is easy to read. .. rubric:: Footnotes .. [#round] .... also called "parentheses". .. [#curly] .... also called "braces".