I am curious if it is possible to create a block like the one on this page - it is on the right side of the page and says "Today's Most Popular Stories" then there are 3 tabs - i would love to do that on my site. is it possible?

http://www.ibtimes.com/articles/20061009/anti-spam-lawsuit.htm

thanks!

Comments

allen074’s picture

morning bump

dvessel’s picture

Is it possible? Definitely. I've found almost no limitations on what can be achieved with Drupal. It's just a matter of implementing it into your theme. I haven't run into a module to make it easy if that's what your looking for.

Here's something to get you started. You should be comfortable with working in your template files. They both require jquery -which will be included in Drupal 5. You can include them manually though.

http://sputnik.pl/code/files/js/jquery/auto/jquery_auto_demo.html?test=two
http://www.stilbuero.de/2006/05/13/accessible-unobtrusive-javascript-tab...

joon

allen074’s picture

thanks - but how do i get the tabs to hit the drupal blocks?

thats my worry - i have no idea how to do that part!

thanks

dvessel’s picture

It's a bit more complicated than I thought it would be. Those tabs need to be structured in a very strict way. I played with the one from stilbuero.

Structure we need:

<div id="container">
  <ul>
    <li><a href="#section-1">Section 1</a></li>
    <li><a href="#section-2">Section 2</a></li>
    <li><a href="#section-3">Section 3</a></li>
  </ul>
  <div id="section-1">
    …
  </div>
  <div id="section-2">
    …
  </div>
  <div id="section-3">
    …
  </div>
</div>

But the blocks being output from drupal would be closer to this times the number of blocks:

<div id="block..1">
  <h2>title</h2>
  <div class="content">
    ...
  </div>
</div>

<div id="block..2">
  <h2>title</h2>
  <div class="content">
    ...
  </div>
</div>

etc..

The titles are grouped with the content so it just won't work. The titles have to be grouped into <li> one after the other. But jQuery does have the ability to modify DOM elements so it can be restructured. Here's what I came up with. I hope I can make this clear since it's a bit convoluted.

First you have to dedicate a block region to this tabbing behavior. Lets say we it's called tab_block_group. This can be modified inside the template.php file. Then inside your page.tpl.php file you would have something like this placed wherever it makes sense.

<?php
if ($tab_block_group) { ?>
<div id="tab-block-container">
  <?php print $tab_block_group; ?>
</div>
<?php
} ?>

The div#tab-block-container created here will contain the tabs and $tab_block_group will print out the blocks for this region.

Download jQuery.js and the jQuery.tabs.js files and include them in the head of the page.tpl.php template. We'll do the same with the style sheets -included with the tab script. All the files has to be in your theme folder.

/drupal-install/themes/your-theme/..

There is a conflict with autocomplete.js and jQuery so you can disable it whenever autocomplete.js is loaded. It's a cheap workaround but if you don't want this restriction then look here.

http://drupal.org/node/88979

Right above the </head> -closing tag inside page.tpl.php, paste this in.

// check for autocomplete.js
<?php if (!preg_match("/autocomplete.js/",$head)) { ?>

// load style sheets.
<link rel="stylesheet" href="<?php echo url($directory.'/tabs.css') ?>" type="text/css" media="print, projection, screen" />
<!--[if lte IE 7]>
<link rel="stylesheet" href="<?php echo url($directory.'/tabs-ie.css') ?>" type="text/css" media="projection, screen" />
<![endif]-->

// load javascript.
<script type="text/javascript" src="<?php echo url($directory.'/jQuery.js') ?>"></script>
<script type="text/javascript" src="<?php echo url($directory.'/jQuery.tabs.js') ?>"></script>

<script type="text/javascript">

  // only when ready!
  $(document).ready(function(){

    // inserts "ul.title-group" into the container.
    $("#tab-block-container").prepend("<ul class=\"title-group\"></ul>");

    // moves "a.tab-link" which are block titles into "ul.title-group".
    // the title must be modified conditionally inside block.tpl.php
    $("#tab-block-container ul.title-group").prepend($("#tab-block-container a.tab-link"));

    // wraps "li.title" around "a.tab-link".
    $("#tab-block-container ul.title-group a.tab-link").wrap("<li class=\"title\"></li>");

    // trigger jQuery.tab.js by telling it what to work on then set optional effects.
    // by the time the browser executes this next line, the proper structure is in place.
    $("#tab-block-container").tabs({fxFade: true, fxSpeed: 250});

  });

</script>

<?php
}?>

Now open your block.tpl.php file. I don't know how yours is structured so I'll just post a simplified version of mine:

<?php

// set block id to be reused later.
$block_id = 'block-'.$block->module.'-'.$block->delta;

// important!! The block region has to be our designated one.
if ($block->region == tab_block_group) {
  // links are needed to activate the tabs. Link to the block id.
  // a class is set here to manipulate it with jQuery.
  $subject = '<a href="#'.$block_id.'" class="tab-link">'.$block->subject.'</a>';

} else {
  // For all other regions, a standard subject.
  $subject = '<h2 class="title">'.$block->subject.'</h2>';

} ?>

// set our id's & classes. This becomes our target.
<div <?php {
  echo 'id="'.$block_id.'"';
  echo ' class="block block-',$block->module,'"';
} ?>>

  <?php echo $subject ?>

  <div class="content">
    <?php echo $block->content ?>
  </div>
  
</div>

The block gives it's normal output when it is not part of the tab region. The title is turned into a link so it can activate the tabs. It's going to look ugly so it's up to you to style it to fit your theme.

Go in and setup your blocks from your admin pages. You can order them there and fill as many as you want. Each will have its' own tab.

I tried it on my site that's in the middle of being redesigned. -will break horribly in IE Scroll all the way to the bottom.

http://beta.dvessel.com

jQuery is sick! There's so much more that can be done.

joon

dman’s picture

A tidy solution to a nice question, I'd say.
Brilliantly presented. I nominate this for a snippet page.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

allen074’s picture

wow - i cant wait to try this out in the next day or two - that is some solution - thank you!

dvessel’s picture

Thanks, that sounds like a good idea. I think I'll do that.

@allen, tell us if it worked out. Good luck.

Oh, and you might want to strip out the comments. Some of it is out of place and it will render out on your pages. -duh!

joon

dvessel’s picture

Just found a better way to do this. No need to modify the block template. As long as the outer containing div block outputs a unique ID and the subject has a class of "title" it will work.

Transplant this in with the other code.

// only when ready!!
$(document).ready(function(){

  // iterate through each block creating links and altering the structure.
  $("#tab-block-container > .block").each(
    function() {

      $(".title",this)
        .wrap('<li class="tab-title"></li>')
        .wrap('<a href="#' + $(this).id() + '"></a>');

      // copy the inner text of .title object and make it a direct child of the link.
      $("li.tab-title > a",this).append($(".title",this).text());

      // remove the old title.
      $("li.tab-title .title",this).remove();

    }
  );

  // create an unordered list and make it the first element in #tab-block-container.
  $("#tab-block-container").prepend('<ul class="title-group"></ul>');

  // move all the list items that we just processed to the unordered list container.
  $("#tab-block-container > .title-group").prepend($("#tab-block-container .tab-title"));

  // trigger with effects!!
  $("#tab-block-container").tabs({fxFade: true, fxSpeed: 250});

}

I tried to make it as compact as I could. If anyone has ideas to make it more efficient that'd be great.

joon

dvessel’s picture

Just posted to the handbook page. Use those instructions.

http://drupal.org/node/89338

joon

dman’s picture

It would be nice if it could start off with a screenshot or at least a diagram of what it's trying to achieve - that's not very clear from context.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

dvessel’s picture

I completely agree with you. Unfortunately I can't post an image. Just filed an issue about it but I'm not holding my breath. Will try to come up with another solution to make it more clear when possible.

joon