info343/lectures/internal-nav-jquery-mobile/index.shtml

<!--#include virtual="../s5/commontop.html" -->
      <title>Lecture 17: Ajax Navigation &amp; jQuery Mobile — 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 17</h1>
            <h2>Ajax Navigation &amp; jQuery Mobile</h2>
         </div>
      </div>

      <div class="presentation">
         <div class="slide">
            <h1>Internal Navigation &amp; jQuery Mobile</h1>
            <h3>Lecture 17</h3>
            <!-- <h4>Reading: 10.3–10.4</h4> -->

            <p class="license">
               © 2012 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>Internal Navigation</h1>
            
            <ul>
               <li>Many sites now provide JS-based navigation <em>within a single HTML page</em>
                  <ul>
                     <li>Ex: Google search</li>
                  </ul>
               </li>
               <li>Page contains “skeleton” with site navigation, and several “sub-pages” worth of main content</li>
               <li>Clicking links swaps out portions of the page, without loading a new HTML file</li>
               <li>Can load new “sub-page” elements via Ajax instead of having them in the initial HTML file (“Ajax navigation”)</li>
               <li>Motivations:
                  <ul>
                     <li>No more “refresh flicker”</li>
                     <li>Can display loading animation while new page is being loaded</li>
                     <li>Can animate transitions between pages
                        <ul>
                           <li>Especially common in mobile apps, where UI conventions involve “slide” effects</li>
                        </ul>
                     </li>
                  </ul>
               </li>
            </ul>
         </div>
         
         
         <div class="slide">
            <h1>Example: Internal Navigation</h1>
<div class="example">
<pre class="examplecode js" style="float: right; width: 48%">
$(document).ready(function() {
   <span class="comment">// When hash changes, show the page with</span>
   <span class="comment">// specified ID.</span>
   <em>$(window).hashchange</em>(function() {
      <em>navigateTo(window.location.hash);</em>
   });
   <span class="comment">// If hash in URL when page loads,</span>
   <span class="comment">// display that; else display first page.</span>
   if (window.location.hash) {
      navigateTo(window.location.hash);
   } else {
      navigateTo($('section.page').first());
   }
});
<span class="comment">// Hide old page, and display new one.</span>
function navigateTo(page) {
   $('section.page.current').removeClass('current');
   <em>$(page).addClass('current');</em>
}
</pre>
<pre class="examplecode html" style="float: left; width: 52%">
&lt;nav&gt;&lt;ul&gt;
   &lt;li&gt;&lt;a href="<em>#page1</em>"&gt;Page 1&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="<em>#page2</em>"&gt;Page 2&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="<em>#page3</em>"&gt;Page 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;
&lt;section <em>class="page" id="page1"</em>&gt;...&lt;/section&gt;
&lt;section <em>class="page" id="page2"</em>&gt;...&lt;/section&gt;
&lt;section <em>class="page" id="page3"</em>&gt;...&lt;/section&gt;
...
</pre>
<pre class="examplecode css" style="float: left; width: 52%">
<span class="comment">/* hide all initially */</span>
section<em>.page</em> { display: none; }
<span class="comment">/* page to be shown */</span>
section<em>.page.current</em> { display: block; }
</pre>
</div>
            <ul>
               <li>Use the <code>hashchange</code> event to show/hide pages when hash portion of URL changes.</li>
            </ul>
            
         </div>
         
         
         <div class="slide">
            <h1>Example: Ajax Navigation</h1>
<div class="example">
<pre class="examplecode html">
&lt;a href="contact.html"&gt;Contact Us&lt;/a&gt;
</pre>
<pre class="examplecode js">
$(document).ready(function() {
   <em>$(window).hashchange(navigate);</em>
   <em>$('a').click(hijack);</em>
});
function navigate() {
   var filename = <em>window.location.hash</em>.substring(3); <span class="comment">// remove '#!/'</span>
   <em>$('#content').load(filename);</em> <span class="comment">// inject HTML fragment file into #content</span>
}
function hijack(event) {
   <em>event.preventDefault();</em> <span class="comment">// prevent browser from navigating to page</span>
   <em>window.location.hash = '#!/' + this.href;</em> <span class="comment">// "navigate" to hash-fragment instead</span>
}
</pre>
</div>
            <ul>
               <li>Can be combined with internal navigation
                  <ul>
                     <li><code>#!</code> (“hash-bang”) can be used to differentiate from internal navigation</li>
                  </ul>
               </li>
               <li>Instead of <code>hashchange</code>, can use newer (less supported) <a href="http://diveintohtml5.info/history.html">HTML5 History API</a> and <code>.pushState()</code> to change URL in address bar without loading a new page.</li>
               <li>This example assumes a fragment HTML file (just content — no head, body, doctype, etc.).
                  <ul>
                     <li>Could instead load full HTML document and extract a page’s DOM object from it.</li>
                  </ul>
               </li>
            </ul>
            
         </div>
         
         
         <div class="slide">
            <h1>jQuery Mobile <img src="jquery-logo.png" alt="jQuery Mobile" style="height: 1.5em; vertical-align: top"/></h1>
            
<div class="example" style="font-size: 90%">
<pre class="examplecode html">
&lt;head&gt;
   ...
   <em>&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;</em>
   <em>&lt;link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css"&gt;</em>
   &lt;script src="http://code.jquery.com/jquery-1.8.2.min.js"&gt;&lt;/script&gt;
   <em>&lt;script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"&gt;&lt;/script&gt;</em>
   ...
&lt;/head&gt;
</pre>
</div>
            <ul>
               <li>For mobile sites/apps, can use jQuery Mobile to handle internal/Ajax navigation.</li>
               <li>Also offers mobile-focused widgets, toolbars, page transitions, etc.</li>
               <li>Powerful CSS-based <a href="http://jquerymobile.com/themeroller/">theme engine</a>.</li>
               <li>Uses HTML5 custom <code>data-*</code> attributes to specify structure of internal pages.</li>
               <li><em>Automatically</em> hijacks links to handle internal/Ajax navigation — no JS required!</li>
            </ul>
         </div>
         
         
         <div class="slide">
            <h1>Internal/Ajax Navigation with jQuery Mobile</h1>
<div class="example">
<pre class="examplecode html" style="font-size: 60%; float: left; width: 50%">
&lt;nav <em>data-role="navbar"</em>&gt;&lt;ul&gt;
   &lt;li&gt;&lt;a href="<em>#page1</em>"&gt;Page 1&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="<em>#page2</em>"&gt;Page 2&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="<em>page3.html</em>"&gt;Page 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;

&lt;section <em>data-role="page" id="page1"</em>&gt;
   &lt;header <em>data-role="header"</em>&gt;
      &lt;h1&gt;This is page one&lt;/h1&gt;
   &lt;/header&gt;
   &lt;section <em>data-role="content"</em>&gt;
      &lt;p&gt;...&lt;a href="<em>#page2</em>"&gt;Page 2&lt;/a&gt;...&lt;/p&gt;
   &lt;/section&gt;
   &lt;footer <em>data-role="footer"</em>&gt;
      &lt;p&gt;...&lt;/p&gt;
   &lt;/footer&gt;
&lt;/section&gt;
</pre>
<pre class="examplecode html" style="font-size: 65%; float: right; width: 50%">
&lt;section <em>data-role="page" id="page2"</em>&gt;
   &lt;header <em>data-role="header"</em>&gt;
      &lt;h1&gt;This is page two&lt;/h1&gt;
   &lt;/header&gt;
   &lt;section <em>data-role="content"</em>&gt;
      &lt;p&gt;...&lt;a href="<em>#page1</em>"&gt;Page 2&lt;/a&gt;...&lt;/p&gt;
   &lt;/section&gt;
   &lt;footer <em>data-role="footer"</em>&gt;
      &lt;p&gt;...&lt;/p&gt;
   &lt;/footer&gt;
&lt;/section&gt;
...
</pre>
</div>
            <ul>
               <li>If your page is properly structured with <code>data-role</code> attributes, jQuery Mobile automatically takes care of JS code for internal navigation.
                  <ul>
                     <li>Link internally with <code>#<var>pageid</var></code>, externally with a filename.</li>
                  </ul>
               </li>
               <li>In this example, <samp>page3.html</samp> must be a <strong>FULL HTML FILE</strong> that can be navigated to directly.
                  <ul>
                     <li>jQuery Mobile extracts the first <code>data-role="page"</code> element from it and injects that on-screen.</li>
                  </ul>
               </li>
            </ul>
            
         </div>
         
         
         
<!--#include virtual="../s5/commonbottom.html" -->