Code tabs widget

I implemented this with nested shortcodes as suggested. An outer shortcode tabs has children tab which contain code blocks:

 {{% tabs %}}
   {{% tab "Java" %}}
     ```java
        System.out.println("hello tabs");
     ```
   {{% /tab %}}

   {{% tab "JavaScript" %}}
     ```javascript
       console.log("hello tabs");
     ```
   {{% /tab %}}
 {{% tabs %}}

In my case I’m using bootstrap nav-tabs. That requires a certain HTML structure and IDs that wouldn’t work for the shortcode structure that’s easy to use.

What I did was dump the contents into the DOM and then use JavaScript to fix up the structure, and used some onclick handling to make the correct tab active.

Here’s the tabs shortcode:

<div class='code-tabs'>
  <ul class="nav nav-tabs"></ul>
  <div class="tab-content">{{ .Inner }}</div>
</div>

Here’s the (nested) tab shortcode:

<div class="tab-pane" title="{{ .Get 0 }}">
  {{ .Inner }}
</div>

And here’s the (admittedly crude) JavaScript:

$('.tab-content').find('.tab-pane').each(function(idx, item) {
  var navTabs = $(this).closest('.code-tabs').find('.nav-tabs'),
      title = $(this).attr('title');
  navTabs.append('<li><a href="#">'+title+'</a></li');
});

$('.code-tabs ul.nav-tabs').each(function() {
  $(this).find("li:first").addClass('active');
})

$('.code-tabs .tab-content').each(function() {
  $(this).find("div:first").addClass('active');
});

$('.nav-tabs a').click(function(e){
  e.preventDefault();
  var tab = $(this).parent(),
      tabIndex = tab.index(),
      tabPanel = $(this).closest('.code-tabs'),
      tabPane = tabPanel.find('.tab-pane').eq(tabIndex);
  tabPanel.find('.active').removeClass('active');
  tab.addClass('active');
  tabPane.addClass('active');
});

(I’m using highlight.js for code formatting; haven’t tried it with pygments.)

Paired with some CSS, you can get a nice tabbed code block layout:

7 Likes