The University of Arizona
Homework 4

CSC 346 - Homework 4 #

In this homework assignment we'll begin working with the JavaScript programming language. You will turn in a .zip file of a folder containing the following files:

What to turn in #

yournetid-hw04/
        Dockerfile
        html/
            index.html
            js/
                hw04.js

Points #

This assignment will be worth 50 points. Turning the assignment in early will earn you an additional 5 points extra credit.

  • Early submission: February 15th 11pm MST (UTC-7)
  • Final Due Date: February 17th 11pm MST (UTC-7)

Getting Started #

You will need to create one web page, one JavaScript file, and a Dockerfile defining an image that will serve up your simple website.

The starter .zip for this assignment contains the basic directory structure, a starter Dockerfile, HTML file for Part 1, and a javascript file for the remaining parts.

https://www2.cs.arizona.edu/classes/cs346/spring24/homework/NETID-hw04.zip

Dockerfile #

In order to view our webpage, we will include it in a docker container running the nginx web server. If you've set up your homework project folder as described above, the following Dockerfile should get your html files into the container.

FROM nginx:1.25
COPY ./html /usr/share/nginx/html/

You can then build your container with the following command:

$ docker build -t hw04:latest .

If you want the convenience of not having to rebuild your docker image each time you change your web page, remember that you can mount in a folder from your working directory in the docker run command:

$ docker run -i --rm --name hw04container -p 8080:80 \
    -v "$PWD/html:/usr/share/nginx/html/" hw04:latest

You can now open your page in a browser by visiting http://localhost:8080/.

This lets you edit and save your files, and just hit reload in your browser window, speeding up your development process.

Not seeing what you expect? Double check that you are in the correct homework folder, and that the tag of the image you built is the same one that you are running.

Part 1 #

First we need to include the javascript code in your HTML page. To do this you will need to add a <script> element to your HTML page which tells the browser how and were to load your javascript code file from. See slide 50 from the Javascript slides.

When finished, your page should look pretty close to the following. If you don't see the "Javascript file loaded!" text under Part 1, you're not loading your javascript file quite right yet.

A screenshot of a simple HTML page with the elements described above

Part 2 #

This will mostly just demonstrate how to think about solving the remaining problems. We want to display a message inside of the part2answer span when the button is clicked, similar to what is happening in Part 1. The contents of the span should be a string with the following format:

elementName clicked. x(Xcoord) y(Ycoord)

These values will come from the event object which is passed when you receive a click event.

First, we will need to define a function which will be called when our button is clicked. This will be a normal function declaration:

function runPart2(event) {
    var answerElement = document.getElementById("part2answer")
    answerText = `${event.target.id} clicked.  x(${event.x}) y(${event.y})`
    answerElement.textContent = answerText
}

We start off with the function declaration signature, expecting an event argument to be passed to our function. Next we will need to get a reference to our answer span, so we can update its text content with our answer. This is done with the document.getElementById method, and this is why we made sure to have id attributes on all of our important HTML elements. Having unique ids makes getting references to them with JavaScript very straightforward.

Then we assemble a string containing our answer text, and assign it to the answerText variable. Here we used the backtick character to surround our string, which lets us use JavaScript's Template Literals feature. This allows for direct variable interpolation inside of the string using the ${expression} syntax. This allows for much cleaner strings when you need to have the values of variables included. Compare this to standard string concatenation:

// The following two statements are equivalent
answerText = `${event.target.id} clicked.  x(${event.x}) y(${event.y})`
answerText = event.target.id + " clicked.  x(" + event.x + ") y(" + event.y + ")"

Finally, we assign our answerText content to the answerElement.textContent property. This updates the page with our value.

So far we have a function which will update an element on the page when it is called, but nothing is calling it yet.

We want our function to be called when we click on the "Run part 2" button. To do this, we need to attach a new event listener to that button:

part2 = document.getElementById("part2button")
part2.addEventListener("click", runPart2)

Here again we need to first get a reference to the right button using document.getElementById. Then we register our runPart2 function as a new event listener for the "click" event.

At this point, your hw04.js file should look like this for Part 2:

function runPart2(event) {
    var answerElement = document.getElementById("part2answer")
    answerText = `${event.target.id} clicked.  x(${event.x}) y(${event.y})`
    answerElement.textContent = answerText
}
part2 = document.getElementById("part2button")
part2.addEventListener("click", runPart2)

Now you should be able to load up http://localhost:8080/ in your browser (after running your docker container) and click on the Run part 2 button to see our code executed, and the page update.

Part 3 #

For part 3, we want to get introduced to the JavaScript Date object. For this problem, you will need to create a new Date object for the current date and time and assign it to a variable. You then need to call your object's toDateString() method, and store the output of that in an answerText variable. Lastly you need to update the part3answer span element with the answerText.

Here's a skeleton of code for this to get you started:

function runPart3(event) {
    // Create a new Date object and store it in a new variable.

    // Call the toDateString() method on your variable, and store
    //     the result in a new variable named answerText.

    // Obtain a reference to the part3answer element and 
    //     store it in a variable named answerElement.

    // Assign the answerText to the answerElement's textContent property.
    answerElement.textContent = answerText
}
// Obtain a reference to the part3button element, and store it
//     in a variable named part3
part3 = document.getElementById("part3button")
// Attach an event listener to the part3 element's click event
//     and pass it our runPart3 function.
part3.addEventListener("click", runPart3)

Part 4 #

For Part 4, we want to convert a string of comma (,) separated values into an array. Here we will take the input from an input element on our page. For example if we type in one,two,three into the input field and click the Run part 4 button, it should output ["one","two","three"]. Recall from class that we can use the split() method of the String object to do this.

Part 5 #

For Part 5, we will compute some values of the famous Fibonacci sequence. Recall that the Fibonacci sequence requires to initial conditions, and then the next value is computed by adding the current value and the previous value. For this, you will need to create your own Fibonacci Class.

We'll use the newer Class syntax to define our Fibonacci class. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes for more information.

To start off our Fibonacci calculations, we'll need two values. We will get these from a comma separated pair from the part5input element. For exmaple if we type in "0,1" into that field, we'll get the classic Fibonacci sequence. We will print out the initial values, and then the next 10 values in the sequence, for a total of 10 values. Remember that our input will be Strings, and if you "add" strings together it's just string concatenation. For example "1" + "1" reults in "11", which is not what we want. You will need to convert these to a Number.

Part 6 #

For the last part, we'll make an API call to the healthcheck method of a PictureGram API. This method just replies with a basic "OK" status, and echos back details of the request itself.

We'll need a separate function to be executed once the API call completes. This function will update the web page with the results of the API call. Since we made the part6answer element a <pre> element, it will be nicely formatted for the JSON data we'll get.

For our runPart6 function, we need to make an HTTP call using the Fetch API. I mean if you want to do it with XmlHttpRequest you can, bit wouldn't recommend it 😆.

The healthcheck method of the API will echo back any query string arguments that are passed long. We'll just pass one along with our API request, called "parameter", and use the value from part6input. Query string arguments are appended to the end of a URL after a question mark, and are key=value pairs. If we put "apple" into the input field, then the API call we would make would be:

https://csc346picturegram.test.apps.uits.arizona.edu/healthcheck?parameter=apple

You can test this particular API out in a regular web browser. If you put that URL in to a browser and visit it, you can see what the response will be.

Note! The fetch() API will throw all sorts of CORS errors if you try and run your file by simply loading it in the browser from your local file system. i.e. if you did an "Open File..." from your browser and just open up your index.html that way. The security model of browser won't let the network request be accessible to your JavaScript code.

Be sure to run your container, and access your file through http://localhost:8080/.

For a more throughough walkthroug and explanation of the fetch API, see the AJAX Example under the Examples section of this site.

Final Results #

Your final result should look something similar to this. Things like the date will be different, and the results will depend on your input values.

A screenshot of a simple HTML page with all the buttons pushed and results shown