WordPress Theme Using jQuery Mobile

Learning Objectives

  1. Introduction to jQuery Mobile.
  2. How to use jQuery Mobile Components.
  3. Basics of WordPress theme development.
  4. How to create WordPress theme for mobile using jQuery Mobile.

Try accessing my website using mobile device to preview the mobile theme that we will develop in this tutorial or download theme files and run it from local machine.

Update: Mobile theme is currently turned off because it was creating problem with caching plugin.

Source Files

Introducing jQuery Mobile

jQuery Mobile is official jQuery’s web framework used to develop web based UI for mobile devices. It’s currently in Alpha stage. I was impressed when I first saw its demos and how less code we developers have to write to develop mobile web app.

It’s cross platform framework. Write web app once and run on multiple platforms including iOS, Android, Windows Phone, Symbian, Blackberry, and many more. Click here to view complete compatibility list of browsers on different operating systems.

Using jQuery Mobile

Before integrating jQuery Mobile with WordPress, let’s take a look how jQuery Mobile works. jQuery Mobile makes heavy use of Html5 data attributes. I will explain usage of those components which I will be using in WordPress theme.

Before explaining its UI elements, include all the required files (css and js) as shown below.

<link rel="stylesheet" href="css/jquery.mobile.css" />
<script type="text/javascript" src="js/jquery-1.4.4.js"></script>
<script type="text/javascript" src="js/jquery.mobile.js"></script>

Page

All of your html pages must start with Html5 doctype. All the components of the page must be wrapped in div having data-role=”page” and contents of page must go in div having data-role=”content”.

<!DOCTYPE html> 
<html> 
	<head> 
	<title>Page Title</title> 
	<link rel="stylesheet" href="css/jquery.mobile.min.css" />
	<script src="js/jquery-1.4.4.min.js"></script>
	<script src="js/jquery.mobile.min.js"></script>
</head>
<body> 
 
<div data-role="page">
    <div data-role="content">page content goes here...</div>
</div><!-- /page -->
 
</body>
</html>

Read more about Page component.

Toolbars

I will use header and footer toolbars in wordpress theme. To use header and footer toolbars, all you need is to place two divs having data-role header and footer in div data-role=”page”.

<div data-role="page">
    <div data-role="header"> 
	<h1>Page Heading</h1> 
    </div>
 
    <div data-role="content">page content goes here...</div>
 
    <div data-role="footer">
	<h1>Page Footer</h1>
    </div>
</div><!-- /page -->

Read more about Toolbars

Collapsible Sets

Collapsible set is a collection of collapsible content which user can view/hide by clicking its title. This component will be used to display list of blog posts. Here’s the markup for Collapsible set.

<div data-role="collapsible-set">
    <div data-role="collapsible" data-collapsed="true">
	<h2>Title 1</h2>
	Collapsible content goes here...
    </div>
 
    <div data-role="collapsible" data-collapsed="true">
	<h2>Title 2</h2>
	Collapsible content goes here...
    </div>
</div>

Read more about Collapsible component.

I hope you got the idea how easy is to use jQuery Mobile components. All you need to do is write Html in proper format and rest is done by Javascript and CSS. Here’s how it look.

jQuery Mobile page

Preparing WordPress for jQuery Mobile

I mostly start my WordPress project by modifying default TwentyTen theme or Starkers theme. In this article I will be modifying TwentyTen theme.

Header

Let’s first strip the header.php by removing unnecessary code from it. Here’s the stripped down version.

<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<title><?php wp_title('|', true, 'right'); ?></title>
<link rel="stylesheet" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
<!--add jQuery core file-->
<script type="text/javascript" src="<?php bloginfo( 'template_directory' ); ?>/js/jquery-1.4.4.js"></script>
<!--add jQuery Mobile-->
<script type="text/javascript" src="<?php bloginfo( 'template_directory' ); ?>/js/jquery.mobile.js"></script>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<div id="wrapper" data-role="page">
    <div id="header" data-role="header">
	<h1>iFadey Blog</h1>
        <div id="navbar" data-role="navbar">
            <?php wp_nav_menu( array( 'container' => '' ) ); ?>
        </div><!-- end navbar -->
    </div><!-- end header -->
 
    <div id="content" data-role="content">

As you can see from the above code that each div element is given data-role. wrapper div is actually the Page component. Similarly header div contains the header title and navigation component (having data-role=”navbar”). “navbar” actually contain the links of custom menu created from wp-admin. wp_nav_menu() is used to display the custom menu.

Similarly content div started here in header will contain the blog content and this div will end in footer.php.

Footer

Similarly modify the footer as shown below.

</div><!-- end content -->
 
<div id="footer" data-role="footer"> 
    <h4>Copyright 2009 - 2011. All Rights Reserved</h4>
</div><!-- end footer -->
</div><!-- end wrapper -->
</body>
</html>

Content div ends here and footer toolbar is also here with closing tag of wrapper (Page component).

Index

Now modify index.php file which by default display blog posts as a list with pagination.

<?php get_header(); ?>
 
<?php
/* Run the loop to output the posts.
 * If you want to overload this in a child theme then include a file
 * called loop-index.php and that will be used instead.
 */
 get_template_part( 'loop', 'index' );
?>
 
<?php get_footer(); ?>

As you can see the index.php is very simple. It’s only calling other functions to print the required Html code. get_header() and get_footer() display the code in header.php and footer.php. It’s similar to including a file in PHP using include keyword.

Loop

All the logic for displaying blog posts will go in loop.php and the function get_template_part() in index.php actually displays the content of loop.php file. I stripped down loop.php of TwentyTen theme for use in mobile theme.

<?php if ( ! have_posts() ) : ?>
    <div id="post-0" class="post error404 not-found">
	<h1 class="entry-title"><?php _e( 'Not Found', 'twentyten' ); ?></h1>
	<div class="entry-content">
		<p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyten' ); ?></p>
		<?php get_search_form(); ?>
	</div><!-- .entry-content -->
    </div><!-- #post-0 -->
<?php endif; ?>

The first part of loop.php displays the Page Not Found page and search form. It actually checks for existance of post(s) using function have_posts(). The important thing to note here is _e() function. Every string we need to print is passed to _e() or __(). For example _e( ‘Not Found’, ‘twentyten’ ). This is done to make our theme multilingual.

_e() is used to translate and echo the string. __() also translate and returns it so you can store it in a variable.

Search form is displayed using get_search_form() function and you view code for search from wp-includes/general-template.php. Here’s the code of search form in get_search_form().

$form = '<form role="search" method="get" id="searchform" action="' . home_url( '/' ) . '" >
    <div><label class="screen-reader-text" for="s">' . __('Search for:') . '</label>
    <input type="text" value="' . get_search_query() . '" name="s" id="s" />
    <input type="submit" id="searchsubmit" value="'. esc_attr__('Search') .'" />
    </div>
    </form>';

The second part of this file is the wordpress loop for displaying posts. Let’s take a look at it step by step.

<div data-role="collapsible-set">
<?php while ( have_posts() ) : the_post(); ?>
    <div id="post-<?php the_ID(); ?>" <?php post_class(); ?> data-role="collapsible" data-collapsed="true">
	<h2 class="entry-title"><?php the_title(); ?></h2>
    </div>
<?php endwhile; ?>
</div><!--end data-role="collapsible-set"-->

Above code wraps the loop in div having data-role collapsible-set to make the inner collapsible components part of single set which behaves like Accordian UI element.

The loop iterates over each blog post and displays a div with unique id using function the_ID(). Similarly post_class() function apply CSS classes to this div which are useful to change look and feel using CSS. Then comes the data-role which is used to make it collapsible element. Finally data-collapsed is set to true so it won’t display its content by default. User have to click the title to display its content.

Then comes the h2 tag which contains the post title text. This h2 will be the title of collapsible component.

Now add the following code below post title as shown below.

<h2 class="entry-title"><?php the_title(); ?></h2>
 
<div class="entry-meta">
    <?php twentyten_posted_on(); ?>
</div><!-- .entry-meta -->

The div element with class entry-meta contains the meta information (posted date and author name) about this post. twentyten_posted_on() is a custom function in functions.php which prints the meta information.

<?php if ( is_archive() || is_search() ) : // Only display excerpts for archives and search. ?>
    <div class="entry-summary">
	    <?php the_excerpt(); ?>
    </div><!-- .entry-summary -->
<?php else : ?>
    <div class="entry-content">
	<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?>
	<?php wp_link_pages( array( 'before' => '<div class="page-link">' . __( 'Pages:', 'twentyten' ), 'after' => '</div>' ) ); ?>
    </div><!-- .entry-content -->
<?php endif; ?>

The above code first checks that the current request is for archive or is a search page which appears after user enter keyword and click Search button. If it’s an archive or search, then it displays the excerpt (post summary) of each post. Excerpts are displayed using function the_excerpt().

The else part of if condition displays the complete contents of each post. This part is executed when we open the home page of blog containing list of blog posts with pagination. Note that the post contents are displayed using the_content() function. This function checks for <!‐‐more‐‐> tags to stop displaying the content on that location and display a link “Continue reading →”.

The next line in else part is a function call to wp_link_pages(). This function is used to paginate a single post. For example your post is too long and you don’t want to display it in a single page. You can simply write a quicktag <–nextpage–> where you want to stop displaying the post content and display pagination links.

Single Post Pagination

<div class="entry-utility">
    <?php if ( count( get_the_category() ) ) : ?>
	    <span class="cat-links">
		    <?php printf( __( '<span class="%1$s">Posted in</span> %2$s', 'twentyten' ), 'entry-utility-prep entry-utility-prep-cat-links', get_the_category_list( ', ' ) ); ?>
	    </span>
	    <span class="meta-sep">|</span>
    <?php endif; ?>
</div><!-- .entry-utility -->

The next part in the loop.php is div with class entry-utility. This div contains the if condition to check whether there are any categories assigned to current post. Function get_the_category() returns an array containing categories and count() is used to count the total elements in array returned from get_the_category() function. If there are any categories, it simply prints the two span tags. First span with class “cat-links” contain the categories separated by comma. Second span contains the separator |. This separator is added to separate categories from comments link which we will add next.

<?php endif; ?>
 
<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), __( '1 Comment', 'twentyten' ), __( '% Comments', 'twentyten' ) ); ?></span>

Add above line after endif. Function comments_popup_link() is used to display link to comments. If there is a single comment or more than one comment then it displays the link as “NUM Comments” (where NUM is the total comments) otherwise it displays a link “Leave a comment”.

The last thing which will go in entry-utility div is the Edit link which will be displayed when admin user is logged in. This link take the logged in user to edit post page in admin panel.

<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>

Add above line right below comments_popup_link() funciton call.

Finally add the following code snippet below the ending div of data-role=”collapsible-set”.

</div><!--end data-role="collapsible-set"-->
 
<?php if ( $wp_query->max_num_pages > 1 ) : ?>
    <div id="nav-above" class="navigation">
	<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?></div>
	<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?></div>
    </div><!-- #nav-above -->
<?php endif; ?>

The last part of this file displays the Older posts/Newer posts links using functions next_posts_link and previous_posts_link. This is done to allow pagination on blog posts.

Next/Previous Pages

Bit of CSS

Add following CSS in style.css.

@import url("css/jquery.mobile.css");
 
#nav-below, #nav-above, .entry-meta, .entry-utility, .page-link {
    background: #EFEFEF;
 
    box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset;
    -moz-box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset;
    -webkit-box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset;
 
    font-size: .8em;
    padding: 4px;
}
 
.nav-previous { float: left; }
.nav-next { float: right; }
 
.page-link {
    font-size: 1.1em;
    text-align: center;
    margin: 6px 0;
}
 
.demo_source {
    font-size: 1.5em;
    text-align: center;
}
.demo_source a { text-shadow: 1px 1px 0 #fff; }
 
.more-link {
    font-size: 1.4em;
    text-decoration: none;
    text-shadow: 0 0 6px rgba(0, 0, 0, .2);
}
.more-link:hover { text-shadow: none; }
 
/*clearfix taken from Html5 Boilerplate http://html5boilerplate.com*/
.clearfix:before, .clearfix:after {
  content: "\0020"; display: block; height: 0; visibility: hidden;	
}
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }

Note that instead of adding the jQuery Mobile’s CSS file in header.php, I imported it in style.css. As you can see from the above styles that .nav-previous and .nav-next are floated left and right. Both of these classes are applied to links which are childern of #nav-below and #nav-above. Because of floating children of #nav-above and #nav-below, we need to apply clearfix class to both of these nav bars. Also remember that these nav bars contain links of next/previous post relative to currently opened one.

First open single.php and add class clearfix to #nav-above. But remove #nav-below from single.php because we are building this theme for mobile devices so we need to reduce Html and CSS. Now the opening div of #nav-above must look like this:

<div id="nav-above" class="navigation clearfix">

jQuery Mobile is new library and current in Alpha stage. So you may face problems in few devices and also performance is not optimal (specially when using it online).


comments powered by Disqus