Introduction to programming

More challenges

In this part of the series we are going to have a go at build one or two little standalone projects, which will give you some coding practice, introduce a couple of new concepts; we can hopefully and hopefully give you some fun at the same time.

A shopping list

The first example we'll look at is a simple little program that allows you to enter items into an input field and then submit them to add them to a list that appears below. The final working example can be seen at My shopping list — but no peeking at the code until you've tried it yourself!

The brief

New things in this challenge

We have already seen how you can alter the content of an HTML element by capturing the element in a variable using something like

var element = document.querySelector(".class");

and then setting the innerHTML property of that variable to anything you like:

element.innerHTML = "Hello!";

Well, you can also create new HTML elements from nothing, using the document.createElement() method and passing it an element name. For example:

var myNewElement = document.createElement('p');

You can then do many things with this element, but in this case we are going to look at adding the element to the document inside another element. For example:

var myExistingElement = document.querySelector(".myClass");
myNewElement.innerHTML = "My paragraph now has some content!";
myExistingElement.appendChild(myNewElement);

This would result in the following HTML now existing in the page:

<div class="myClass">
<!-- This div element was already in the HTML -->
  <p>My paragraph now has some content!</p>
  <!-- This p element was created by JavaScript -->
</div>

Let's do it

  1. Create a new copy of the template file to write this example into, into the usual way.
  2. As a first step, let's add some HTML inside our HTML area.
  3. <div class="form">
      <label for="item">Add item to list: </label>
      <input type="text" class="item" id="item">
      <button class="submit">Submit item</button>
      <button class="clear">Clear items</button>
    </div>
    
    <ul>
    
    </ul>
  4. Now we need to grab all of the items we want to do stuff to and store them in variables. We ought to grab the form input, both buttons, and the empty unordered list (<ul>) element:
  5. var itemInput = document.querySelector(".item");
    var clear = document.querySelector(".clear");
    var submit = document.querySelector(".submit");
    var list = document.querySelector("ul");
  6. Next, we need a function that will grab whatever value is inside the form input at the time it is run, and put it inside a list item (<li> element) inside the unordered list. This should happen when the Submit item button is clicked. Inside our function we need to:
    • Store the current value of the form input in a variable (remember we can access the value with formElement.value).
    • Create a new list item (<li> element) using document.createElement(), like we discussed above.
    • Set the value of the list item's innerHTML property to the form input value we captured in the above step.
    • Append the list item as a child of the unordered list using appendChild(), like we discussed above.
    • Set the value of the form input to equal an empty string ("") to empty it.
  7. Note: Outside the function we need to attach an onclick event handler to the Submit item button so it runs the function we just wrote when it is clicked.

    Add this code to your JavaScript area:

    function addItem() {
      var currentItem = itemInput.value;
      var listItem = document.createElement("li");
      listItem.innerHTML = currentItem;
    
      list.appendChild(listItem);
    
      itemInput.value = "";
    }
    
    submit.onclick = addItem;
  8. The only other major bit of work is to create a function that deletes the existing list items and empties the form input element when the clear button is clicked. to do this, we need to create a function that
    • sets the innerHTML of the unordered list to nothing ("")
    • sets the value of the form input to equal an empty string ("").
  9. Enter the following into the JaavScript area, below your previous function.

    clear.onclick = function() {
      list.innerHTML = "";
      itemInput.value = "";
    }

You'll notice in my final code that I used an anonymous function for this second part, and just attached it directly to the onclick handler. But you could do it a different way if you like.

A text search app

Our second example is slightly more complex, and highlights one of the main uses of JavaScript: processing text. In this demo we will create an app that will take a big chunk of text you feed into it and a search term, search through it, and then highlight where the search term appears in the chunk of text.

The brief

When looking at a brief like this, it helps to examine what is needed, and write out a list of all the items, so we are clear:

Grabbing a piece of paper and sketching out a rouch mock of the thing you are about to build can also be tremendously helpful.

New things in this challenge

JavaScript contains many built in features for manipulating strings. We've already seen how you can concatenate strings together:

var myName = 'Chris';
var myAge = 35;

alert('My name is ' + myName + ' and I am ' + myAge + ' years old.');

Here we are concatenating some raw text strings and variable values together to make one big string. But we can go a lot further than this. Here we'll be using two new string manipulation functions.

The first one is called indexOf(), and it finds an instance of one string inside another. For example:

var result = 'My name is Chris'.indexOf('Chris');

So here we are writing out a string, then invoking the indexOf() function of the string, with an argument of "Chris". This causes the browser to search through the string, check whether "Chris" appears inside the string, and store the position that it appears in, in the result variable. The result should be 11, because "Chris" starts (the letter "C" appears) at character 12 of the string (remember that computers start counting from 0, not 1).

Note: If the indexOf() argument is not found in the string, it will return a result of -1. This is pretty useful, as we shall see later.

The second new function is called replace(). This is a function that allows you to replace parts of a string with something else, and then return the updated string. For example:

var result = 'My name is Chris'.replace('Chris', 'Bob');

Here we are writing out a string, then invoking the replace() function of the string. In this case it is taking two arguments, the string we want to find ("Chris") and the string we want to replace it with ("Bob"). The replacement is caried out, and the updated string is stored in the result variable. The result should be "My name is Bob".

replace() can also take an optional third argument containing a regular expression (a string matching pattern), which sets some rules about how the replacement should occur, for example if you want to ignore case sensitivity, or replace all instances of a string or just one. These are pretty complicated so I won't be covering these in detail; the only one I'll be covering is the "g" option, which causes the replace() function to replace all instances of the replace string, not just the first one. So for example, try this:

var result1 = 'My name is Chris Chris Chris'.replace('Chris', 'Bob');
var result2 = 'My name is Chris Chris Chris'.replace('Chris', 'Bob', 'g');

result1 should be equal to "My name is Bob Chris Chris", while result2 should be "My name is Bob Bob Bob".

Let's do it

Ok, so let's get to it, and build this thing. Again start with a new copy of the template file. In the HTML area, add the following HTML:

<div class="form">
  <div>
    <label for="text">Enter your text to search: </label><textarea class="text" id="text" cols="80" rows="15"></textarea>
  </div>
  <div>
    <label for="searchString">Enter text to search for: </label><input type="text" class="searchString" id="searchString">
  </div>
  <button class="submit">Search</button><button class="clear">Clear</button>
</div>

<p class="resultMessage"></p>
<p class="results"></p>

Now we'll go through the following steps, writing the JavaScript in the JavaScript pane:

  1. First we'll capture both buttons and the two paragraphs at the bottom of the HTML in variables:
  2. var searchButton = document.querySelector(".submit");
    var clearButton = document.querySelector(".clear");
    
    var resultMessage = document.querySelector(".resultMessage");
    var results = document.querySelector(".results");
  3. The next task is the biggest and most difficult part of the application. We now need to write a central function that carries out the main search and result reporting tasks. First, create an empty function:
  4. function runSearch() {
    }
  5. Inside this function, we'll grab the current text values inside the textarea element and the text input element and store them in variables. Add the following inside the function's curly braces:
  6. var text = document.querySelector(".text").value;
    var searchString = document.querySelector(".searchString").value;
  7. Next, we'll use the indexOf() function we explored earlier to check whether the searchString is contained inside the text, and store the result in a variable. Add this line below:
  8. var confirmResult = text.indexOf(searchString);
  9. Next, add the following if...elsecode> structure, which gives the user a message if the searchString, text or both are empty, to tell them to fill in the text boxes. If this is not the case, we will do something else, to be covered below.
  10. if(text === "" || searchString === "") {
      resultMessage.innerHTML = "You need to enter a search term and block of text to search!";
    } else {
      
    }
  11. Now we will look at what needs to go inside the else part of the code. First we need to nest another if ... else structure inside this block. We need to do something magical if the indexOf() test says that the searchString is found inside the text (which we'll cover in the next step). If it isn't, then we want to give the user a message to tell them that the search term has not been found in the text block, and clear the contents of the results paragraph (in case anything was set there in previous searches.) Put the next block of code inside the previous else { ... } block.
  12. if(confirmResult !== -1) {
    
    } else {
      resultMessage.innerHTML = "Your search term has not been found in the text";
      results.innerHTML = "";
    }
  13. Finally for this function, add the following code into the inner if(confirmResult !== -1) { ... } block. If confirmResult doesn't have a value of -1, it means that the searchString has been found in the text block, so we will use text.replace() to find where, and highlight all instances. This is done by replacing all instances of the term with the same term wrapped in an HTML <strong> element.
  14. var newText = text.replace(searchString, "<strong>" + searchString + "</strong>", "g");
    
    results.innerHTML = newText; 
    resultMessage.innerHTML = "Search term highlighted in text";
  15. We also need a function that will clear everything out, effectively resetting the whole app. You need to empty both form fields (input and textarea), and empty both paragraphs (resultsMessage and results.) Add the following below the first function:
  16. function clearFields() {
      document.getElementById("text").value = "";
      document.getElementById("searchString").value = "";
    
      resultMessage.innerHTML = "";
      results.innerHTML = "";
    }
  17. The last step is to add onclick handlers to the Search and Clear buttons so that they run the two functions we just wrote. This is the easy bit! Add the following to the bottom of the JavaScript area:
  18. searchButton.onclick = runSearch;
    clearButton.onclick = clearFields;

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. Share it, make it better, use it for good.