Lecture 7: JavaScript and the DOM

Today's Agenda

Form elements

The DOM, DOM elements

Unobtrusive JavaScript

Buttons: <button>

            
              <button onclick="myFunction();">Click me!</button>
          

HTML

output

Button's text appears inside tag; can also contain images

To make a responsive button or other UI control:

  1. Choose the control (e.g., button) and event (e.g., mouse click) of interest
  2. Write a JavaScript function to run when the event occurs
  3. Attach the function to the event on the control

Accessing an Element: document.getElementById

            
            let name = document.getElementById("id");
         

JS

document.getElementById returns the DOM object for an element with a given id (note that you omit the # when giving an id)

document.getElementById: An Example

            
            <img id="pokeball" src="images/pokeball.jpg" alt="a pokeball" />
            <button onclick="changeImage();">Click me!</button>
          

HTML

            
            function changeImage() {
              let pokeballImg = document.getElementById("pokeball");
              pokeballImg.src = "images/mystery.gif";
            }
          

JS

a pokeball

output

<input>

            
            <!-- 'q' happens to be the name of Google's required paramter -->
            <input type="text" name="q" value="Colbert Report" />
            <input type="submit" value="Booyah!" />
          

HTML

output

Input element is used to create many UI controls (an inline element that must be self-closed

name attribute specifies name of query parameter to pass to server

type can be button, checkbox, file, hidden, password, radio, reset, submit, text, ...

value attribute specifies control's initial text

<input> Text Fields

            
              <input type="text" size="10" maxlength="8" /> NetID <br />
              <input type="password" size="16" /> Password
              <input type="submit" value="Log In!" />
            

HTML

NetID
Password

output

input attributes: disabled, maxLength, readonly, size, value

size attribute controls onscreen width of text field

maxlength limits how many characters the user is able to type into the field

Text boxes: <textarea>

            
              <textarea rows="4" cols="20">
              Type your comments here.
              </textarea>
          

HTML

output

Initial text is placed inside textarea tag (optional)

Required rows and cols attributes specify height/width in characters

optional readonly attribute means text cannot be modified

The DOM

A tree-shaped structure built out of all of the HTML elements in a page, accessible via JavaScript

Visualizing the tree


            <html>
              <head>
                <title> ... </title>
              </head>
              <body>
                <h1> ... </h1>
                <div>
                  <p> ... </p>
                </div>
              </body>
            </html>
            

HTML

DOM

Document Object Model (DOM)

A set of JavaScript objects that represent each element on the page

Each tag in a page corresponds to a JavaScript DOM object

JS code can talk to these objects to examine elements' state

  • e.g. see whether a box is checked

We can change state

  • e.g. insert some new text into a div

We can change styles

  • e.g. make a paragraph red

How to get DOM elements in JS:

  1. Ask for them by id: document.getElementyById(...)
  2. Query for them with CSS style selectors:
    • document.querySelector(...)
    • document.querySelectorAll(...)
  3. Make new ones! document.createElement(...)

Getting a DOM element in JS:


  

HTML


  let pTag = document.getElementById("october");
            

JS

What's inside a DOM object?

For starters, the HTML attributes. This HTML:


        <img src="images/puppy.png" alt="A fantastic puppy photo"/>
            

HTML

Has a DOM object (let's call it puppyImg) with these two properties:

  • puppyImg.src -- set by the browser to images/puppy.png
  • puppyImg.alt -- set by the browser to "A fantastic puppy photo"

Accessing Properties of a DOM object (Example)


        <p>See our <a href="sale.html" id="saleslink">Sales</a> today!</p>
        <img id="icon" src="images/borat.jpg" alt="Borat" />
        <caption class="photo user-upload">Beauty.</caption>
        

HTML


let icon    = document.getElementById("icon");
let theLink = document.getElementById("saleslink");
let caption = document.querySelector("caption");
        

JS

Property Description Example
tagName element's HTML tag icon.tagName is "IMG"
className CSS classes of element caption.className is "photo user-upload"
src URL target of an image icon.src is "images/borat.jpg"
href URL target of a link theLink.href is "sale.html"

innerHTMLproperty

All DOM elements have a property called innerHTML that has the contents of the HTML tag as a string:


        <ul id="dr-seuss">
            <li>Thing 1</li>
            <li>Thing 2</li>
        </ul>
        

HTML


        let elm = document.getElementById("dr-seuss");
        // elm.innerHTML : "\n    
  • Thing 1
  • \n
  • Thing 2
  • \n"

    JS

    Ok, what do we do with DOM objects?

    Set their properties, and the page changes in response

    This is how give behavior to web pages: use JavaScript to manipulate the DOM by changing the properties of DOM elements

    Modifying DOM Elements (Example)

    
    <a id="fb-link" href="http://www.facebook.com">Facebook</a>
                

    HTML

    Before the JavaScript runs, we'd see:

    And after we run this Javascript:

    
    let link = document.getElementById("fb-link");
    link.innerHTML = "MySpace is back in a really big way."
                

    JS

    We'd see:

    Unobtrusive JavaScript

    Unobtrusive JavaScript

    Now we'll see how to write unobtrusive JavaScript code

    • HTML with no JavaScript code inside the tags
    • uses the JS DOM to attach and execute all JavaScript event handlers

    Allows separation of web site into 3 major categories:

    • content(HTML) - what is it?
    • presentation(CSS) - how does it look?
    • behavior(JavaScript) - how does it respond to user interaction?

    Obtrusive Event Handlers (bad)

    
    <button onclick="okayClick();">OK</button>
                

    HTML

    
    // called when OK button is clicked
    function okayClick() {
        alert("booyah");
    }
                

    JS

    This is bad style (HTML is cluttered with JS code)

    Goal: remove all JavaScript code from the HTML body

    Attaching an event handler in JavaScript code

    
    let objectName.onevent = function;
              

    JS (template)

    <button id="ok">OK</button>
                

    HTML

    
    let okButton = document.getElementById("ok");
    okButton.onclick = okayClick;
                

    JS (example)

    It is legal to attach event handlers to elements' DOM objects in your JavaScript code

    Notice that you do not put parentheses after the function's name

    This is better style than attaching them in the HTML

    When does my code run?

    <html>
      <head>
        <script src="myfile.js" type="text/javascript"></script>
      </head>
      <body> ... </body>
    </html>
            

    HTML

    let x = 3;
    function f(n) { return n + 1; }
    function g(n) { return n - 1; }
    x = f(x);
                

    myfile.js -- JavaScript

    Your file's JS code runs the moment the browser loads the script tag

    • Any variables are declared immediately
    • Any functions are declared but not called, unless your global code explicitly calls them

    At this point in time, the browser has not yet read your page's body

    • None of the DOM objects for tags on the page have been created yet

    A failed attempt at being unobtrusive

    
    <html>
      <head>
        <script src="myfile.js" type="text/javascript"></script>
      </head>
      <body>
        <div><button id="ok">OK</button></div> 
        (... more html ...)
                

    HTML

    let btn = document.getElementById("ok");
    btn.onclick = okayClick;  // this is bad: btn is null at this point
                

    myfile.js -- JavaScript

    Problem: global JS code runs the moment the script is loaded

    Script in head is processed before page's body has loaded

    No elements are available yet or can be accessed yet via the DOM

    We need a way to attach the handler after the page has loaded...

    The window.onload event

    function functionName() {
      // put code to initialize the page here
    }
    
    // instruct window to run the function when the page has loaded:
      window.onload = functionName;
              

    JS (template)

    There is a global event called window.onload event that happens once everything in the page has been loaded

    If you attach a function as a handler for window.onload, it will run at that time

    An unobtrusive event handler

    
    <button id="ok">OK</button>   <!-- (1) -->
                

    HTML

    
    // called when page loads; sets up event handlers
    function pageLoad() {
      let ok = document.getElementById("ok"); // (3)   
      ok.onclick = okayClick;
    }
            
    function okayClick() {
      alert("booyah");                        // (4)
    }
            
    window.onload = pageLoad;                   // (2)
                

    JS

    Common Unobtrusive JS Errors

    event names are all lowercase, not capitalized like most variables window.onLoad = pageLoad; window.onload = pageLoad;

    JS

    you shouldn't write () when attaching the handler

    (if you do, it calls the function immediately, rather than setting it up to be called later) ok.onclick = okayClick(); ok.onclick = okayClick;

    JS

    The JSLint checker will catch this mistake

    Related: can't directly call functions like alert; must enclose in your own function

    ok.onclick = alert("booyah"); ok.onclick = okayClick; function okayClick() { alert("booyah"); }

    JS

    Anonymous functions

    
    function(parameters) {
      ... statements ...;
    }
              

    JavaScript allows you to declare anonymous functions

    Quickly creates a function without giving it a name

    Can be stored as a variable, attached as an event handler, etc.

    Anonymous function example

    
    window.onload = function() {
      let ok = document.getElementById("ok");
      ok.onclick = okayClick;
    };
    
    function okayClick() {
      alert("booyah");
    }
                

    JS

    or, the more concise, but perhaps harder to read:

    window.onload = function() {
                document.getElementById("ok").onclick = function() {
                    alert("booyah");
                };
            };
                

    Unobtrusive styling

    
    function okayClick() {
      this.style.color = "red";       // <-- bad style
      this.className = "highlighted"; // <-- better style
    }
                

    HTML

    .highlighted { color: red; }
                

    CSS

    Well-written JavaScript code should contain as little CSS as possible

    Use JS to set CSS classes/IDs on elements

    Define the styles of those classes/IDs in your CSS file

    The danger of global variables

    
    let count = 0;
    function incr(n) {
      count += n;
    }
    function reset() {
      count = 0;
    }
    
    incr(4);
    incr(2);
    console.log(count);
                

    globals can be bad; other code and other JS files can see and modify them

    How many global symbols are introduced by the above code?

    • 3 global symbols: count, incr, and reset

    Enclosing code in a function

    
    function everything() {
      let count = 0;
      function incr(n) {
        count += n;
      }
      function reset() {
        count = 0;
      }
            
      incr(4);
      incr(2);
      console.log(count);
    }
            
    everything(); // call the function to run the code
                

    JS

    The above example moves all the code into a function; variables and functions declared inside another function are local to it, not global

    How many global symbols are introduced by the above code?

    • 1 global symbol: everything (can we get it down to 0?)

    The "module pattern"

    
    (function() {
      statements;
    })();
              

    Wraps all of your file's code in an anonymous function that is declared and immediately called

    0 global symbols will be introduced!

    The variables and functions defined by your code cannot be messed with externally

    Module pattern example

    (function() { let count = 0; function incr(n) { count += n; } function reset() { count = 0; } incr(4); incr(2); console.log(count); })();

    How many global symbols are introduced by the above code?

    • 0 global symbols

    JavaScript "strict" mode

    
    "use strict";
            
    ...your code...
              

    JS

    Writing "use strict"; at the very top of your JS file turns on strict syntax checking:

    • Shows an error if you try to assign to an undeclared variable
    • Stops you from overwriting key JS system libraries
    • Forbids some unsafe or error-prone language features

    You should always turn on strict mode for your code in this class!

    JS Skeleton

    
     
    
                

    HTML

    
    (function() {
    
      // set-up code that doesn't involve the DOM 
      //   (e.g. setting up initial values, arrays, etc.)
    
      window.onload = function() {
        // phew! your code goes here
      };
    
      //function definitions go here
    
    })();
                

    JS