CS1116/CS5018

Web Development 2

Dr Derek Bridge

School of Computer Science & Information Technology

University College Cork

Client-side Javascript

Client-side JavaScript comprises the core language plus the BOM and DOM.

The Browser Object Model (BOM)

The Document Object Model (DOM)

The hierarchical structure of HTML documents

<html>
    <head>
        <title>A simple document</title>
    </head>
    <body>
        <p>
            Some words.
        </p>
        <p>
            More words 
            <em>and emphasised words</em>
            and final words.
        </p>
    </body>
</html>
The HTML node has head and body nodes as its children. The head node has a title node as its child. The title node has a text node as its child. The body node here has two p nodes as children. The first p node has a text node as its child. The second p has three children: a text node, an em node and another text node. The em node has a text node as its child.

Note the different types of node: the document node, the element nodes, and the text nodes

Finding element nodes in JavaScript

Class exercise

<html lang="en">
    <head>
        <title>Lorem ipsum</title>
    </head>
    <body>
        <section id="sectA">
            <p class="opening">Lorem ipsum dolor sit amet consectetuer adipiscing.</p>
            <p class="closing">Lorem ipsum dolor sit amet consectetuer adipiscing.</p>
        </section>
        <section id="sectB">
            <p class="opening">Lorem ipsum dolor sit amet consectetuer adipiscing.</p>
            <p>Lorem ipsum dolor sit amet consectetuer adipiscing.</p>
            <p class="closing">Lorem ipsum dolor sit amet consectetuer adipiscing.</p>
        </section>
    </body>
</html>

Class exercise: which element nodes get retrieved?

  1. section_element = document.querySelector('#sectB');
  2. p_elements = document.querySelectorAll('p');
  3. p_elements = document.querySelectorAll('#sectB p');
  4. opening_elements = document.querySelectorAll('.opening');
  5. opening_elements = document.querySelectorAll('#sectB .opening');

section_element = document.querySelector('#sectB');

The second section is retrieved.

section_element = document.querySelector('#sectB');

The second section is retrieved.

p_elements = document.querySelectorAll('p');

The second section is retrieved.

p_elements = document.querySelectorAll('p');

All paragraphs are retreived.

p_elements = document.querySelectorAll('#sectB p');

The second section is retrieved.

p_elements = document.querySelectorAll('#sectB p');

The paragraphs in the second section are retrieved.

opening_elements = document.querySelectorAll('.opening');

The second section is retrieved.

opening_elements = document.querySelectorAll('.opening');

The opening paragraphs are retrieved.

opening_elements = document.querySelectorAll('#sectB .opening');

The second section is retrieved.

opening_elements = document.querySelectorAll('#sectB .opening');

The opening paragraphs of the second section are retrieved.

NB: It's still an 'array'.

Creating new element nodes and new text nodes

Changing the tree's nodes and values

A somewhat pointless example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Example A</title>
    <script src="exampleA.js" type="module">
    </script>
  </head>
  <body>
    <p>
      First paragraph.
    </p>
    <p>
      Second paragraph.
    </p>
  </body>
</html>
document.addEventListener('DOMContentLoaded', init, false);

function init() {
    let body_element = document.querySelector('body');
    let new_p_element = document.createElement('p');
    let new_text_node = document.createTextNode('Third paragraph');
    new_p_element.appendChild(new_text_node);
    body_element.appendChild(new_p_element);
}

A more concise approach

Properties of element nodes

Another pointless example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Example B</title>
    <script src="exampleB.js" type="module">
    </script>
  </head>
  <body>
    <section>
      <p>
        First paragraph.
      </p>
      <p>
        Second paragraph.
      </p>
    </section>
  </body>
</html>
 
document.addEventListener('DOMContentLoaded', init, false);

function init() {
    let section_element = document.querySelector('section');
    section_element.id = 'my_section';
    let p_elements = document.querySelectorAll('p');
    i = 0;
    for (let p of p_elements) {
        p.id = 'p' + i;
        i = i + 1;
    }
}

A proper example: the HTML

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Make me smile</title>
        <script src="rollover.js" type="module"></script>
    </head>
    <body>
        <p>
            <img id="face" src="frown.jpg">
        </p>
    </body>
</html>

A proper example: the JavaScript

let img_element;
    
document.addEventListener('DOMContentLoaded', init, false);

function init() {
    (new Image()).src = 'smile.jpg';
    img_element = document.querySelector('#face');
    img_element.addEventListener('mouseover', make_it_smile, false);
    img_element.addEventListener('mouseout', make_it_frown, false);
}

function make_it_smile() {
    img_element.src = 'smile.jpg';
}

function make_it_frown() {
    img_element.src = 'frown.jpg';
}

Changing the value of the class attribute

Yet another pointless example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Example C</title>
    <script src="exampleC.js" type="module">
    </script>
  </head>
  <body>
    <section>
      <p>
        First paragraph.
      </p>
      <p>
        Second paragraph.
      </p>
    </section>
  </body>
</html>
document.addEventListener('DOMContentLoaded', init, false);

function init() {
    let p_elements = document.querySelectorAll('p');
    for (let p of p_elements) {
        p.className = 'paras';
    }
}