AJAX navigation menu – 03

Staying DRY

The menu, in its AJAX-powered form, is really a way of pulling pages and posts into the content area of the page without needing a page refresh. In practical terms said area of the site will need to be populated with HTML markup dynamically generated either via JavaScript (AJAX version) or via PHP (standard version).
I’m taking the easy way to stay DRY here and instead of a work flow like this one:

  • ajax request -> load JSON from db -> populate markup with data -> fill the container area
  • normal template request -> load data from db -> create HTML from template.php -> fill the container area

I will use the Handlebars templating engine in its PHP implementation and JavaScript version to have a common first part and have a flow like

  • AJAX request -> load the Handlebars template (a .handlebars file) content -> compile it using JavaScript version of Handlebars -> append to content area
  • normal template request -> load the Handlebars template (a .handlebars file) content -> compile it using PHP version of Handlebars -> echo to the page

This way I’m keeping the templates synchronized and will avoid repeating markup throughout the code. That’s a not well known approach for me but seems fitting now. I will store the Handlebars templates in .handlebars files to be able to use WordPress built-in locate_template or get_template_part functions on the PHP side; on the JavaScript side I will use the jQuery.get method to retrieve the template contents.

An example template

Following along best WordPress practices I’d like to write the basic templates files like index.php this way

<?php

use someNamespace\HandlebarGuy as HBGuy;

get_header(); ?>

    <div id="primary" class="content-area">
        <main id="main" class="site-main" role="main">

            if (have_posts()) {
                // like 'get_template_part("content", $name)'
                // but making it pass via Handlebars
                HBGuy::renderTemplate('content', get_post_format());
            }
            else
                // no doubt about the name here
                // use 'content-none.handlebars' file
                HBGuy::renderTemplate('content', 'none');

        </main>
    </div>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

where someNamespace\HandlebarGuy is an helper class I have not implemented yet.
If the content template in question was the content-single.handlebars, as an example, I will write the template file not using standard PHP and HTML markup syntax but using Handlebars syntax like

// file content-single.handlebar

{{#each post}}
    <h2>{{title}}</h2>
    <p>{{content}}</p>
{{/each}}

and what I’m ending with is pure Handlebars syntax ready to be parsed. At least so I hope since I’ve never used Handlebars before.
This works for standard WordPress template hierarchy and custom page templates as well.

The inside man

While it’s easy to discern which template to use at page load that gets complicated when asynchronously done via AJAX because the page or post query is not there to be interrogated.
I’m using Thermal API to retrieve data from the database in place of a custom made function and that means that, when the user clicks a menu item linking to a page or post, I will send GET requests to an url like

http://testing.dev/wp_api/v1/posts/701

to receive a response like

{
    "author": {
        "avatar": [
            {
                "height": 96,
                "url": "http://0.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?s=96",
                "width": 96
            }
        ],
        "display_name": "themedemos",
        "id": 2,
        "id_str": "2",
        "meta": {
            "description": "",
            "first_name": "",
            "last_name": "",
            "nickname": "themedemos"
        },
        "nicename": "themedemos",
        "posts_url": "http://testing.dev/author/themedemos/",
        "user_url": ""
    },
    "comment_count": 0,
    "comment_status": "open",
    "content": "Use this static Page to test the Theme's handling of the Front Page template file.",
    "content_display": "<p>Use this static Page to test the Theme&#8217;s handling of the Front Page template file.</p>",
    "date": "2011-05-21T01:49:43+00:00",
    "excerpt": "",
    "excerpt_display": "<p>Use this static Page to test the Theme&#8217;s handling of the Front Page template file. This is the Front Page content. Use this static Page to test the Front Page output of the Theme. The Theme should properly handle both Blog Posts Index as Front Page and static Page as Front Page. If the site [&hellip;]</p>\n",
    "id": 701,
    "id_str": "701",
    "media": [],
    "menu_order": 0,
    "meta": {},
    "mime_type": "",
    "modified": "2014-04-15T07:33:19+00:00",
    "name": "front-page",
    "parent": 0,
    "parent_str": "0",
    "permalink": "http://testing.dev/front-page/",
    "status": "publish",
    "taxonomies": {},

    "template": "page-templates/full-width.php",

    "title": "Front Page",
    "type": "page"
}

I’ve added the template key via a Thermal API add-on plugin I’ve made and detailed in a previous post. This seems like a good first step in the right direction but will only count when querying for a page.
I will have to devise a way to go from a URL to a template to, guess WP_Query is involved, return a more meaningful template information.

Leaving Headway behind

I’ve tried to get template information using Headway theme framework but really could not make it work in a reasonable time. I will get back on the subject in the future but will have to work with a vanilla WordPress theme for the project at hand.

Next step

I’ve made some proof-of-concept experiments to load and compile Handlebars template both in PHP and in Javascript and that seems to be the way. I will implement the PHP helper classes, and add them to my libraries, and try to get an index page up and running as soon as possible.

I appreciate your input