Module 2.2

Web Applications continued...

Dynamic Content in the Browser

The pages that are shown to the user are defined using the HTML language. A single HTML document consists of nested and sequential elements that define the structure and the content of the page.

Each element may contain attributes that may have one or more values. For example, an input element typically has the attribute name, and the value of that attribute is then used to identify the data from that input element as it is being sent to the server. Other common attribute names include id that is used to define a unique identifier for the element and class that is used to define a classification for that element.

Javascript

While HTML is the language for defining the structure and content of a web page, Javascript is a language for defining dynamic content to the page. javascript is a programming language, and like almost any programming language, it is executed one command at a time, top to bottom, left to right.

Javascript file names typically end with .js and they are included to a HTML page using the script element. The element script has an attribute src, which defines the location of the source code file.

When adding Javascript code to a Spring Boot project, it is typically added to the folder src/main/resources/public/javascript/. All the files in the folder src/main/resources/public are made publicly available and downloadable through the server. Given that a Javascript file — say code.js is in the folder javascript, the script-element is used as follows: <script th:src="@{/javascript/code.js}"></script>.

Assume that the file code.js has the following content, i.e. a function that displays an alert pop-up with the text "Hello there!".

function sayHello() {
    alert("Hello there!");
}

The Javascript file can be included to a HTML site as follows. Note that we load the Javascript file at the end of the document. This is both to allow the browser to parse the page before including the Javascript code, and to avoid any blocking downloading of content.

<!DOCTYPE html>
<html>
    <head>
        <title>Title (shown in the browser bar)</title>
    </head>
    <body>
        <header>
            <h1>Title on the page.</h1>
        </header>

        <article>
            <p>Text content (within a paragraph, p). By pressing
            the button below, a javascript function "sayHello" is called.</p>
            <input type="button" value="Boom!" onclick="sayHello();" />
        </article>

        <!-- Ask the browser to load the Javascript -->
        <script th:src="@{javascript/code.js}"></script>

    </body>
</html>

Modifying page content with Javascript

Each element in a web page can be accessed and modified using Javascript. Specific elements can be identified using the querySelector method. It allows identifying elements based in the id-attribute value (identified with a hash), as well as the class attribute value (identified with a dot). If multiple elements with the same class exist, querySelectorAll is used.

<!DOCTYPE html>
<html>
    <head>
        <title>Title (shown in the browser bar)</title>
    </head>
    <body>

        <article>
            <input type="text" id="content" value="0"></input></p>
            <input type="button" value="Add!" onclick="increment();" />
        </article>

        <!-- Ask the browser to load the Javascript -->
        <script th:src="@{javascript/code.js}"></script>

    </body>
</html>

In the above HTML document, the input field can be identified with the id value "content". Using Javascript, the value of the field could be changed as follows.

function increment() {
    document.querySelector("#content").value = "new value";
}

The above functionality would change the field value to "new value", which is not exactly what the function promises. We can, also, change the functionality so that it increments the previous value by one.

function increment() {
    var value = Number(document.querySelector("#content").value) + 1;
    document.querySelector("#content").value = value;
}

Setting a value as a part of text

In the previous example, the value attribute of a text field was altered. However, some elements do not have an attribute called value. Instead, for some elements, the value of the element is inside the element. Changing the value inside an element can be changed — for example — using the innerHTML parameter of an element.

As an example, one could create a simple validator that verifies that an input field is not empty.

<!DOCTYPE html>
<html>
    <head>
        <title>Title (shown in the browser bar)</title>
    </head>
    <body>

        <article>
            <p>Type in your username</p>
            <p id="error"></p>
            <input type="text" id="content"></input></p>
            <input type="button" value="Add!" onclick="validate();" />
        </article>

        <!-- Ask the browser to load the Javascript -->
        <script th:src="@{javascript/code.js}"></script>

    </body>
</html>
function validate() {
    var content = document.querySelector("#content").value;
    if(!content) {
        document.querySelector("#error").innerHtml = "No content to process";
        return;
    }

    // do something else
}
:
Loading interface...
:
Loading interface...

Login to view the exercise

Adding elements to a page

New elements can be created using the createElement function. In the example below, a new p element is created, and text content is added to it. Finally, the paragraph is added to an element with the id "messages".

var paragraph = document.createElement("p");
var textContent = document.createTextNode("content");

paragraph.appendChild(textContent);

document.querySelector("#messages").appendChild(paragraph);

JSON dataformat and retrieving data from a server

Objects and data in Javascript are typically represented using the Javascript Object Notation (JSON) format. The format follows essentially a key: value structure, where variables are separated using commas. The definition of an object starts and ends with a bracket. For example, a person could be represented as follows.

var person = {name: "Jack Bauer", age: 24};

Assuming that the page would have an element with an id "user", the person details could be added to the page dynamically. Variable values can be retrieved using dot notation.

var person = {name: "Jack Bauer", age: 24};
document.querySelector("#user").innerHtml = person.name;

Often, we wish to retrieve data from the server. This can be done using the XMLHttpRequest object as follows.

var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
        var response = JSON.parse(xmlHttp.responseText);
        document.querySelector("#content").innerHTML = response.value.joke;
    }
}
xmlHttp.open("GET", "http://api.icndb.com/jokes/random/", true);
xmlHttp.send(null);

In the example above, a query is made to the address "http://api.icndb.com/jokes/random/". When a response is received, it is processed and content from the response is shown to a user in an element with the id "content".

Returning JSON Data from the Web Application

The controller classes can return JSON data as well. If a method that returns an object is annotated using the @ResponseBody annotation, then the object will be returned as a JSON object by default. Let us assume that we have a class Book, which is as follows:

public class Book {
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Now a controller that returns a Book object and has been annotated with the @ResponseBody annotation would return a JSON object as a response to the request made to that address.

@RequestMapping("/books")
@ResponseBody
public Book getBook() {
    Book book = new Book();
    book.setName("The Book of Eli.");
    return book;
}
Loading
You have reached the end of this section! Continue to the next section:

Remember to check your points from the ball on the bottom-right corner of the material!