Building an HTML5 Mobile App using jQuery Mobile and ASP.NET MVC

By March 15, 2012 Mobile One Comment

The mobile revolution has created a plethora of new platforms and languages. It
is rare to see old technologies successfully reaching new grounds together. A good
example of this is .NET MVC and jQuery
Mobile
. The blends of Razor, HTML, CSS, and jQuery make mobile a very familiar
territory, a package that makes things quick, easy, and beautiful!

Setup the Project

The first thing you want to do is fire up Visual Studio and create a new MVC 3 Internet
Application. This will give you membership, templates, and sample content to your
website with a single click. Our goal from here is to extend it to a mobile site.
To make this more interesting though, let us make it iPad optimized as well.

Add NuGet Package

To help with the device detection, we will be using the open source .NET project
called 51Degrees.Mobi.
It extends the “Request.Browser
object by getting information from the Wireless Universal Resource File (WURFL) – one of the most comprehensive
and up-to-date databases of mobile device information. This will allow us to find
out what smartphone or tablet the user is using. 51Degrees.Mobi is also available
as a NuGet package, so “Add this Library package” to your Visual Studio project.

One thing to note here, by default the 51Degrees.Mobi package uses a simple redirection
to the “~/Mobile” folder to get you started – quick, dirty, and probably more relevant
for Web Forms. For our purpose though, let us redirect views not URL’s to keep things
MVC-licious. This means deleting the new “~/Mobile” folder that was created, as
well as removing the <redirect> element inside the <fiftyOne> section
in “~/App_Data/51Degrees.mobi.config”.

NOTE: The WURFL file that currently comes with the 51Degrees package is a bit outdated
and does not recognize iPad2 devices. Under “~/App_Data”, update “wurfl.xml.gz”
and “web_browsers_patch.xml” from
WURFL’s latest repository
to correct this.

MVC Controllers

Now let us move on to the controllers. In the HomeController, add the below condition
statement in the Index action. This will pass mobile devices to another controller:

public ActionResult Index()
{
ViewBag.Message = “Welcome to ASP.NET MVC!”;

//HANDLE MOBILE DEVICE IF APPLICABLE
if (Request.Browser.IsMobileDevice)
{
return RedirectToAction(null, “Mobile”);
}
else
{
return View();
}
}

The code above expects a MobileController. So right click on the “~/Controllers”
folder and add a controller called “MobileController”. Once the class opens, modify
the Index action with the below code:

public ActionResult Index()
{
return View(MobileUtils.GetViewName());
}

Fine Tuning Device Detection

How does “MobileUtils.GetViewName” know what view to use based on device? We have
to create a nifty static utility! Create a new folder called “~/Utilities” and add
a new class called “MobileUtils”. Paste the below method there:

public static string GetViewName()
{
var context = HttpContext.Current;
string viewName = null;

if (context != null && context.Request.Browser.IsMobileDevice)
{
//GET MANUFACTURER OF DEVICE
string manufacturer = context.Request.Browser.MobileDeviceManufacturer.ToLower().ToString();
string model = context.Request.Browser.MobileDeviceModel.ToLower().ToString();
bool isTablet = Convert.ToBoolean(context.Request.Browser[“is_tablet”] ?? “false”);

//HANDLE TABLE IF APPLICABLE
if (isTablet)
{
//FOR IPAD AND OTHER TABLETS
viewName = “Tablet”;
}
else
{
//DETERMINE VIEW NAME BASED ON DEVICE
switch (manufacturer)
{
case “apple”:
case “android”:
case “windows”:
case “nokia”:
case “rim”:
default:
viewName = “Index”;
break;
}
}
}

return viewName;
}

The “GetViewName” method uses the new 51Degrees.Mobi helpers to figure out the view
name to return based on the user’s device. Notice the manufacturer, model, and is_tablet
variables can be used to determine this. The code is a little stubbed out in case
you want to extend it per device.

MVC Views

Now we can start to create views per device, but first let us create a template
for the mobile pages. This will contain the HTML5 template needed for jQuery Mobile
to work. Under the folder “~/Views/Shared”, create a new view called “_LayoutMobile”
and paste the below content in there. This uses the hosted jQuery Mobile scripts
and styles which contains all the magic.

<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href=”http://code.jquery.com/mobile/latest/jquery.mobile.min.css” rel=”stylesheet” type=”text/css” />
<script src=”http://code.jquery.com/jquery.min.js” type=”text/javascript”></script>
<script src=”http://code.jquery.com/mobile/latest/jquery.mobile.min.js” type=”text/javascript”></script>
<meta name=”viewport” content=”width=device-width, initial-scale=1″ />
</head>
<body>
@RenderBody()
</body>
</html>

NOTE: I also created “_LayoutTablet” in my sample solution to take advantage the
jQuery Mobile Splitview
plugin
for tablets.

With the new mobile layout in place, create the default mobile view by right clicking
on the Index action and add a view. Choose the new mobile layout that was just created.

This will be the view used for “generic” mobile devices. Create a new view called
“Tablet” under the “~/Views/Mobile” folder in the same way (use _LayoutTablet if
you created one). This will be specifically sent to tablets, such as iPad’s, which
is determined from the MobileUtils.GetViewName method.

This takes care of the MVC side of things. It should be straight HTML5 and jQuery
Mobile from here!

jQuery Mobile

Let me pause for a minute and give a brief explanation of what jQuery Mobile is
and how to use it. First let me rid your fears; you only need to know HTML markup
to use jQuery Mobile! There is little reason to touch CSS and even jQuery. All you
have to do is decorate your HTML markup with attributes and classes – and that’s
it! By using HTML5 data-* attribute and CSS classes, jQuery Mobile determines the
role and properties of the elements, then automagically adds styles and modifies
the markup from there. Check out this sample:

<div data-role=”page”>

<div data-role=”header”>
<h1>Page Title</h1>
<a href=”#” data-icon=”search” class=”ui-btn-right” data-iconpos=”notext”>Search</a>

</div><!– /header –>

<div data-role=”content”>
<p>Page content goes here.</p>
<div data-role=”controlgroup”> <a href=”index.html” data-role=”button”>Link 1</a> <a href=”index.html” data-role=”button”>Link 2</a> <a href=”index.html” data-role=”button”>Link 3</a> </div>
</div><!– /content –>

<div data-role=”footer”>
<h4>Page Footer</h4>
</div><!– /footer –>
</div><!– /page –>

What a beautiful interface layer! Instead of forcing you to procedurally create
the interface like other mobile web frameworks (ehhmmm
Sencha
), jQuery Mobile goes with the natural flow of web concepts, such
as HTML5, CSS3, and jQuery. The anatomy of a jQuery Mobile page can be seen above.
It contains a “div” wrapper defined with the data-role=”page” attribute. This acts
like the “body” of mobile page. “Pages” will contain “div” children that have their
own data-role attributes. Some data-role examples include “header”, “content”, “footer”,
“navbar”, “listview”, “button”, and more. There are other data-* attributes and
CSS classes available for the jQuery Mobile framework, such as data-position=”fixed”,
data-theme=”b”, data-icon=”gear”, class=”ui-btn-right”,
and others
.

Interface for Mobile Devices

Now armed with this knowledge, open up the Mobile/Index view and paste the below
markup:

@{
ViewBag.Title = “Mobile Dashboard”;
Layout = “~/Views/Shared/_LayoutMobile.cshtml”;
}

<div data-role=”page”>

<div data-role=”header”>
<h1>@ViewBag.Title</h1>
<a href=”#” data-icon=”star” class=”ui-btn-left”>Profile</a>
<a href=”#” data-icon=”search” class=”ui-btn-right” data-iconpos=”notext”>Search</a>
</div>

<div data-role=”content”>
<ul data-role=”listview”>
<li data-role=”list-divider”>Comments unread <span class=”ui-li-count”>47</span></li>
<li>
<div data-role=”navbar”>
<ul>
<li><a href=”#” data-icon=”grid”>Blogs</a></li>
<li><a href=”#” data-icon=”grid”>Gallery</a></li>
<li><a href=”#” data-icon=”check”>News</a></li>
<li><a href=”#” data-icon=”star”>Events</a></li>
<li><a href=”#” data-icon=”grid”>Surveys</a></li>
<li><a href=”#” data-icon=”check”>Polls</a></li>
<li><a href=”#” data-icon=”star”>Store</a></li>
<li><a href=”#” data-icon=”home”>Forums</a></li>
<li><a href=”#” data-icon=”star”>Tweets</a></li>
<li><a href=”#” data-icon=”grid”>Contact</a></li>
</ul>
</div>
</li>
</ul>
</div>

<div data-role=”footer”>
<div data-role=”controlgroup” data-type=”horizontal”>
<a href=”#” data-role=”button” data-icon=”info” data-iconpos=”notext” data-inline=”true”>Info</a>
<a href=”#” data-role=”button” data-icon=”gear” data-iconpos=”notext” data-inline=”true”>Options</a>
</div>
</div>

</div>

Interface for Tablet Devices

Next open the Mobile/Tablet view and paste the below markup:

@{
ViewBag.Title = “Tablet Dashboard”;
Layout = “~/Views/Shared/_LayoutTablet.cshtml”;
}
<div data-role=”panel” data-id=”menu” data-hash=”crumbs” data-context=”a#default”>
<!– Start of first page –>
<div data-role=”page” id=”main”>
<div data-role=”header” data-backbtn=”false”>
<h1>
Main</h1>
</div>
<!– /header –>
<div data-role=”content”>
<ul data-role=”listview” data-theme=”g”>
<li>About
<ul>
<li><a href=”#aboutsv” data-panel=”main”>About Splitview</a></li>
<li><a href=”#secondarypage” data-panel=”main”>Secondary Page</a></li>
</ul>
</li>
<li>Features
<ul>
<li><a href=”#panels” data-panel=”main”>Panels</a></li>
<li><a href=”#orientation” data-panel=”main”>Orientation</a></li>
<li><a href=”#scroll” data-panel=”main”>Scroll</a></li>
<li><a href=”#context” data-panel=”main”>Context Loading</a></li>
</ul>
</li>
<li><a href=”#page3″ data-panel=”main”>Page 3</a></li>
<li><a href=”#page4″ data-panel=”main”>Page 4</a></li>
</ul>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 2nd page –>
<div data-role=”page” id=”demo”>
<div data-role=”header” data-backbtn=”false”>
<h1>
Demos</h1>
</div>
<!– /header –>
<div data-role=”content”>
<ul data-role=”listview” data-theme=”g”>
<li><a href=”#bar” data-panel=”main” id=”default”>Bar</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li>First level list
<ul>
<li>Second level list
<ul>
<li><a href=”#bar” data-panel=”main”>long list test</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
</ul>
</li>
<li><a href=”#bar” data-panel=”main”>Bar</a></li>
<li><a href=”#badz” data-panel=”main”>badz</a></li>
</ul>
</li>
</ul>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
</div>
<!– panel menu –>
<div data-role=”panel” data-id=”main”>
<!– Start of 6th page –>
<div data-role=”page” id=”aboutsv”>
<div data-role=”header”>
<h1>
About SplitView</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
This is the <a href=”https://github.com/asyraf9/jquery-mobile/” target=”_blank”>jQuery
Mobile Splitview plugin</a> that renders splitview pages accordingly to tablet
devices, e.g. iPad. Hopefully the “splitview” component makes it to the core jQuery Mobile
framework instead of remaining an unsupported, 3rd party plugin.</p>
<h2>
Features</h2>
<ul>
<li>auto-detection of how to render for the browser you are using.</li>
<li>independent panel scrolling (still a lot more to work on here)</li>
<li>orientation and resize aware – renders the side panel in a popover fashion when
in portrait mode</li>
<li>context awareness – can be programmed so that opening a page on the side panel also
opens a page on the main panel</li>
<li>deep-link (and history) awareness – linking to a specific page in the main panel
works, and hitting on the back and forward button on your browser also works (only
for the main panel pages)</li>
<li>panel specific links – links on the side panel can affect pages in the main panel,
or in the side panel itself.</li>
</ul>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 5th page –>
<div data-role=”page” id=”secondarypage”>
<div data-role=”header”>
<h1>
Secondary Page</h1>
</div>
<!– /header –>
<div data-role=”content”>
<h3>
Some title</h3>
<p>
Fusce a nisi at dolor rutrum tristique. Donec faucibus metus vitae lorem scelerisque
malesuada scelerisque enim imperdiet. Aliquam in erat orci. Ut ultrices, erat eu
luctus accumsan, lorem nibh cursus purus, in laoreet nisi tellus interdum sem. Nulla
fringilla molestie lectus nec hendrerit. In in mollis tortor. Nunc lectus tortor,
porttitor vitae viverra non, dignissim ac ligula. In tincidunt libero id turpis
gravida iaculis rhoncus dolor aliquam. Vestibulum congue massa nec nibh sagittis
tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas. Quisque quis urna arcu. Quisque feugiat ante id turpis ultrices
vel imperdiet ipsum volutpat. Donec enim magna, pretium eu scelerisque ut, pretium
placerat risus.</p>
Sed sed lacinia ante. Aenean non quam in ipsum pharetra condimentum.
<p>
Donec turpis lacus, pharetra ac viverra sit amet, lobortis eu nisl. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur porttitor
dignissim orci ut feugiat. Praesent quis auctor purus. Suspendisse non elit accumsan
mi pellentesque laoreet. Nullam et sapien sed nibh dictum tempor sit amet ut velit.
Vestibulum varius ultricies lorem sed ultricies. Vestibulum auctor velit vitae ante
eleifend eget bibendum metus rutrum. Nulla facilisis luctus mi laoreet rutrum. Nunc
accumsan urna at elit pellentesque ut venenatis lectus adipiscing. Ut et arcu urna.
Aliquam eros leo, ultricies vel porta nec, tempor sit amet leo. Quisque imperdiet
facilisis orci ut malesuada. Nunc eget elit mauris. Mauris sed felis lectus.</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 7th page –>
<div data-role=”page” id=”panels”>
<div data-role=”header”>
<h1>
Panels</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
In order for splitview to work, we defined two more <b>&lt;div&gt;</b> tags to enclose
the pages – one called ‘main’, the right hand panel, and ‘menu’ which is the left
sidebar panel</p>
<p>
This provides us with a few advantages:</p>
<p>
1. It allows us to define the area new pages should be loaded in. We do this by
using data-panel attributes on anchor tags. example:<br />
<br />
<b style=”padding-left: 30px;”>&lt;a href=”some_other_page” data-panel=”main”&gt;</b>
</p>
<p>
2. It allows us to define if a panel’s page transitions should be tracked in history
or not.</p>
<p style=”padding-left: 30px;”>
This uses the data-hash attribute on the panels. It takes three options – ‘true’,’false’,
and ‘crumbs’ with true as default. The ‘crumbs’ setting changes the panel’s back
button into a button that points to the previous page, and disables jQMobile from
tracking the panel’s history
</p>
<p>
3. It allows us to hide and show the panel depending on screen orientation, and
unobtrusively disable it when the site is viewed on mobile browsers</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 8th page –>
<div data-role=”page” id=”orientation”>
<div data-role=”header”>
<h1>
Orientation and Resize</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
Very simply put, SplitView dynamically lays out the pages based on your tablet’s
(iPad, etc) orientation, as well as your desktop’s screen size. Try it out, resize
your browser, or turn your iPad to see it in portrait and landscape modes!</p>
<p>
NOTE: you may have to refresh the view if you scale the browser window down to a
mobile size – less than 480px – Splitview determines upon page load if it should
lay the pages out in splitview mode or mobile mode (the default jQmobile implementation)</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 9th page –>
<div data-role=”page” id=”scroll”>
<div data-role=”header”>
<h1>
Scrolling</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
Splitview detects if your device is touch enabled or not. it will then implement
the proper scrolling mechanism for your device. This is possible thanks to the jQuery
Mobile team’s experimental momentum scroll implementation, which the team promptly
pointed us to. Thanks!
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<div data-role=”page” id=”context”>
<div data-role=”header”>
<h1>
Context Loading</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
When you navigate on to some menus on the ‘menu’ panel, you’ll find that it is more
intuitive for users that the main panel also transitions to a related page. This
is what we call context page loading<p>
<p>
Splitview now supports this. you need to define a data-context attribute on the
panel with a value of the selector of the link you’d like the main page to transition
to. this link has to be inside the page that is transitioning into view in the menu
panel, and it has to reference the main panel using the data-panel attribute. Example:</p>
<p style=”padding-left: 30px;”>
<b>data-context=”a#default”</b></p>
<p>
This will look for a link with id=”default” on the newly transitioned page, and
trigger a click event on it, changing the main panel to that page (<b>NOTE:</b>
the link needs to refer to the main panel using the data-panel=”main” attribute!)</p>
<p>
To see this in action, click on the demo button at the bottom of the menu panel
on the left</p>
<p>
Also, you can also define a data-context attribute on a page itself – this will
override any data-context attributes defined on the panels</p>
<p>
There are still a few things i need to do to make sense of context for both pages,
e.g. when hitting back on history, what happens etc, but they will have to wait
for now :)</p>
<p>
<b>ANOTHER NOTE:</b> To make this happen, I made some small changes to the changePage
method in jQMobile core. use the version of jQuerymobile found in the experiments/compiled/
folder of my fork. It will not break any changePage calls you’ve made on your own
js code</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 10th page –>
<div data-role=”page” id=”page3″>
<div data-role=”header”>
<h1>
Page 3</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
Vestibulum porta pretium nunc, at adipiscing tortor fringilla sit amet. Sed venenatis
varius turpis, vel fringilla purus egestas in. Curabitur interdum mauris nec velit
vehicula sed aliquam nulla convallis. Nulla id magna libero, sagittis fringilla
metus. Suspendisse dapibus tincidunt tristique. Fusce interdum tincidunt tincidunt.
Phasellus tempus fringilla augue eget tincidunt. Donec facilisis mauris ut metus
eleifend eget scelerisque nulla sagittis. Ut vel elit non risus dapibus luctus.
Pellentesque vel nibh tortor.</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<div data-role=”page” id=”page4″>
<div data-role=”header”>
<h1>
Page 4</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
Fusce a nisi at dolor rutrum tristique. Donec faucibus metus vitae lorem scelerisque
malesuada scelerisque enim imperdiet. Aliquam in erat orci. Ut ultrices, erat eu
luctus accumsan, lorem nibh cursus purus, in laoreet nisi tellus interdum sem. Nulla
fringilla molestie lectus nec hendrerit. In in mollis tortor. Nunc lectus tortor,
porttitor vitae viverra non, dignissim ac ligula. In tincidunt libero id turpis
gravida iaculis rhoncus dolor aliquam. Vestibulum congue massa nec nibh sagittis
tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas. Quisque quis urna arcu. Quisque feugiat ante id turpis ultrices
vel imperdiet ipsum volutpat. Donec enim magna, pretium eu scelerisque ut, pretium
placerat risus.</p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 3rd page –>
<div data-role=”page” id=”bar”>
<div data-role=”header”>
<h1>
Bar</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
I’m first in the source order so I’m shown as the page.</p>
<p>
<a href=”#badz”>Back to badz</a></p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
<!– Start of 4th page –>
<div data-role=”page” id=”badz”>
<div data-role=”header”>
<h1>
badz</h1>
</div>
<!– /header –>
<div data-role=”content”>
<p>
I’m first in the source order so I’m shown as the page.</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque consectetur,
ligula quis convallis gravida, tortor odio mattis purus, a fringilla mauris velit
eu nisi. Vivamus laoreet tincidunt diam, sit amet tristique purus lobortis ac. Etiam
commodo placerat elit. In aliquam dapibus felis, molestie molestie purus scelerisque
sit amet. Donec vitae varius arcu. Aliquam dapibus dolor magna, nec posuere felis.
Nullam in suscipit massa. Duis nec nulla nec urna sollicitudin fringilla. Proin
at rutrum mi. Maecenas vitae urna ante, ac gravida tortor.</p>
<p>
Vestibulum porta pretium nunc, at adipiscing tortor fringilla sit amet. Sed venenatis
varius turpis, vel fringilla purus egestas in. Curabitur interdum mauris nec velit
vehicula sed aliquam nulla convallis. Nulla id magna libero, sagittis fringilla
metus. Suspendisse dapibus tincidunt tristique. Fusce interdum tincidunt tincidunt.
Phasellus tempus fringilla augue eget tincidunt. Donec facilisis mauris ut metus
eleifend eget scelerisque nulla sagittis. Ut vel elit non risus dapibus luctus.
Pellentesque vel nibh tortor.</p>
<p>
Fusce a nisi at dolor rutrum tristique. Donec faucibus metus vitae lorem scelerisque
malesuada scelerisque enim imperdiet. Aliquam in erat orci. Ut ultrices, erat eu
luctus accumsan, lorem nibh cursus purus, in laoreet nisi tellus interdum sem. Nulla
fringilla molestie lectus nec hendrerit. In in mollis tortor. Nunc lectus tortor,
porttitor vitae viverra non, dignissim ac ligula. In tincidunt libero id turpis
gravida iaculis rhoncus dolor aliquam. Vestibulum congue massa nec nibh sagittis
tempor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas. Quisque quis urna arcu. Quisque feugiat ante id turpis ultrices
vel imperdiet ipsum volutpat. Donec enim magna, pretium eu scelerisque ut, pretium
placerat risus.</p>
Sed sed lacinia ante. Aenean non quam in ipsum pharetra condimentum.
<p>
Donec turpis lacus, pharetra ac viverra sit amet, lobortis eu nisl. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur porttitor
dignissim orci ut feugiat. Praesent quis auctor purus. Suspendisse non elit accumsan
mi pellentesque laoreet. Nullam et sapien sed nibh dictum tempor sit amet ut velit.
Vestibulum varius ultricies lorem sed ultricies. Vestibulum auctor velit vitae ante
eleifend eget bibendum metus rutrum. Nulla facilisis luctus mi laoreet rutrum. Nunc
accumsan urna at elit pellentesque ut venenatis lectus adipiscing. Ut et arcu urna.
Aliquam eros leo, ultricies vel porta nec, tempor sit amet leo. Quisque imperdiet
facilisis orci ut malesuada. Nunc eget elit mauris. Mauris sed felis lectus.</p>
<p>
Duis purus sem, condimentum eget posuere sed, vulputate non lorem. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras risus urna,
commodo quis interdum sit amet, elementum vitae lacus. Ut tempor hendrerit ante
et facilisis. Vivamus elementum purus justo, ut auctor arcu. Cras varius rhoncus
venenatis. Nulla dignissim velit a erat euismod pretium. In sed leo orci, et consectetur
justo. Vestibulum ipsum urna, cursus in placerat in, malesuada eu odio. Nunc eget
ullamcorper tortor. In commodo, turpis sed egestas egestas, dolor sem mattis nulla,
eu semper lectus metus at eros. Sed cursus nisl id risus fermentum quis aliquam
odio pretium. Quisque justo eros, blandit gravida tristique eget, rhoncus in magna.
Integer volutpat faucibus dolor, sit amet tempor metus ornare consequat. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Nunc et lacus enim, sit amet consequat turpis.</p>
<p>
<a href=”#foo”>Back to foo</a></p>
</div>
<!– /content –>
<div data-role=”footer” data-position=”fixed” data-id=”ew-footer” class=”ui-splitview-hidden”>
<div data-role=”navbar”>
<ul>
<li><a href=”#main” class=”ui-btn-active” data-transition=”slideup”>Main</a></li>
<li><a href=”#demo” data-transition=”slideup”>Demos</a></li>
</ul>
</div>
<!– /navbar –>
</div>
<!– /footer –>
</div>
<!– /page –>
</div>
<!– panel main –>

Conclusion

We are done! This is just a simple dashboard prototype for a mobile website. If
you view the site with a computer, you will be served the Home/Index view for regular
website browsing. For mobile devices, you will be automatically routed to the Mobile
controller which will further detect what mobile device you are using. The controller
will service Tablet view for the iPad and all other mobile devices will be served
the Index view.

Desktop Browsing

Mobile Browsing

Tablet Browsing

Check It Out for Yourself!

HAPPY CODING!!

More Reading:

The following two tabs change content below.

Basem Emara

Software Architect at Falafel Software
Basem has over 10 years experience as a consultant and developer for dozens of projects for educational, advocacy, non-profit, small business, enterprise, and governmental organizations. As an innovator who recognizes and leverages the power of the web, he has been able to help real estate agencies, schools, hospitals, wholesale distributors, shipping carriers, and other businesses pioneer their industries utilizing the best that today’s technology has to offer from a more creative point of view. Simple yet elegant is the key to his approach, as well as the belief that continual process improvement is always possible.

Latest posts by Basem Emara (see all)