Friday, July 31, 2015

Wrap Up

This series of posts (read from the bottom up) started with the premise:
This series of posts explores the basics of creating WordPress themes for one's use; as opposed to creating one for redistribution.  The distinction is important as we will only focus on developing it for a particular use and thus greatly simplify the effort. 
This effort also is focused on giving one maximal control over the site (HTML, CSS, and JavaScript) with minimal use of programming (WordPress and PHP).
In the end, we have created a fully functional WordPress theme that is ready to be styled to one's liking.  A copy of the result can be found at: https://github.com/larkintuckerllc/barebones.

 Enjoy.

Enabling Comments

To enable comments on just posts, one needs to implement the following (adding to pages is a matter of updating page.php).

First add the following just below the content on single.php.

single.php
<?php
if (comments_open() || get_comments_number()) :
  comments_template();
endif;
?>

Then create a comments.php template file:

comments.php
<?php
if (post_password_required()) {
 return;
}
?>
<div id="comments" class="comments-area">
  <?php if (have_comments()) : ?>
    <ul class="comment-list">
    <?php wp_list_comments(); ?>
    </ul>
  <?php endif; ?>
  <?php comment_form(); ?>
</div>

Interestingly, one does not need to implement the comments-popup.php listed in the template hierarchy unless one enables comment popups.  At this point, we have considered all the primary files (and some secondary ones) in the WordPress template hierarchy <https://developer.wordpress.org/themes/basics/template-hierarchy/>

Handling Inserted Images and Videos (YouTube)

When writing up training materials for a customer on managing a WordPress site, came across this subtle feature that themes need to handle: handing inserted images and videos (YouTube).

In particular, the WYSIWYG editor allows one to left, center, and right align images which puts certain classes on the image that the theme's style needs to handle: https://codex.wordpress.org/Wrapping_Text_Around_Images.

The following is a solution that also handles small (phone) screens gracefully.

style.css
img.alignleft, img.alignright, img.aligncenter {
  display: block;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 10px;
  height: auto;
  max-width: 100%;
}

@media (min-width: 768px) {
  img.alignright {
     float: right;
     margin-left: 10px;
  }
  .alignleft {
     float: left;
     margin-right: 10px;
  }
}

While not so much of a theme issue, one also needs to handle videos, e.g., how does one wrap text around videos (handle small screens).  In this case, the solution is a plugin: https://wordpress.org/plugins/advanced-responsive-video-embedder/.

Wednesday, July 1, 2015

Multiple Content Areas

Out of of the box, WordPress only supports a single content area per page / post; with the custom fields feature providing limited additional flexibility.  Luckily, a very powerful WordPress plugin called Advanced Custom Fields (ACF) can be used support multiple content areas per page / post.

To get started, install the Advanced Custom Fields plugin.

Using admin > Custom Fields create a new field group called home with two WYSIWYG fields named top and bottom and set it to show when Page is equal to home.  To limit the end-user to just editing these fields, hide all the other elements from the edit screen.

With this in place, we can update the front-page.php as follows:

front-page.php
<?php get_header(); ?>
<?php wp_nav_menu(array('theme_location' => 'header-menu')); ?>
<?php get_search_form(); ?>
<?php while (have_posts()) : the_post(); ?>
  <?php the_field('top'); ?>
  <?php the_field('bottom'); ?>
<?php endwhile; ?>
<?php get_footer(); ?>

While this example only used WYSIWYG fields, we can limit the end-user to content like plain text and images to be used in highly styled elements.

Tuesday, June 30, 2015

Organizing the Templates

Now that we have implemented the key template files (outside of commenting), we have introduced a significant amount of repetition; repetition is bad.  A simple fix is to move the common top and bottom of the HTML files into header.php and footer.php and then include them into each file.

header.php
<html>
  <head>
    <title>Barebones</title>
    <?php wp_head() ?>
  </head>
  <body>

footer.php
<?php wp_footer() ?>
  </body>
</html>    

And then into each of the other files we add the following to the top (replacing the header.php content):

<?php get_header(); ?>

and the following to the bottom (replacing the footer.php content):

<?php get_footer(); ?>

Adding Search

WordPress includes a search feature that is easy to implement.  On front-page.php add the following:

front-page.php
<?php get_search_form(); ?>

With this in place, the search results page is defaulting to index.php which does not work. We will start with copying page.php to search.php. We then will make some refinements.

search.php
<html>
  <head>
    <title>Barebones</title>
    <?php wp_head() ?>
  </head>
  <body>
    <?php wp_nav_menu(array('theme_location' => 'header-menu')); ?>
    <?php if (function_exists('yoast_breadcrumb')) {
      yoast_breadcrumb();
     }?>
    <?php get_search_form(); ?>
    <?php if (have_posts()) : ?>
      <?php while (have_posts()) : the_post(); ?>
        <p><b><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></b></p>
      <?php endwhile; ?>
    <?php else : ?>
      <p>No matches.</p>
    <?php endif; ?>
    <?php wp_footer() ?>
  </body>
</html>

Pinning Down Posts

Now that we have the infrastructure for the home page and the hierarchy of sub-pages, we need to explore content that is organized by time, i.e., posts, for ideas like press release archives.

First, we need to update the default category for posts and change its name from Uncategorized to something more useful, e.g., Press Releases, by using admin > Posts > Categories.

Then we create a couple of posts by using admin > Posts > All Posts.

Finally, we can go into admin > Appearance .> Menus to add the archive screen for the Press Releases category to the menu.

At this point, however, navigating to the category archive does not result in the desired result as it is picking up the index.php file for the template.  Looking at the template hierarchy again we see that we need to create archive.php by simply copying over page.php:  https://developer.wordpress.org/themes/basics/template-hierarchy/.

The problem now, however, is that the screen is not geared towards a list of posts.  A better layout would a list of as follows:

Post Title (linked to full post)
Post Date
Beginning part of the post.

To implement this, we update archive.php as follows:

archive.php
<html>
  <head>
    <title>Barebones</title>
    <?php wp_head() ?>
  </head>
  <body>
    <?php wp_nav_menu(array('theme_location' => 'header-menu')); ?>
    <?php if (function_exists('yoast_breadcrumb')) {
      yoast_breadcrumb();
     }?>
    <?php while (have_posts()) : the_post(); ?>
      <p><b><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></b><br />
      <i><?php the_time('F j, Y'); ?></i><br />
      <?php the_content('', false); ?></p>
    <?php endwhile; ?>
    <?php wp_footer() ?>
  </body>
</html>

Now that we have the archive, the link to the full post brings up our index.php for the template.  To fix this, we copy page.php to single.php and update as follows:

single.php
<html>
  <head>
    <title>Barebones</title>
    <?php wp_head() ?>
  </head>
  <body>
    <?php wp_nav_menu(array('theme_location' => 'header-menu')); ?>
    <?php if (function_exists('yoast_breadcrumb')) {
      yoast_breadcrumb();
    }?>
    <?php while (have_posts()) : the_post(); ?>
      <p><b><?php the_title(); ?></b><br />
      <i><?php the_time('F j, Y'); ?></i><br /></p>
      <?php the_content(); ?>
    <?php endwhile; ?>
    <?php wp_footer() ?>
  </body>
</html>

Finally, in order to get the breadcrumbs to work for post pages change admin > SEO > Advanced > Taxonomy to... > Posts to Category.

Refining the Templates

Now that we have added the breadcrumbs, we might be thinking that we do not need it on the home page, just on the sub-pages. As a matter of fact, we likely are thinking that the home page need a completely different structure than the sub-pages.  Looking back at the template hierarchy we can address this easily: https://developer.wordpress.org/themes/basics/template-hierarchy/.

We start by copying index.php to three new files:

  • front-page.php
  • page.php
  • 404.php

On front-page.php, we can delete the breadcrumb block.

On 404.php, we can delete the breadcrumb and "The Loop" block, i.e., the code looping on posts and add a bit about the page not being found.

Because we are not currently using, posts, search, or commenting the index.php file is no longer in use. For completeness, we can change the content of index.php to look like the 404.php file as a catch all.

Monday, June 29, 2015

Menuing

With out three page structure, we need to a way to navigate from the home page to the pages A and B. Luckily, WordPress provides a navigation menus feature that makes this easy: https://codex.wordpress.org/Navigation_Menus.

The first step is to add to functions.php:

functions.php
function register_my_menu() {
  register_nav_menu('header-menu',__('Header Menu'));
}
add_action( 'init', 'register_my_menu' );

note: The weird double-underscore is use for language, e.g., Spanish, translation if enabled.

Then we add the following just below the body tag in index.php.

index.php
<?php wp_nav_menu(array('theme_location' => 'header-menu')); ?>

Now as we update the menu in admin > Appearance > Menus, we can see the changes reflected on all of the pages.

Setting Up Permalinks

A quick visit to admin > Settings > Permalinks (e.g., setting it to Post name) will give one nice looking URLs.

Setting Up Breadcrumbs

This is essentially the "menu" for navigating back up the hierarchy of pages.

Here we use our first Wordpress Plugin; the one that we are using is called WordPress SEO  Use admin > Plugins to get this done and insert the following in index.php where one wants the breadcrumb to appear, e.g., just below the navigation menu.

index.php
<?php if (function_exists('yoast_breadcrumb')) {
  yoast_breadcrumb();
}?>

note: This plug-in serves a number other SEO purposes that we will address in a later post.

Adding in Third-Party CSS and JavaScript Libraries

Because we are going to want to use third-party CSS and JavaScript libraries, we need to learn how to accomplish this in Wordpress.

As an example, we are going to load the Bootstrap library: http://getbootstrap.com/. The first step is to get the files into the template folder, e.g., wp-content/themes/barbones.  In my case, I used a tool called bower to get the files downloaded: http://bower.io/.

We do this by simply updating index.php as follows:

index.php
<html>
  <head>
    <title>Barebones</title>
    <link rel="stylesheet" href="<?php echo bloginfo("template_url"); ?>/bower_components/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>">
  </head>
  <body>
    <?php while (have_posts()) : the_post(); ?>
      <?php the_content(); ?>
    <?php endwhile; ?>
    <script src="<?php echo bloginfo("template_url"); ?>/bower_components/jquery/dist/jquery.min.js"></script>
    <script src="<?php echo bloginfo("template_url"); ?>/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
  </body>
</html>

note: The locations of one's bootstrap files will differ depending on how one download them.

A Better Way

While the above method is super clean, it does not play well with Wordpress and other plugins, e.g., any JavaScript or CSS that they need will not be inserted.  The most obvious example of this is the lack of the WordPress toolbar when logged in.

The proper way then involves registration and enqueueing both JavaScript and CSS resources; e.g., the following explains script registration: https://codex.wordpress.org/Function_Reference/wp_register_script.

The first step is to create and update the functions.php file with the following as the example of using bootstrap:

functions.php
<?php
  function add_theme_scripts() {
    wp_register_style('bootstrap',
      get_template_directory_uri() .
      '/bower_components/bootstrap/dist/css/bootstrap.min.css',
      array(), '20150629', 'all');
    wp_register_style('style', get_stylesheet_uri(),
      array(), '20150629', 'all');
    wp_register_script('bootstrap',
      get_template_directory_uri() .
      '/bower_components/bootstrap/dist/js/bootstrap.min.js',
      array('jquery'), '20150629', true);
    wp_enqueue_style('bootstrap');
    wp_enqueue_style('style');
    wp_enqueue_script('bootstrap');
  }
  add_action('wp_enqueue_scripts', 'add_theme_scripts');
// REMOVED CLOSING TAG PER WP CODING STANDARDS

note: As to removing the closing tag: https://make.wordpress.org/core/handbook/coding-standards/php/#remove-trailing-spaces.

Then we need to update index.php as follows:

index.php
<html>
  <head>
    <title>Barebones</title>
    <?php wp_head() ?>
  </head>
  <body>
    <?php while (have_posts()) : the_post(); ?>
      <?php the_content(); ?>
    <?php endwhile; ?>
    <?php wp_footer() ?>
  </body>
</html>

A Minimally Useful Theme

Now we are going to make the theme minimally useful by updating the index.php and the style.css files.

index.js
<html>
  <head>
    <title>Barebones</title>
    <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>">
  </head>
  <body>
    <?php while (have_posts()) : the_post(); ?>
      <?php the_content(); ?>
    <?php endwhile; ?>
  </body>
</html>

style.css
body {
  background-color: yellow;
}

The first thing one will notice is that the stylesheet is now being applied (however hideous).  In order to see the posts (actually can be either posts or pages) showing on the screen, we need to add some content.  Since we are focused on creating a home page and a hierarchy of sub pages, we will create the following pages with some random content, e.g., "hello from page A", etc.
  • home
  • A
  • B
note: We will treat pages A and B as top level pages instead of setting home as their parent to give us clean URLs later.

When viewing a page, i.e., selecting view from admin,  one will now see the content displayed on the screen.

Finally, we will go ahead and set the home page to load as what loads when the site is loaded without any query string (i.e., the home page of the site). Use admin > settings > reading > Front page displays to set this.

Sunday, June 28, 2015

Bootstrapping a Theme

This series of posts explores the basics of creating WordPress themes for one's use; as opposed to creating one for redistribution.  The distinction is important as we will only focus on developing it for a particular use and thus greatly simplify the effort.

This particular use will to have:
  • Static Home Page
  • Hierarchy of Sub Pages
  • Search
  • Press Releases
  • Mega Menu
  • Breadcrumbs
This effort also is focused on giving one maximal control over the site (HTML, CSS, and JavaScript) with minimal use of programming (WordPress and PHP).

The starting point to understanding theme development is the template hierarchy: https://developer.wordpress.org/themes/basics/template-hierarchy/.  Rather than building out a bunch of template files to start with; we will start slowly and introduce them one at a time.

Bootstrapping a Theme

Create a new folder for your theme, e.g., barebones, in the WordPress folder: wp-content/themes.

Populate this new folder with two files:

index.php
<html>
  <head>
    <title>Barebones</title>
  </head>
  <body>
    <p>Hello Barebones</p>
  </body>
</html>
An empty style.css file.

At this point we have a theme that we can activate.  This theme, however, is not terrible useful at all that it does is display the text Hello Barebones regardless of the query string.