AJAX navigation menu – 05

I’ve completed the jQuery ajaxify plugin to encapsulate and delegate the AJAX-powered navigation the menu needs, giving the whole menu super-powers now requires me just to queue the right scripts in the block enqueue_action method

public static function enqueue_action($block_id, $block, $original_block = null)
{
    $handle = 'ajaxnav';
    $src = Script::suffix(AJAXNAV_URL . 'assets/js/ajax_navigation.js');
    $deps = array('jquery', 'jquery-ajaxify');
    wp_enqueue_script($handle, $src, $deps);
}

and in the ajax_navigation.js script I only have to call the jQuery plugin with proper parameters like

/*global jQuery, $, document, console, Spinner*/
/**
 * AJAX Navigation Block
 * http://theaveragedev.com
 *
 * Copyright (c) 2014 theAverageDev (Luca Tumedei)
 * Licensed under the GPLv2+ license.
 */

jQuery(document).ready(function($) {
    $('.menu-ajax').ajaxify({
        loadToSelector: '.theContent',
        loadFromSelector: '.block-type-content .block-content'
    });
});

as I’ve described in a previous post.
What’s happening is that the plugin will filter the content loaded from the pages down to the .block-type-content .block-content selector and replace the html previously in the .theContent selector with the new html.

Beyond hard-coding

Since I’m implementing something I’d like to use in the future, specifically an Headway theme block plugin, it really makes no sense forcing the future theme developer, me or another, to use hard-coded strings to initialize the plugin; furthermore the jQuery plugin comes with more options to initialize it and that means all those should, when it comes to the block settings offered to a theme developer, be explicitly “settable” vie the block options. First thing is to make the JavaScript plugin able to accept options

jQuery(document).ready(function($) {
    $('.menu-ajax').ajaxify(ajaxNavMenuOptions);
});

now the script will presume an ajaxNavMenuOptions object is defined in the global scope and that it will contain the desired settings. To ensure such an object literal is printed to the page I will use the wp_localize_script function in the block enqueue_action method

public static function enqueue_action($block_id, $block, $original_block = null)
{
    $handle = 'ajaxnav';
    $src = Script::suffix(AJAXNAV_URL . 'assets/js/ajax_navigation.js');
    $deps = array('jquery', 'jquery-ajaxify');
    wp_enqueue_script($handle, $src, $deps);

    // print the plugin options to the page
    $data = array(
        'loadToSelector' => '.theContent',
        'loadFromSelector' => '.block-type-content .block-content');
    wp_localize_script($handle, 'ajaxNavMenuOptions', $data);
}

nothing has changed in the result here but I’m now able to fetch settings from the block plugin and pass them in the plugin.

Which options?

I will start exposing all of the jQuery plugin options to the block plugin interface to allow a theme developer to really configure it to it’s own needs and will, eventually, reduce them later; I will populate the ajaxnav\BlockOptions file like

<?php
namespace ajaxnav;

class BlockOptions extends \HeadwayBlockOptionsAPI {

    public $tabs = array(
        'ajaxify-settings' => 'AJAX Settings'
    );

    public $inputs = array(

        'ajaxify-settings' => array(

            'load_from_selector' => array(
                'type' => 'text',
                'name' => 'load_from_selector',
                'label' => 'loadFrom selector',
                'tooltip' => 'Use jQuery selector syntax here.',
                'default' => '.block-type-content .block-content'
            ),

            'load_to_selector' => array(
                'type' => 'text',
                'name' => 'load_to_selector',
                'label' => 'loadTo selector',
                'tooltip' => 'Use jQuery selector syntax here.',
                'default' => '.block-type-content'
            ),
            'exclude_selector' => array(
                'type' => 'text',
                'name' => 'exclude_selector',
                'label' => 'exclude selector',
                'tooltip' => 'Use jQuery selector syntax here.',
                'default' => ''
            ),
            'before_load' => array(
                'type' => 'textarea',
                'name' => 'before_load',
                'label' => 'beforeLoad callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function($context, $contentArea, oldContent){}'
            ),
            'after_load' => array(
                'type' => 'textarea',
                'name' => 'after_load',
                'label' => 'afterLoad callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function($context, $contentArea, newContent){}'
            ),
            'after_fail' => array(
                'type' => 'textarea',
                'name' => 'after_fail',
                'label' => 'afterFail callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function($context, $contentArea, oldContent){}'
            ),
            'ajax_anchor_clicked' => array(
                'type' => 'textarea',
                'name' => 'ajax_anchor_clicked',
                'label' => 'ajaxAnchorClicked callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function(evt){}'
            ),
            'external_anchor_clicked' => array(
                'type' => 'textarea',
                'name' => 'external_anchor_clicked',
                'label' => 'externalAnchorClicked callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function(evt){}'
            ),
            'no_ajax_anchor_clicked' => array(
                'type' => 'textarea',
                'name' => 'no_ajax_anchor_clicked',
                'label' => 'noAjaxAnchorClicked callback function',
                'tooltip' => 'Use JavaScript syntax here.',
                'default' => 'function(evt){}'
            ),
        )
    );
}

to have the theme developer presented with such an array of settings

Many settings
Many settings

and will print the options to the page inside the ajaxNavMenuSettings object modifying the enqueue_action to

public static function enqueue_action($block_id, $block, $original_block = null)
{
    $handle = 'ajaxnav';
    $src = Script::suffix(AJAXNAV_URL . 'assets/js/ajax_navigation.js');
    $deps = array('jquery', 'jquery-ajaxify');
    wp_enqueue_script($handle, $src, $deps);
    // retrieve this block settings
    if ($original_block) {
        $block = $original_block;
    }
    // settings for the block will be stored in the $settings->data key/value
    // array
    $settings = new \tad\wrappers\headway\BlockSettings($block);
    wp_localize_script($handle, 'ajaxNavMenuOptions', $settings->data);
}

and will now be able to see the settings in action in the block output.

Next steps

I will increase the usability of the block removing any styling attempt and will refactor the script code to better integrate the possibility for the theme developer to pass functions to it.

I appreciate your input