info343/minilabs/8/solutions.php

<p>Below is are possible answers to the questions in this lab.</p>

<style type="text/css">
   #solution ol {
      margin: 0;
      padding: 0 1em 0 2.5em;
      background-color: white;
      border: solid 1px #ccc;
   }
   
   #solution pre {
      border: solid 1px #ccc;
      padding: .05em .25em;
   }
   
   #solution code {
      color: #666;
   }
   
   #solution code strong {
      color: #800;
   }
   
   #solution code ins {
      color: #800;
      font-weight: bold;
      background-color: inherit;
      text-decoration: underline;
   }
   
   #solution code em {
      font-weight: bold;
      font-style: normal;
      font-family: Menlo, Consolas, "Andale Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Lucida Console", "Lucida Sans Typewriter", Monaco, monospace;
      color: #800;
   }
   
   #solution code del {
      background-color: inherit;
      color: #800;
      font-weight: bold;
   }
</style>

<header>
   <h3>HTML/Basic CSS</h3>
</header>

<ol>
   <li>
      <p>An ID is for a single, unique element on the page. (No two things on the same page can have the same ID.) According to <a href="http://stackoverflow.com/a/192066">this StackOverflow answer</a>, a single element cannot have two different IDs. However, a single element can have multiple classes (separated by spaces), and multiple elements in a page can have the same class(es):</p>
<pre style="width: 28em"><code>&lt;p class="<strong>note important</strong>"&gt;...&lt;/p&gt;
...
&lt;ul&gt;
&lt;li class="<strong>important</strong>"&gt;&lt;/li&gt;
&lt;/ul&gt;</code></pre>
   </li>
   
   <li>
      <p>Following is the snippet with corrections applied:</p>
<pre><code>...
&lt;body&gt;
<ins>&lt;div&gt;</ins>&lt;img <em>id="foo"</em> src="foo.jpg" <ins>alt="..."</ins> <ins>/</ins>&gt;<ins>&lt;/div&gt;</ins>
&lt;div <em>class="bar"</em>&gt;
&lt;em&gt;Lorem ipsum<del>&lt;br/&gt;</del>
<del>&lt;br/&gt;</del>
&lt;strong <em>class="bar"</em>&gt;dolor<ins>&lt;/strong&gt;</ins>&lt;/em&gt;<ins>&lt;strong&gt;</ins> sit&lt;/strong&gt; amet, ...
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.google.com/?q=lorem+ipsum<ins>&amp;amp;</ins>hl=en"&gt;Amet!&lt;/a&gt;<del>&lt;/li&gt;</del>
&lt;ul&gt;
&lt;li <em>id="foo"</em>&gt;et al.&lt;/li&gt;
&lt;/ul&gt;
<ins>&lt;/li&gt;</ins>
&lt;/ul&gt;
&lt;/body&gt;
...
</code></pre>
      
      <p>Validation errors:</p>
      <ul>
         <li>An <code>img</code> is an inline-block element. Inline and inline-block elements always need to be wrapped in a block element (like <code>div</code>).</li>
         <li>The <code>img</code> and the <code>li</code> cannot have the same <code>id</code> attribute.</li>
         <li>The <code>img</code> is missing an <code>alt</code> attribute and the self-closing slash (in XHTML).</li>
         <li>The <code>em</code> and <code>strong</code> tags were improperly nested.</li>
         <li>The embedded <code>ul</code> was improperly nested; it needed to be inside an <code>li</code>, not in the outer <code>ul</code>.</li>
         <li>There was an unescaped ampersand in the link’s URL. Ampersands always need to be escaped, even inside a URL: <code>&amp;amp;</code></li>
      </ul>
      
      <p>Bad Things:</p>
      <ul>
         <li>It’s usually bad style to attach the same class to a child element and its parent. Not always, but this is a red flag that means you’re probably doing something wrong.</li>
         <li>Arguably, the <code>div</code> of the class <code>bar</code> should be a paragraph instead of a div, because it contains a sentence.</li>
         <li>More than one <code>br</code> tag in a row is bad. Use CSS margin/padding to add vertical space between elements.</li>
      </ul>
   </li>
   
   <li>The technical term for “tag” is <strong>element</strong>. The technical term for properties of those tags is <strong>attribute</strong>.</li>
</ol>


<header>
   <h3>Layout</h3>
</header>

<ol>
   <li>
      <p>From inside to outside, the box model properties are:</p>
      <ul>
         <li><code>width</code>/<code>height</code> (the “content area”)</li>
         <li><code>padding</code> (space inside the border, outside the content area)</li>
         <li><code>border</code></li>
         <li><code>margin</code> (space outside the border, between elements)</li>
      </ul>
   </li>
   
   <li>
      <ul>
         <li>
            <p>So far we’ve learned about <i>inline</i> (e.g., <code>strong</code>, <code>em</code>, <code>span</code>, <code>a</code>, etc.), <i>block</i> (<code>p</code>, <code>div</code>, <code>ul</code>/<code>ol</code>, <code>li</code>, <code>dl</code>/<code>dt</code>/<code>dd</code>, etc.), and <i>inline-block</i> (<code>img</code>) elements.</p>
         </li>
         <li>The CSS <code>display</code> property allows you to change an element from one type to another.</li>
         <li>Block-level elements have full box models, as do inline-block. Inline elements, however, are missing <code>margin-top</code>, <code>margin-bottom</code>, and <code>width</code>/<code>height</code>.</li>
      </ul>
   </li>
   
   <li>
      <p>A few different ways of hiding an element:</p>
      <ul>
         <li>
            <p>Setting <code>display: none</code>…</p>
            <ul>
               <li>…in CSS: <code>display: none;</code></li>
               <li>…from JS: <code><var>elem</var>.style.display = 'none';</code></li>
               <li>…using jQuery: <code><var>$obj</var>.css('display', 'none');</code></li>
            </ul>
         </li>
         <li>
            <p>Setting <code>visibility: hidden</code>…</p>
            <ul>
               <li>…in CSS: <code>visibility: hidden;</code></li>
               <li>…from JS: <code><var>elem</var>.style.visibility = 'hidden';</code></li>
               <li>…using jQuery: <code><var>$obj</var>.css('visibility', 'hidden');</code></li>
            </ul>
            <p>(Note that this will make the element invisible, but still take up space.)</p>
         </li>
         <li>Using jQuery’s <code>.hide()</code> function (which sets <code>display: none</code> underlying).</li>
      </ul>
   </li>
   
   <li>
      <p>One way of accomplishing this is by using “outer” and “inner” container elements for each column. Widths are specified on the outer containers, both of which are floated left. The inner containers can then have fixed margin or padding without affecting the overall width of the outer elements.</p>
   </li>
   <li>
      <ul>
         <li>
            <p>The position property has four possible values:</p>
            <dl>
               <dt><code>static</code></dt>
                  <dd>The element’s default behavior.</dd>
               <dt><code>relative</code></dt>
                  <dd>The element becomes a “bounding parent” for any absolutely- or fixed-positioned children. Also, specifying <code>left</code>, <code>right</code>, <code>top</code>, or <code>bottom</code> shifts the element <em>with respect to where it was</em> in the normal document flow.</dd>
               <dt><code>absolute</code></dt>
                  <dd>The element is removed from the normal document flow (so that later elements re-flow). It is positioned at the absolute location specified by the <code>left</code>, <code>right</code>, <code>top</code>, and <code>bottom</code> properties. (If inside a relatively-positioned element, this is with respect to that element’s boundaries; otherwise, it’s with respect to the visible portion of the page on-screen.)</dd>
               <dt><code>fixed</code></dt>
                  <dd>The element is removed from the normal document flow (so that later elements re-flow). It is positioned at the location <em>with respect to the browser window</em> specified by the <code>left</code>, <code>right</code>, <code>top</code>, and <code>bottom</code> properties. It doesn’t move when the page is scrolled.</dd>
            </dl>
         </li>
         <li><code>left</code>, <code>right</code>, <code>top</code>, and <code>bottom</code>. And also <code>z-index</code>.</li>
         <li>See above for how <code>left</code>, <code>right</code>, <code>top</code>, and <code>bottom</code> affect the placement of an element depending on the value for <code>position</code>.</li>
      </ul>
   </li>
</ol>

<header>
   <h3>The DOM &amp; jQuery</h3>
</header>

<style type="text/css">
   #solution figure {
      position: static;
      width: auto;
      margin: 0;
   }
   #solution var {
      font-weight: bold;
   }
   #solution figcaption {
      padding-left: .625em;
   }
   #solution table {
/*               background-color: fuchsia;*/
/*               margin: 1em;*/
   }
   #solution caption {
      display: none;
   }
   #solution table th,
   #solution table td {
      padding: .25em .5em;
      white-space: nowrap;
      vertical-align: baseline;
   }
</style>

<ol>
   <li>The DOM is an inventory of the HTML elements on the page and their various properties, including CSS styles that are applied to them. Every element is represented with an object in the DOM, and these objects can have their properties changed to modify the contents or appearance of things on-screen.</li>
   <li>A DOM object is something that you can interact with to change an element on-screen. A jQuery object is a set of search results returned by <code>$()</code>. It contains zero or more DOM objects, and has special methods to perform the same operation on all of the DOM objects inside of it.</li>
   <li>
      <p>In the table below, <code><var>elem</var></code> means a standard DOM object, and <code><var>$obj</var></code> means a jQuery object.</p>
      <table>
         <thead>
            <tr>
               <th>Operation</th>
               <th>Standard DOM</th>
               <th>jQuery</th>
            </tr>
         </thead>
         <tbody>
            <tr>
               <td>Setting CSS styles</td>
               <td><code><var>elem</var>.style.<var>property</var> = '<var>value</var>';</code></td>
               <td><code><var>$obj</var>.css('<var>property</var>', '<var>value</var>');</code></td>
            </tr>
            <tr>
               <td>Changing an element’s text</td>
               <td><code><var>elem</var>.innerHTML = '<var>string</var>';</code></td>
               <td><code><var>$obj</var>.text('<var>string</var>');</code></td>
            </tr>
            <tr>
               <td>Attaching a click handler</td>
               <td><code><var>elem</var>.onclick = <var>func</var>;</code></td>
               <td><code><var>$obj</var>.click(<var>func</var>);</code></td>
            </tr>
            <tr>
               <td>
                  Running something when the<br>
                  page has finished loading
               </td>
               <td><code>window.onload = <var>func</var>;</code></td>
               <td><code>$(document).ready(<var>func</var>);</code></td>
            </tr>
            <tr>
               <td>Attaching an event handler</td>
               <td><code><var>elem</var>.on<var>event</var> = <var>func</var>;</code></td>
               <td><code><var>$obj</var>.<var>event</var>(<var>func</var>);</code></td>
            </tr>
            <tr>
               <td>Getting an element by ID</td>
               <td><code>var <var>elem</var> = document.getElementById('<var>id</var>');</code> *</td>
               <td><code>var <var>$obj</var> = $('#<var>id</var>');</code> †</td>
            </tr>
            <tr>
               <td>Creating a new element</td>
               <td><code>var <var>elem</var> = document.createElement('<var>tag</var>');</code> *</td>
               <td><code>var <var>$obj</var> = $('&lt;<var>tag</var>&gt;');</code> †</td>
            </tr>
            <tr>
               <td>
                  Getting/setting an HTML<br>
                  attribute
               </td>
               <td>
                  <code>var <var>value</var> = <var>elem</var>.<var>attribute</var>;</code><br>
                  <code><var>elem</var>.<var>attribute</var> = '<var>value</var>';</code>
               </td>
               <td>
                  <code>var <var>value</var> = <var>$obj</var>.attr('<var>attribute</var>');</code><br>
                  <code><var>$obj</var>.attr('<var>attribute</var>', '<var>value</var>');</code>
               </td>
            </tr>
            <tr>
               <td>
                  Getting/setting the value<br>
                  of a form field
               </td>
               <td>
                  <code>var <var>value</var> = <var>elem</var>.value;</code><br>
                  <code><var>elem</var>.value = '<var>value</var>';</code>
               </td>
               <td>
                  <code>var <var>value</var> = <var>$obj</var>.val()</code>;<br>
                  <code><var>$obj</var>.val('<var>value</var>');</code>
               </td>
            </tr>
         </tbody>
         <tfoot>
            <tr>
               <td></td>
               <td style="white-space: inherit;">* returns a standard DOM object; must be wrapped in <code>$()</code> to get a jQuery object</td>
               <td>† returns a jQuery object</td>
            </tr>
         </tfoot>
      </table>
   </li>
   
   <li>
      <p>Following is the snippet with some preliminary corrections:</p>
<pre><code><del>$('foo').innerHTML = 'Hello world, I'm a string!';</del>
window.onload<del>()</del> = <ins>function()</ins> {
<ins>$('foo').innerHTML = 'Hello world, I'm a string!';</ins>
<ins>var</ins> <del>$</del>bar = 42;
document.getElementById('.bar').css('width', <del>$</del>bar);
}<ins>;</ins>
</code></pre>
      <p>Since the first line tries to access an element from the page, it must be delayed until after the page has finished loading. Thus the entire first line needs to go inside the <code>onload</code> function.</p>
      
      <p>The <code>window.onload</code> line has two major syntax errors corrected. The variable declaration has the <code>var</code> keyword added, and the <code>$</code> removed from the name of the variable. (This is the “Bad Thing”: There is a convention to include a <code>$</code> at the beginning of variables <em>which store jQuery objects</em>. Since that variable stores a plain number, and not a jQuery object, so it should not have a <code>$</code>.)</p>
      
      <p>Following are some more corrections:</p>
      
<pre><code><del>window.onload =</del> <ins>$(document).ready(</ins>function() {
<del>$</del> <ins>document.getElementById</ins>('foo').innerHTML = 'Hello world, I<ins>\</ins>'m a string!';
var bar = 42;
<del>document.getElementById</del> <ins>$</ins>('.bar').css('width', bar <ins>+ 'px'</ins>);
}<ins>)</ins>;
</code></pre>
      <p>Now we’ve replaced the <code>window.onload</code> (the “Inferior Thing”) with jQuery’s slightly better <code>$(document).ready()</code>.</p>
      <p>Line 2 used the <code>$()</code> function in conjunction with a bare word (no hash) and <code>.innerHTML</code> — two things that can only be used with <code>document.getElementById()</code>, not <code>$()</code>.</p>
      <p>On line 4 we have the opposite problem: the function parameter is a CSS-style selector for a class, and not an ID — and we’re using it in conjunction with the jQuery <code>.css()</code> function, not the standard DOM <code>.style</code>. So the name of the function needs to be <code>$()</code>, not <code>document.getElementById()</code>.</p>
      <p>Line 2 also had an unescaped apostrophe inside a single-quoted string; either the apostrophe needed to be escaped (as shown), or the string needed to be double-quoted instead.</p>
      <p>Lastly, although jQuery might be smart about fixing this problem for us, we need to remember the units in any CSS dimension we set.</p>
   </li>
   
   <li>A properties and methods are variables and functions attached to an object. “Function” and “method” are often used interchangeably (frequently by a slip of the tongue), but technically they’re slightly different.</li>
</ol>