<!--#include virtual="../s5/commontop.html" -->
<title>Lecture 17: Ajax Navigation & 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 & jQuery Mobile</h2>
</div>
</div>
<div class="presentation">
<div class="slide">
<h1>Internal Navigation & 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%">
<nav><ul>
<li><a href="<em>#page1</em>">Page 1</a></li>
<li><a href="<em>#page2</em>">Page 2</a></li>
<li><a href="<em>#page3</em>">Page 3</a></li>
</ul></nav>
<section <em>class="page" id="page1"</em>>...</section>
<section <em>class="page" id="page2"</em>>...</section>
<section <em>class="page" id="page3"</em>>...</section>
...
</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">
<a href="contact.html">Contact Us</a>
</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">
<head>
...
<em><meta name="viewport" content="width=device-width, initial-scale=1"></em>
<em><link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css"></em>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<em><script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script></em>
...
</head>
</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%">
<nav <em>data-role="navbar"</em>><ul>
<li><a href="<em>#page1</em>">Page 1</a></li>
<li><a href="<em>#page2</em>">Page 2</a></li>
<li><a href="<em>page3.html</em>">Page 3</a></li>
</ul></nav>
<section <em>data-role="page" id="page1"</em>>
<header <em>data-role="header"</em>>
<h1>This is page one</h1>
</header>
<section <em>data-role="content"</em>>
<p>...<a href="<em>#page2</em>">Page 2</a>...</p>
</section>
<footer <em>data-role="footer"</em>>
<p>...</p>
</footer>
</section>
</pre>
<pre class="examplecode html" style="font-size: 65%; float: right; width: 50%">
<section <em>data-role="page" id="page2"</em>>
<header <em>data-role="header"</em>>
<h1>This is page two</h1>
</header>
<section <em>data-role="content"</em>>
<p>...<a href="<em>#page1</em>">Page 2</a>...</p>
</section>
<footer <em>data-role="footer"</em>>
<p>...</p>
</footer>
</section>
...
</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" -->