Tuesday, April 30, 2013

Tutorial: How To Create A Tab Widget In WordPress

Tutorial: How To Create A Tab Widget In WordPress:


  
In this tutorial, you’ll learn how to create the Tabber widget, which is very useful for when multiple widgets need to fit in a sidebar. It saves space and streamlines the appearance and functionality of your WordPress-powered website.
In the past, there were different methods of doing this, most of which were theme-dependent. As we’ll see in this tutorial, creating a tabbed widget that works on its own and with any theme is easily accomplished. So, let’s jump in and learn how to create our own Tabber widget, which we’ve made available for downloading at the end of this article.
create-tabber-widget-splash

Saving Sidebar Space

The main advantage of tabs is that you can fit more widgets into the sidebar. And tabs look good. The image below shows how much vertical space is taken up by three standard widgets (using the default Twenty Ten theme). The default layout is on the left, and our tabber widget is on the right:
tabber_example

Before We Start

A few things are useful to know. Because we are building a widget in this article, you might want to learn about WordPress’ Widgets API and how to create a basic widget:
Use these resources as needed while following the tutorial along.

The Basic Idea

The idea for this widget is simple: select a sidebar, and the Tabber widget will grab all of its widgets and display them as tabs. In the widget’s interface, you can select a sidebar, specify an extra CSS class and optionally apply your own styles. When enabled, the plugin will register an extra sidebar (which may be removed if you have other ways to add a sidebar). Then, using the same code, you can add more sidebars, and each of them can hold instances of the Tabber widget.
To control your widgets, Tabber uses idTabs for jQuery, created by Sean Catchpole, but you could always use another solution. Note that additional CSS is loaded to style the resulting widget.
Here is the basic HTML structure required to create tabs:

<ul>
  <li><a href="#widget-1">Widget one</a></li>
  <li><a href="#widget-2">Widget two</a></li>
<ul>
<div id="widget-1">
  Widget one's content
</div>
<div id="widget-2">
  Widget two's content
</div>
Unfortunately, you can’t get such a structure directly by using WordPress’ sidebar and widget rendering. Typically, WordPress’ widget structure looks like this:

<div id="widget-1">
  <h2>Widget one</h2>
  Widget one's content
</div>
<div id="widget-2">
  <h2>Widget two</h2>
  Widget two's content
</div>
So, the goal with Tabber is to transform any widget’s output into markup that can be used to display tabs. To complicate matters, different themes might register sidebars that do not use a <div> to hold a widget or use <h2> to show its title. For example, WordPress’ new default theme, Twenty Twelve, uses <aside> and <h3> tags for this. Other themes may use complicated markup that can’t be predicted or successfully transformed into the output needed for tabs.
The solution to this problem is to intercept the widget’s parameters before rendering, and then to restructure them into useful structures using JavaScript or jQuery for the tabbed output. More on that later.

Tabber Widget Loading

Now that we understand the goal, let’s look at the demo plugin. Our plugin contains a main PHP file, one JavaScript file and one CSS file. The PHP file contains the widget and loads the CSS and JavaScript, like so:

add_action('init', 'd4p_st_init');
add_action('widgets_init', 'd4p_st_widgets_init');

function d4p_st_init() {
    register_sidebar(array('name' => 'Tabber Example Sidebar', 'description' => 'Add widgets to this sidebar to use it from Tabber widget.'));

    if (!is_admin()) {
        $url = plugins_url('d4p-smashing-tabber');

        wp_enqueue_script('jquery');
        wp_enqueue_script('d4p_st_tabber', $url.'/tabber.js', array('jquery'));
        wp_enqueue_style('d4p_st_tabber', $url.'/tabber.css');
    }
}

function d4p_st_widgets_init() {
    register_widget('d4p_sr_tabber');
}
Here, the function d4p_st_init is run during WordPress’ init action. It will register one sidebar (line 5) and enqueue the jQuery, JavaScript and CSS files using the wp_enqueue_script and wp_enqueue_style functions (lines 10 to 12).
Then, the function d4p_st_widgets_init is called during WordPress’ widgets_init action. We register the widget on line 17.
Widget Interface

Widget interface.

The Main Tabber Widget Class

Tabber is a normal widget, and in this case it is located in the d4p_sr_tabber class.

Settings: Plugin Interface

The widget has two settings:
  • “sidebar”

    to hold the ID of the selected sidebar
  • “css”

    for extra CSS classes to style the Tabber widget
When selecting which sidebar to use, you must avoid using the sidebar that holds the Tabber widget. Otherwise, it will spin into endless recursion. To avoid this, before rendering the widget’s content, check whether the selected sidebar is the same as the parent sidebar. This can’t be prevented while the widget is set up, because the widget’s panel affords very little control over this.
Also, using sidebars that are not normally used is a good idea. To help with this, the plugin includes sample code to help you add an extra sidebar.
The form and update methods contained in the d4p_sr_tabber class are used to display the widget’s interface in the “Widgets” panel and to save its settings, and they are not that interesting. But it is worth taking a closer look at how to display the widget on the front end.

Main Display Method

Here is the main widget method:

public function widget($args, $instance) {
  add_filter('dynamic_sidebar_params', array(&$this, 'widget_sidebar_params'));

  extract($args, EXTR_SKIP);
  $this->id = $widget_id;

  echo $before_widget;
  if ($args['id'] != $instance['sidebar']) {
    echo '<div id="'.$widget_id.'">';
    echo '<ul></ul>';
    dynamic_sidebar($instance["sidebar"]);
    echo '</div>';
  } else {
    echo 'Tabber widget is not properly configured.';
  }
  echo $after_widget;

  remove_filter('dynamic_sidebar_params', array(&$this, 'widget_sidebar_params'));
}
In this code, line 2 adds a filter that modifies the widget’s rendering parameters before they are processed. With this filter, all widgets rendered after that point will have their parameters modified as needed for successful transformation to tabbed form. And that will be done for the widgets in the selected sidebar on line 11, using the dynamic_sidebar function.
This function requires the name of the sidebar, and it will display all widgets in it. Line 9 contains the check mentioned before, to prevent recursion when displaying sidebar content if the selected sidebar is the same as the parent sidebar.
Lastly, the filter is removed, and any widgets belonging to other sidebars are displayed normally, without modification.

Widget Modification

To prepare for the transformation done with JavaScript, the tabber widget includes the d4p-tabber-widget class, which contains an empty <ul> tag.
The filter used to modify the widget’s parameters looks like this:

public function widget_sidebar_params($params) {
  $params[0]['before_widget'] = '<div id="'.$params[0]['widget_id'].'">';
  $params[0]['after_widget'] = '</div>';
  $params[0]['before_title'] = '<a href="#">';
  $params[0]['after_title'] = '</a>';

  return $params;}
Depending on how the sidebar is registered, this code will change the rendering parameters to a format that is close to the format needed for tabs. But JavaScript is still needed to move the widget’s title into the <ul> tag for the control tabs. After this filter, the widget’s output will look like this:

<div id="widget-1">
  <a href="#">Widget one</a>
  Widget one's content
</div>

JavaScript For Widget Transformation

Once the widget’s presentation is modified, one thing remains: to complete the transformation and get the titles from the widgets and turn them into tabs:
jQuery(document).ready(function(){
  jQuery(".d4p-tabber-widget").each(function(){
  var ul = jQuery(this).find("ul.d4p-tabber-header");

  jQuery(this).children("div.d4p-st-tab").each(function() {
    var widget = jQuery(this).attr("id");
    jQuery(this).find('a.d4p-st-title').attr("href", "#" + widget).wrap('<li></li>').parent().detach().appendTo(ul);
  });

  jQuery(this).idTabs();
  });
});
This code uses jQuery to get all of the Tabber widgets based on the .d4p-tabber-widget CSS class, and each one gets the element (where the tabs will go):
  • With line 5, we find all individual widgets belonging to the Tabber widget.
  • On line 6, we get the widget’s ID needed for the tab to connect it to the widget’s content.
  • On line 7, we find the title <a> element, set its href attribute to that of the widget’s ID, wrap it in a </li> element, remove it from its current location, and move it into the tab’s <ul> element.
  • After this, the <div> will hold only its content.
Final Tabber Example

Final Tabber example.
Finally, when all this is done, we enable idTabs to activate the tabs control. And with the default styling loaded from the tabber.css file, you can see how Tabber looks with three widgets in it (see screenshot above). Feel free to experiment and adjust the styling to your theme.

How To Install The Tabber Plugin

As with any other plugin, unpack it, upload it to WordPress’ plugins folder, and activate it from the plugins panel. When you go to the “Widgets” panel, you will see an additional sidebar, “Tabber Example Sidebar,” at the end on the right. And “Available Widgets” will show one more widget, “D4P Smashing Tabber.”
Add this new widget to the “Main Sidebar.” From the “Sidebar” widget drop-down menu, select “Tabber Example Sidebar,” and save the widget. Now, open the “Tabber Example Sidebar” and add the widgets you want to be displayed as tabs. You can add as many widgets as you want, but pay attention because if you add too many, the tab’s control will break to two or more lines, and it will not look pretty. Starting with two or three widgets is best.

Conclusion

Creating one widget to display several other widgets as a tab isn’t very difficult, as you can see. The trick is in adjusting the widgets’ output to a format that can be transformed into tabs, and then using JavaScript to display them. We’ve explored just one possible transformation method; you can always experiment with ways to rearrange widget elements.
We used idTabs here, but there are many methods of displaying tabs, and not all of them require JavaScript:
I prefer using a jQuery-based solution, and idTabs is very easy to use and easy to style and it works in all browsers. Check out other solutions, and see what extra features they offer to enhance your own tabbed widgets.
(al)

© Milan Petrović for Smashing Magazine, 2013.

DIGITAL JUICE

No comments:

Post a Comment

Thank's!