Displaying the First Item in a List Type View Outside of a List

When theming a list type view, I ran into a problem trying to get the first item to display as a title and paragraph and the subsequent ones to display as links inside of a list. For example:

Title of Article 1
Paragraph teaser for article 1. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

* Article 2
* Article 3

My goal was to avoid creating two separate views - one to display the title and teaser and another one to display the list of articles. I was able to get the example above into a view by following these steps:

1. I created a view called home_blurb that displayed by a list of recent articles in my Content Type called "Archived Articles"

  $view = new stdClass();
  $view->name = 'home_blurb';
  $view->description = 'Home Blurb';
  $view->access = array (
);
  $view->view_args_php = '';
  $view->page = FALSE;
  $view->page_title = '';
  $view->page_header = '';
  $view->page_header_format = '3';
  $view->page_footer = '';
  $view->page_footer_format = '3';
  $view->page_empty = '';
  $view->page_empty_format = '3';
  $view->page_type = 'node';
  $view->url = 'test_home';
  $view->use_pager = TRUE;
  $view->nodes_per_page = '10';
  $view->block = TRUE;
  $view->block_title = 'Home Blurb';
  $view->block_header = '';
  $view->block_header_format = '3';
  $view->block_footer = '';
  $view->block_footer_format = '3';
  $view->block_empty = '';
  $view->block_empty_format = '3';
  $view->block_type = 'list';
  $view->nodes_per_block = '3';
  $view->block_more = FALSE;
  $view->block_use_page_header = FALSE;
  $view->block_use_page_footer = FALSE;
  $view->block_use_page_empty = FALSE;
  $view->sort = array (
    array (
      'tablename' => 'node',
      'field' => 'sticky',
      'sortorder' => 'ASC',
      'options' => '',
    ),
    array (
      'tablename' => 'comments',
      'field' => 'timestamp',
      'sortorder' => 'ASC',
      'options' => 'normal',
    ),
  );
  $view->argument = array (
  );
  $view->field = array (
    array (
      'tablename' => 'node',
      'field' => 'title',
      'label' => '',
      'handler' => 'views_handler_field_nodelink',
      'options' => 'link',
    ),
    array (
      'tablename' => 'node',
      'field' => 'body',
      'label' => '',
      'handler' => 'views_handler_field_teaser',
    ),
  );
  $view->filter = array (
    array (
      'tablename' => 'node',
      'field' => 'type',
      'operator' => 'OR',
      'options' => '',
      'value' => array (
  0 => 'archived_articles',
),
    ),
  );
  $view->exposed_filter = array (
  );
  $view->requires = array(node, comments);
  $views[$view->name] = $view;

2. I used the Views Theme Wizard to generate code for the simple list theme type with my home_blurb view. Next, I created a new file called views-list-home_blurb.tpl.php in my template directory and pasted the appropriate code into my template.php file.

3. I modified the views-list-home_blurb.tpl.php code to be the following:

<?php if ($count == 0): ?>
<h3><?php print $title?></h3>
<?php print $body?>

<?php else: ?>
<?php print $title?>
<?php endif; ?>

4. I added the following function to my template.php file. It is a modified version of theme_item_list:

<?php
function theme_teaser_item_list($items = array(), $title = NULL, $type = 'ul', $attributes = NULL) {
 
$output = '<div class="teaser-item-list">';
  if (isset(
$title)) {
   
$output .= '<h3>'. $title .'</h3>';
  }

  if (!empty(
$items)) {
   
$ItemCount = count($items);

   if (
$ItemCount = 1):
   
$output .= $items[0];
   endif;

 
$output .= "<$type" . drupal_attributes($attributes) . '>';

    foreach (
$items as $item) {
     
$attributes = array();
     
$children = array();
      if (
is_array($item)) {

        foreach (
$item as $key => $value) {
          if (
$key == 'data') {
           
$data = $value;
          }
          elseif (
$key == 'children') {
           
$children = $value;
          }
          else {
           
$attributes[$key] = $value;
          }
        }
      }
      else {
       
$data = $item;
      }
      if (
count($children) > 0) {
       
$data .= theme_item_list($children, NULL, $type, $attributes); // Render nested list
     
}

      if (
$ItemCount > 1){
     
$output .= '<li' . drupal_attributes($attributes) . '>'. $data .'</li>';
      }
    
$ItemCount++;
    }
   
$output .= "</$type>";
  }
 
$output .= '</div>';
  return
$output;
}
?>

5. I modified function phptemplate_views_view_list_home_blurb by deleting item_list and replacing it with teaser_item_list. Here is the complete function:

function phptemplate_views_view_list_home_blurb($view, $nodes, $type) {
  $fields = _views_get_fields();

  $taken = array();

  // Set up the fields in nicely named chunks.
  foreach ($view->field as $id => $field) {
    $field_name = $field['field'];
    if (isset($taken[$field_name])) {
      $field_name = $field['queryname'];
    }
    $taken[$field_name] = true;
    $field_names[$id] = $field_name;
  }

  // Set up some variables that won't change.
  $base_vars = array(
    'view' => $view,
    'view_type' => $type,
  );

  foreach ($nodes as $i => $node) {
    $vars = $base_vars;
    $vars['node'] = $node;
    $vars['count'] = $i;
    $vars['stripe'] = $i % 2 ? 'even' : 'odd';
    foreach ($view->field as $id => $field) {
      $name = $field_names[$id];
      $vars[$name] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view);
      if (isset($field['label'])) {
        $vars[$name . '_label'] = $field['label'];
      }
    }
    $items[] = _phptemplate_callback('views-list-home_blurb', $vars);
  }
  if ($items) {
    return theme('teaser_item_list', $items);
  }
}

Me Again...

flanksteak - March 15, 2008 - 22:40

I finally got it working, however I just eliminated steps 4 & 5 – Step 4 continued to give me a WSOD. Why this works, I have no idea. I also was able to add the teaser thumbnail, so thanks much for your help.

Now, what I would like to do is to be able to add this same functionality for a number of different Content Types. Is it possible to do so without having to add a entirely separate function for each Content Type in the template.php file? It looks like one could do callback to that same views-list-home_blurb.tpl.php for each content type, no?

Again, total newbie here, but I'm just trying to wrap my head around the php. Any help you could give is much appreciated.

thx,
B

On the right track

JuliaKM - March 16, 2008 - 17:29

You are on the right track, you can use the same callback for different content views. For example, on my site, I'm using views-list-home_blurb' as a template for a bunch on views. On these views, in my theming function, I use the callback:

$items[] = _phptemplate_callback('views-list-home_blurb', $vars);

This line above tells phptemplate what template file to call. So, if you had a different file named my_favorite_template.tpl.php, you would call it with:

$items[] = _phptemplate_callback('my_favorite_template', $vars);

 
 

Drupal is a registered trademark of Dries Buytaert.