Session 09 - Javascript, Part 2

Harvard Extension School  
Fall 2022

Course Web Site: https://cscie12.dce.harvard.edu/

Topics

  1. Javascript - What can you do?
  2. Ice Cream Options
  3. JS Data Structures - array and "object" (key/value pair)
  4. Loops and Iteration
  5. Working with Key/Value objects and Arrays
  6. Expanding and Collapsing Tree Structures
  7. Responsive Navigation

Session 09 - Javascript, Part 2, slide1
Javascript - What can you do?, slide2
Getting Started with JavaScript, slide3
JavaScript Review, slide4
WAIT! for DOM to be loaded, slide5
Ways of Accessing the DOM, slide6
Ice Cream Options, slide7
JS Data Structures - array and "object" (key/value pair), slide8
Loops and Iteration, slide9
Javascript and DOM: Building Content, slide10
Javascript and DOM: Building Content, slide11
Javascript and DOM: Building Content, slide12
DOM methods vs innerHTML, slide13
Working with Key/Value objects and Arrays, slide14
Expanding and Collapsing Tree Structures, slide15
Responsive Navigation, slide16
Responsive Navigation, slide17

Presentation contains 17 slides

Javascript - What can you do?

Programmatic access to all aspects of your web page!

Getting Started with JavaScript

JavaScript Review

  1. JS in HTML. Including JavaScript in HTML with script element, with either src attribute or JS code.
    <script src="scripts/site.js" ></script>
    or
    <script>
    /* JS code here */
    console.log('hello from JS!');
    </script>
  2. Variables. Declare variables with let and sometimes const.
    Though you will see the older var, but avoid that.
    You may also see const which declares a constant (a variable that won't be changed).
    let courseName = 'CSCI E-12',
      courseTerm = 'Fall 2022',
      courseInstructor = 'David' ;
  3. Console is your friend. Your browser developer tools will be critical to use, and especially the "Console". Log to the console in JS with
    console.log('hello there!');
  4. When is the code executed?script in head or right before the body close tag.
    But it is good practice to rely on specific events, especially the DOMContentLoaded event!

    The .addEventListener method takes two arguments. The first is the event name as a string, and the second is the function to execute when that event happens.

    document.addEventListener('DOMContentLoaded', function(){
        /* here's where JS goes for when DOM is loaded */
        console.log('the DOM has been loaded and parsed!');
    });
  5. Events - many are user-driven such as click, focus, blur, submit, mouseover, mouseout, keypress.
    And one important one happens when the browser has processed and loaded the HTML DOM — DOMContentLoaded.
    Even listeners are added through JavaScript!
  6. Functions. Functions can be named, and they can also be anonymous (unnamed) when setting event handlers. Functions can have arguements.

    Named function that accepts an argument:

    function square(x) {
      let numberSquared = x*x;
      return numberSquared;
    }

    Anonymous functions — function() {} — are often used in setting event listeners

    document.addEventListener('DOMContentLoaded', function(){
      /* here's where JS goes for when DOM is loaded */
      console.log('the DOM has been loaded and parsed!');
    });
  7. JavaScript gives us ways to access the DOM as well as manipulate it! Some common ways of accessing the DOM are getElementById, querySelector, querySelectorAll as well as classList, classList.add, classList.remove, classList.toggle.
    We can also construct content with methods like createElement, createTextNode, appendChild, and innerHTML

WAIT! for DOM to be loaded


document.addEventListener("DOMContentLoaded", function(){
  console.log("DOM has been loaded!");
});

Some examples will show putting the script before the body end tag </body> instead of setting a DOMContentLoaded event listener on the document

Ways of Accessing the DOM

querySelector and querySelectorAll

getElementById

This returns a single element node that we can directly operate on.
Remember that id values must be unique, so we only get a single match!

Ice Cream Options

ice cream optionsice cream options

Example 9.1 - Ice Cream Options - Example 9.1

 <form method="post" name="ice_cream" id="ice_cream" action="https://cs12.net/form/submit.php">
   <fieldset>
     <legend>Would you like ice cream?     </legend>
     <label>
       <input type="radio" name="want" id="ic_yes" value="yes"/>
Yes     </label>
     <label>
       <input type="radio" name="want" id="ic_no" value="no"/>
No     </label>   </fieldset>
   <fieldset id="icecream_options">
     <legend>Ice Cream Options     </legend>
     <fieldset>
       <legend>Would you like a cup or a cone?       </legend>
       <label>
         <input type="radio" id="container_cup" name="container" value="cup"/>
Cup       </label>
       <label>
         <input type="radio" id="container_cone" name="container" value="cone"/>
Cone       </label>     </fieldset>
     <fieldset>
       <legend>What topping do you want?       </legend>
       <label>
         <input type="checkbox" name="toppings" id="toppings_wc" value="whipcream"/>
Whipped cream       </label>
       <label>
         <input type="checkbox" name="toppings" id="toppings_jimmies" value="jimmies"/>
Jimmies       </label>
       <label>
         <input type="checkbox" name="toppings" id="toppings_sprinkles" value="sprinkles"/>
Sprinkles       </label>
       <label>
         <input type="checkbox" name="toppings" id="toppings_nuts" value="nuts"/>
Nuts       </label>
       <label>
         <input type="checkbox" name="toppings" id="toppings_cherry" value="cherry"/>
Cherry       </label>     </fieldset>   </fieldset>
   <button type="submit">Submit Order   </button>
 </form> 

In style element (<style>) within head element:

body {
  font-family: helvetica, sans-serif;
  margin: 1rem 5%;
  line-height: 1.5;
}

form fieldset {
  margin-bottom: 1rem;
}

label {
  display: block;
}

input[type=submit],
button[type=submit] {
  display: block;
}

#icecream_options {
  border-style: none;
}

.hidden {
  display: none;
}

In script element within head element (<script>):


console.log("hello!");

document.addEventListener("DOMContentLoaded", function(){
    /* do stuff here */
    console.log("dom is loaded!");

    /*

    x hide options when page is loaded
    x click events for to yes and no radio
    x display or hide the options as appropriate
    (hide for 'no', show for 'yes')

    */

    let iceCreamOptions = document.querySelector("#icecream_options");
    console.log(iceCreamOptions);
    iceCreamOptions.classList.add("hidden");

    /* get the "want" input radio */
    let wantRadioInputs = document.querySelectorAll("form input[name=want]");
    console.log(wantRadioInputs);

    wantRadioInputs.forEach(
        function(wantRadio){
            wantRadio.addEventListener("click",function(){
                console.log("want radio is clicked!");
                let yesRadio = document.querySelector("#ic_yes");
                console.log(yesRadio);
                console.log(yesRadio.checked);
                if ( yesRadio.checked == true ) {
                    iceCreamOptions.classList.remove("hidden");
                } else {
                    iceCreamOptions.classList.add("hidden");
                }
            })
        }
    );

})

JS Data Structures - array and "object" (key/value pair)

array Example:


                ['Autumn', 'Winter', 'Spring', 'Summer']
              

object Examples:

Simple "name/value" pairs:


                {
                  "lastName" : "Bacow",
                  "firstName" : "Lawrence",
                  "email" : "president@harvard.edu"
                }
              

"name/value" pairs, with values being an array (list) of things:


                {
                  "apples" : ['Macoun','Empire','Honey Crisp','Albemarle Pippin'],
                  "oranges" : ['Naval Orange','Tangelo','Clementine','Valencia Orange']
                }
              

And even movies


{ "movies" : [
                "Casino Royale",
                "Quantum of Solace",
                "Skyfall",
                "Spectre",
                "No Time to Die"
             ]
}

Movie data with more detail.

Loops and Iteration

let oranges = ['Naval Orange','Tangelo','Clementine','Valencia Orange'];
/* Iterate with for..of */
console.log("Iterate with: item of array");
for (const myorange of oranges) {
   console.log(myorange);
}
console.log("DONE!");

/* Iterate with 'classic' for (i = 0 ; i < LENGTH ; i++) */
console.log("Iterate with classic for i = ;  < ; i++");
for (let i = 0; i < oranges.length; i++ ) {
   console.log(i);
   console.log(oranges[i]);
}
console.log("DONE!");

/* Iterate with '.forEach()' */
console.log("Iterate with forEach()");
oranges.forEach(function(myorange){
  console.log(myorange);
});
console.log("DONE!");

Javascript and DOM: Building Content

DOM create nodes

And do the same for the other three seasons to get:
DOM create nodes

Javascript and DOM: Building Content

Example 9.2 - Example 9.2
 
 <p>
   <button id="makelist" type="submit">Build List of Seasons   </button>
 </p>
 <div id="seasonslist1"> 
 </div>

In script element within head element (<script>):

function makeSeasonsList() {
  let ul_node = document.createElement("ul");

  /* Autumn */
  let li_node1 = document.createElement("li");
  let li_text1 = document.createTextNode("Autumn");
  li_node1.appendChild(li_text1);

  /* Winter */
  let li_node2 = document.createElement("li");
  let li_text2 = document.createTextNode("Winter");
  li_node2.appendChild(li_text2);

  /* Spring */
  let li_node3 = document.createElement("li");
  let li_text3 = document.createTextNode("Spring");
  li_node3.appendChild(li_text3);

  /* Summer */
  let li_node4 = document.createElement("li");
  let li_text4 = document.createTextNode("Summer");
  li_node4.appendChild(li_text4);

  /* Append the list items to the ul */
  ul_node.appendChild(li_node1);
  ul_node.appendChild(li_node2);
  ul_node.appendChild(li_node3);
  ul_node.appendChild(li_node4);

  /* Place on page */
  let container = document.getElementById("seasonslist1");
  container.appendChild(ul_node);
}

/* Wait for DOM to be loaded, then add the click listener
   to the button */
document.addEventListener('DOMContentLoaded',function(){
  document.getElementById('makelist').addEventListener('click', makeSeasonsList);
});

Javascript and DOM: Building Content

Using an array (a list).

let seasons = ['Spring', 'Summer', 'Autumn', 'Winter'];

Iterate through Array

Example 9.3 - Example 9.3
 
 <p>
   <button id="makelist" type="submit">Build List of Seasons   </button>
 </p>
 <div id="seasonslist2"> 
 </div>

In head element:

<script src="example3.js"> </script>

Contents of example3.js

function makeSeasonsList() {
ul_node = document.createElement("ul");
let seasons = ['Spring', 'Summer', 'Autumn', 'Winter'];
for (let i = 0 ; i < seasons.length ; i++ ) {
  let mytext = i + " " + seasons[i];
  let text_node = document.createTextNode(mytext);
  let li_node = document.createElement("li");
  li_node.appendChild(text_node);
  ul_node.appendChild(li_node);
};
let container = document.getElementById("seasonslist2");
container.appendChild(ul_node);
}
/* Wait for DOM to be loaded, then add the click listener
   to the button */
document.addEventListener('DOMContentLoaded',function(){
  document.getElementById('makelist').addEventListener('click', makeSeasonsList);
});

Using forEach array method

Example 9.4 - Example 9.4
 
 <p>
   <button id="makelist" type="submit">Build List of Seasons   </button>
 </p>
 <div id="seasonslist3"> 
 </div>

In head element:

<script src="example4.js"> </script>

Contents of example4.js

function makeSeasonsList() {
  ul_node = document.createElement("ul");
  let seasons = ['Spring', 'Summer', 'Autumn', 'Winter'];
  seasons.forEach(function(s){
    let text_node = document.createTextNode(s);
    let li_node = document.createElement("li");
    li_node.appendChild(text_node);
    ul_node.appendChild(li_node);
  });
  let container = document.getElementById("seasonslist3");
  container.appendChild(ul_node);
}

/* Wait for DOM to be loaded, then add the click listener
   to the button */
document.addEventListener('DOMContentLoaded',function(){
  document.getElementById('makelist').addEventListener('click', makeSeasonsList);
});

DOM methods vs innerHTML

Working with Key/Value objects and Arrays

Data:

{
  "apples" : ['Macoun','Empire','Honey Crisp','Albemarle Pippin'],
  "oranges" : ['Naval Orange','Tangelo','Clementine','Valencia Orange']
}
Example 9.5 - Example 9.5
 
 <h1>List of Fruits from Data </h1>
 <div id="fruits"><!-- list goes here -->
 </div>

In script element within head element (<script>):

"use strict";

let fruits = {
    "apples": ['Macoun', 'Empire', 'Honey Crisp', 'Albemarle Pippin'],
    "oranges": ['Naval Orange', 'Tangelo', 'Clementine', 'Valencia Orange']
};
document.addEventListener('DOMContentLoaded',function(){
    buildFruitList();
});

function buildFruitList(){
    let fruitList = document.createElement('ul');
    for (const f in fruits) {
        console.log(f);
        let li = document.createElement('li');
        li.appendChild(document.createTextNode(f));
        if (Array.isArray(fruits[f])) {
            console.log(fruits[f]);
            let itemList = document.createElement('ul');
            for (const item of fruits[f]) {
                let li = document.createElement('li');
                li.appendChild(document.createTextNode(item));
                itemList.appendChild(li);
            }
            li.appendChild(itemList);
        }
        fruitList.appendChild(li);
    }
    document.getElementById('fruits').appendChild(fruitList);
}

JavaScript:

"use strict";

let fruits = {
    "apples": ['Macoun', 'Empire', 'Honey Crisp', 'Albemarle Pippin'],
    "oranges": ['Naval Orange', 'Tangelo', 'Clementine', 'Valencia Orange']
};
document.addEventListener('DOMContentLoaded',function(){
    buildFruitList();
});

function buildFruitList(){
    let fruitList = document.createElement('ul');
    for (const f in fruits) {
        console.log(f);
        let li = document.createElement('li');
        li.appendChild(document.createTextNode(f));
        if (Array.isArray(fruits[f])) {
            console.log(fruits[f]);
            let itemList = document.createElement('ul');
            for (const item of fruits[f]) {
                let li = document.createElement('li');
                li.appendChild(document.createTextNode(item));
                itemList.appendChild(li);
            }
            li.appendChild(itemList);
        }
        fruitList.appendChild(li);
    }
    document.getElementById('fruits').appendChild(fruitList);
}

Expanding and Collapsing Tree Structures

Responsive Navigation

menu

menu

menu

Responsive Navigation