<!--#include virtual="../s5/commontop.html" -->
<title>Lecture 6: Unobtrusive Event Handling & Querying the DOM — INFO 343 Autumn 2012</title>
</head>
<body>
<div class="layout">
<div id="controls"><!-- DO NOT EDIT --></div>
<div id="currentSlide"><!-- DO NOT EDIT --></div>
<div id="header"></div>
<div id="footer">
<h1>INFO 343 Lecture 6</h1>
<h2>Unobtrusive Event Handling & Querying the DOM</h2>
</div>
</div>
<div class="presentation">
<div class="slide">
<h1>Unobtrusive Event Handling & Querying the DOM</h1>
<h3>Lecture 6</h3>
<!-- <h4>Reading: 8.1–8.3, 9.1–9.2</h4> -->
<p class="license">
Except where otherwise noted, the contents of this presentation are Copyright 2010 Marty Stepp, Jessica Miller, and/or Morgan Doocy.
</p>
<div class="w3c">
<a href="http://validator.w3.org/check/referer"><img src="../s5/images/w3c-xhtml11.png" alt="Valid XHTML 1.1" /></a>
<a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../s5/images/w3c-css.png" alt="Valid CSS!" /></a>
</div>
</div>
<div class="slide">
<h1>Recall: Obtrusive event handlers (bad)</h1>
<div class="example">
<pre class="examplecode html">
<button <em class="bad">onclick="okayClick();"</em>>OK</button>
</pre>
<pre class="examplecode js">
<span class="comment">// called when OK button is clicked</span>
function okayClick() {
alert("booyah");
}
</pre>
<div class="exampleoutput insertoutput"></div>
</div>
<ul>
<li>this is bad style (HTML is cluttered with JS code)</li>
<li>goal: remove all JavaScript code from the HTML body</li>
<li class="incremental">first, some background on objects and methods…</li>
</ul>
</div>
<div class="slide titleslide">
<h1>Functions & Objects</h1>
<ol>
<li><strong>Functions & Objects</strong></li>
<li>Global DOM Objects</li>
<li>“Unobtrusive” event handlers</li>
<li>JavaScript libraries</li>
<li>Querying the DOM with jQuery</li>
<li>Inspecting the page with jQuery</li>
</ol>
</div>
<div class="slide">
<h1>
Anonymous functions
<span class="readingsection">(8.1.2)</span>
</h1>
<pre class="syntaxtemplate js">
function(<var>parameters</var>) {
<var>statements</var>;
}
</pre>
<ul>
<li>JavaScript allows you to declare <span class="term">anonymous functions</span></li>
<li>quickly creates a function without giving it a name</li>
<li>can be stored as a variable, attached as an event handler, etc.</li>
</ul>
</div>
<div class="slide">
<h1>Anonymous vs. named functions</h1>
<p>The following are exactly equivalent:</p>
<div class="example">
<pre class="examplecode js">
function <em>foo</em>() {
<span class="comment">// ...</span>
}
</pre>
</div>
<div class="example">
<pre class="examplecode js">
var <em>foo</em> = function() {
<span class="comment">// ...</span>
};
</pre>
</div>
<p>In either case we can use the function names like variables, executing the function only when parentheses are added:</p>
<div class="example">
<pre class="examplecode js">
var <em>bar</em> = <em>foo</em>;
<span class="comment">// the following runs the same function twice</span>
<em>foo</em>();
<em>bar</em>();
</pre>
</div>
</div>
<div class="slide">
<h1>Passing functions as parameters</h1>
<pre class="examplecode js">
function gandalf(verb) {
alert("You shall not: " + verb.toUpperCase());
}
function runFunction(func, value) {
func(value); <span class="comment">// calls whichever function is passed, passing value as a parameter</span>
}
runFunction(gandalf, "pass!!!!!"); <span class="comment">// 'You shall not: PASS!!!!!'</span>
runFunction(function(meaning) {
alert("The meaning of life is: " + meaning); <span class="comment">// 'The meaning of life is: 42'</span>
}, 42);
</pre>
<ul>
<li>Because functions are stored in variables, we can pass them as parameters to be called later.</li>
<li>We might even pass anonymous functions directly as parameters!</li>
</ul>
</div>
<!-- <div class="slide">
<h1>Anonymous function example</h1>
<div class="example">
<pre class="examplecode js">
var foo = <em>function() {</em>
alert('Hello world!');
<em>};</em>
foo();
</pre>
<div class="exampleoutput">
<button onclick="alert('booyah');">OK</button>
</div>
</div>
<ul>
<li>or the following is also legal (though harder to read and bad style):</li>
</ul>
<pre class="examplecode js">
window.onload = <em>function() {</em>
var okButton = document.getElementById("ok");
okButton.onclick = <em>function() {</em>
alert("booyah");
<em>};</em>
<em>};</em>
</pre>
</div> -->
<div class="slide">
<h1><a href="http://www.w3schools.com/js/js_objects.asp">Objects</a></h1>
<pre class="syntaxtemplate js">
var <var>name</var> = { <var>key</var>: <var>value</var>, ... }
</pre>
<pre class="examplecode js">
var foo = {
bar: 'Booyah!',
baz: 42
};
alert(foo.bar); <span class="comment">// 'Booyah!'</span>
alert(foo.baz); <span class="comment">// '42'</span>
foo.qux = "I'm a new property!";
alert(foo.qux); <span class="comment">// "I'm a new property!"</span>
</pre>
<ul>
<li>Declare a new object with <code>{ ... }</code></li>
<li>Comma-separated list of properties/values specified with <code><var>prop</var>: <var>value</var>, <var>...</var></code></li>
<li>Property values can be a mixture of types</li>
</ul>
</div>
<!-- <div class="slide">
<h1>Methods in objects</h1>
<pre class="examplecode js">
var
</pre>
</div> -->
<div class="slide titleslide">
<h1>Global DOM Objects</h1>
<ol>
<li>Functions & Objects</li>
<li><strong>Global DOM Objects</strong></li>
<li>“Unobtrusive” event handlers</li>
<li>JavaScript libraries</li>
<li>Querying the DOM with jQuery</li>
<li>Inspecting the page with jQuery</li>
</ol>
</div>
<div class="slide">
<h1>The six global DOM objects</h1>
<p>Every Javascript program can refer to the following global objects:</p>
<table class="standard">
<tr>
<th>name</th><th>description</th>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_document.asp">document</a></code>
</td>
<td>
current HTML page and its content
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_history.asp">history</a></code>
</td>
<td>
list of pages the user has visited
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_location.asp">location</a></code>
</td>
<td>
URL of the current HTML page
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_navigator.asp">navigator</a></code>
</td>
<td>
info about the web browser you are using
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_screen.asp">screen</a></code>
</td>
<td>
info about the screen area occupied by the browser
</td>
</tr>
<tr>
<td>
<code><a href="http://www.w3schools.com/htmldom/dom_obj_window.asp">window</a></code>
</td>
<td>
the browser window
</td>
</tr>
</table>
</div>
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_window.asp"><code>window</code></a> object</h1>
<p class="description">
the entire browser window; the top-level object in DOM hierarchy
</p>
<ul>
<li>technically, all global code and variables become part of the <code>window</code> object</li>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/dom_obj_document.asp"><code>document</code></a>,
<a href="http://www.w3schools.com/htmldom/dom_obj_history.asp"><code>history</code></a>,
<a href="http://www.w3schools.com/htmldom/dom_obj_location.asp"><code>location</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_win_name.asp"><code>name</code></a>
</li>
</ul>
</li>
<li>methods:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/met_win_alert.asp"><code>alert</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_confirm.asp"><code>confirm</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_prompt.asp"><code>prompt</code></a> (popup boxes)
</li>
<li>
<a href="http://www.w3schools.com/htmldom/met_win_setInterval.asp"><code>setInterval</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_setTimeout.asp"><code>setTimeout</code></a>
<a href="http://www.w3schools.com/htmldom/met_win_clearInterval.asp"><code>clearInterval</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_clearTimeout.asp"><code>clearTimeout</code></a> (timers)
</li>
<li>
<a href="http://www.w3schools.com/htmldom/met_win_open.asp"><code>open</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_close.asp"><code>close</code></a> (popping up new browser windows)
</li>
<li>
<a href="http://www.w3schools.com/htmldom/met_win_blur.asp"><code>blur</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_focus.asp"><code>focus</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_moveBy.asp"><code>moveBy</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_moveTo.asp"><code>moveTo</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_print.asp"><code>print</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_resizeBy.asp"><code>resizeBy</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_resizeTo.asp"><code>resizeTo</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_scrollBy.asp"><code>scrollBy</code></a>,
<a href="http://www.w3schools.com/htmldom/met_win_scrollTo.asp"><code>scrollTo</code></a>
</li>
</ul>
</li>
</ul>
</div>
<!--
<div class="slide">
<h1>Popup windows with <code>window.open</code></h1>
<pre class="examplecode js">
<em>window.open</em>("http://foo.com/bar.html", "My Foo Window",
"width=900,height=600,scrollbars=1");
</pre>
<hr class="spacedrule" />
<ul>
<li><a href="http://www.w3schools.com/htmldom/met_win_open.asp"><code>window.open</code></a> pops up a new browser window</li>
<li>THIS method is the cause of all the terrible popups on the web!</li>
<li>some popup blocker software will prevent this method from running</li>
</ul>
</div>
-->
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_document.asp"><code>document</code></a> object</h1>
<p class="description">
the current web page and the elements inside it
</p>
<ul>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/coll_doc_anchors.asp"><code>anchors</code></a>,
<code>body</code>,
<a href="http://www.w3schools.com/htmldom/prop_doc_cookie.asp"><code>cookie</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_doc_domain.asp"><code>domain</code></a>,
<a href="http://www.w3schools.com/htmldom/coll_doc_forms.asp"><code>forms</code></a>,
<a href="http://www.w3schools.com/htmldom/coll_doc_images.asp"><code>images</code></a>,
<a href="http://www.w3schools.com/htmldom/coll_doc_links.asp"><code>links</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_doc_referrer.asp"><code>referrer</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_doc_title.asp"><code>title</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_doc_url.asp"><code>URL</code></a>
</li>
</ul>
</li>
<li>methods:
<ul>
<li><a href="http://www.w3schools.com/htmldom/met_doc_getelementbyid.asp"><code>getElementById</code></a></li>
<li><a href="http://www.w3schools.com/htmldom/met_doc_getelementsbyname.asp"><code>getElementsByName</code></a></li>
<li><a href="http://www.w3schools.com/htmldom/met_doc_getelementsbytagname.asp"><code>getElementsByTagName</code></a></li>
<li>
<a href="http://www.w3schools.com/htmldom/met_doc_close.asp"><code>close</code></a>,
<a href="http://www.w3schools.com/htmldom/met_doc_open.asp"><code>open</code></a>,
<a href="http://www.w3schools.com/htmldom/met_doc_write.asp"><code>write</code></a>,
<a href="http://www.w3schools.com/htmldom/met_doc_writeln.asp"><code>writeln</code></a>
</li>
</ul>
</li>
<li><a href="http://www.w3schools.com/htmldom/dom_obj_document.asp">complete list</a></li>
</ul>
</div>
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_location.asp"><code>location</code></a> object</h1>
<p class="description">
the URL of the current web page
</p>
<ul>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/prop_loc_host.asp"><code>host</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_hostname.asp"><code>hostname</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_href.asp"><code>href</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_pathname.asp"><code>pathname</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_port.asp"><code>port</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_protocol.asp"><code>protocol</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_loc_search.asp"><code>search</code></a>
</li>
</ul>
</li>
<li>methods:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/met_loc_assign.asp"><code>assign</code></a>,
<a href="http://www.w3schools.com/htmldom/met_loc_reload.asp"><code>reload</code></a>,
<a href="http://www.w3schools.com/htmldom/met_loc_replace.asp"><code>replace</code></a>
</li>
</ul>
</li>
<li><a href="http://www.w3schools.com/htmldom/dom_obj_location.asp">complete list</a></li>
</ul>
</div>
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_navigator.asp"><code>navigator</code></a> object</h1>
<p class="description">
information about the web browser application
</p>
<ul>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/prop_nav_appname.asp"><code>appName</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_nav_appversion.asp"><code>appVersion</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_nav_browserlanguage.asp"><code>browserLanguage</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_nav_cookieenabled.asp"><code>cookieEnabled</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_nav_platform.asp"><code>platform</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_nav_useragent.asp"><code>userAgent</code></a>
</li>
<li><a href="http://www.w3schools.com/htmldom/dom_obj_navigator.asp">complete list</a></li>
</ul>
</li>
<li>
Some web programmers examine the <code>navigator</code> object to see what browser is being used, and write browser-specific scripts and hacks:
<pre class="examplecode js">
if (navigator.appName === "Microsoft Internet Explorer") { ...
</pre>
<ul>
<li>(this is poor style; you should not need to do this)</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_screen.asp"><code>screen</code></a> object</h1>
<p class="description">
information about the client's display screen
</p>
<ul>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/prop_screen_availheight.asp"><code>availHeight</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_screen_availwidth.asp"><code>availWidth</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_screen_colordepth.asp"><code>colorDepth</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_screen_height.asp"><code>height</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_screen_pixeldepth.asp"><code>pixelDepth</code></a>,
<a href="http://www.w3schools.com/htmldom/prop_screen_width.asp"><code>width</code></a>
</li>
<li><a href="http://www.w3schools.com/htmldom/dom_obj_screen.asp">complete list</a></li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>The <a href="http://www.w3schools.com/htmldom/dom_obj_history.asp"><code>history</code></a> object</h1>
<p class="description">
the list of sites the browser has visited in this window
</p>
<ul>
<li>properties:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/prop_his_length.asp"><code>length</code></a>
</li>
</ul>
</li>
<li>methods:
<ul>
<li>
<a href="http://www.w3schools.com/htmldom/met_his_back.asp"><code>back</code></a>,
<a href="http://www.w3schools.com/htmldom/met_his_forward.asp"><code>forward</code></a>,
<a href="http://www.w3schools.com/htmldom/met_his_go.asp"><code>go</code></a>
</li>
</ul>
</li>
<li><a href="http://www.w3schools.com/htmldom/dom_obj_history.asp">complete list</a></li>
<li>sometimes the browser won't let scripts view <code>history</code> properties, for security</li>
</ul>
</div>
<div class="slide titleslide">
<h1>“Unobtrusive” event handlers</h1>
<ol>
<li>Functions & Objects</li>
<li>Global DOM Objects</li>
<li><strong>“Unobtrusive” event handlers</strong></li>
<li>JavaScript libraries</li>
<li>Querying the DOM with jQuery</li>
<li>Inspecting the page with jQuery</li>
</ol>
</div>
<div class="slide">
<h1>Recall: Obtrusive event handlers (bad)</h1>
<div class="example">
<pre class="examplecode html">
<button <em class="bad">onclick="okayClick();"</em>>OK</button>
</pre>
<pre class="examplecode js">
<span class="comment">// called when OK button is clicked</span>
function okayClick() {
alert("booyah");
}
</pre>
<div class="exampleoutput insertoutput"></div>
</div>
<ul>
<li>this is bad style (HTML is cluttered with JS code)</li>
<li>goal: remove all JavaScript code from the HTML body</li>
</ul>
</div>
<div class="slide">
<h1>Attaching an event handler from JavaScript (almost)</h1>
<pre class="syntaxtemplate js">
<span class="comment">// where <var>element</var> is a DOM element object</span>
<var>element</var>.<var>event</var> = <var>function</var>;
</pre>
<div class="example">
<pre class="examplecode html">
<button <em>id="ok"</em>>OK</button>
</pre>
<pre class="examplecode js">
document.getElementById("ok").<em>onclick</em> = <em>okayClick</em>;
</pre>
<div class="exampleoutput insertoutput"></div>
</div>
<ul>
<li>it is legal to attach event handlers to elements' DOM objects in your JavaScript code
<ul>
<li>
notice that you do <strong>not</strong> put parentheses after the function's name
</li>
</ul>
</li>
<li>this is better style than attaching them in the HTML</li>
<li>Where should we put the above code?</li>
</ul>
</div>
<div class="slide">
<h1>When does my code run?</h1>
<div class="example">
<pre class="examplecode html">
<head>
<em><script src="myfile.js" type="text/javascript"></script></em>
</head>
<body> ... </body>
</pre>
<pre class="examplecode examplecode2 examplecodelast js">
<span class="comment">// global code</span>
alert("This alerts right away, every time the page is loaded!");
function foo() {
alert("This message is only shown if foo is called.");
}
</pre>
</div>
<ul>
<li>your file's JS code runs the moment the browser loads the <code>script</code> tag
<ul>
<li>
any variables are declared immediately
</li>
<li>
any functions are declared but not called, unless your global code explicitly calls them
</li>
</ul>
</li>
<li class="incremental">at this point in time, the browser has not yet read your page's <code>body</code>
<ul>
<li>
none of the DOM objects for tags on the page have been created yet
</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>A failed attempt at being unobtrusive</h1>
<div class="example">
<pre class="examplecode html">
<head>
<em><script src="myfile.js" type="text/javascript"></script></em>
</head>
<body>
<div><button id="ok">OK</button></div>
</pre>
<pre class="examplecode examplecode2 examplecodelast js">
<span class="comment">// global code</span>
<em class="bad">document.getElementById("ok").onclick = okayClick;</em>
<span class="comment">// error: document.getElementById("ok") is null</span>
</pre>
</div>
<ul>
<li>problem: global JS code runs the moment the script is loaded</li>
<li>script in <code>head</code> is processed before page's <code>body</code> has loaded
<ul>
<li>no elements are available yet or can be accessed yet via the DOM</li>
</ul>
</li>
<li>we need a way to attach the handler after the page has loaded...</li>
</ul>
</div>
<div class="slide">
<h1>
The <code>window.onload</code> event
<span class="readingsection">(8.1.1)</span>
</h1>
<pre class="syntaxtemplate js">
<span class="comment">// just declaring this function now; it doesn't execute yet</span>
function <var>functionName</var>() {
<var>element</var>.<var>event</var> = <var>functionName</var>;
<var>element</var>.<var>event</var> = <var>functionName</var>;
...
}
<span class="comment">// tell the browser to run <var>functionName</var> as soon as the HTML
// has finished loading</span>
<em>window.onload = <var>functionName</var>;</em>
</pre>
<ul>
<li>we want to attach our event handlers right after the HTML is done loading</li>
<ul>
<li>there is a global event called <code>window.onload</code> that occurs at that moment</li>
</ul>
<li>in <code>window.onload</code> handler we attach all the other handlers to run when events occur</li>
</ul>
</div>
<div class="slide">
<h1>An unobtrusive event handler</h1>
<div class="example">
<pre class="examplecode html">
<span class="comment"><!-- look Ma, no JavaScript! --></span>
<button id="ok">OK</button>
</pre>
<pre class="examplecode examplecode2 js">
<span class="comment">// called when page loads; sets up event handlers</span>
function pageLoad() {
document.getElementById("ok").onclick = okayClick;</em>
}
function okayClick() {
alert("booyah");
}
<em>window.onload = pageLoad;</em> <span class="comment">// global code</span>
</pre>
<div class="exampleoutput">
<button onclick="alert('booyah');">OK</button>
</div>
</div>
</div>
<div class="slide">
<h1>Problems with <code>window.onload</code></h1>
<pre class="examplecode js">
function foo() {
alert('This function will never be called.');
}
<em>window.onload = foo;</em>
function bar() {
alert('This function gets called instead of foo!');
}
<em>window.onload = bar;</em> <span class="comment">// foo gets clobbered!</span>
</pre>
<ul>
<li>What if we want to run more than one function?</li>
<li>What if the functions are in separate files?</li>
<li>More obscure problem: images haven’t loaded yet when <code>window.onload</code> occurs</li>
</ul>
</div>
<div class="slide titleslide">
<h1>JavaScript libraries</h1>
<ol>
<li>Functions & Objects</li>
<li>Global DOM Objects</li>
<li>“Unobtrusive” event handlers</li>
<li><strong>JavaScript libraries</strong></li>
<li>Querying the DOM with jQuery</li>
<li>Inspecting the page with jQuery</li>
</ol>
</div>
<div class="slide">
<h1>Problems with JavaScript & the DOM</h1>
<p>
JavaScript is a powerful language, but it has many flaws:
</p>
<ul>
<li>the DOM can be clunky to use
<ul>
<li><code>document.getElementById</code> gets only a single element</li>
<li>other ways of getting elements are difficult to use</li>
</ul>
</li>
<li>the same code doesn’t always work the same way in every browser
<ul>
<li>code that works great in Firefox, Safari, ... will fail in IE and vice versa</li>
</ul>
</li>
<li>many developers work around these problems with hacks (checking if browser is IE, etc.)
<ul>
<li>adapting JavaScript to different browsers is very time consuming!</li>
<li>manually adapting/fixing the same problems on every website is difficult for everyone!</li>
</ul>
</li>
<li>specific examples:
<ul>
<li>event handlers (<code>onclick</code>, <code>onload</code>) easy to clobber; non-clobbering <code>addEventListener</code> not supported by all browsers</li>
<li><code>style</code> property can’t read any styles applied from an external CSS file; <code>getComputedStyle</code> not supported by all browsers</li>
<li>standard-DOM <code>nextChild</code>, <code>previousChild</code> properties link to mostly-useless text nodes</li>
</ul>
</li>
</ul>
</div>
<div class="slide">
<h1>Solution: JavaScript libraries</h1>
<p class="description">pluggable JavaScript files which provide useful, time-saving features and plug “gaps” in standard JS/DOM</p>
<style type="text/css">
#js_libraries {
list-style-type: none;
}
#js_libraries .library {
display: inline-block;
/* background-color: fuchsia;*/
margin: 1em;
vertical-align: middle;
}
</style>
<ul id="js_libraries">
<li class="library"><a href="http://dojotoolkit.org/"><img src="images/dojo.png" alt="Dojo JavaScript library" /></a></li>
<li class="library"><a href="http://developer.yahoo.com/yui/"><img src="images/yui.png" alt="YUI JavaScript library" /></a></li>
<li class="library"><a href="http://www.prototypejs.org/"><img src="images/prototype.png" alt="Prototype JavaScript library" /></a></li>
<li class="library"><a href="http://jquery.com/"><img src="images/jquery.png" alt="jQuery JavaScript library" /></a></li>
<li class="library"><a href="http://mootools.net/"><img src="images/mootools.png" alt="MooTools JavaScript library" /></a></li>
</ul>
<p>JavaScript libraries add many useful features to JavaScript and the DOM:</p>
<ul>
<li>easier ways of navigating the DOM and interacting with the page</li>
<li>improved event-driven programming</li>
<li>useful extensions to built-in JavaScript objects (<code>String</code>, <code>Array</code>, etc.)</li>
<li>cross-browser compatibility fixes</li>
<li>easier Ajax programming (seen later)</li>
</ul>
</div>
<div class="slide">
<h1>The <a href="http://jquery.com/">jQuery</a> JavaScript library</h1>
<p class="description"><img src="images/jquery.png" alt="jQuery JavaScript library"></p>
<pre class="examplecode html" style="font-size: 80%">
<script <em>src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"</em>
type="text/javascript"></script>
</pre>
<p>This quarter we’ll be using the jQuery library.</p>
<ul>
<li>Most popular JavaScript library
<ul>
<li>Used by 55% of the 10,000 most-popular websites, including Google, WordPress, and Drupal</li>
<li>Very active user community, with lots of tutorials and resources</li>
</ul>
</li>
<li>Extensible with plugins
<ul>
<li>thousands of plugins available at <a href="http://plugins.jquery.com/">jQuery Plugins</a> (under construction; <a href="http://archive.plugins.jquery.com/">older archive</a>)</li>
</ul>
</li>
<li>Small(ish), efficient</li>
<li>Easy-to-use API</li>
<li>Neat special effects</li>
</ul>
</div>
<div class="slide">
<h1>The jQuery (<a href="http://api.jquery.com/jQuery/">$</a>) function</h1>
<pre class="syntaxtemplate js">
var <var>name</var> = $('<var>CSS-style selector</var>');
var <var>name</var> = jQuery('<var>CSS-style selector</var>');
</pre>
<pre class="examplecode js">
var $okbutton = <em>$('#ok')</em>;
</pre>
<ul>
<li>Most powerful and frequently-used function in jQuery</li>
<li>Parameter: any CSS-style selector, as a string
<ul>
<li>Example: <code>$('#nav li.selected a')</code></li>
</ul>
</li>
<li>Selects and returns elements from the DOM matching the CSS selector</li>
<li>Returns a special <em>jQuery object</em> containing the matched DOM objects
<ul>
<li>Convention: name jQuery objects beginning with $</li>
</ul>
</li>
<li>Function is also called <code>jQuery</code>, but <code>$</code> is by far most common</li>
</ul>
</div>
<div class="slide">
<h1>Attaching an event handler the jQuery way</h1>
<pre class="examplecode js">
<del>document.getElementById('ok').onclick = okClick;</del>
</pre>
<pre class="examplecode js">
<span class="comment">// when the 'ok' button is clicked, call the function 'okClick'</span>
<em>$('#ok').click</em>(okClick);
</pre>
<ul>
<li>Applies an <code>onclick</code> handler to each element returned by <code>$()</code>
<ul>
<li>There may be one or many of them</li>
</ul>
</li>
<li>Accounts for browser differences</li>
<li>Ensures multiple click handlers can be attached to the same element</li>
<li>Other mouse-related handlers: <code><a href="http://api.jquery.com/dblclick/">dblclick</a></code>, <code><a href="http://api.jquery.com/mousedown/">mousedown</a></code>, <code><a href="http://api.jquery.com/mouseup/">mouseup</a></code>, <code><a href="http://api.jquery.com/mousemove/">mousemove</a></code></li>
</ul>
</div>
<!-- <div class="slide">
<h1>Attaching event handlers the Prototype way</h1>
<pre class="syntaxtemplate js">
<del><var>element</var>.on<var>event</var> = <var>function</var></del>;
<var>element</var>.observe("<var>event</var>", <var>function</var>);
</pre>
<pre class="examplecode js">
<span class="comment">// call the playNewGame function when the Play button is clicked</span>
$("play").observe("click", playNewGame);
</pre>
<ul>
<li>
to use Prototype's event features, you must attach the handler using the DOM element object's <code>observe</code> method (added by Prototype)
</li>
<li>
pass the <strong>event name</strong> as a string, and the <strong>function name</strong> to call
</li>
<li>
handlers <em>must</em> be attached this way for Prototype's event features to work
</li>
</ul>
<ul class="aside" style="margin-top: 2em">
<li>
<code>observe</code> substitutes for <a href="http://www.quirksmode.org/js/events_advanced.html"><code>addEventListener</code></a> (not supported by IE)
</li>
</ul>
</div> -->
<div class="slide">
<h1>jQuery alternative to <code>window.onload</code></h1>
<pre class="syntaxtemplate js">
function pageLoad() {
<span class="comment">// attach event handlers...</span>
}
<del>window.onload = pageLoad;</del>
<em>$(document).ready</em>(pageLoad);
</pre>
<pre class="examplecode js">
<span class="comment">// attach playNewGame click handler when page has finished loading</span>
$(document).ready(function() {
$('#play').click(playNewGame);
});
</pre>
<ul>
<li>runs the specified function when the document and DOM are “ready”
<ul>
<li>i.e., when all HTML and images have loaded</li>
</ul>
</li>
<li>
allows multiple scripts to run <code>onload</code> handlers when the page has finished loading
</li>
</ul>
</div>
<!-- <div class="slide">
<h1>Attaching multiple event handlers with <code>$$</code></h1>
<pre class="examplecode js">
<span class="comment">// listen to clicks on all buttons with class "control" that
// are directly inside the section with ID "game"</span>
document.observe('dom:loaded', function() {
var gameButtons = <em>$$("#game > button.control")</em>;
for (var i = 0; i < gameButtons.length; i++) {
<em>gameButtons[i].observe("click", gameButtonClick);</em>
}
});
function gameButtonClick() { ... }
</pre>
<ul>
<li>you can use <code>$$</code> and other DOM walking methods to unobtrusively attach event handlers to a group of related elements in your <code>window.onload</code> code</li>
</ul>
</div> -->
<!-- <div class="slide">
<h1>Common unobtrusive JS errors</h1>
<ul>
<li>many students mistakenly write <code>()</code> when attaching the handler
<pre class="examplecode js">
<del>window.onload = pageLoad();</del>
window.onload = <em>pageLoad</em>;
<del>okButton.onclick = okayClick();</del>
okButton.onclick = <em>okayClick</em>;
</pre>
<ul>
<li>our <span class="term">JSLint</span> checker will catch this mistake</li>
</ul>
</li>
<li>event names are all lowercase, not capitalized like most variables
<pre class="examplecode js">
<del>window.onLoad = pageLoad;</del>
window.<em>onload</em> = pageLoad;
</pre>
</li>
</ul>
</div> -->
<div class="slide titleslide">
<h1>Querying the DOM with jQuery</h1>
<ol>
<li>Functions & Objects</li>
<li>Global DOM Objects</li>
<li>“Unobtrusive” event handlers</li>
<li>JavaScript libraries</li>
<li><strong>Querying the DOM with jQuery</strong></li>
<li>Inspecting the page with jQuery</li>
</ol>
</div>
<div class="slide">
<h1>Complex DOM manipulation problems</h1>
<p>
How would we do each of the following in JavaScript code? Each involves modifying each one of a group of elements ...
</p>
<ul>
<li>When the Go button is clicked, reposition all the <code>div</code>s of class <code>puzzle</code> to random x/y locations.</li>
<li>When the user hovers over the maze boundary, turn all maze walls red.</li>
<li>Change every other item in the <code>ul</code> list with <code>id</code> of <code>TAs</code> to have a gray background.</li>
</ul>
<p style="font-size: 200%; font-style: italic; margin: 1em 0">Querying = selecting + filtering + traversing</p>
</div>
<div class="slide">
<h1>
The DOM tree
<span class="readingsection">(8.3)</span>
</h1>
<div class="figure">
<img src="images/dom_tree.gif" alt="DOM tree" />
</div>
<ul>
<li>
The elements of a page are nested into a tree-like structure of objects
<ul>
<li>
the DOM has properties and methods for traversing this tree
</li>
</ul>
</li>
<li>Relationships expressed in terms of parent/child, sibling, ancestor/decendant</li>
</ul>
</div>
<div class="slide">
<h1>Selecting elements from the DOM</h1>
<pre class="syntaxtemplate js">
$('<var>selector</var>')
<var>jQueryObj</var>.add('<var>selector</var>')
</pre>
<pre class="examplecode js">
var $links = <em>$('#header li.selected a')</em>;
$links = $links<em>.add('table.contents tr:nth-child(odd) a')</em>;
$links = $links<em>.add('a.popout')</em>;
$links.click(popoutClick); <span class="comment">// do something to the entire set of selected elements</span>
</pre>
<ul>
<li>Use <code>$</code> with CSS-style selectors to target elements in the DOM</li>
<li>Use <code>add</code> function with more selectors to add new elements to a query</li>
<li>Multiple “search results” can be combined into the same jQuery object</li>
<li>Use any valid CSS selector, or a jQuery extension (see next slides)</li>
</ul>
</div>
<div class="slide">
<h1>CSS 1–2 Selectors</h1>
<table id="css2_selectors" class="standard" style="font-size: 90%">
<tr>
<td><code>*</code>, <code>#<var>id</var></code>, <code>.<var>class</var></code></td>
<td>all selector; ID & class selectors</td>
</tr>
<tr>
<td><code><var>selector1</var>, <var>selector2</var>, <var>selectorN</var></code></td>
<td>multiple selector</td>
</tr>
<tr>
<td><code><var>ancestor</var> <var>descendant</var></code></td>
<td>descendant selector</td>
</tr>
<tr>
<td><code><var>parent</var> > <var>child</var></code></td>
<td>child selector</td>
</tr>
<tr>
<td><code><var>prev sibling</var> + <var>next sibling</var></code></td>
<td>next adjacent sibling selector</td>
</tr>
<tr>
<td><code><var>prev sibling</var> ~ <var>following siblings</var></code></td>
<td>following siblings selector</td>
</tr>
<tr>
<td><code>:first-child</code></td>
<td>first child selector</td>
</tr>
<tr>
<td><code>:link</code>†, <code>:active</code>†, <code>:visited</code>†</td>
<td>hyperlink state selectors</td>
</tr>
<tr>
<td><code>:hover</code>†, <code>:focus</code></td>
<td>hover (mouse) and focus (receiving input, for form fields) state selectors</td>
</tr>
<tr>
<td style="white-space: nowrap"><code>[<var>attr</var>]</code>†, <code>[<var>attr</var>="<var>value</var>"]</code>, <code>[<var>attr</var>~="<var>value</var>"]</code></td>
<td>attribute selectors</td>
</tr>
</table>
<p class="aside" style="font-size: 90%">† Supported by jQuery only in browsers with native support via <code>querySelectorAll()</code>.</p>
</div>
<div class="slide">
<h1>CSS 3 Selectors</h1>
<style type="text/css">
#css2_selectors code,
#css3_selectors code {
white-space: nowrap;
}
</style>
<table id="css3_selectors" class="standard" style="font-size: 90%">
<tr>
<td><code>:target</code>†</td>
<td>URL target selector</td>
</tr>
<tr>
<td><code>:enabled</code>, <code>:disabled</code>, <code>:checked</code></td>
<td>enabled/disabled (form controls) and checked (radio, checkbox) state selectors</td>
</tr>
<tr>
<td><code>:nth-child(<var>a</var>n+<var>b</var>)</code>, <code>:nth-child(odd)</code>, <code>:nth-child(even)</code></td>
<td><var>n</var>th child selectors</td>
</tr>
<tr>
<td><code>:first-of-type</code>†, <code>:last-of-type</code>†, <code>:nth-of-type(<var>a</var>n+<var>b</var>)</code>†</td>
<td><var>n</var>th child of a type selectors</td>
</tr>
<tr>
<td><code>:last-child</code>, <code>:only-child</code>, <code>:only-of-type</code>†</td>
<td>last/only child selectors</td>
</tr>
<tr>
<td><code>:empty</code></td>
<td>empty element selector</td>
</tr>
<tr>
<td><code>:not(<var>selector</var>)</code></td>
<td>negation selector</td>
</tr>
</table>
<p class="aside" style="font-size: 90%">† Supported by jQuery only in browsers with native support via <code>querySelectorAll()</code>.</p>
</div>
<div class="slide">
<h1>jQuery-specific selectors</h1>
<p>These selectors are supported by <code>$</code>, <code>add</code>, and other jQuery functions but aren’t part of any CSS spec.</p>
<table id="jquery_selectors" class="standard" style="font-size: 90%">
<tr>
<td><code>:even</code>, <code>:odd</code></td>
<td>even/odd element selector</td>
</tr>
<tr>
<td><code>:gt(<var>index</var>)</code>, <code>:eq(<var>index</var>)</code>, <code>:lt(<var>index</var>)</code></td>
<td>greater than, equal, or less than index result selectors</td>
</tr>
<tr>
<td><code>:first</code>, <code>:last</code></td>
<td>first and last result selectors</td>
</tr>
<tr>
<td><code>:visible</code>, <code>:hidden</code></td>
<td>visible/hidden element selector</td>
</tr>
<tr>
<td><code>:selected</code></td>
<td>selected <code><option></code> element selector</td>
</tr>
<tr>
<td><code>:has(<var>selector</var>)</code></td>
<td>having-element selector</td>
</tr>
</table>
</div>
<div class="slide">
<h1>Filtering a jQuery selection</h1>
<pre class="syntaxtemplate js">
<var>jQueryObj</var>.not('<var>selector</var>')
<var>jQueryObj</var>.first()
<var>jQueryObj</var>.last()
<var>jQueryObj</var>.eq(<var>index</var>)
<var>jQueryObj</var>.slice(<var>start</var>, <var>end</var>)
<var>jQueryObj</var>.filter('<var>selector</var>')
</pre>
<pre class="examplecode js">
var $links = $('#header li.selected a'); <span class="comment">// start with a broader set of results</span>
$links = $links<em>.not('#contact')</em>; <span class="comment">// remove some</span>
var $first_row = $('table.contents tr')<em>.first()</em>; <span class="comment">// get the first result</span>
var $third_row = $('table.contents tr')<em>.eq(2)</em>; <span class="comment">// get the nth result</span>
</pre>
<ul>
<li>Use filter functions to remove certain results from the set</li>
<li>Can reduce results to only a single element with <code>first</code>, <code>last</code>, <code>eq</code></li>
<li>Can find descendants of current results which match selector using <code>filter</code></li>
</ul>
</div>
<div class="slide">
<h1>Traversing the DOM with jQuery</h1>
<pre class="syntaxtemplate js">
<var>jQueryObj</var>.parent()
<var>jQueryObj</var>.parents()
<var>jQueryObj</var>.children()
<var>jQueryObj</var>.next()
<var>jQueryObj</var>.prev()
<var>jQueryObj</var>.siblings()
<var>jQueryObj</var>.contents()
<var>jQueryObj</var>.find('<var>selector</var>')
</pre>
<pre class="examplecode js">
var $foos = $('.foo'); <span class="comment">// set of all foos</span>
var $foos_parents = $foos.parent(); <span class="comment">// set of the parent of each foo</span>
var $foos_ancestors = $foos.parents(); <span class="comment">// set of ancestors of each foo</span>
var $foos_aunts_uncles = $foos.parent().siblings();
var $foos_children = $foos.children(); <span class="comment">// children of all foos</span>
var $lis_in_foos = $foos.find('li'); <span class="comment">// all li's inside foos</span>
</pre>
<ul>
<li>Can use parent/child, sibling, ancestor/descendent relations to find elements related to a selection</li>
</ul>
</div>
<div class="slide titleslide">
<h1>Inspecting the page with jQuery</h1>
<ol>
<li>Functions & Objects</li>
<li>Global DOM Objects</li>
<li>“Unobtrusive” event handlers</li>
<li>JavaScript libraries</li>
<li>Querying the DOM with jQuery</li>
<li><strong>Inspecting the page with jQuery</strong></li>
</ol>
</div>
<div class="slide">
<h1>Setting styles with jQuery</h1>
<pre class="syntaxtemplate js">
<del><var>obj</var>.style.<var>property</var> = '<var>value</var>'</del>
<var>jQueryObj</var>.css('<var>property</var>')
<var>jQueryObj</var>.css('<var>property</var>', '<var>value</var>')
</pre>
<pre class="examplecode js">
$('a:link').css('text-decoration', 'none');
var top_margin = $('p').css('margin-top'); <span class="comment">// only gets the margin of the FIRST result</span>
</pre>
<ul>
<li>Gets or sets the CSS property on all elements in <var>jQueryObj</var></li>
<li>Easier than standard DOM
<ul>
<li>Can’t inspect styles using <code>.style</code></li>
<li>Have to use other functions <code>.getComputedStyle()</code> or <code>.currentStyle</code> / <code>.runtimeStyle</code>, which are inconsistent across browsers</li>
</ul>
</li>
<li>Important: when inspecting styles, only returns the property of the <strong>first</strong> result</li>
</ul>
</div>
<div class="slide">
<h1>Adding/removing classes with jQuery</h1>
<pre class="syntaxtemplate js">
<del><var>obj</var>.className = '<var>class(es)</var>'</del>
<var>jQueryObj</var>.addClass('<var>class</var>')
<var>jQueryObj</var>.removeClass('<var>class</var>')
<var>jQueryObj</var>.toggleClass('<var>class</var>')
<var>jQueryObj</var>.hasClass('<var>class</var>')
</pre>
<pre class="examplecode js">
$('#header ul li:first-child').addClass('selected');
</pre>
<ul>
<li>In standard DOM, have to manually parse/edit <code>className</code> string to add/remove a class.</li>
<li>jQuery adds functions to add, remove, toggle classes</li>
</ul>
</div>
<div class="slide">
<h1>Setting HTML attributes with jQuery</h1>
<pre class="syntaxtemplate js">
<del><var>obj</var>.<var>attributeName</var> = '<var>value</var>'</del>
<var>jQueryObj</var>.attr('<var>name</var>')
<var>jQueryObj</var>.attr('<var>name</var>', '<var>value</var>')
<var>jQueryObj</var>.removeAttr('<var>name</var>')
</pre>
<pre class="examplecode js">
<del>document.getElementById('puppies').src = 'images/hoff.jpg';</del>
$('img#puppies').attr('src', 'images/hoff.jpg');
</pre>
<ul>
<li>Identical to setting the attribute on a regular DOM object, but applies to all results in set</li>
</ul>
</div>
<div class="slide">
<h1>Form properties in jQuery</h1>
<pre class="syntaxtemplate js">
<del><var>formObj</var>.value = '<var>text</var>'</del>
<del><var>radioOrCheckboxObj</var>.checked = <var>boolean</var></del>
<del><var>optionObj</var>.selected = <var>boolean</var></del>
var value = <var>jQueryObj</var>.val()
<var>jQueryObj</var>.val('<var>new value</var>')
<var>jQueryObj</var>.is(':checked')
<var>jQueryObj</var>.prop('checked', <var>boolean</var>)
<var>jQueryObj</var>.is(':selected')
<var>jQueryObj</var>.prop('selected', <var>boolean</var>)
<var>jQueryObj</var>.is(':disabled')
<var>jQueryObj</var>.prop('disabled', <var>boolean</var>)
</pre>
<pre class="examplecode js">
<del>document.getElementById('netid').value = 'mdoocy';</del>
<del>document.getElementById('vegetarian').checked = false;</del>
<del>document.getElementById('submit').disabled = true;</del>
$('#netid').val('mdoocy');
$('#vegetarian').prop('checked', false);
$('#submit').prop('disabled', true);
</pre>
<ul>
<li>Set/get value in text box with <code>.val()</code></li>
<li>Use <code>.is()</code> to inspect other properties, <code>.prop()</code> to set them</li>
</ul>
</div>
<div class="slide">
<h1>Getting/setting HTML & text content in jQuery</h1>
<pre class="syntaxtemplate js">
<del>var text = <var>obj</var>.innerHTML</del>
<del><var>obj</var>.innerHTML = '<var>text</var>'</del>
var text = <var>jQueryObj</var>.text()
<var>jQueryObj</var>.text('<var>new value</var>')
var HTML = <var>jQueryObj</var>.html()
<var>jQueryObj</var>.html('<var>new HTML code</var>')
</pre>
<pre class="examplecode js">
<del>var mission_statement = document.getElementById('mission').innerHTML;</del>
<del>document.getElementById('mission').innerHTML = "To boldly go where no can has gone before";</del>
<del>document.getElementById('plan').innerHTML = "<ol><li>Code</li><li>???</li><li>Profit!</li></ol>";</del>
var mission_statement = $('#mission').text();
$('#mission').text('To boldly go where no can has gone before');
$('#plan').html('<ol><li>Code</li><li>???</li><li>Profit!</li></ol>');
</pre>
<ul>
<li>Use <code>.text()</code> to get/set plain-text content in an element</li>
<li>Use <code>.html()</code> to get/set HTML content in an element</li>
</ul>
</div>
<!--#include virtual="../s5/commonbottom.html" -->