Tables
|
|
|
|
<?php /*
* table.class.php - quick and dirty table classes
*
* @author Aaron D. Campbell <acampbell@autotransteam.com>
*
* TODO: make rowspan work with 0 as parameter (0 is to span ALL rows)
*/
/*
* Cell - basic cell creation
*/ class Cell{
//$settings - array - containing all possible settings as keys
public $settings = array('data'=>NULL, 'abbr'=>NULL, 'rowspan'=>NULL,
'colspan'=>NULL, 'id'=>NULL, 'style'=>NULL, 'class'=>NULL,
'lang'=>NULL, 'dir'=>NULL, 'title'=>NULL, 'onclick'=>NULL,
'ondblclick'=>NULL, 'onmousedown'=>NULL,
'onmouseup'=>NULL, 'onmouseover'=>NULL,
'onmousemove'=>NULL, 'onmouseout'=>NULL,
'onkeypress'=>NULL, 'onkeydown'=>NULL, 'onkeyup'=>NULL,
'align'=>NULL, 'char'=>NULL, 'charoff'=>NULL,
'valign'=>NULL);
//$data is this cell's data, and $th is a bool telling if the cell is a header cell
public $data, $th;
/*
* public function __construct
*
* @param string $data The data for the cell
* @param array $settings an associative array containing any of the following keys:
* 'abbr' - string - abbreviation for header cell
* 'rowspan' - int - number of rows spanned by cell
* 'colspan' - int - number of columns spanned by cell
* 'id' - string - document-wide unique id for cell
* 'style' - string - style info for cell
* 'class' - string - space-separated list of classes for cell
* 'lang' - string - language code for contents of cell
* 'dir' - string - direction for weak/neutral text in cell (LTR | RTL)
* 'title' - string - advisory title
* 'align' - string - align, text alignment (left | center | right | justify | char)
* 'char' - string - alignment char, e.g. char=':'
* 'charoff' - string - offset for alignment char
* 'valign' - string - vertical alignment in cell (top | middle | bottom | baseline)
* The following Intrinsic events all correspond to their names, and are strings:
* 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover',
* 'onmousemove', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup'
*
* @param bool $th tells whether the cell is a header cell (<th>).
* Defaults to FALSE
*
* Please note thataccording to w3 standards
* (http://www.w3.org/TR/html4/index/attributes.html), align and valign are NOT
* depreciated as of 04/04/2005 for the following: COL, COLGROUP, TBODY, TD, TFOOT,
* TH, THEAD, or TR
*
* @return void
*/
public function __construct($data=NULL, $settings=array(), $th=false){
//remove all empty settings. They are useless.
$settings = array_diff($settings,array(''));
//Check that dir, align, and valign are set to acceptable values per w3 standards
if(isset($settings['dir'])){
$options = array('rtl', 'ltr');
$settings['dir'] = strtolower($settings['dir']);
if(!in_array($settings['dir'],$options)){unset($settings['dir']);}
}
if(isset($settings['align'])){
$options = array('left', 'center', 'right', 'justify', 'char');
$settings['align'] = strtolower($settings['align']);
if(!in_array($settings['align'],$options)){unset($settings['align']);}
}
if(isset($settings['valign'])){
$options = array('top', 'middle', 'bottom', 'baseline');
$settings['valign'] = strtolower($settings['valign']);
if(!in_array($settings['valign'],$options)){unset($settings['valign']);}
}
/*
* go through each setting. If the setting is valid (a key exists in
* $this->settings for it) set the value accordingly
*/
foreach($this->settings as $setting => $value){
if(array_key_exists(strtolower($setting),$settings)){
$this->settings[$setting] = $settings[$setting];
}
}
$this->data = $data;
$this->th = $th;
}
/*
* public function get_cell
*
* Assembles the cell, including all it's settings, and returns the proper HTML as
* a string
*
* @return string
*/
public function get_cell(){
//set the cell type to 'th' or 'td' depending on $this->th
$cell_type = ($this->th) ? 'th' : 'td';
//$c is the html for the cell
$c = " <{$cell_type}";
//step through the settings for the cell, and add any that are set
foreach($this->settings as $setting => $value){
if(isset($value)){$c .= " {$setting}="{$value}"";}
}
if ($this->data == '') {$this->data = ' ';}
$c .= ">{$this->data}</{$cell_type}>rn";
return $c;
}
}
/*
* Row - basic row creation
*/ class Row{
//$cells is an array containing references to each instance of a Cell in this Row
public $cells = array();
//$settings - array - containing all possible settings as keys
public $settings = array('id'=>NULL, 'style'=>NULL, 'class'=>NULL, 'lang'=>NULL,
'dir'=>NULL, 'title'=>NULL, 'onclick'=>NULL,
'ondblclick'=>NULL, 'onmousedown'=>NULL,
'onmouseup'=>NULL, 'onmouseover'=>NULL,
'onmousemove'=>NULL, 'onmouseout'=>NULL,
'onkeypress'=>NULL, 'onkeydown'=>NULL, 'onkeyup'=>NULL,
'align'=>NULL, 'char'=>NULL, 'charoff'=>NULL,
'valign'=>NULL);
//$cur_cell = reference pointing to the last added instance of Cell
public $cur_cell;
public $restart_colors;
/*
* public function __construct
*
* @param array $settings an associative array containing any of the following keys:
* 'id' - string - document-wide unique id for row
* 'style' - string - style info for row
* 'class' - string - space-separated list of classes for row
* 'lang' - string - language code for contents of row
* 'dir' - string - direction for weak/neutral text in row (LTR | RTL)
* 'title' - string - advisory title
* 'align' - string - align, text alignment (left | center | right | justify | char)
* 'char' - string - alignment char, e.g. char=':'
* 'charoff' - string - offset for alignment char
* 'valign' - string - vertical alignment in row (top | middle | bottom | baseline)
* The following Intrinsic events all correspond to their names, and are strings:
* 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover',
* 'onmousemove', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup'
*
* Please note thataccording to w3 standards
* (http://www.w3.org/TR/html4/index/attributes.html), align and valign are NOT
* depreciated as of 04/04/2005 for the following: COL, COLGROUP, TBODY, TD, TFOOT,
* TH, THEAD, or TR
*
* @return void
*/
public function __construct($settings=array(),$restart_colors=false){
//remove all empty settings. They are useless.
$settings = array_diff($settings,array(''));
//Check that dir, align, and valign are set to acceptable values per w3 standards
if(isset($settings['dir'])){
$options = array('rtl', 'ltr');
$settings['dir'] = strtolower($settings['dir']);
if(!in_array($settings['dir'],$options)){unset($settings['dir']);}
}
if(isset($settings['align'])){
$options = array('left', 'center', 'right', 'justify', 'char');
$settings['align'] = strtolower($settings['align']);
if(!in_array($settings['align'],$options)){unset($settings['align']);}
}
if(isset($settings['valign'])){
$options = array('top', 'middle', 'bottom', 'baseline');
$settings['valign'] = strtolower($settings['valign']);
if(!in_array($settings['valign'],$options)){unset($settings['valign']);}
}
/*
* go through each setting. If the setting is valid (a key exists in
* $this->settings for it) set the value accordingly
*/
foreach($this->settings as $setting => $value){
if(array_key_exists(strtolower($setting),$settings)){
$this->settings[$setting] = $settings[$setting];
}
}
$this->restart_colors = $restart_colors;
}
/*
* public function add_cell
*
* @param string $data
* @param array $settings
* @param bool $th
*
* All params get passed directly to Cell::__construct. Please see the
* Cell::__construct notes for more information
*
* Creates a new instance of the Cell class, and adds it to the end of the cells
* array
*
* updates $this->cur_cell to point to the new cell
*
* @return void
*/
public function add_cell($data=NULL,$settings=array(),$th=false){
$this->cells[] = new Cell($data,$settings,$th);
$this->cur_cell =& $this->cells[sizeof($this->cells)-1];
}
/*
* public function get_row
*
* Assembles the row, including all it's settings and cells, and returns the proper
* HTML as a string
*
* @return string
*/
public function get_row(){
//$r is the html for the row
$r = ' <tr';
//step through the settings for the Row, and add any that are set
foreach($this->settings as $setting => $value){
if(isset($value)){$r .= " {$setting}="{$value}"";}
}
$r .= ">rn";
//step through all the cells, and add them to the row
foreach($this->cells as $cell){$r .= $cell->get_cell();}
$r .= " </tr>rn";
return $r;
}
}
/*
* Table - basic table creation
*/ class Table{
/*
* $head_rows is an array containing references to each instance of a Row that
* are part of the head (thead) of the table
*/
public $head_rows = array();
/*
* $body_rows is an array containing references to each instance of a Row that
* are part of the body (tbody) of the table
*/
public $body_rows = array();
/*
* $foot_rows is an array containing references to each instance of a Row that
* are part of the head (tfoot) of the table
*/
public $foot_rows = array();
//$settings - array - containing all possible settings as keys
public $settings = array('id'=>NULL, 'style'=>NULL, 'class'=>NULL, 'lang'=>NULL,
'dir'=>NULL, 'title'=>NULL, 'onclick'=>NULL,
'ondblclick'=>NULL, 'onmousedown'=>NULL,
'onmouseup'=>NULL, 'onmouseover'=>NULL,
'onmousemove'=>NULL, 'onmouseout'=>NULL,
'onkeypress'=>NULL, 'onkeydown'=>NULL, 'onkeyup'=>NULL,
'frame'=>NULL, 'rules'=>NULL, 'summary'=>NULL,
'width'=>NULL, 'border'=>0, 'cellspacing'=>0,
'cellpadding'=>0);
public $row_colors = NULL;
//$cur_row = reference pointing to the last added instance of Row
public $cur_row;
/*
* Number of rows and columns in the table.
* $num_rows in incremented
* $num_cols is set inside prep_table()
*/
public $num_cols = 0;
public $num_rows = 0;
/*
* public function __construct
*
* @param array $settings an associative array containing any of the following keys:
* 'id' - string - document-wide unique id for row
* 'style' - string - style info for row
* 'class' - string - space-separated list of classes for row
* 'lang' - string - language code for contents of row
* 'dir' - string - direction for weak/neutral text in row (LTR | RTL)
* 'title' - string - advisory title
* 'frame' - string - which parts of table frame to render
* (void|above|below|hsides|lhs|rhs|vsides|box|border)
* 'rules' - string - rulings between rows and cols (none|groups|rows|cols|all)
* 'summary' - string - purpose/structure for speech output
* 'width' - string - table width
* 'border' - int - controls frame width around table
* 'cellspacing' - int - spacing between cells
* 'cellpadding' - int - spacing within cells
* 'row_colors' - array | string - array OR comma-seperated values, these are
* background colors, given in hex, that alternate for each row.
* They will NOT override a color set for a specific row.
* They default to: #FFFFFF & #EFEFEF
* The following Intrinsic events all correspond to their names, and are strings:
* 'onclick', 'ondblclick', 'onmousedown', 'onmouseup', 'onmouseover',
* 'onmousemove', 'onmouseout', 'onkeypress', 'onkeydown', 'onkeyup'
*
* @return void
*/
public function __construct($settings = array()){
//remove all empty settings. They are useless.
$settings = array_diff($settings,array(''));
//Check that dir, frame, and rules are set to acceptable values per w3 standards
if(isset($settings['dir'])){
$options = array('rtl', 'ltr');
$settings['dir'] = strtolower($settings['dir']);
if(!in_array($settings['dir'],$options)){unset($settings['dir']);}
}
if(isset($settings['frame'])){
$options = array('void', 'above', 'below', 'hsides', 'lhs', 'rhs', 'vsides', 'box', 'border');
$settings['frame'] = strtolower($settings['frame']);
if(!in_array($settings['frame'],$options)){unset($settings['frame']);}
}
if(isset($settings['rules'])){
$options = array('none', 'groups', 'rows', 'cols', 'all');
$settings['rules'] = strtolower($settings['rules']);
if(!in_array($settings['rules'],$options)){unset($settings['rules']);}
}
//get the row_colors to alternate
if(isset($settings['row_colors'])){
if(!is_array($settings['row_colors'])){
$this->row_colors = explode(',',$settings['row_colors']);
}else{$this->row_colors = $settings['row_colors'];}
foreach($this->row_colors as $key => $value){
if(!preg_match('/^#/',$value)){$this->row_colors[$key] = '#'.$this->row_colors[$key];}
}
unset($settings['row_colors']);
}else{$this->row_colors = array('#FFFFFF','#EFEFEF');}
/*
* go through each setting. If the setting is valid (a key exists in
* $this->settings for it) set the value accordingly
*/
foreach($this->settings as $setting => $value){
if(array_key_exists(strtolower($setting),$settings)){
$this->settings[$setting] = $settings[$setting];
}
}
}
/*
* public function add_row
*
* @param array $settings
*
* All params get passed directly to Row::__construct. Please see the
* Row::__construct notes for more information
*
* Creates a new instance of the Row class, and adds it to the end of the body_rows
* array (rows that will go into tbody)
*
* updates $this->cur_row to point to the new Row
*
* @return Row
*/
public function &add_row($settings=array(),$restart_colors=false){
$this->body_rows[] = new Row($settings,$restart_colors);
$this->cur_row = $this->body_rows[sizeof($this->body_rows)-1];
$this->num_rows++;
return $this->body_rows[sizeof($this->body_rows)-1];
}
/*
* public function add_body_row
*
* @param array $settings
*
* All params get passed directly to Row::__construct. Please see the
* Row::__construct notes for more information
*
* Creates a new instance of the Row class, and adds it to the end of the body_rows
* array (rows that will go into tbody)
*
* updates $this->cur_row to point to the new Row
*
* @return Row
*/
public function &add_body_row($settings=array(),$restart_colors=false){
$this->body_rows[] = new Row($settings,$restart_colors);
$this->cur_row = $this->body_rows[sizeof($this->body_rows)-1];
$this->num_rows++;
return $this->body_rows[sizeof($this->body_rows)-1];
}
/*
* public function add_head_row
*
* @param array $settings
*
* All params get passed directly to Row::__construct. Please see the
* Row::__construct notes for more information
*
* Creates a new instance of the Row class, and adds it to the end of the head_rows
* array (rows that will go into thead)
*
* updates $this->cur_row to point to the new Row
*
* @return Row
*/
public function &add_head_row($settings=array(),$restart_colors=false){
$this->head_rows[] = new Row($settings,$restart_colors);
$this->cur_row = $this->head_rows[sizeof($this->head_rows)-1];
$this->num_rows++;
return $this->head_rows[sizeof($this->head_rows)-1];
}
/*
* public function add_foot_row
*
* @param array $settings
*
* All params get passed directly to Row::__construct. Please see the
* Row::__construct notes for more information
*
* Creates a new instance of the Row class, and adds it to the end of the foot_rows
* array (rows that will go into tfoot)
*
* updates $this->cur_row to point to the new Row
*
* @return Row
*/
public function &add_foot_row($settings=array(),$restart_colors=false){
$this->foot_rows[] = new Row($settings,$restart_colors);
$this->cur_row = $this->foot_rows[sizeof($this->foot_rows)-1];
$this->num_rows++;
return $this->foot_rows[sizeof($this->foot_rows)-1];
}
/*
* public function get_table
*
* Assembles the table, including all it's settings and rows, and returns the proper
* HTML as a string
*
* @return string
*/
public function get_table(){
//run prep_table to fix minor errors, etc.
$this->prep_table();
//run change_colspan0 to fix colspan=0 problem with IE (IE does not support it)
$this->change_colspan0();
//$t is the html for the row
$t = '<table';
//step through the settings for the table, and add any that are set
foreach($this->settings as $setting => $value){
if(isset($value)){$t .= " {$setting}="{$value}"";}
}
$t .= ">rn";
//Add all the rows, in the correct order (head, foot, body)
//step through all the head_rows, and add them to the table in thead tags
if(sizeof($this->head_rows) > 0){
$t .= " <thead>rn";
foreach($this->head_rows as $row){$t .= $row->get_row();}
$t .= " </thead>rn";
}
//step through all the foot_rows, and add them to the table in tfoot tags
if(sizeof($this->foot_rows) > 0){
$t .= " <tfoot>rn";
foreach($this->foot_rows as $row){$t .= $row->get_row();}
$t .= " </tfoot>rn";
}
//step through all the body_rows, and add them to the table in tbody tags
if(sizeof($this->body_rows) > 0){
$t .= " <tbody>rn";
foreach($this->body_rows as $row){$t .= $row->get_row();}
$t .= " </tbody>rn";
}
$t .= "</table>rn";
return $t;
}
/*
* private function change_colspan0
*
* Checks all cells, and if colspan is set to '0' it changes it to the total
* columns in the table. This is because IE does not support the w3 standard where
* colspan="0" means "span the whole table"
*
* @return void
*/
private function change_colspan0(){
$row_groups = array('head_rows'=>&$this->head_rows,'body_rows'=>&$this->body_rows,'foot_rows'=>&$this->foot_rows);
foreach($row_groups as &$rows){
foreach($rows as &$row){
foreach($row->cells as &$cell){
if((isset($cell->settings['colspan'])) && ($cell->settings['colspan'] == '0')){
$cell->settings['colspan'] = $this->num_cols;
}
}
}
}
}
/*
* private function find_diff
*
* @param array $c an array of cells per row in a table
*
* Modifies an array to how many cells need to be added to each row, in order for
* the table to be right
*
* @return void
*/
private function find_diff(&$c){
if($c != NULL){$c = $this->num_cols - $c;}else{$c = 0;}
}
/*
* private function prep_table
*
* Fixes common errors with HTML tables:
* All empty cells are filled with ' '
* All rows are adjusted to be the same length
*
* Also adds alternating row colors
*
* @return void
*/
private function prep_table(){
$color = 0;
$cols_from_rowspan = array();
$col_count = array();
//put all row arrays into an array, so we can loop through them in order that
//they appear. This helps with rowspans
$row_groups = array('head_rows'=>&$this->head_rows,'body_rows'=>&$this->body_rows,'foot_rows'=>&$this->foot_rows);
//step through row groups (head, body, foot)
foreach($row_groups as $key=>&$rows){
//add element to the $col_count array, correspoding to the current group
$col_count[$key] = array();
//step through the rows in the current row_group
foreach($rows as &$row){
//$cells is used to calculate the number of cells in each row
$cells = 0;
//add in cells from previous row spans
if(isset($cols_from_rowspan[0])){$cells += array_shift($cols_from_rowspan);}
//step through each cell in the current row
foreach($row->cells as &$cell){
//if there IS a colspan set, compensate
if(isset($cell->settings['colspan'])){
//if colspan is NOT set to 0, increment cell count by colspan
if($cell->settings['colspan'] != '0'){
$cells += $cell->settings['colspan'];
}
//if colspan IS set to 0, and There are more cells in this row...unset
//colspan...you can't have colspan=0 & have more cells
elseif(count($row->cells) != 1){
unset($cell->settings['colspan']);
$cells++;
}
//if colspan IS set to 0, and it's the only cell in the row, set cell count
//to NULL (later used by $this->find_diff to let it know NOT to adjust
//the number of cells in this row)
else{$cells = NULL;}
}
//If there is no colspan set, increment the cell count ($cells)
else{$cells++;}
//If there is a rowspan set, compensate
if(isset($cell->settings['rowspan'])){
//for each row that is spaned, add 1 or the colspan to an array...later
//used to adjust the next rows.
for($i=0;$i<$cell->settings['rowspan']-1;$i++){
if(isset($cols_from_rowspan[$i])){
if(isset($cell->settings['colspan'])){$cols_from_rowspan[$i] += $cell->settings['colspan'];}
else{$cols_from_rowspan[$i]++;}
}
else{
if(isset($cell->settings['colspan'])){$cols_from_rowspan[$i] = $cell->settings['colspan'];}
else{$cols_from_rowspan[$i] = 1;}
}
}
}
}
//Set the col_count for the current group, for the current row to the number
//of cells in this row
$col_count[$key][] = $cells;
//if the number of cells in this row is more than previous rows, adjust the
//table's number of columns
if($cells > $this->num_cols){$this->num_cols = $cells;}
if($row->restart_colors){$color = 0;}
//if there is no background color for the row, use the next row color in sequence
if(!preg_match('/background-color:#[0-9A-F]{6}/',$row->settings['style'])){
if(!isset($row->settings['style'])){$row->settings['style'] = '';}
$row->settings['style'] .= "background-color:{$this->row_colors[$color%sizeof($this->row_colors)]};";
}
//increment to next color
$color++;
}
}
//step through the column counts from each row group
foreach($col_count as $array => &$cur_col_count){
//change the array of cells per row into an array of numbers of cells to be
//added to each row to fix the table.
array_walk($cur_col_count,array(&$this,'find_diff'));
//remove any rows that do NOT need any adjustment
$cur_col_count = array_diff($cur_col_count,array(0));
//adjust rows, by adding cells
foreach($cur_col_count as $key => $diff){
for($i=0;$i<$diff;$i++){
$this->{$array}[$key]->add_cell(' ');
}
}
}
}
} ?>
|
|
|
Usage Example
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TAble Class Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
.ruled td{border-bottom:1px solid #CCCCCC;}
</style>
</head>
<body>
<?php include('table.class.php'); $table = new Table(array('class'=>'ruled','style'=>"width:100%; border:0; padding:0; margin:0;", 'row_colors'=>'#FFFFFF,#EFEFEF')); $cur_row = $table->add_head_row(array('style'=>'font-weight:bold;')); $cur_row->add_cell('<h2>Example Table</h2>',array('colspan'=>0)); $cur_row = $table->add_row(); $cur_row->add_cell('Row 1 - Column 1'); $cur_row->add_cell('Row 1 - Column 2'); $cur_row->add_cell('Row 1 - Column 3'); $cur_row->add_cell('Row 1 - Column 4'); $cur_row = $table->add_row(); $cur_row->add_cell('2-1'); $cur_row->add_cell('2-2'); $cur_row->add_cell('2-3'); $cur_row->add_cell('2-4'); $cur_row = $table->add_row(); $cur_row->add_cell('3-1'); $cur_row->add_cell('3-2'); $cur_row->add_cell('Cell will be added ->'); $cur_row = $table->add_row();
$cur_row->add_cell(); $cur_row->add_cell('<- Will not have 'empty cell' issue in IE ->'); $cur_row->add_cell(); $cur_row->add_cell('4-4');
//Setting a CSS background-color will override the alternating color. This row should be grey, but will be white.
$cur_row = $table->add_foot_row(array('style'=>'font-size:.5em; background-color:#FFFFFF;')); $cur_row->add_cell('Example Table Footer',array('colspan'=>0,'style'=>'text-align:center;'));
echo $table->get_table(); ?> </body>
</html>
|
|
|
Rate This Script
|
|
|
|