Carrington Build Documentation

Creating Custom Module and Row Options

Introduction

Carrington Build allows developers to create custom module and row options. One example of an application of this technology is adding a custom CSS class to a row or module. Row and module options are fairly free-form and are responsible for: providing their own user interface, registering and processing their own AJAX endpoint, and implementing their functionality using Build actions and filters.

Implementation

Constructor

Both cfct_row_option and cfct_module_option ultimately extend the cfct_option abstract class. It is necessary that you override the constructor and provide your option a name, and a slug.

class my_custom_row_option extends cfct_row_option {
    public function __construct() {
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }
    ...
}

Provide your UI

The only other required function you extend to create an option is the html() function. This is the function that provides the UI for your option. It is passed the module or row data, along with the option data used by this option.

class my_custom_row_option extends cfct_row_option {
    public function __construct() {
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }

    public function html($row_data, $option_data) {
        return '<div>The UI</div>';
    }
    ...
}

The cfct_option class also provides the load_view function that allows you to take a more template approach.

class my_custom_row_option extends cfct_row_option {
    public function __construct() {
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }

    public function html($row_data, $option_data) {
        return $this->load_view(dirname(__FILE__).'my-view-file.php', array('some' => 'data'));
    }
    ...
}

In this example the variable $some would be passed to the view file containing 'data'.

Register your endpoint and provide javascript to process

Once you have your UI in place you need to be able to save the data you are gathering there. To do this you must register your options ajax endpoint, and write the javascript to process and submit the data.

In the constructor of your option, you can do something like this to register an ajax endpoint with build.

    public function __construct() {
        global $cfct_build;
        $cfct_build->register_ajax_handler('my_custom_row_option_update', array($this, 'ajax_update'));
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }

This tells build that whenever it receives an ajax request with the action of my_custom_row_option_update, call the ajax_update() function of $this class. So now we just need to implement our ajax_update() function.

Below I’ve shown a basic example of retrieving the build data, modifying it, and saving our modifications.

class my_custom_row_option extends cfct_row_option {
    public function __construct() {
        global $cfct_build;
        $cfct_build->register_ajax_handler('my_custom_row_option_update', array($this, 'ajax_update'));
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }

    public function html($row_data, $option_data) {
        return $this->load_view(dirname(__FILE__).'my-view-file.php', array('some' => 'data'));
    }

    public function ajax_update($data) {
        global $cfct_build;
        $post_data = $cfct_build->get_postmeta($data['post_id']);

        // Get Option Data
        $option_data = $post_data['row-options'][$data['row_id']][$this->id_base];

        // Manipulate $option_data with submitted POST $data

        // Re-set option data before saving
        $post_data['row-options'][$data['row_id']][$this->id_base] = $option_data;

        if (!$cfct_build->set_postmeta($data['post_id'], $post_data)) {
            throw new cfct_row_exception(__('Could not save postmeta for post on row intrusion update','carrington-build'));
        }

        return new cfct_message(array(
            'something' => 'you',
            'want' => 'to',
            'return' => 'as json',
        ));
    }
    ...
}

Implement the effect

At this point we have a row option UI and we’re storing the data it produces. Now you can register actions in your constructor to produce the desired effect.

    public function __construct() {
        global $cfct_build;
        $cfct_build->register_ajax_handler('my_custom_row_option_update', array($this, 'ajax_update'));

        add_action('some_action', array($this, 'action_handler'));

        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');
    }

Where to put them

You can register custom row/module option locations with something like this in your functions.php file

function cf_extra_row_option_dirs( $dirs ) {
    return array_merge($dirs, array(
        trailingslashit(get_template_directory()) . 'carrington-build-row-options/'
    ));
}
add_filter('cfct-row-option-dirs', 'cf_extra_row_option_dirs');

This will register an additional row-option directory at /path/to/your/theme/carrington-build-row-options.

Register your option

So now that we have a complete option, we can register it to apply to all rows or modules or individual row types or module types.

Globally

To register your option to take effect on all rows or modules, do something like the following in your option constructor. This utilizes the cfct-build-row-options filter to add your option globally.

    public function __construct() {
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');

        // Add this option to all rows
        add_filter(
            'cfct-build-row-options',
            create_function('$options',
                'return array_merge($options, array("cfct_row_option_custom_classes"));'
            )
        );
    }

Apply to a specific Row/Module

There are two ways to apply your option to a specific type of row/module.

  1. For built in row/module types

For built in types you can add the option to a specific type by doing something like the following.

    public function __construct() {
        parent::__construct(__('My Custom Row Option', 'your-textdomain'), 'my-custom-row-option');

        // Add this option to only the cfct_row_a row type
        add_filter(
            'cfct-build-row-options',
            create_function('$options, $row_class',
            'return ($row_class == "cfct_row_a") ?
                array_merge($options, array("cfct_row_option_positioning")) :
                $options;'
            ),
            10, 2
        );
    }

This makes sure you only apply the option to cfct_row_a row type.

  1. For custom row/module types

If you are the one building the row, and want to pack a custom option in you can simply include the option file in your row definition. Then all you need to do is override the get_extras() function in your row definition and append the option type.

    ...
    public function get_extras() {
        return array_merge(parent::get_extras(), array('my_custom_row_option'));
    }
    ...
Back to Carrington Build

These sections are available to the public. The remaining sections are available exclusively to customers.