A Complete Guide of jQuery Mobile for Beginners
There’s no doubt about it. Wherever developers look and whoever they talk to, mobile is at the top of the list. Talk to a C-level executive, and the conversation turns to mobile, and the question “How do I get me some of that?†comes up. Talk to other developers, and they tell you they’re targeting mobile devices. Mobile has become a big deal as smartphones have taken hold in the consumer marketplace.
In the years leading up to the current focus on mobile applications and devices, Web developers have been adding more and more client-side functionality to their applications. You can see this in the use of client-side JavaScript libraries like jQuery.
With the growth of the market for mobile devices, the ability to create applications that run across platforms is very important for developers and for businesses that are trying to keep their expenses in check. There are a set of applications, mostly in the area of content consumption (think Amazon.com), that run well in a mobile Web browser. Unfortunately, there are differences between Web browsers on various mobile devices. The goal of the recently introduced jQuery Mobile (jQM) library is to provide cross-browser support to allow developers to build applications that can run across the various mobile Web browsers and provide the same—or at least a very similar—user interface.
The jQuery Mobile library was introduced in an alpha release in the fall of 2010 and released to manufacturing in November 2011. At the time of this writing, the current version of jQuery Mobile is 1.1.1. By the time you read this, jQuery Mobile will almost certainly have reached version 1.2.0. The library has been embraced by Microsoft, Adobe and other companies for mobile Web development. In August 2011, jQM had 32 percent market share compared with other mobile JavaScript frameworks such as iWebKit and jQTouch. This market share is impressive given that it started from zero little more than 12 months ago, and the 1.0 release is the first officially supported release.
Getting Started
Let’s start by looking at the basics of a jQuery Mobile page, as shown in the code below.
<!DOCTYPE html> <html> <head> <title>jQuery Mobile</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.css" /> <script src="http://code.jquery.com/jquery-1.7.1.min.js" type="text/javascript"></script> <script src="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js" type="text/javascript"></script> </head> <body> <div data-role="page" data-theme="c"> <div data-role="header"> <h1>jQuery Mobile</h1> </div> <div data-role="content"> <p>jQuery Mobile is an HTML, Javascript, mobile library that you will like. ASP.NET web pages make it easy to build powerful .NET based applications for the web. </p> </div> <div data-role="footer"> <h4>Friday, July 27, 2012 - Copyright SDI</h4> </div> </div> </body> </html>
You should notice several things:
- The doctype is the standard doctype for an HTML5 Web page.
- The viewport is set in a metatag. The viewport is used by the browser to determine the amount of a Web page to display on the screen. Mobile devices by default assume that pages are about 900 pixels wide, which scrunches a Web page down to a screen of that size. In the code above, the browser is set to the screen width of the device.
- A CSS style sheet is loaded for use by jQM.
- The jQuery library is loaded and used by jQM.
- The jQM .js file is loaded.
- The .css file and the two JavaScript files are loaded from the jQuery content delivery network (CDN).
- The page contains header, content and footer sections.
I’m sure you’re wondering what jQM actually gives developers. If you look at the page created by the above code in a mobile browser, the content is displayed with header, content (or main body) and footer sections. Logically, the content is displayed as shown in Figure 1.
Figure 1. Basic Organization of a jQM Page
Attributes
Attributes are one of the first things that developers notice about jQM. Strictly speaking, the data-* attributes that developers see are part of the HTML5 specification. The feature’s name is “custom data attributes†and is defined in the W3C specification. This allows developers to add a custom attribute to a tag while keeping a jQM mobile page valid. The value to developers is that this allows jQM to define custom attributes for a mobile page. jQM can then take those custom attributes and act on them. For example, a <div/> tag with the header attribute can be styled automatically by the library without the developer needing to do anything. Beyond setting styles for an attribute, this declarative approach also allows software development tools to add functionality and improve the development experience.
You might now be asking, “Great, what types of attributes are available?†In the code shown above, notice that the page, header, content and footer attribute values are set. These are referred to as a role. (The concept of a page, header, content and footer is fairly self-explanatory, so I won’t discuss it further.) In jQM, a role is defined by the data-role attribute. Some of the other roles that you’ll see in jQM include the following:
- Navbar defines a navigation bar, which is typically displayed within a header.
- The button role displays a button, typically by using an <a href> link.
- The listview is the mobile equivalent to the tables with grids of data that are part of the desktop Web metaphor.
jQuery Mobile Template
Applications usually have many pages associated with them. You can find a lot of discussion about—and valid reasons for—placing mobile pages in a single file, but the truth is that it’s not realistic to try to place your complete application in one page. If Twitter can’t get this right, you probably don’t have the resources necessary to get this 100 percent right either.
Let’s take a look at how this works for ASP.NET developers. First, think about the various ASP.NET rendering stacks that you can use. There’s ASP.NET WebForms, which has been around since the 1.0 release of the Microsoft .NET Framework. WebForms was a great improvement to classic ASP. Unfortunately for the mobile world, the viewstate and the limited control over HTML output are a problem for developers, so we’ll bypass this technology. (It’s not hard to resolve these issues, but they take a lot more work than this article can describe.)
Most developers will want to use a different technology, one that gives them more control over the situation. Thankfully, Microsoft has other options. These options are the ASP.NET MVC and ASP.NET Web Pages platforms. Both approaches use the Razor view engine to provide the server-side development language that will output the resulting HTML. Other view engines are available, but this article is geared toward “what’s in the ASP.NET box.â€
The code below shows a template that uses the Razor view engine.
<!DOCTYPE html> <html> <head> <title>@Page.Title</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.css" /> <script src="http://code.jquery.com/jquery-1.7.1.min.js" type="text/javascript"></script> @if (IsSectionDefined("Head")) { @RenderSection("Head", false); } <script src="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js" type="text/javascript"></script> </head> <body> <div data-role="page"> <div data-role="header"> @if (IsSectionDefined("HeaderSection")) { @RenderSection("HeaderSection", false) } else { <h1>@Page.Title</h1> } </div> <div data-role="content"> <p>@RenderBody()</p> </div> <div data-role="footer"> @if (IsSectionDefined("FooterSection")) { @RenderSection("FooterSection", false) } else { <h4>@DateTime.UtcNow.ToLongDateString() - Copyright SDI</h4> } </div> </div> </body> </html>
In the layout file, take note of several things:
- The jQM .css, jQuery .js and jQM .js files are all loaded from a CDN. Loading from a CDN helps developers because with the popularity of jQM, there’s a high likelihood that the jQM libraries will already be cached by another Web application on a user’s machine. If the libraries are already loaded, you’ll see a boost in performance over loading those libraries from your application’s Web server. In the mobile world, bandwidth, latency and general connectivity are precious resources. Anything that can be done to improve performance is a good thing. A secondary, and slightly more selfish reason, is that loading files from an application’s server takes some amount of bandwidth. Bandwidth costs money at some level, so you can save some development funds by using someone else’s CDN. As a side note, I don’t want to dig into CDNs too much in this article. Three popular ones that I’m familiar with are the Google CDN, the jQuery CDN and the Microsoft CDN. Dave Ward has a great blog post on CDNs. You’ll find a link in the list of references at the end of this article.
- The basic page structure setup. There are sections for a header, content and footer. Each of these content sections has a corresponding set of server-side code. If the content page does not have a HeaderSection defined, a default is sent to the user. The same approach occurs with the FooterSection. Each of these sections is optional. The body of the page is the only required section for our template. The body of our content page will be displayed in this area.
- Notice the head and header section. The reason for the head section is that the mobileinit event must be created before the jQM js file is loaded. You’ll learn more about the mobileinit event later in this article.
Mobile Controls and HTML
Developers can use a number of new form elements in the mobile HTML world. These come from the HTML5 specification. Here are a few of the input types from the specification:
- range—Used for inputting a numeric value with a minimum and maximum value.
- tel—Used to input a phone number. The user is presented with a numeric-optimized keyboard for input.
- url—This is a url input type through which a text field is presented to a user. The user is presented with a URL-optimized keyboard for input.
- search—The search input type.
- number—The number input type for inputting a numeric value from the keyboard.
- date, datetime, time, datetime-local, month and week—These are a series of date and time associated controls that are part of the HTML5 specification.
Along with these controls are a series of attributes that developers can use to provide additional assistance to the user and control to the developer.
- Auto capitalization—The autocapitalize attribute can be used to set the default capitalization of a text box. This can be helpful for users when entering a proper name.
- Autocorrection—The autocorrect attribute can be used to turn on or off the autocorrect capability in a text box.
- Placeholder—The placeholder attribute provides a description to the user regarding what the user should enter in a text box.
You may be wondering why a developer needs to worry about these controls. That’s a very valid question. Thankfully, if developers take advantage of these new controls and attributes, the jQM framework will provide the necessary styling to the controls, so they will be displayed with the look of a native control. For example, take a look at the following code:
<input type="text" placeholder="input" /> <input type="range" min="0" max="100" value="50" /> <input type="tel" value="555-1212" /> <a href="Default.cshtml" data-role="button">Save Data</a>
In this code, the placeholder attribute is used on a text input control. jQM provides some styling, such as the rounded corners shown in Figure 2. The range control is an HTML5 control and will be styled as a slider by jQM. The tel control type is a telephone number control. In the iPhone, selecting the number results in calling the number. In Android 4.0.3 (used in the screen shot), the built-in browser does not support the tel input type, but notice that when the tel input type is selected, the telephone-optimized keyboard is displayed. Finally, there is an <a> tag that has a data-role=â€button†attribute. The result is that the <a> tag is styled as a button by jQM.
Figure 2. JQM Provided Styling
Not all form elements are supported by all mobile Web browsers. If a developer uses a form element that a browser doesn’t support, the browser will default to displaying a text form field element in place of the unsupported control. The developer can handle this situation by determining whether the browser provides the necessary support. For this task, the Javascript library Modernizr is very popular.
Note: The new mobile controls in HTML5 are not really part of jQuery Mobile. I’ve mentioned them here because HTML5 has been widely implemented (at least partially) in mobile devices. jQM can then take these controls, attributes and other elements and update their display. For example, jQM will take the input type=â€range†control and display a slider with a text box that has the current value of the slider.
If you don’t want all the styling provided by jQM, setting the attribute data-role=”none” on a tag turns off jQM styling for that control.
How Does jQuery Mobile Apply Styling and the Look?
jQM has a very simple approach to styling. By default, jQM does the following:
- Takes the lightest approach possible, which means that developers and designers do not have to fight a complex styling system.
- Lets the browser’s native rendering take precedence.
- Adds padding for easier reading. The padding that’s added should be a relatively small amount.
- Uses the jQM theme system to apply a “look†for fonts and colors. (You’ll learn more about themes later in the article.)
jQM also implements “progressive enhancement†and “graceful degradation.†This means that when an application runs on an advanced browser, it will support the more advanced capabilities of the browser, and when an application runs a less advanced browser, jQM will scale back the features it uses.
Listview Control
Along with the HTML5 input types, jQM provides a new control named the listview, which provides a view of data and navigation. Typically, data in a listview is bound in some way, either on the server (and then sent to the mobile device) or built via a call to a Web service through AJAX.
Here’s some simple code for a listview:
<ul data-role="listview"> <li><a href="Default.cshtml">Windows 8</a></li> <li><a href="Default.cshtml">Windows Phone</a></li> <li><a href="Default.cshtml">Windows RT</a></li> </ul>
Notice that an unordered list is used along with a series of list items. The data-role attribute for the unordered list is set to listview. Through the data-role attribute setting, jQM picks up that the control is a listview and supplies the look of the UITableView from iOS.
You can see the output of the listview code in Figure 3. There are the three links shown in the code as well as an image accessory showing that by touching the item, the user will be redirected to the URL defined in the <a href>. Finally, depending on the device that the user runs the code on, a listview item is shaded as a user drags a finger across the control.
Figure 3. A Simple Listview Displayed in the Windows Phone Emulator
Now let’s dig into a slightly more complicated example of a listview. Here, we’ll add separators, a search control and instructions in the search control.
<ul id="listViewMore" data-filter="true" data-filter-placeholder="Search OSs" data-role="listview" data-autodividers="true"> <li data-role="list-divider">A</li> <li><a href="Default.cshtml">Android</a></li> <li data-role="list-divider">I</li> <li><a href="Default.cshtml">iPhone</a></li> <li><a href="Default.cshtml">iPad</a></li> <li data-role="list-divider">L</li> <li><a href="Default.cshtml">Linux</a></li> <li data-role="list-divider">W</li> <li><a href="Default.cshtml">Windows 8</a></li> <li><a href="Default.cshtml">Windows Phone</a></li> <li><a href="Default.cshtml">Windows RT</a></li> </ul>
In this listview, setting the data-filter attribute to true turns on the search control and associates it with the listview. A great built-in feature is that typing in the search control automatically updates the listview with the records that match the search criteria. Setting the data-filter-placeholder value results in a placeholder being displayed in devices that support the placeholder attribute. The code also uses the data-autodividers attribute. Setting this value to true automatically creates a divider. The divider is created using the first letter of the display. Personally, I found that this was unreliable. I found that setting a list item’s data-role attribute to “list-divider†was much more reliable.
Figure 4 shows the more advanced settings of the listview displayed on an Android device, taken in an Android x86 emulator session running on the native browser.
Figure 4. Listview with Dividers and Search on an Android Device
Note: If an application needs to dynamically add data to a listview, you might need to call the refresh method on the listview. This is done by the javascript method $(“#listidâ€).listview(‘refresh’);
In this code sample, “#listid†is the ID of the listview that the program needs to update and is shown in standard jQuery notation.
Navigation
Navigation is very important in mobile applications. For example, there isn’t enough screen real estate for a big Back button at the top of the application. In iOS, applications typically implement a Back-style button in the header of an application. In Android, devices have a Back button in hardware or software that users can easily select to go to the previous screen. How should this navigation happen in a jQM application? jQM makes it easy for applications to provide their own navigation, but, admittedly, this gives an application the look of an iOS application by default.
Take a look at the following code within a header. The output is shown in Figure 5.
<a href="Default.cshtml" data-icon="check">Save</a> <h1>Edit Contact</h1> <a href="Default.cshtml" data-icon="delete" data-theme="b">Exit</a>
Notice the data-icon attributes set in the code. There are a number of predefined icons. In Figure 5, the <a> tags are automagically converted into buttons with rounded corners.
Figure 5. Navigation Buttons Created in jQM
For a button outside a header, you can apply the attribute data-role=”button†to an <a> tag. Adding the attribute data-rel=â€back†to a link in the header creates a Cancel button.
Page Loading and AJAX
To navigate between pages, jQM uses the <a> tag. This is standard HTML, so what can be so exciting about that? Well, jQM takes an application’s <a> tags and provides some improvements to the navigation experience provided to users.
First, when a user navigates between pages in a Web application run on the desktop, typically there’s a flash, and the screen goes blank for a very short time while new content is loaded. In a mobile application running on a device, no flash occurs while screens are loaded. Usually, a short animation occurs, and an indicator is displayed while the screen retrieves any data that it needs to display to the user. Wouldn’t it be great if a mobile Web application could provide the seamless display and transitions of a mobile native application?
Thankfully, jQM provides the infrastructure to support the mobile native application experience in mobile Web applications. jQM does not provide this for every page, so let’s look at the various cases. In a mobile Web application there tend to be several types of links:
- Links within one page of the application to a different page of the application
- Links within one page in an application to a different page in the same physical file
- Links to other jQM applications
- Links to no jQM applications
- Special mobile links, such as those to a telephone number to call someone else
For the purposes of this discussion, I’ll focus on navigation between pages in the same application. Here’s a simple example: We start with page 1. When the user clicks on the link to page 2, the user sees a short transition sequence, by default a loading spinner, and then page 2. An examination of the URL shows that it contains page1 followed by a hash (#) and then a reference to page 2. The page loading magic is performed for us via jQM, loaded by an AJAX request.
Now, what happens when you want to load a page but not via an AJAX request? There are two ways (and possibly more) to disable an AJAX-based loading of a page. To do this via code, add the attribute data-rel=â€external†to an <a> tag. This forces a link to be used as an absolute external link in jQM. Also add the data-ajax=â€false†attribute to a link. This forces jQM to act as though the link is an absolute external link.
Display Themes and Color Swatches
You may have noticed by now that the jQM default color choices are fairly boring and very iOS looking. Developers have the opportunity to change this behavior through the color themes. In jQM, a theme defines the text colors, background colors, gradients and fonts that are used to display content. If you are familiar with the jQuery UI ThemeRoller system, working with jQM themes will be fairly simple.
The jQM theme system comes with five predefined swatches that are identified as A, B, C, D and E (see Figure 6):
- The A theme has the highest level of visual priority. Users will see a significant use of black in this theme.
- The B theme has a secondary amount of visual priority. Users will see a significant use of blue in this theme.
- The C theme has a baseline amount of visual priority. Users will see a significant use of gray in this theme.
- The D theme has an alternate secondary level. The difference between themes C and D is a slight color variation in the background colors, which might not be distinguishable in the figure or on devices. It is up to the developer see if there are any differences in their specific situation.
- The E theme is an accent swatch.
Figure 6. Variations in the jQM Theme System
In addition, you can create your own themes by using the jQM ThemeRoller, which is available at http://jquerymobile.com/themeroller/.
jQuery Mobile Events and Configuration
If you are familiar with jQuery, then you are familiar with the document .ready event. This event fires when the document of a page is loaded and is exceedingly valuable when a Web page initially loads. The page can then create any dynamic content at startup. In the mobile world, this becomes even more valuable because users have only so much bandwidth, and we need to be efficient with our data usage.
jQM loads pages differently than jQuery. In jQuery, the browser is solely responsible for the loading of pages. With jQM, the pages are loaded by the browser via jQM, which I covered in an earlier section. The effect for the developer is that a document’s .ready event is not guaranteed to be called when a page is loaded via jQM. To help address this, jQM exposes an event called mobileinit. The mobileinit event is fired when a page is loaded via jQM and presented to the user. The mobileinit event is handled on the document element and bound using jQuery’s bind method, as you can see here:
<script language="javascript" type="text/javascript"> $(document).bind('mobileinit', function () { // Put your initialization code here alert("jQM has been successfully initialized."); }); </script>
After the mobileinit event, there are numerous other events that can be handled, including:
- On a page creation, loading or display
- Widgets can expose an event when their layout changes
- Orientation events that address how mobile devices can be moved and rotated
- Gesture events so that a user can perform some touch events
- Virtual click events, which are a series of events that help you handle the touchstart and touchmove events without having to work with the specifics of a given platform.
Once the jQM mobileinit event is fired, a new object, the $.mobile object, is available from the jQuery $ main object. Within the $.mobile object, developers can change many of the default settings in jQM.
Note: The mobileinit event must be set up before the jQuery Mobile .js file is loaded.
Page Events
Every jQM page has a set of creation, loading and show events:
- pagebeforeload, pageload and pageloadfailed are fired when an external page is loaded
- pagebeforechange, pagechange and pagechangefailed are page change events. These events are fired when a user is navigating between pages in the applications.
- pagebeforeshow, pagebeforehide, pageshow and pagehide are page transition events. These events are fired before, during and after a transition and are named.
- pagebeforecreate, pagecreate and pageinit are for page initialization.
- pageremove can be fired and then handled hen a page is removed from the DOM
The code below shows some examples. In this code snippet, there are several things to notice:
- The code forces AJAX to be enabled. If AJAX is not enabled, some events may not fire.
- When the events fire, the function to handle them takes two parameters. These parameters can return fairly complex data.
- Application developers will most likely be interested in the page transition events.
- For ASP.NET WebForms developers, these events are conceptually very similar to server-side events.
- The pagebeforecreate and pageshow events are fired when the page with ID “two†is loaded. The pageload event is fired when any page is loaded from the current page.
$(document).bind("mobileinit", function () { $.extend($.mobile, { ajaxEnabled: true }); $("#two").live("pagebeforecreate", function (event, data) { alert("pagebeforecreate called"); }) $(document).bind("pageload", function (event, data) { alert("pageload called"); }) $("#two").live("pageshow", function (event, data) { alert("pageshow was called"); }); });
Gesture Events
Gestures are a very common action in touch environments. Dragging a finger across the screen is a natural operation to move between pages, navigate between records and so on. Here is a code sample where an alert is fired for a gesture:
$(document).bind("mobileinit", function () { $(document).live("swiperight", function () { alert("swipe right"); }); });
Orientation Events
One of the interesting things about mobile devices is that they are not in a fixed position in their display. All jokes about not holding the iPhone properly aside, at times a user will change the orientation of the device when using an application, which could happen as a result of general movement of the device, handing it to a friend or something similar. For example, ESPN’s college football scoreboard in the fall of 2011 tracked the orientation of the device. If the device’s orientation was changed to portrait, the scoreboard would not fit properly, and the user received a message to change the orientation. While somewhat inconvenient, this was done by tracking the orientation changes on the device. Tracking and binding the orientation event in jQM is fairly simple, as you can see here:
$(window).bind("orientationchange", function (orientation) { alert(orientation); })
Note: Many of these events will not work properly if AJAX loading is turned off.
Summary
Mobile is definitely popular and only getting more important every day. Having written mobile Web applications before jQuery Mobile, trust me when I say that jQM has made my life much easier.
One of the things I battle with is what should go into an article and what can be kept out. I sincerely hope that this article gives you the necessary information and helps you get started with mobile Web development with jQuery Mobile.
Internet Explorer and HTML5
Admittedly, HTML5 is still a moving target. In May 2011, HTML5 was moved to a “Last Call†status by the W3C to confirm that the standard was technically sound. In May 2012, the HTML5 specification was moved back to the “Working Draft†state. This signifies that there is still work to do. WHATWG has renamed its HTML5 living standard to HTML. For developers, there is a lot of confusion regarding what is and is not HTML5.
While there are many parts of the HTML5 standard that are still in flux, there are many parts that are solid and implemented in various browsers. Some of these features included with the recently released Internet Explorer 10 are listed below. I hope you are as excited as I am to put them to use.
- H.264 and Video tag. With support for the h.264 video standard, IE needs one less browser plugin to display video. H.264 is the format standard that major sites have gone with, and Internet Explorer supports the standard. Along with support for the codec, the video tag is now supported.
- Embedded Audio tag. HTML5 provides support for an embedded audio tag in HTML5. Internet Explorer supports the mp3 and aac codecs.
- Scalable Vector Graphics. SVG allows for the creation of graphics that scale because they are drawn with vectors and not images.
- CSS3: CSS is how the web is formatted. IE9 supports standards-based CSS3, such as Selectors, Namespaces, Color, Values, Backgrounds, Borders, and Fonts
- AppCache. The AppCache enables webpages to cache resources locally. This will help developers speed up applications because resources can be accessed locally, and not from a remote server.
- Drag and Drop. Support for the draggable attribute makes any HTML element ona page draggable. In addition, the files attribute has been added to the dataTransfer object to enable drag and drop support for one or more files from your local filesystem to a web site.
- Forms. Support for the new HTML5 input types, new attributes for the input element and the progress element have been added.
- History. Support for the History interface has been added. This will help improve a site’s history stack and control of the url.
For a list of more features added to Internet Explorer to support HTML, check out this url on MSDN at the Internet Explorer Developer Center: http://msdn.microsoft.com/en-us/library/ie/hh673546%28v=vs.85%29.aspx
Resources
The jQuery Mobile site: http://jquerymobile.com/
Events in jQuery Mobile: http://jquerymobile.com/test/docs/api/events.html
Data icons in jQuery Mobile: http://jquerymobile.com/test/docs/buttons/buttons-icons.html
My friend Stephen Long. He was also a great tech editor for my most recent book. You can find him on Twitter at: http://twitter.com/long2know. He is a great guy, and you should follow him. My friend Dave Ward. Dave is the author at http://encosia.com and can be found on Twitter at http://twitter.com/encosia. Dave also has a great article on content delivery networks at http://encosia.com/3-reasons-why-you-should-let-google-host-jquery-for-you/.
My friend Kevin Darty. Kevin loves reading through my mobile material and is always a great source for ideas. He can be found on Twitter at http://twitter.com/kdarty.
Market share of various Web/HTML mobile frameworks: http://trends.builtwith.com/Reports/Mobile-Web-Technology-2011/Mobile-Web-Technology-2011.html.
iOS theme: http://taitems.tumblr.com/post/20768414285/jquery-mobile-1-0-1-ios-theme-compatible
Android theme: https://github.com/jjoe64/jquery-mobile-android-theme
Windows Phone theme: http://blogs.msdn.com/b/interoperability/archive/2012/04/25/more-news-from-ms-open-tech-announcing-the-open-source-metro-style-theme.aspx
About the Author
Wallace McClure is a redneck from Tennessee who somehow found his way to Atlanta and Georgia Tech. He was lucky enough to graduate from there twice, with a BS and MS in electrical engineering. He’s always loved things that were new and different, which led to his love of writing software (starting in COBOL and x86 asm), digging into Microsoft’s Web technologies, jumping whole-hog into the .NET Framework 1.0 beta, following in love with mobile way back in 1999, and a whole host of things he probably shouldn’t have done but did anyway. Somewhere along the way, he was contacted by someone representing a publisher that would eventually get purchased by John Wiley and Sons and folded into their Wrox division. Several books later, he’s run the gamut from software architecture, to scaling applications, ADO.NET, SQL Server, Oracle, Web, AJAX and mobile technologies. He’s worked for startup companies and many different organizations, all the way up through U.S. federal government agencies.
When not writing software, writing about software, talking about software or thinking he is a comedian, Wally can be found playing golf, in the gym or coaching basketball.
Twitter: http://twitter.com/wbm
Facebook: https://www.facebook.com/morewally
LinkedIn: http://www.linkedin.com/in/wallymcclure