Welcome!
Everything is fine.

JavaScript Document Object Model (DOM)

Outline

  1. Announcements
  2. Review
    • DOM
    • Events
    • Event Handlers
  3. Your questions
  4. Exercises in Pairs

Announcements

  • Zodiac Partners will be assigned after the break.
  • Part 1 Retake results
    • Some did great (bravo!), but
    • quite a few did poorly. (9/16 got less than 70)
    • I did anonymized grading, so I don't yet know who is in each list
    • I'll reveal and send out from Gradescope this afternoon.
    • If you want to do a second (last) retake, contact me.
  • Part 2 Wednesday after the break
  • Still grading A3; sorry
  • Have a great break!

Ottergram

I'll demo why we're learning all this:

interactive Ottergram

We can also review (again) after the break, when we'll dig into the Ottergram code.

DOM

The DOM is a bridge from JavaScript to the document. It's a set of objects, properties, and methods that allow JavaScript to modify the document.

jQuery

  • you have to load jQuery; it's not built-in.
    • Typically from a CDN (like we did with normalize.css)
  • it defines a global function jQuery and a synonym $
  • technique is usually to select some elements and then operate on them with methods like this:
$(selector string).method(arg1, arg)

loading jQuery

Here's one example:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

or

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

You will see this in all examples from now on, and it's in this template-jq.html file, which you are welcome to copy:

cp ~cs204/pub/readings/template-jq.html some_file.html

Feel free to copy any of those in your own code. The template file also has my bounds plugin

Chaining

jQuery methods typically return the same wrapped set so that further methods can be chained on:

$(selector string).meth1().meth2().meth3();

or

$(selector string)
    .meth1()
    .meth2()
    .meth3();

Notice that the semi-colon to end the statement is only on the last line.

Connection to Ottergram

The idea of having the browser dynamically show a different picture by changing the src attribute of an img element is exactly what the interactive version of Ottergram does.

Content Methods

You can modify the contents of an element using the .text() or .html() methods:

<div id="fred"></div>
<div id="george"></div>

Like this:

$("#fred").text("I'm one of the Weasley twins. I'm the better-looking one");
$("#george").html("Actually, <em>I</em> am the better-looking one");

You can also modify attributes:

<img id="fw" src="fred.jpg" alt="Fred Weasley">

Like this:

$("#fw").attr('src','george.jpg').attr('alt',"George Weasley");

Style Methods

There are also lots of jQuery methods to work with CSS:

$("h2").css('color','purple');
$("h2").addClass('important');
$("h2").removeClass('optional');

These do pretty much what you'd guess they do.

Events

When a user does certain actions, they count as events:

  • click on something
  • mouse over something
  • change the value of a form input
  • submit a form

and many others.

Event Handlers

The browser has normal actions that it does when an event occurs, but it can also run some of your code. It does that by invoking a function that you set up earlier.

Example:

function handleClickOnFred() {
    ....
}    

$("#fred").click(handleClickOnFred);

note the lack of parentheses after the function name when it's an argument

Or, as an anonymous function:

$("#fred").click(function () { ... });

Note that:

  1. Neither of these do anything until the element is clicked on
  2. The function is run when the click event happens, not before
  3. If the user clicks several times, the function runs each time
  4. The function is passed in without putting parentheses after it, which would invoke it.

Quiz Questions

Let's talk about question 4. It is extremely common to be confused by this. It is one of the essential concepts we are learning this semester.

To attach a function named turnBlue to a button whose id is fred so that the function is invoked when we click on the button, we do

A. $("fred").click(turnBlue());
B. $("#fred").click(turnBlue());
C. $("fred").click(turnBlue);
D. $("#fred").click(turnBlue); 

And let's talk about a particular example of a function:

function die() {
    const max = 6;  // six-sided die
    return 1+Math.floor(max*Math.random());
}

Let's talk about a poor docstring for that function. How about:


// computes a random floating point number between zero and 1. 
// Multiplies that number by a constant, max, which is 6.
// Then takes the floor of that product, rounding it down to an integer.
// Adds one to the integer and returns the result.

Let's talk about a good docstring for that function. How about:

// returns a random integer from 1 to 6, inclusive

Docstrings should be written for the caller (human programmer), to help them understand what the function does and how to use it.

  • What is die?
  • What is die()?
  • If you want a die roll right now, which do I give you?
  • If you want a die to use for game night, which do give you?

your questions

Exercises

There is a short series of exercises in our course folder. Here's how to copy the collection:

cd ~/public_html/cs204/
cp -r ~cs204/pub/downloads/js3 js3
cd js3
code colors1.html

Here's the first web page: js3/colors1.html. We'll view the source (it's short) to make sure we are comfortable with it.

Breakouts

  • work through these;
  • we'll sync at various times for me to show my solutions

Exercise 1: Color Rotation

As you saw, we have the following code:

var mainColors = ["red","green","blue","yellow","cyan","magenta"];
var currColorIndex = 0;

Write a function named nextColor that takes no arguments and returns the next color (a string) in the array. It should treat the array as circular, meaning that the "next" entry after the last is the first.

Note that you will not need a loop here.

Implement the function and reload your page. Test it using the JS console. Note that this won't modify the document in any way. Here's what the calls in the console will look like:

> nextColor();
< "green"
> nextColor();
< "blue"

Here's my solution:


function nextColor() {
    currColorIndex++;
    if( currColorIndex > mainColors.length - 1 ) {
        currColorIndex = 0;
    }
    return mainColors[currColorIndex];
}

You can see and test the solution in the js3/colors2.html File. Test it by opening the console and invoking the function a few times.

jQuery

Using jQuery, we can change the CSS for any set of elements by using a selector (a string using the same language as for CSS files), the .css method, and arguments comprising a CSS property-value pair:

$(sel).css(prop,val);

For example, to change every H2 element to have a line under it, we could do:

$("h2").css("border-bottom","1px solid green");

Exercise 2: Setting the Color

Write a function name setNextColor to set the color of all the LI elements in the list of colors to the new color, as returned by nextColor. The function will take no arguments and return no values. Implement, save the file,reload, and test it using the JS console.

Here's my solution:

This is the simplest solution:


function setNextColor() {
    $("li").css("color", nextColor());
}

It could also be done with a local variable, like this:


function setNextColor() {
    var color2 = nextColor();
    $("li").css("color", color2);
}

If we want to be more specific about which LI elements, we could use a descendant selector, specifying the desired ancestor:


function setNextColor() {
    $("#colorList li").css("color", nextColor());
}

js3/colors3.html has the solution. Test it by opening the console and invoking the setNextColor() function a few times.

Events and Event Handlers

Events are things that happen in the browser, often triggered by the user, such as an element being clicked on or the page finishing loading.

The DOM allows developers like us to attach JavaScript functions to be invoked when certain events occur.

jQuery makes it easy to do this:

  • To attach a function named fred, do this:
    
    $(sel).click(fred);
    
  • To attach an anonymous function, do this:
    
    $(sel).click(function () { ... });
    

Exercise 3: Attach the Function

Attach the setNextColor function to the button. Click the button to test it.

Here's my solution:


$("#nextColorButton").click(setNextColor);

Notice that the argument is just the name of the function. It is not setNextColor(), which would be the result of executing the function.

You can see and try the solution in js3/colors4.html

Exercise 4: Change an image

Write some code to dynamically replace the roses with violets (violets.jpeg) when the #changeFlowersButton is clicked.

Here's my solution:


$("#changeFlowerButton").click(function () {
     $("#flower").attr('src','violets.jpeg'); });

Or, if you want to avoid the anonymous function:


function changeToViolets() {
    $("#flower").attr('src','violets.jpeg');
}

$("#changeFlowerButton").click(changeToViolets);

But the anonymous function is the way the pros would do it, unless they wanted to be able to do the change to violets from someplace else.

js3/solved4.html is the solution.

To switch back to roses, reload the page. Making a button to switch back is left as an exercise for the interested student.

End Breakout Rooms

We'll end the breakout rooms there, and I'll talk briefly about the zodiac assignment if there's time.

Zodiac Assignment

You are now ready for the zodiac assignment

jQuery's Flaw and a Plug-in

h3 id=fred

h3 id=george

I'll demo jQuery's flaw, and the bounds plugin on the H3 elements above; try them yourself:

$('i3');
$('#ferd');
$('i3').css('color','red');
$('#ferd').css('color','red');
$('i3').some().css('color','red');
$('#ferd').one().css('color','green');

Then fix the typos and try again:

$('h3').some().css('color','red');
$('#fred').one().css('color','green');

Content Methods

There are lots of jQuery methods to insert nodes and content and otherwise modify the structure of the document.

Here are some examples. We'll walk through them.

Section 1

  1. apples
  2. bananas

hermione

$("<li>").text('bread').appendTo("#groceries");
$("#groceries").append
        ("<li><em>lots</em> of chocolate</li>");
$("#sec1").html("<b>important</b> stuff");
$("#groceries > li").remove();
$("#hermione").attr("src","hermione.jpeg");
  • The first creates a new LI element not attached to the document (notice the angle brackets around "LI": omitting the angle brackets would mean to select all existing LI elements). Then, change the text inside the list item to 'apples' and, finally, append the LI element to the existing element whose ID is groceries
  • This example shows a different way to attach a new LI to an existing element. Notice the change from append() to appendTo()
  • The .html() method allows any HTML to be inserted, replacing whatever content is already there.
  • This code removes every LI that is a direct child of the element whose ID is groceries, so now they are all gone.
  • This code changes the src attribute of an element, presumably something that supports src such as an IMG tag. This code allows jQuery to dynamically change the pictures on a page.

There are lots more (check the api.jquery.com site), but the general idea is what's important.

Note that if you do a view source you won't see these changes, because view source is the original, not the current document.

Conclusion

The DOM means we can dynamically change the document using JavaScript

jQuery is a library to make that easier

Events are opportunities to get our own code executed.

That's done by adding event handlers (a function)