I have a query in a custom module that produces 2 colunes of data. The potential exists for the list to be long. I'd prefer to split the list into 4-6 columns (2-3 major lists) and show more the data per page vs white space on the right. Can someone suggest how I can theme this?

Comments

nevets’s picture

The details somewhat depend on if you using tables are ok or not. This example uses tables and is untested (i.,e. it may have typos :) )

<?php
//  Note:  This is just a sketch, detail depend on your data and
// And what you want in each column
// Presents data in N lists with
// M columns per list
$sql = "Your SELECT statement";
$results = db_query($sql);
$column = 0;
$columns_per_list = 2// Number of columns per list
$max_lists = 3// Number of lists
$max_columns = $max_lists * $columns_per_list;
$rows = array();
$row = array();
while (
$data = db_fetch_object($results) ) {
  if (
$column >= $max_columns ) {
    
$rows[] = $row;
    
$row = array();
    
$column = 0;
  }
 
$row[$column] = "First column of data";
 
$row[$column+1] = "Second column of data";
 
$column += $columns_per_list;
}
if ( !
is_empty($row) ) {
 
// Add empty data as need to fill remaining columns in row
 
for ( $i = $column; $i < $max_columns; $i++) {
  
$row[$i] = '';
  }
 
$rows[] = $row;
}

$output = theme('table', array(), $rows);
?>
bfbryan’s picture

It is referring to the line if ( ! is_empty($row) ) {

I don't know if it is due to other stuff I have in my query. Here it is:

<?php
function companysearch_nodes_output($tid = NULL) {
  if (
$tid == NULL) {
   
drupal_not_found();
  }
 
$header_title_1 = array('data' => 'Ticker', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
$header_title_2 = array('data' => 'Company', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
 
$header = array($header_title_1, $header_title_2);
   
 
$sql = "SELECT a.nid, a.title, b.field_ticker_value FROM {node} a LEFT JOIN ";
 
$sql .= "{content_type_company} b ON a.nid = b.nid LEFT JOIN {term_node} c ";
 
$sql .= "ON a.nid = c.nid LEFT JOIN {term_data} d ON c.tid = d.tid WHERE ";
 
$sql .= "a.type = 'company' AND c.tid = '%d' ORDER BY a.title";
 
$results = db_query($sql, $tid);
 
 
$column = 0;
 
$columns_per_list = 2// Number of columns per list
 
$max_lists = 3// Number of lists
 
$max_columns = $max_lists * $columns_per_list;

    if (
db_num_rows($results) > 0) {
     
$rows = array();
     
$row = array();
    while (
$data = db_fetch_object($results) ) {
        if (
$column >= $max_columns ) {
    
$rows[] = $row;
    
$row = array();
    
$column = 0;
  }
 
$row[$column] = l($data->field_ticker_value, "node/$data->nid", array('title' => t('Company info')), NULL, NULL, FALSE, FALSE);
 
$row[$column+1] = $data->title;
 
$column += $columns_per_list;
}
  if ( !
is_empty($row) ) {
 
// Add empty data as need to fill remaining columns in row
 
for ( $i = $column; $i < $max_columns; $i++) {
  
$row[$i] = '';
  }
 
$rows[] = $row;
}
  
     
$table_attributes = array('id' => 'company-profile-table', 'cellpadding' => 5);
   
   
$output = theme('table', $header, $rows, $table_attributes);
  }
    return (
$output);
   
}
?>
nevets’s picture

;is_empty; should have been 'empty', so

  if ( ! is_empty($row) ) {

should have been

  if ( ! empty($row) ) {
bfbryan’s picture

Right now it orders it across each column. Looking for:

A D G
B E H
C F I

vs.

A B C
D E F
G H I

Thanks

bfbryan’s picture

How do I carry the header also into each column?

nevets’s picture

Do you want the header text to appear in each table cell?

nevets’s picture

Does 'A' represent one column of data or two (the orginal problem was pairs of data in multiple lists on a page)

bfbryan’s picture

Looking to display the header across both lists.

nevets’s picture

This version should place the data by row first and also repeats the heading titles for each list

<?php
function companysearch_nodes_output($tid = NULL) {
  if (
$tid == NULL) {
   
drupal_not_found();
  }
 
$columns_per_list = 2// Number of columns per list
 
$max_lists = 3// Number of lists
 
$max_columns = $max_lists * $columns_per_list;
 
 
$titles[] = array('data' => 'Ticker', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
$titles[] = array('data' => 'Company', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
    
// Repeat the header across the lists
 
$header = array();
  for (
$column = 0; $column < $max_columns; $column += $columns_per_list ) {
     
$index = $column % $columns_per_list;
     
$header[] = $titles[$index];
     
$header[] = $titles[$index+1];
  }     
  
 
$sql = "SELECT a.nid, a.title, b.field_ticker_value FROM {node} a LEFT JOIN ";
 
$sql .= "{content_type_company} b ON a.nid = b.nid LEFT JOIN {term_node} c ";
 
$sql .= "ON a.nid = c.nid LEFT JOIN {term_data} d ON c.tid = d.tid WHERE ";
 
$sql .= "a.type = 'company' AND c.tid = '%d' ORDER BY a.title";
 
$results = db_query($sql, $tid);
 
    
$record_count = db_num_rows($results);

    if (

$record_coun > 0) {
        
$row_count = (int)($record_count / $max_lists);
        
// May need to add another row
        
if ( $record_count > $row_count * $max_lists ) {
            
$row_count++;
         }
        
       
// Build an empty table
       
$rows = array();
        for (
$r = 0; $r < $row_count; $r++ ) {
           
$rows[] = array_fill(0, $max_columns, '');
        }
       
     
$column_index = 0;
     
$row_index = 0;

    while (

$data = db_fetch_object($results) ) {
            if (
$row_index >= $row_count ) {
               
$row_index = 0;
               
$column_index += $columns_per_list;
            }
         
$rows[$row_index][$column_index] = l($data->field_ticker_value, "node/$data->nid", array('title' => t('Company info')), NULL, NULL, FALSE, FALSE);
         
$rows[$row_index][$column_index+1] = $data->title;
         
$row_index++;
        }

       

$table_attributes = array('id' => 'company-profile-table', 'cellpadding' => 5);
  
   
$output = theme('table', $header, $rows, $table_attributes);
  }
 
  return (
$output);
}
?>
bfbryan’s picture

but some is confusing. Regardless is works great. Thanks again for your help.

bfbryan’s picture

nevets ,

I am trying to combine the table group/offset code you gave me before and the 2 columns. I got most of it except I think I have something out of order. All the nodes (ticker and title) are listed in the 2 columns and the sectors are listed too but all the sectors are listed below in the first column. Any insight as to what is out of order. Thanks again.

<?php
function companysearch_companypage () {
 
$column = 0;
 
$columns_per_list = 4// Number of columns per list
 
$max_lists = 2// Number of lists
 
$max_columns = $max_lists * $columns_per_list;
 
 
$titles[] = array('data' => '');
 
$titles[] = array('data' => 'Ticker', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
$titles[] = array('data' => 'Company', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
 
// Repeat the header across the lists
 
$header = array();
  for (
$column = 0; $column < $max_columns; $column += $columns_per_list ) {
     
$index = $column % $columns_per_list;
     
$header[] = $titles[$index];
     
$header[] = $titles[$index+1];
     
$header[] = $titles[$index+2];
     
$header[] = $titles[$index+3];
  }     
 
   
$name = '%'.urldecode(arg(1)).'%';
   
$results = db_query("SELECT a.nid, a.title, b.field_ticker_value, f.name AS sector, f.tid AS sectid
        FROM {node} a LEFT JOIN {content_type_company} b ON a.nid = b.nid
        LEFT JOIN {term_node} c ON c.nid = b.nid
        LEFT JOIN {term_data} d ON d.tid = c.tid
        LEFT JOIN {term_hierarchy} e ON c.tid = e.tid
        LEFT JOIN {term_data} f ON e.parent = f.tid
        WHERE a.type = 'company'
        AND title LIKE '%s' ORDER BY sector, a.title"
, $name);
   
   
$record_count = db_num_rows($results);
    if (
$record_count > 0) {
        
$row_count = (int)($record_count / $max_lists);
        
// May need to add another row
        
if ( $record_count > $row_count * $max_lists ) {
            
$row_count++;
         }
       
   
// Build an empty table
     
$sector = '';
     
$rows = array();
        for (
$r = 0; $r < $row_count; $r++ ) {
           
$rows[] = array_fill(0, $max_columns, '');
        }
       
     
$column_index = 0;
     
$row_index = 0;
     
       
// Loop through the data
       
while ( $data = db_fetch_object($results) ) {
       
// Have we seen this sector name
           
if ( $data->sector !=$sector ) {
       
// No, add a row to the table with the sector name that spans all the columns
              
$rows[] = array(array('data' => l($data->sector, 'taxonomy/term/'.$data->sectid, array('title' => t('Industry List')), NULL, NULL, FALSE, FALSE), 'colspan' => 3));
              
$sector = $data->sector;
            }
        if (
$row_index >= $row_count ) {
               
$row_index = 0;
               
$column_index += $columns_per_list;
            }
   
  
// Add the details for one company  
   
$rows[$row_index][$column_index] = array('data' => '', 'class' => 'spacer');
   
$rows[$row_index][$column_index+1] = l($data->field_ticker_value, "node/$data->nid", array('title' => t('Company info')), NULL, NULL, FALSE, FALSE);
         
$rows[$row_index][$column_index+2] = $data->title;
         
$row_index++;
        }

       
$table_attributes = array('id' => 'company-profile-table', 'cellpadding' => 5);
  
   
$output = theme('table', $header, $rows, $table_attributes);
  }
 
  return (
$output);
}
?>
nevets’s picture

The reason you see them added at the end is the code pre-builds the empty table before looping through the data.

Since you want the data in the form

A D G
B E H
C F I

you have complicated the problem considerably.

Consider the following pairings where letters represent the data and numbers the sector

A - 1
B - 1
C - 2
D - 2
E - 2
F - 2
G - 3
H - 3
I - 3

Would you want the final result to be

1 C 3
A D H
B E I
2 F J

or maybe

1
A B
2
C D E
F
3
H I J

or maybe something else. I will leave it up to you as an exercise to decide what format you want and how to achieve it. One parting though, you could produce a "normal" table with just the 3 columns and one list then split in N parts (Where N is the number of lists) and buildup the secondary table for display using the N lists.

bfbryan’s picture

it would make sense to do the last option where it groups them together by $sector with 2 lists in each. I had it set to just group with a single list but it didn't utilize the space appropriately. You know, always trying to avoid going beyond the fold.

nevets’s picture

This version combines logic from the first version (data goes across first, then down), adds the header logic from the second version and adds rows with the section link as needed. It also adds the spacer column at the start of each list

<?php
function companysearch_nodes_output($tid = NULL) {
  if (
$tid == NULL) {
   
drupal_not_found();
  }
 
$columns_per_list = 3// Number of columns per list
 
$max_lists = 3// Number of lists
 
$max_columns = $max_lists * $columns_per_list;
 
 
$titles[] = array('data' => 'Ticker', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');
 
$titles[] = array('data' => 'Company', 'style' => 'font-size: 1.1em;', 'style' => 'font-family: Verdana;');

    

// Repeat the header across the lists
 
$header = array();
  for (
$column = 0; $column < $max_columns; $column += $columns_per_list ) {
     
$index = $column % $columns_per_list;
     
$header[] = $titles[$index];
     
$header[] = $titles[$index+1];
  }
  
 
$sql = "SELECT a.nid, a.title, b.field_ticker_value FROM {node} a LEFT JOIN ";
 
$sql .= "{content_type_company} b ON a.nid = b.nid LEFT JOIN {term_node} c ";
 
$sql .= "ON a.nid = c.nid LEFT JOIN {term_data} d ON c.tid = d.tid WHERE ";
 
$sql .= "a.type = 'company' AND c.tid = '%d' ORDER BY a.title";
 
$results = db_query($sql, $tid);
 
 
$column = 0;
 
$section = '';

    if (

db_num_rows($results) > 0) {
       
$rows = array();
       
        while (
$data = db_fetch_object($results) ) {
            if (
$data->section != $section ) {
                if ( ! empty(
$row) ) {
                   
$rows[] = $row;
                }
               
$rows[] = array(array('data' => l($data->sector, 'taxonomy/term/'.$data->sectid, array('title' => t('Industry List')), NULL, NULL, FALSE, FALSE), 'colspan' => $max_columns));
               
               
$row = array_fill(0, $max_columns, '');
               
$column = 0;
            }
            else if (
$column >= $max_columns ) {
               
$rows[] = $row;
               
$row = array_fill(0, $max_columns, '');
               
$column = 0;
            }
       
           
// Add the details for one company 
           
$row[$column] = array('data' => '', 'class' => 'spacer');
           
$row[$column+1] = l($data->field_ticker_value, "node/$data->nid", array('title' => t('Company info')), NULL, NULL, FALSE, FALSE);
           
$row[$column+2] = $data->title;
           
           
$column += $columns_per_list;
        }
       
       
$table_attributes = array('id' => 'company-profile-table', 'cellpadding' => 5);
       
       
$output = theme('table', $header, $rows, $table_attributes);
  }
    return (
$output);
  
}
?>
bestknight’s picture

subscribing