User-defined Functions


Functions: A Summary

Here are some important things about functions. These were lifted from one of the great books of the Head First Series, Head First JavaScript Programming.

  • Declare a function using the function keyword, followed by the name of the function.
  • Use parentheses to enclose any parameters a function has. Use empty parentheses if there are no parameters.
  • Enclose the body of the function in curly braces.
  • The statements in the body of a function are executed when you call a function.
  • Calling a function and invoking a function are the same thing.
  • You call a function by using its name and passing arguments to the function’s parameters (if any).
  • A function can optionally return a value using the return statement.
  • A function creates a local scope for parameters and any local variables the function uses.
  • Variables are either in the global scope (visible everywhere in your program) or in the local scope (visible only in the function where they are declared).
  • Declare local variables at the top of the body of your function.
  • If you forget to declare a local variable using var, that variable will be global, which could have unintended consequences in your program.
  • Functions are a good way to organize your code and create reusable chunks of code.
  • You can customize the code in a function by passing in arguments to parameters (and using different arguments to get different results).
  • Functions are also a good way to reduce or eliminate duplicate code.
  • You can use JavaScript’s many built-in functions, like alert, prompt, and Math.random, to do work in your programs.
  • Using built-in functions means using existing code you don’t have to write yourself.
  • It’s a good idea to organize your code so your functions are together, and your global variables are together, at the top of your JavaScript file.

Understand and Modify

In the following there is an example of a webpage that use Javascript functions. Your task is to understand what the code does and then perform certain modifications that will allow you to reuse the code in different situations.

Pronouncing English Words

The first example uses a Javascript function to add an audio element on the fly to a page. Press each button to hear the sound. Then look at the source of the page. The relevant part is this:

<div id="words">
  <p><span>apple</span><img src="icons/play.png" alt="sound icon"><audio></audio></p>
  <p><span>pomegranate</span><img src="icons/play.png" alt="sound icon"><audio></audio></p>
  <p><span>watermelon</span><img src="icons/play.png" alt="sound icon"><audio></audio></p>
  <p><span>cucumber</span><img src="icons/play.png" alt="sound icon"><audio></audio></p>
</div>    

As you can notice, the audio tag is empty, and the sound is added by the Javascript code whenever the sound icon image that serves as a button is clicked.

Here is the JavaScript code that automatically adds the event handler playSound to every img element. This is very similar to what we did in the Animal Gallery example.

// get the list of img elements that are sound icons
var iconsList = document.querySelectorAll("#words img");
        
// iterate through the list to bind to every element the event handler
// for the onclick event
for (var i=0; i < iconsList.length; i++){
    var icon = iconsList[i];
    icon.onclick = playSound;
}

Notice the use of the document.querySelectorAll. Differently from document.querySelector which returns only the first element it finds the first method returns all elements defined by the selector as an array of elements. Try it out in the console to see it for yourselves.

Below is the code for the playSound function. Notice that it uses the special variable this to refer to the clicked icon. Then it uses the DOM structure (the fact that the element img has two siblings, one on each side) to access them and get the word from the previous sibling and set the audio attributes to the next sibling.

  
function playSound(){

  console.log(this) // Check that it refers to the <img> element

  //get the text from the <span> element that is its previous sibling
  //Check the HTML code to see that <img> and <span> are siblings.
  var word = this.previousSibling.innerHTML;

  // get the <audio> element which is its next sibling
  var audio = this.nextSibling;

  // specify values for the attributes of the <audio> element
  // notice how the URL is generated by concatenating a fixed part 
  // with the concrete word
  var attributes = {src: "https://ssl.gstatic.com/dictionary/static/sounds/de/0/" + word + ".mp3",
                                      autoplay: "autoplay",
                                      type: "audio/mpeg"};

  // set the attributes of the <audio> element, so that it can play the sound
  for (property in attributes) {
          audio.setAttribute(property, attributes[property]);
      }         

}
  

Finally, notice the special use of the for loop with the properties of an object. We are using the for loop, so that we don't need to call the method setAttribute many times for each attribute we want to set.

Modify

Now that you know how the example works, modify the code for your purposes. Here are some ideas, but feel free to pursue your own ideas:

  1. Write an HTML page that has a simple form that asks the user to enter one English word. Modify the playSound function to read the word from the input and then pronounce it. Note: not all English words are in the dictionary. You can check the console to see for words that were not found, you'll see a GET error.
  2. Write a second HTML page that instead of a form it has an array of many words and it randomly selects one everytime a button "Show Word" is clicked and displays it on the page. Then, add a button "Pronounce" that will play the audio of the word. Modify the playSound method so that now it works for both pages. For that, you'll need to use parameters for the input word and the audio element, so that the function is independent of the HTML elements of the page. Then, invoke your function with arguments, depending on which page is using it.