info343/lectures/form-validation/lecture14-unobtrusive-timers.shtml

<!--#include virtual="commontop.html" -->
      <title>Web Programming Step by Step, Lecture 14: Unobtrusive JavaScript and Timers</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><em>Web Programming Step by Step</em>, Lecture 14</h1>
            <h2>Unobtrusive JavaScript and Timers</h2>
         </div>
      </div>

      <div class="presentation">
         <div class="slide">
            <h1><a href="http://www.webstepbook.com/">Web Programming Step by Step</a></h1>
            <h3>Lecture 14 <br /> Unobtrusive JavaScript and Timers</h3>
            <h4>Reading: 7.2 - 7.3; 8.1 - 8.2; 9.2.6</h4>

            <p class="license">
               Except where otherwise noted, the contents of this presentation are Copyright 2010 Marty Stepp and Jessica Miller.
            </p>

            <div class="w3c">
               <a href="http://validator.w3.org/check/referer"><img src="images/w3c-xhtml11.png" alt="Valid XHTML 1.1" /></a>
               <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="images/w3c-css.png" alt="Valid CSS!" /></a>
            </div>
         </div>
         
         
         
         <div class="slide">
            <h1>Problems with JavaScript</h1>

            <p>
               JavaScript is a powerful language, but it has many flaws:
            </p>

            <ul>
               <li>the DOM can be clunky to use</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.)
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>
               <a href="http://prototypejs.org/">Prototype</a> framework
            </h1>

<pre class="examplecode js" style="font-size: smaller">
&lt;script <em>src=&quot;http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js&quot;</em> 
 type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</pre>

            <ul>
               <li>the <a href="http://prototypejs.org/">Prototype</a> JavaScript library adds many useful features to JavaScript:
                  <ul>
                     <li>many useful <a class="popup" href="http://prototypejs.org/learn/extensions">extensions to the DOM</a></li>
                     <li>added methods to String, Array, Date, Number, Object</li>
                     <li>improves event-driven programming</li>
                     <li>many cross-browser compatibility fixes</li>
                     <li>makes <a class="popup" href="http://prototypejs.org/learn/introduction-to-ajax">Ajax programming</a> easier (seen later)</li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>
               The <a href="http://www.prototypejs.org/api/utility/dollar"><code>$</code></a> function
               <span class="readingsection">(9.1.3)</span>
            </h1>

            <pre class="syntaxtemplate js">
$(&quot;<var>id</var>&quot;)
</pre>

            <ul>
               <li>
                  returns the DOM object representing the element with the given <code>id</code>
               </li>
               <li>
                  short for <code>document.getElementById(&quot;<var>id</var>&quot;)</code>
               </li>
               <li>
                  often used to write more concise DOM code:
                  
                  <pre class="examplecode js">
$(&quot;footer&quot;).innerHTML = $(&quot;username&quot;).value.toUpperCase();
</pre>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>
               Unobtrusive JavaScript
               <span class="readingsection">(8.1.1)</span>
            </h1>

            <ul>
               <li>JavaScript event code seen previously was <em>obtrusive</em>, in the HTML; this is bad style</li>
               <li>now we'll see how to write <a href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript"><em>unobtrusive</em> JavaScript</a> code
                  <ul>
                     <li>HTML with minimal JavaScript inside</li>
                     <li>uses the DOM to attach and execute all JavaScript functions</li>
                  </ul>
               </li>
               <li>allows <a href="http://alistapart.com/articles/behavioralseparation">separation</a> of web site into 3 major categories:
                  <ul>
                     <li><span class="term">content</span> (HTML) - what is it?</li>
                     <li><span class="term">presentation</span> (CSS) - how does it look?</li>
                     <li><span class="term">behavior</span> (JavaScript) - how does it respond to user interaction?</li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>Obtrusive event handlers (bad)</h1>

            <div class="example">
               <pre class="examplecode html">
&lt;button <em class="bad">onclick=&quot;okayClick();&quot;</em>&gt;OK&lt;/button&gt;
</pre>

               <pre class="examplecode js">
<span class="comment">// called when OK button is clicked</span>
function okayClick() {
   alert(&quot;booyah&quot;);
}
</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 in JavaScript code</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">
&lt;button <em>id=&quot;ok&quot;</em>&gt;OK&lt;/button&gt;
</pre>
               <pre class="examplecode js">
$(&quot;ok&quot;).<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">
   &lt;head&gt;
      <em>&lt;script src=&quot;myfile.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</em>
   &lt;/head&gt;

   &lt;body&gt; ... &lt;/body&gt;
</pre>

<pre class="examplecode examplecode2 examplecodelast js">
<span class="comment">// global code</span>
var x = 3;
function f(n) { return n + 1; }
function g(n) { return n - 1; }
x = f(x);
</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">
   &lt;head&gt;
      <em>&lt;script src=&quot;myfile.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</em>
   &lt;/head&gt;

   &lt;body&gt;
      &lt;div&gt;&lt;button id=&quot;ok&quot;&gt;OK&lt;/button&gt;&lt;/div&gt;
</pre>

<pre class="examplecode examplecode2 examplecodelast js">
<span class="comment">// global code</span>
<em class="bad">$(&quot;ok&quot;).onclick = okayClick;</em>   <span class="comment">// error: $("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">// this will run once the page has finished loading</span>
function <var>functionName</var>() {
   <var>element</var>.<var>event</var> = <var>functionName</var>;
   <var>element</var>.<var>event</var> = <var>functionName</var>;
   ...
}

<em>window.onload = <var>functionName</var>;</em>   <span class="comment">// global code</span>
</pre>
            
            <ul>
               <li>we want to attach our event handlers right after the page is done loading</li>
                  <ul>
                     <li>there is a global event called <code>window.onload</code> event 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">&lt;!-- look Ma, no JavaScript! --&gt;</span>
&lt;button id=&quot;ok&quot;&gt;OK&lt;/button&gt;
</pre>

               <pre class="examplecode examplecode2 js">
<span class="comment">// called when page loads; sets up event handlers</span>
function pageLoad() {
   $(&quot;ok&quot;).onclick = okayClick;</em>
}

function okayClick() {
   alert(&quot;booyah&quot;);
}

<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>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">
            <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 function example</h1>

            <div class="example">
               <pre class="examplecode js">
window.onload = <em>function() {</em>
   var okButton = document.getElementById(&quot;ok&quot;);
   okButton.onclick = okayClick;
<em>};</em>

function okayClick() {
   alert(&quot;booyah&quot;);
}
</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(&quot;ok&quot;);
   okButton.onclick = <em>function() {</em>
      alert(&quot;booyah&quot;);
   <em>};</em>
<em>};</em>
</pre>
         </div>
         
         
         
         <div class="slide">
            <h1>
               Unobtrusive styling
               <span class="readingsection">(8.2.3)</span>
            </h1>

<pre class="examplecode js">
function okayClick() {
   <del>this.style.color = &quot;red&quot;;</del>
   this.<em>className = &quot;highlighted&quot;</em>;
}
</pre>

<pre class="examplecode css">
.<em>highlighted</em> { color: red; }
</pre>
            
            <ul>
               <li>well-written JavaScript code should contain as little CSS as possible</li>
               <li>use JS to set CSS classes/IDs on elements</li>
               <li>define the styles of those classes/IDs in your CSS file</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>
               Timer events
               <span class="readingsection">(9.2.6)</span>
            </h1>
            
            <div class="topfigure" style="width: 12%">
               <img src="images/timer.gif" alt="timer" style="width: 100%" />
            </div>
            
            <table class="standard">
               <tr>
                  <th>
                     method
                  </th>
                  <th>
                     description
                  </th>
               </tr>
               
               <tr>
                  <td>
                     <code><a href="http://www.w3schools.com/htmldom/met_win_settimeout.asp">setTimeout</a>(<var>function</var>,&nbsp;<var>delayMS</var>);</code>
                  </td>
                  <td>
                     arranges to call given function after given delay in ms
                  </td>
               </tr>

               <tr>
                  <td>
                     <code><a href="http://www.w3schools.com/htmldom/met_win_setinterval.asp">setInterval</a>(<var>function</var>,&nbsp;<var>delayMS</var>);</code>
                  </td>
                  <td>
                     arranges to call function repeatedly every <var>delayMS</var> ms
                  </td>
               </tr>
               
               <tr>
                  <td>
                     <code><a href="http://www.w3schools.com/htmldom/met_win_cleartimeout.asp">clearTimeout</a>(<var>timerID</var>);</code> <br />
                     <code><a href="http://www.w3schools.com/htmldom/met_win_clearinterval.asp">clearInterval</a>(<var>timerID</var>);</code>
                  </td>
                  <td>
                     stops the given timer so it will not call its function
                  </td>
               </tr>
            </table>
            
            <ul>
               <li>
                  both <code>setTimeout</code> and <code>setInterval</code> return an ID representing the timer
                  <ul>
                     <li>
                        this ID can be passed to <code>clearTimeout</code>/<code>Interval</code> later to stop the timer
                     </li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>
               <code>setTimeout</code></a> example</a>
            </h1>

            <div class="example">
               <pre class="examplecode html">
&lt;button <em>onclick=&quot;delayMsg();&quot;</em>&gt;Click me!&lt;/button&gt;
&lt;span <em>id=&quot;output&quot;</em>&gt;&lt;/span&gt;
</pre>

               <pre class="examplecode examplecode2 js">
function delayMsg() {
   <em>setTimeout(booyah, 5000)</em>;
   $(&quot;output&quot;).innerHTML = &quot;Wait for it...&quot;;
}

function booyah() {   <span class="comment">// called when the timer goes off</span>
   $(&quot;output&quot;).innerHTML = &quot;BOOYAH!&quot;;
}
</pre>

               <div class="exampleoutput">
                  <button onclick="document.getElementById('output').innerHTML = 'Wait for it...'; setTimeout(&quot;document.getElementById('output').innerHTML = 'BOOYAH!';&quot;, 5000)">Click me!</button>
                  <span id="output"></span>
               </div>
            </div>
         </div>



         <div class="slide">
            <h1>
               <code>setInterval</code> example
            </h1>

            <div class="example">
               <pre class="examplecode examplecode2 js">
<em>var timer = null;</em>  <span class="comment">// stores ID of interval timer</span>

function delayMsg2() {
   if (timer == null) {
      <em>timer = setInterval(rudy, 1000)</em>;
   } else {
      <em>clearInterval(timer)</em>;
      timer = null;
   }
}

function rudy() {   <span class="comment">// called each time the timer goes off</span>
   $(&quot;output&quot;).innerHTML += &quot; Rudy!&quot;;
}
</pre>

               <div class="exampleoutput">
                  <script type="text/javascript">
                     window.timer = null;

                     window.delayMsg2 = function() {
                        if (timer == null) {
                           timer = setInterval(rudy, 1000);
                        } else {
                           clearInterval(timer);
                           timer = null;
                        }
                     };

                     window.rudy = function() {
                        document.getElementById("output2").innerHTML += " Rudy!";
                     };
                  </script>
                  
                  <button onclick="delayMsg2();">Click me!</button>
                  <span id="output2"></span>
               </div>
            </div>
         </div>



         <div class="slide">
            <h1>Passing parameters to timers</a></h1>

            <div class="example">
               <pre class="examplecode js">
function delayedMultiply() {
   <span class="comment">// 6 and 7 are passed to multiply when timer goes off</span>
   setTimeout(multiply, 2000<em>, 6, 7</em>);
}
function multiply(<em>a, b</em>) {
   alert(a * b);
}
</pre>

               <div class="exampleoutput insertoutput">
                  <button onclick="delayedMultiply();">Click me</button>
               </div>
            </div>

            <ul>
               <li>any parameters after the delay are eventually passed to the timer function
                  <ul>
                     <li>doesn't work in IE6; must create an intermediate function to pass the parameters</li>
                  </ul>
               </li>
               <li>
                  why not just write this?
                  <pre class="examplecode js">
setTimeout(<em>multiply(6 * 7)</em>, 2000);
</pre>
               </li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Common timer errors</h1>
            
            <ul>
               <li>
                  many students mistakenly write <code>()</code> when passing the function

                  <pre class="examplecode js">
<del>setTimeout(booyah(), 2000);</del>
setTimeout(<em>booyah</em>, 2000);

<del>setTimeout(multiply(num1 * num2), 2000);</del>
setTimeout(<em>multiply</em>, 2000<em>, num1, num2</em>);
</pre>

                  <ul>
                     <li>what does it actually do if you have the <code>()</code> ?</li>
                     <li class="incremental">it calls the function immediately, rather than waiting the 2000ms!</li>
                  </ul>
               </li>
            </ul>
         </div>



<!--#include virtual="commonbottom.html" -->