Thesis 2 Box Development Beginner Template

Thesis 2 can be extended with boxes. Boxes are similar to plugins for WordPress, but with a few key differences.

  • Boxes can take full advantage of the Thesis API and its various methods.
  • Boxes can load their resources conditionally – relative to each template.

There are other less obvious advantages but the two key differences above make a significant difference and are arguable a leap or two ahead of plugins.

Being able to take advantage of the Thesis API is powerful in itself. The methods that are accessible make development a pleasant experience. The API allows for clean code and less repetition with a more logical approach and plenty of reusable code.

One of the key methods that the Thesis API has is the preload() method. This method allows you to load resources that are present only on the template(s) that the box is active on. That means no more globally loaded Resources! unless of course it needs to be loaded everywhere then you can use the construct() method.

Example Thesis 2 Boxes

Below I will show a few examples of Thesis box templates. Each box will gradually be more complex.

In order to create a Thesis 2 box you first need to create a folder my-first-box.

Inside that folder you will need a PHP file called box.php

Simple Thesis 2 Box

This will be the simplest possible Thesis 2 box.

<?php
/*
Name: My First Box
Author: Matthew Horne - Diywpblog.com
Description: This is an example box.
Version: 1.0
Class: my_first_box
License: MIT
*/
class my_first_box extends thesis_box {

   protected function translate() 
   {
      $this->title = __('My First Thesis Box', $this->_class);
   }
   
   public function html($args = array()) 
   {
      extract($args = is_array($args) ? $args : array());
      
      $string = "Hello World!";     
      echo $string;
   }  
}

This will produce a simple output – “Hello Word!” – wherever the box is positioned in the HTML Editor.

Adding some Options

Outputting a string of text is simple enough, but its not really useful since we need a way for our users to modify that output. We need to add some options and Thesis provides us with 3 methods.

  • Instance-based Options options()
  • HTML-based Options html_options()
  • Class-based Options class_options()

Each method has a specific purpose and use case.

Instance-based Options

These are options that effect a single instance of a box. Some boxes can be generated multiple times in the HTML Editor.

2 instances of the same box

Instance based options are accessible via Thesis > Skin Content > Name of the Box

HTML-based Options

This method is useful for options that are  not intended to be edited or changed in anyway other than through the HTML Editor. For example an option to set the class of a box.

HTML Based Option via the HTML Editor

Thesis has a method to quickly add class and ID options.

$html = $thesis->api->html_options();

This method can also accept an array of of HTML Tags.

$html = $thesis->api->html_options(array(
   'p' => 'p',
   'div' => 'div',
   'span' => 'span'), 'p');

HTML Options with HTML Tag drop down

Finally you can unset the class or ID since some boxes may require an ID, some may require a Class and some may require both.

unset($html['id']);

Class-based Options

Class based options affect all instances of the box. So whether that is 1 instance or 10 instances – these options will affect those boxes.

Common usage for these options are;

  • Non instance based boxes that require a unique admin page (thesis Aweber and Mailchimp boxes).
  • Boxes that require an admin page to set defaults for all instances of the box.

By default these options are accessible via the Thesis Box drop-down menu.

Class Based Options Default Location

Example Box using all Options Methods

<?php
/*
Name: My First Box
Author: Matthew Horne - Diywpblog.com
Description: This is an example box.
Version: 1.0
Class: my_first_box
License: MIT
*/
class my_first_box extends thesis_box {

   // translation functions are added here
   protected function translate() 
   {
      $this->title = $this->name = __('My First Thesis Box', $this->_class);
   }

   // instance based options
   public function options()
   {
      global $thesis;
      return array(
         'option_name' => array(
            'type' => 'text',
            'width' => 'long',
            'label' => __('My First Instance Based Option!', $this->_class),
            'tooltip' => __('My First Tooltip!', $this->_class)));
   }

   // HTML Options
   public function html_options()
   {
      global $thesis;
      $html = $thesis->api->html_options(array(
         'p' => 'p',
         'div' => 'div',
         'span' => 'span'), 'p');
      unset($html['id']);
      return $html;
   }

   // class based options
   public function class_options()
   {
      global $thesis;
      return array(
         'option_name' => array(
            'type' => 'text',
            'width' => 'long',
            'label' => __('My First Class Based Option!', $this->_class),
            'tooltip' => __('My First Tooltip!', $this->_class)));

   }

   // the html method is where our output happen
   public function html($args = array()) 
   {
      global $thesis;
      extract($args = is_array($args) ? $args : array());
      $tab = str_repeat("\t", !empty($depth) ? $depth : 0);

      // this method combines all of our options into a single array
      // instance based options take precedence over class based options.
      $options = $thesis->api->get_options(array_merge($this->_html_options(), $this->_options()), $this->options);
      $html = !empty($options['html']) ? $options['html'] : 'p';
      $string = !empty($options['option_name']) ? $options['option_name'] : '';

      // once your options are prepared you can echo the output
      echo "$tab<$html class=\"some_class", (!empty($this->options['class']) ? ' '. trim($thesis->api->esc($this->options['class'])) : ''), "\">" .$message . "</$html>\n";
   }
}

Post Meta Options

Sometimes we need to add some post meta options that allow users to customize some or all of the output on a per post/page basis.

To do this we need to call the Thesis post_meta() function.

protected function post_meta()
{
   global $thesis;
   return array(
      'title' => $this->title,
      'context' => 'normal',
      'priority' => 'default',
      'fields' => array(
      'option_name' => array(
         'type' => 'text',
         'width' => 'long',
         'label' => __('My First Post Meta Based Option!', $this->_class),
         'tooltip' => __('My First Post Meta Tooltip!', $this->_class))));
}
Note: It is important to understand that post_meta options will only show on posts and pages that have the post_meta option available in the post editor as well as the box present in the relevant template.

We will need to modify our HTML output to accommodate our new post_meta option which is simply a case of specifying priority.

public function html($args = array())
{
   global $thesis;
   extract($args = is_array($args) ? $args : array());
   $tab = str_repeat("\t", !empty($depth) ? $depth : 0);
   
   // this method combines all of our options into a single array
   // instance based options take precedence over class based options.
   $options = $thesis->api->get_options(array_merge($this->_html_options(), $this->_options()), $this->options);
   $html = !empty($options['html']) ? $options['html'] : 'p';
   
   // We have now added our post meta option to our $string variable
   // Since the post meta is checked first, it will output if it exists else it will continue
   $string = (!empty($this->post_meta['option_name']) ?
      $this->post_meta['option_name'] : (!empty($options['option_name']) ? $options['option_name'] : ''));
   
   // once your options are prepared you can echo the output
   echo "$tab<$html class=\"some_class", (!empty($this->options['class']) ? ' '. trim($thesis->api->esc($this->options['class'])) : ''), "\">" .$message . "</$html>\n"; 
}

 

Quick Recap: So far we have created a simple box that makes use of all available “Option Methods” provided by the Thesis API.

Loading Box Related Assets

Like plugins, boxes sometimes require assets to enable them to function correctly. These assets could be images, JavaScript files or CSS.

There are two methods provided by the Thesis API to accomplish this task for front end assets (That’s assets that should be loaded on the user facing end).

  • Construct Method construct()
  • Preload Method preload()

Construct Method

The construct method is similar to the way that WordPress loads assets. (The whole load everywhere philosophy that WordPress is entrenched in)

Enqueuing resources is just a matter of registering them and then enqueuing them with the standard method provided by WordPress with one less step since you don’t really need to create a separate function and add_action. You can just register and enqueue your resources directly and they will initialize as normal.

For our example I am going to add a CSS stylesheet and JavaScript file.

protected function construct()
{
   global $thesis; // this gives us access to thesis version number

   // register and enqueue stylesheet
   wp_register_style('my-box-css', THESIS_USER_BOXES_URL. '/my-first-box/assets/css/box.css', false, $thesis->version);
   wp_enqueue_style('my-box-css');

   // register and enqueue JavaScript
   $dependents = array('jquery'); // array of dependents
   $to_footer = true;
   wp_register_script( 'my-box-js', THESIS_USER_BOXES_URL. '/my-first-box/assets/js/box.js', $dependents, $thesis->version, $to_footer);
   wp_enqueue_script( 'my-box-js' );
}

I have added two variables $dependents and $to_footer to the arguments for registering our JavaScript, that is so it makes more sense upon viewing since not everyone knows what the arguments are for, although you should.

Preload Method

The preload method is one of my favorite methods in the Thesis API because it takes away the need for writing programmatic conditions to control where your assets loads. Instead this method loads the assets only if the box exists in the template. (It’s almost self aware!) 😯

Registering and loading your assets is exactly the same as with the construct method.

public function preload()
{
   global $thesis; // this gives us access to thesis version number

   // register and enqueue stylesheet
   wp_register_style('my-box-css', THESIS_USER_BOXES_URL. '/my-first-box/assets/css/box.css', false, $thesis->version);
   wp_enqueue_style('my-box-css');

   // register and enqueue JavaScript
   $dependents = array('jquery'); // array of dependents
   $to_footer = true;
   wp_register_script( 'my-box-js', THESIS_USER_BOXES_URL. '/my-first-box/assets/js/box.js', $dependents, $thesis->version, $to_footer);
   wp_enqueue_script( 'my-box-js' );
}

There are other methods to load CSS and I will cover that in another post which will show you how to make dynamic CSS that becomes “one” with the main skins stylesheet.

There are also methods to load admin resources, that will also be covered in another post.

Complete Example

Below is a complete example without any CSS or JavaScript since that will be up to you and depends entirely on what you are trying to achieve.

This example is simply a basic template for which you can reference. More complex examples will be added.

<?php
/*
Name: My First Box
Author: Matthew Horne - Diywpblog.com
Description: This is an example box.
Version: 1.0
Class: my_first_box
License: MIT
*/
class my_first_box extends thesis_box {

   // translation functions are added here
   protected function translate() 
   {
      $this->title = $this->name = __('My First Thesis Box', $this->_class);
   }

   protected function construct()
   {
      /*
      // uncomment this if your assets are required everywhere.
      global $thesis; // this gives us access to thesis version number

      // register and enqueue stylesheet
      wp_register_style('my-box-css', THESIS_USER_BOXES_URL. '/my-first-box/assets/css/box.css', false, $thesis->version);
      wp_enqueue_style('my-box-css');

      // register and enqueue JavaScript
      $dependents = array('jquery'); // array of dependents
      $to_footer = true;
      wp_register_script( 'my-box-js', THESIS_USER_BOXES_URL. '/my-first-box/assets/js/box.js', $dependents, $thesis->version, $to_footer);
      wp_enqueue_script( 'my-box-js' );
      */
   }

   public function preload()
   {
      global $thesis; // this gives us access to thesis version number

      // register and enqueue stylesheet
      wp_register_style('my-box-css', THESIS_USER_BOXES_URL. '/my-first-box/assets/css/box.css', false, $thesis->version);
      wp_enqueue_style('my-box-css');

      // register and enqueue JavaScript
      $dependents = array('jquery'); // array of dependents
      $to_footer = true;
      wp_register_script( 'my-box-js', THESIS_USER_BOXES_URL. '/my-first-box/assets/js/box.js', $dependents, $thesis->version, $to_footer);
      wp_enqueue_script( 'my-box-js' );
   }

   // thesis post meta based options - can only be called once per box.
   protected function post_meta()
   {
      global $thesis;
      return array(
         'title' => $this->title,
         'context' => 'normal',
         'priority' => 'default',
         'fields' => array(
         'option_name' => array(
            'type' => 'text',
            'width' => 'long',
            'label' => __('My First Post Meta Based Option!', $this->_class),
            'tooltip' => __('My First Post Meta Tooltip!', $this->_class))));
   }


   // instance based options
   public function options()
   {
      global $thesis;
      return array(
         'option_name' => array(
            'type' => 'text',
            'width' => 'long',
            'label' => __('My First Instance Based Option!', $this->_class),
            'tooltip' => __('My First Tooltip!', $this->_class)));

   }

   // HTML Options
   public function html_options()
   {
      global $thesis;
      $html = $thesis->api->html_options(array(
         'p' => 'p',
         'div' => 'div',
         'span' => 'span'), 'p');
      unset($html['id']);
      return $html;
   }

   // class based options
   public function class_options()
   {
      global $thesis;
      return array(
         'option_name' => array(
            'type' => 'text',
            'width' => 'long',
            'label' => __('My First Class Based Option!', $this->_class),
            'tooltip' => __('My First Tooltip!', $this->_class)));

   }

   // the html method is where our output happen
   public function html($args = array())
   {
      global $thesis;
      extract($args = is_array($args) ? $args : array());
      $tab = str_repeat("\t", !empty($depth) ? $depth : 0);

      // this method combines all of our options into a single array
      // instance based options take precedence over class based options.
      $options = $thesis->api->get_options(array_merge($this->_html_options(), $this->_options()), $this->options);
      $html = !empty($options['html']) ? $options['html'] : 'p';

      // We have now added our post meta option to our $string variable
      // Since the post meta is checked first, it will output if it exists else it will continue
      $message = (!empty($this->post_meta['option_name']) ?
         $this->post_meta['option_name'] : (!empty($options['option_name']) ? $options['option_name'] : ''));

      // once your options are prepared you can echo the output
      echo "$tab<$html class=\"some_class", (!empty($this->options['class']) ? ' '. trim($thesis->api->esc($this->options['class'])) : ''), "\">" .$message . "</$html>\n";
      
   }
}

For more information about box options please check out the Thesis API.

If you would like me to write about something specific then let me know in the comments below. The examples shown here are just the tip of the iceberg in terms of what you can do with the Thesis API for boxes.

Meet the Author

Matthew Horne

Matthew Horne is web developer who specializes in optimized development. He also builds custom solutions instead of reverting to plugins. Matthew Has a strong understanding of PHP, JavaScript, jQuery.

3 comments… add one
  • Sam Jan 23, 2015, 4:30 am

    Hi, thanks for the great article! Can you point me to your post on “how to make dynamic CSS that becomes ‘one’ with the main skins stylesheet?” Thx

    • Matthew Horne Jan 23, 2015, 6:55 am

      Hi, the article for dynamic CSS is not currently written up yet.

      • Ian Mar 16, 2015, 12:33 pm

        Hi Matt, I’m looking forward to your article on Dynamic CSS as well, following on from our conversation in the DIY forum 😉

Leave a Comment