AJAX navigation menu 01

For the project at hand I’ve been asked to develop an AJAX navigation menu that should pull content from the database for certain pages and show that content either as a preview or in its entirety. I will be implementing the navigation menu as an Headway block plugin but will try to keep the business logic of the navigation menu as decoupled as possible from the theme framework both as a test of the possibility and to increase its reuse potential.

Templating

Using a grunt-init block plugin template I’ve laid out the basic function and after the mandatory

npm install
grunt watch

in the root folder I will head to the PHP code.

First incarnation and a decoupling choice

In the ajaxnav\Block class I’m setting up the block to be recognized by Headway and then will fill it’s content method to actually print something to the page.

<?php
namespace ajaxnav;

use ajaxnav\AJAXNavMenu;
use tad\wrappers\headway\BlockSettings as Settings;

class Block extends \HeadwayBlockAPI {

    public $id = 'ajaxnav';
    public $name = 'AJAX Nav Block';
    public $options_class = '\ajaxnav\BlockOptions';
    public $description = 'Adds an AJAX-based navigation block to Headway visual theme editor';

    public static function init_action($block_id, $block) 
    {
        // register the nav menu with the theme
        // blatant copy of the default navigation block
        $name = \HeadwayBlocksData::get_block_name($block) . ' &mdash; ' . 'Layout: ' . \HeadwayLayout::get_name($block['layout']);
        register_nav_menu('navigation_block_' . $block_id, $name);
    }

    public function content($block) {
        $themeLocation = 'navigation_block_' . $block['id'];
        AJAXNavMenu::on($themeLocation)->show();
    }
}

Here comes the first decoupling action from the framework: I’m not defining the methods to print the menu to the page in the content method itself but rather will delegate the rendering of the navigation block to another class allowing its use in other contexts

<?php
namespace ajaxnav;

use tad\adapters\Functions;

class AJAXNavMenu
{
    protected $functions;

    public function __construct($themeLocation = '', \tad\interfaces\FunctionsAdapter $functions = null)
    {
        if (!is_string($themeLocation)) {
            throw new \BadMethodCallException("Theme location must be a string.", 1);
        }
        if (is_null($<span class="hiddenGrammarError" pre=""><span class="hiddenGrammarError" pre="">functions)) {
            $functions</span></span> = new Functions();
        }
        $this->functions = $functions;
        $this->themeLocation = $themeLocation;
    }
    public static function on($themeLocation = '')
    {
        return new self($themeLocation);
    }
    public function show()
    {
        // enqueue the style for the menu
        wp_enqueue_style( 
            'ajaxnav', 
            AJAXNAV_URL . 'assets/css/ajax_navigation.css'
            );

        $args = array(
            'theme_location' => $this->themeLocation,
            'menu' => '',
            'container' => 'nav',
            'container_class' => 'menu-ajax-container',
            'container_id' => '',
            'menu_class' => 'menu',
            'menu_id' => '',
            'echo' => true,
            'fallback_cb' => 'wp_page_menu',
            'before' => '',
            'after' => '',
            'link_before' => '',
            'link_after' => '',
            'items_wrap' => '<ul id = "%1$s" class = "%2$s">%3$s</ul>',
            'depth' => 2,
            'walker' => ''
            );

        $this->functions->wp_nav_menu( $args );
    }
}

The class also comes ready for dependency injection and testing.

Next steps

I will implement basic drop down functions for the menu and fix its behavior in various screen sizes before jumping into the AJAX battleground.