<?php
// -------------------------------------------------------------------------------------------------------------------------
// generate a div-based table-like creature, allowing cells to be accessed by index as desired.
//
// by F Phil DeGeorge
// Computer Whisperer, hide@address.com
// -------------------------------------------------------------------------------------------------------------------------
// Tested against IE 7, FireFox 3.0.5, Safari 3.2, Chrome 1.0154 Opera 9.63
// Tested against PHP5, PHP4
// -------------------------------------------------------------------------------------------------------------------------
// class functions
// WhisperTable($id='WsprTbl') -- constructor
// TableID($id) -- should you need to change the ID from what was assigned in the constructor
// ShowHeaders($rHdr=false, $cHdr=false) -- column header (row 0) and row header (column 0), on or off
// TableAlign($align) -- left, center, right
// GetTheTable() -- output the HTML for the table, without style statements
// GetStyles() -- output the style statements
// WriteStyles($file) -- output the style statements as a .css
// CellColSpan($row, $col, $span) -- column span for a given cell
// CellRowSpan($row, $col, $span) -- row span for a given cell, can be set but is NOT supported at this time
// CellValue($row, $col, $value='') -- the content of a given cell
// ColWidth()
// RowHeight($row, $height=0); -- height for the given row (0 == default height)
// TableStyle($style='') -- the style for the table
// RowStyle($row, $style='') -- the style for a row
// OnRowStyle($style='') -- if set, trumps RowStyle, styling for rows 1, 3, 5, etc
// OffRowStyle($style='') -- if set, trumps RowStyle, styling for rows 2, 4, 6, etc
// CellStyle($row, $col, $style='') -- the style for a cell
// ColStyle($col, $style='') -- the style for a column
// AddStyle($style) -- simply add another style to the style's output statement; a passthrough function, really
// SetRowHighlight($style='') -- set a mouse hover highlight of whatever row the mouse is currently over
// SetCellHighlight($style='') -- set a mouse hover highlight of whatever cell the mouse is currently over
// internal helper functions
// Expand($row, $col) -- internal helper function
// SpeakError($msg, $stop=true) -- display internal error messages
// SetDebug($mode=false, $border=false) -- set debug mode on / off, second parameter is whether to place a border around all table elements:table, rows, cells or not
//
// How the table data/specs are stored:
//
// $TheTable['rows'] -- holds the array of rows, row[0] being the column header row
//
// $TheTable['rows'][y] -- the data rows, 0 == column headers, 1 - $NumRows == the data rows
// $TheTable['rows'][y]['style'] -- the style for the given row
// $TheTable['rows'][y]['height'] -- height for the row, in pixels -- optional, defaults to 20px
// $TheTable['rows'][y]['cols'] -- an array of the cells making up the row
//
// $TheTable['rows'][y]['cols'][x]['style'] -- cell style -- over=rides all other styling
// $TheTable['rows'][y]['cols'][x]['colspan'] // yet to be implemented... can be set, but is ignored at this time
// $TheTable['rows'][y]['cols'][x]['rowspan'] // yet to be implemented... can be set, but is ignored at this time
// $TheTable['rows'][y]['cols'][x]['onclick'] // yet to be implemented... but the implications are legion :O
// $TheTable['rows'][y]['cols'][x]['value'] -- the contents for the cell: can be anything
// example (internal) access:
// $ARow = $this->TheTable['rows'][y];
// $ACell = $this->TheTable['rows'][y]['cols'][x]
/**
* WhisperTable -- a "table" done with the Smoke-And-Mirrors of DIVs and CSS
*
* This is an object meant to replace <table> as a method of formatting data in X-by-Y format
* or tabular format. It uses <div>s to accomplish this, and mostly it works quite well.<br/><br/>
* (In reality I have found it no more cranky in usage than <table> has been (some of the problems
* I cite with this class are actually identical to problems I've had when using <table>s
* for formatting data, such as "width:100%" causing formatting issues, especially in Opera or Safari,
* and so on)<br/><br/>
*
* This class has been kept PHP4 compatible.<br/>
* Tested against IE 7, FireFox 3.0.5, Safari 3.2, Chrome 1.0154 Opera 9.63<br/>
* Tested against PHP5, PHP4.<br/><br/>
*
* <b>Random Notes:</b><br/>
* <ul>
* <li><b>[]</b> RowSpan can be set, but is ignored at this time. (Complicated to implement)</li>
* <li><b>[]</b> row 0 is the (optionally displayed) column header row</li>
* <li><b>[]</b> col 0 is the (optionally displayed) row header (ie, row number) column</li>
* <li><b>[]</b> A cell is creating by referencing it, assigning a style or value to it</li>
* <li><b>[]</b> If cell at row 10, col 5 is references, all rows and columns up to that point are "created" at that moment, in default state</li></ul>
*
*<br/><br/><b>Concerning Styles within this "Table"</b><br/><br/>
* The precedence order of styles, lowest to highest<br/>
* <ul>
* <li><b>[]</b> document body or container/parent object (ie, if no styles are set within the table at all, then it's default according to document or the immediate container)</li>
* <li><b>[]</b> table style</li>
* <li><b>[]</b> column style</li>
* <li><b>[]</b> row style (row style will trump column style, in other words)</li>
* <li><b>[]</b> onrow / offrow style (styling for alternating rows)</li>
* <li><b>[]</b> cell style</li></ul>
*<br/>
* A variety of styles / style-statements are produced to go along with each table. These styles can be obtained as
* a string for inclusion directly in the document, or written out as a css file, and manually included
* in the destination file via a standard style link statement. <br/>
* The names used for the various styles are prefixed with the Table's ID, to ensure that the styling for each
* table in a particular page applies only to the table it meant for.<br/><br/>
*
* @todo TableAlign parameter should be changed to define's rather than a string value
* @todo would like this to be stable when width's are spec'd at 100%; it currently is not
* @todo need to figure out why the formatting goes to pieces (in some browsers) when borders are set arond the cells
* @todo want to provide support for onclick and other potentially useful events
* @todo want to provide some predifined "skins" or packaged appearances
* @todo want to provide a database link method, when on specifying a table and an optional select statement, it will then display the data as if it was "bound" to the table
* @todo want to provide a built-in paging mechanism for when data rows go beyond a reasonable number (especially with the previous todo)
* @todo want to allow for "data nesting"; that is, child records, or expanding a row by clicking on a [+] or [-] to open or close the
* @todo want to provide an edit mode where (for example, when displaying table data) the user can edit a value and have it automatically updated back to the data source
*
* @author F Philip DeGeorge Computer Whisperer <hide@address.com>
* @version 0.02
* @copyright Copyright (c) 2009, by F Philip DeGeorge
* @package WhisperTable
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @category UI elements
*
*/
class WhisperTable
{
/**
* @var string the ID string to use for the table on next generation {@link GetTable()}
*/
var $ID; // id for the table
/**
* @var integer internal, the current number of rows defined
*/
var $NumRows; // number of rows
/**
* @var integer internal, the current number of columns defined
*/
var $NumCols; // number of cols
/**
* @var array the central block of data holding the majority of the information / data about the table, including cell values
*/
var $TheTable = array(); // array of rows, including the header row (index 0)
// formatting
/**
* @var string alignment of the table: left, center, right
*/
var $TableAlign; // left, center, right
/**
* @var boolean show the column headers?(row 0)
*/
var $bColHeaders; // show column headers? (Row 0)
/**
* @var boolean show the row headers (column 0, row numbers)
*/
var $bRowHeaders; // show row numbers? (Col 0)
/**
* @var array for controlling individual column widths: by default column widths are distributed evenly. A percentage value
*/
var $ColWidths = array(); // for controlling column widths
// styles
/**
* @var string the style statement for use for the table as a whole
*/
var $TableStyle; // default style for table, rows and cells
/**
* @var array optional column styles
*/
var $ColStyles = array(); // optional column styles
/**
* @var string the style used in alternating row styles for the "on" rows (1, 3, 5...)
*/
var $onRowStyle; // for alternating row styling
/**
* @var string the style used in alternating row styles for the "off" rows (2, 4, 6...)
*/
var $offRowStyle; // for alternating row styling
/**
* @var string additional styles that can be specified to be included with the default / generated styles
*/
var $Styles; // for additional styles being added to this table object
/**
* @var boolean if true, sets debug_mode
* debug mode:
* includes longer error messages (with back-trace)
* includes "pretty print" on the final table output, for easier analysis of results
* shows row numbers (row header column) by default, again for easier analysis of results
* optionally also includes a border around all cells, to show how cells are actually distributed
*/
var $debug_mode; // set debug mode on or off (off by default)
/**
* @var boolean, if true, and debug_mode is true, then puts borders around the cells: NOTE: this sometimes causes formatting problems
*/
var $debug_show_border; // set to true by default when $debug_mode is set.
/**
* constructor, sets up a basic, completely blank "grid" 0 x 0
* @param string $id id to use for this of the table (optional)
*/
function WhisperTable($id='WsprTbl')
{
$this->NumRows = 0;
$this->NumCols = 0;
$this->TableAlign = "center";
$this->TableStyle = '';
$this->bColHeaders = false;
$this->bRowHeaders = false;
$this->ID = $id;
$this->TableStyle= '';
$this->onRowStyle = '';
$this->offRowStyle = '';
$this->Styles = '';
$this->debug_mode = false;
$this->debug_show_border = true; // only operates if debug_mode is true
}
/** set the ID to use for the table as a whole (actually, it becomes the ID of the enclosing <DIV>
* @param string $id id to use for this table, useful if you are re-using the table object to generate another table and want a different id for it
*/
function TableID($id)
{
$this->ID = $id;
}
/**
* show the headers?
* @param boolean $rHdr show the row headers?
* @param boolean $cHdr show the column headers (row numbers)?
*/
function ShowHeaders($rHdr=false, $cHdr=false)
{
$this->bRowHeaders = $rHdr;
$this->bColHeaders = $cHdr;
}
/**
* set the horizontal alignment (location) of the table against the document
* @param string $align the alignment for the table against: valid values are 'center' 'left' or 'right'
*/
function TableAlign($align)
{
if (strtolower($align) != 'center' && strtolower($align) != 'left' && strtolower($align) != 'right')
{
SpeakError('WhisperTable::TableAlign() -- invalid alignment value: only left, center and right accepted');
}
if (empty($align))
{
$this->TableAlign = 'center';
}
else
{
$this->TableAlign = $align;
}
}
/**
* set a column span for the given cell
* NOT YET IMPLEMENTED: you can set the span here, but it ignored at this time when the table is generated
* @param integer $row the row of the cell whose col span is being set.
* @param integer $col the col of the cell whose col span is being set.
* @param integer $span the number of columns this cell is to span across
* @todo ColSpan is not yet fully implemented. It can be set but will be ignored during table generation.
*/
function CellColSpan($row, $col, $span)
{
if ($row < 1 || $col < 1){$this->SpeakError("WhisperTable::CellColSpan() -- invalid row / col parameters");}
$this->Expand($row, $col);
$cell =& $this->TheTable['rows'][$row]['cols'][$col];
$cell['colspan'] = $span;
}
/**
* set a row span for the given cell
* Can be set but is NOT supported at this time...
* (Frankly, I'm not entirely sure how to go about this. I _think_ it can be done with some absolute positioning of the div's affected)
* @param integer $row the row of the cell whose row span is being set.
* @param integer $col the col of the cell whose row span is being set.
* @param integer $span the number of rows this cell is to cover.
* @todo RowSpan is not yet fully implemented. It can be set, but will be ignored during table generation.
*/
function CellRowSpan($row, $col, $span)
{
if ($row < 1 || $col < 1){$this->SpeakError("WhisperTable::CellRowSpan() -- invalid row/col indicated");}
$this->Expand($row, $col);
$cell =& $this->TheTable['rows'][$row]['cols'][$col];
$cell['rowspan'] = $span;
}
/**
* set contents of the given cell
* calling it as "CellValue(x, y)" will clear the contents for that cell
* @param integer $row the row of the cell whose value is being set
* @param integer $col the col of the cell whose value is being set
* @param string $value the value to set, can be HTML code, anything you might want to place in a "cell"
*/
function CellValue($row, $col, $value='')
{
if ($row < 0|| $col < 0){$this->SpeakError("WhisperTable::CellValue() -- invalid row/col indicated");}
$this->Expand($row, $col);
$this->TheTable['rows'][$row]['cols'][$col]['value'] = $value;
}
/**
* set the style of the given cell
* calling it as "CellStyle(x, y)" will clear any style statement for that cell
* @param integer $row the row of the cell whose style is being set
* @param integer $col the col of the cell whose style is being set
* @param string $style the style to use for the given cell: over-rides ALL other style settings
*/
function CellStyle($row, $col, $style='')
{
if ($row < 1 || $col < 1){$this->SpeakError("WhisperTable::CellStyle() -- invalid row/col indicated");}
$this->Expand($row, $col);
$cell =& $this->TheTable['rows'][$row]['cols'][$col];
$cell['style'] = $style;
}
/**
* add a style statement. This is simply added to the styles "output" (GetStyles()), so it really
* is just a sort of pass-through thing. This is useful for things like "onclick()" implementation,
* to set up a style specifically for some action defined by cell content or whatever.
* @param string $style the complete style statment, including (in this one case only) the "style=" and quotes.
*/
function AddStyle($style)
{
if (!empty($style))
{
$this->Styles .= PHP_EOL . $style;
}
}
/**
* height for the given row (0 == default height == 22px)
* <code>
* $tbl->RowHeight(5, 32px); // for, say, setting a larger size font in that row
* ...
* $tbl->RowHeight(5); // restore the row to default size, when table is next generated
* </code>
* @param integer $row the row whose height is being set
* @param integer $height, the height in pixels for this row. If you do not provide this parameter, the row is set to "default" height (22px)
*/
function RowHeight($row, $height=0)
{
if ($row < 0){$this->SpeakError("WhisperTable::RowStyle() -- invalid row indicated");}
$this->Expand($row, $this->NumCols);
$this->TheTable['rows'][$row]['height'] = $height;
}
/**
* set style for the indicated row
* calling it as "RowStyle(y)" will clear any style statement for that row
* This will over-ride any styling set for the table in general, for the indicated row
* @param integer $row the row whose style is being set
* @param string $style the style statement to use for this row (leave off the "style=")
*/
function RowStyle($row, $style='')
{
if ($row < 0){$this->SpeakError("WhisperTable::RowStyle() -- invalid row indicated");}
$this->Expand($row, $this->NumCols);
$this->TheTable['rows'][$row]['style'] = $style;
}
/**
* set style for OnRow -- this is for alternating highlights on a table (a common display format for readability)
* (this will over-ride - trump - any ordinary row styling set)
* If either OnRowStyle or OffRowStyle is set, then any RowStyles that are set will be ignored.
* @param string $style the styling to use for the "on row" (rows 1, 3, 5, ...). Call as OnRowStyle() to clear this setting. Do not include "style="
*/
function OnRowStyle($style = '')
{
$this->onRowStyle = $style;
}
/**
* set style for OffRow -- this is for alternating highlights on a table (a common display format for readability)
* @param string $style the styling to use for the "off row" (rows 2, 4, 6, ...). Call as OffRowStyle() to clear this setting. Do not include "style="
*/
function OffRowStyle($style = '')
{
$this->offRowStyle = $style;
}
/**
* set styling for columns (row and cell styling will over-ride - trump - this styling)
* @param integer $col the col whose style is being set
* @param string $style the style to apply to this column. Do not include "style="
*/
function ColStyle($col, $style='')
{
if ($col < 0) {$this->SpeakError("WhisperTable::ColStyle() -- invalid col indicated");}
$this->Expand($this->NumRows, $col);
$this->ColStyles[$col] = $style;
}
/**
* set column width, in percent only (at this time, at least)
* 0 == default width, which is the available (unassigned) percentage divided evenly among all unsized columns
* if total specified width goes over 100, all the specified widths are discarded and width is distributed evenly among the columns
* <code>
* $tbl->ColWidth(5, 25); // sets column 5 to 25% of the total width
* ...
* $tbl->ColWidth(5); // return column 5 to default width, when table is next generated with {@link GetTable()}
* </code>
* @param integer $col the col whose width is being set
* @param double|integer $prcnt (optional) the percentage of the total for this column. If left off or at zero, width will be assigned during table generation. Can be a floating point value, and some times a value like 99.9% gives the expected results where 100% does not.
*/
function ColWidth($col, $prcnt = 0)
{
if ($col < 0) {$this->SpeakError("WhisperTable::ColStyle() -- invalid col indicated");}
$this->Expand($this->NumRows, $col);
$this->ColWidths[$col] = $prcnt;
}
/**
* set the table style, over-rides the table's container object's (pagebody, a div, whatever) styling
* <code>
* $tbl->TableStyle('background-color:#FFFFCC;color:#0000FF');
* </code>
* @param string $style the style to use for the table. Do not include "style="
*/
function TableStyle($style='')
{
$this->TableStyle = $style;
}
/**
* A style to use for row hover (CSS answer to onmouseover); if style is not specified, a default style is used.
* This function must be called, even to use default styles, for the dynamic highlighting to get turned on
* <code>
* // Supply only the style, not the style's name.
* $tbl->SetRowHighlight('border:1px #FFFFCC;background-color:#FFFF99');
* </code>
* @param string $style the style to use for onmouseover on a row. Default style is provided if you do not wish to provide one
*/
function SetRowHighlight($style='')
{
$this->Styles .= PHP_EOL . '.' . $this->ID . 'Row:hover {';
if (empty($style)){$this->Styles .= 'background-color:#FFBBBB}';}
else{$this->Styles .= $style . '}';}
$this->Styles .= PHP_EOL . '.' . $this->ID . 'OnRow:hover {';
if (empty($style)){$this->Styles .= 'background-color:#FFBBBB}';}
else{$this->Styles .= $style . '}';}
$this->Styles .= PHP_EOL . '.' . $this->ID . 'OffRow:hover {';
if (empty($style)){$this->Styles .= 'background-color:#FFBBBB}';}
else{$this->Styles .= $style . '}';}
}
/**
* style to use for cell hover (CSS version of onmouseover) if style is not specified, a default style is used
* Function must be called to activate this dynamic cell highighting
* <code>
* // Supply only the style, not the style's name. Example:
* $tbl->SetCellHighlight('border:1px #E0E0FF;background-color:#FDFDFF');
* </code>
* @param string $style the style to use for onmouseover on a cell. Default style is provided if you do not wish to provide one
*/
function SetCellHighlight($style='')
{
$this->Styles .= PHP_EOL . '.' . $this->ID . 'Cell:hover {';
if (empty($style)){$this->Styles .= 'background-color:#FFFF99}';}
else{$this->Styles .= $style . '}';}
}
/**
* Produce the HTML for the table, as it is currently defined.
* <code>
* <php
* $tbl = new WhisperTable();
* $tbl->CellValue(5,4,'This is the cell at row 5, col 4');
* $tbl->SetRowHighlight(); // turn on dynamic row highlighting
* echo($tbl->GetStyles()); // the styles -- could also be done as a .CSS, and linked in the header section of the output page
* echo($tbl->GetTable()); // the table itself
* ?>
* </code>
* @return string
*/
function GetTheTable()
{
$TheHTML = '';
if ($this->debug_mode)
{
$TheHTML .= PHP_EOL;
$TheHTML .= '<!-- Whisper Table Begins here : Debug Mode On -->';
$TheHTML .= PHP_EOL;
}
// compute column widths
$this->ColWidths[0]=4; // column zero is always 4%
$assigned = 0;
if ($this->bRowHeaders){$assigned += 4;}
$num_unassigned = 0;
for ($i = 1; $i <= $this->NumCols; $i++)
{
if (!isset($this->ColWidths[$i])) {$this->ColWidths[$i]=0;}
if ($this->ColWidths[$i] == 0) {$num_unassigned++;}
$assigned += $this->ColWidths[$i];
}
if ($assigned > 100 || $assigned == 0)
{
// if it goes over 100%, scrap all assigned values and just do a default even split
$Width = intval(99 / ($this->NumCols));
if ($this->bRowHeaders)
{
// if showing row headers (row numbers, col 0), we don't need col 0 to have an equal share of the available space
// Take 4% for column zero, and divide the rest equally
$Width = intval(96 / ($this->NumCols));
}
for ($i = 1; $i <= $this->NumCols; $i++)
{
$this->ColWidths[$i] = $Width;
}
}
else
{
if ($num_unassigned > 0)
{
$un_width = (99 - $assigned) / $num_unassigned; // 99 because going 100% doesn't work... go figure
for ($i = 1; $i <= $this->NumCols; $i++)
{
if ($this->ColWidths[$i] == 0) {$this->ColWidths[$i] = $un_width;}
}
}
}
// ------------------------------------------------------------------------------------------------------------------
// <<TBD>> THIS NEEDS TO GO AWAY ONCE THE PROBLEM IS REALLY UNDERSTOOD
//
// Short version: adding borders around the cells messes things up BADLY, especially in Opera. This fixes that
// in some cases, but not all.
//
// this works for IE, Safari, Chrome and FireFox... but only if the window is wide enough.
// Opera behaves the opposite: this works if the window is narrow enough... Gadzooks
// I don't really understand what's happening with the divs and why this is even necessary when borders are on.
//
// finagle factor, apparently the problem is the borders taking up additional space
if ($this->debug_mode && $this->debug_show_border)
{
for ($i = 1; $i <= $this->NumCols; $i++)
{
$this->ColWidths[$i] -= 0.1;
}
}
// ------------------------------------------------------------------------------------------------------------------
// overall-enclosing div
if ($this->debug_mode) {$TheHTML .= PHP_EOL;}
$TheHTML .= '<div align="' . $this->TableAlign . '">';
$TheHTML .= '<div class="' . $this->ID . 'Tbl"';
if (!empty($this->TableStyle)) {$TheHTML .= ' style="' . $this->TableStyle . '"';}
$TheHTML .= ' id="' . $this->ID . '"';
$TheHTML .= '>';
// for each row
$rowFlag = false;
for ($y = 0; $y <= $this->NumRows; $y++)
{
$rowFlag = !$rowFlag;
$TheRow = array();
if (!empty($this->TheTable['rows'][$y]))
{
$TheRow = $this->TheTable['rows'][$y];
}
if (!($y == 0 && $this->bColHeaders==false)) // if header row, don't output if headers are off
{
if ($this->debug_mode) {$TheHTML .= PHP_EOL;}
// row class: either "normal" or onrow/offrow
if ($y > 0 && (!empty($this->onRowStyle) || !empty($this->offRowStyle)))
{
if ($rowFlag)
{
$TheHTML .= '<div class="' . $this->ID . 'OffRow"';
}
else
{
$TheHTML .= '<div class="' . $this->ID . 'OnRow"';
}
}
else
{
$TheHTML .= '<div class="' . $this->ID . 'Row"';
}
$stFlag = false;
if (!empty($TheRow['style']))
{
// "normal" styling (not onrow-offrow)
$TheHTML .= ' style="' . $TheRow['style'];
$stFlag=true;
}
// height -- part of the style statement currently being built
if (!empty($TheRow['height']) && $TheRow['height'] > 0)
{
if ($stFlag == false)
{
$TheHTML .= 'style="height:' . $TheRow['height'] . 'px';
}
else
{
$TheHTML .= '; height:' . $TheRow['height'] . 'px';
}
$stFlag = true;
}
if ($stFlag) {$TheHTML .= '"';} // finishes (closes) style statement for the row
$TheHTML .= '>'; // closes the ROW div
// for each column
for ($x = 0; $x <= $this->NumCols; $x++)
{
if (!($x == 0 && !$this->bRowHeaders)) // if column zero, don't output if row numbers are off
{
if ($this->debug_mode) {$TheHTML .= PHP_EOL;}
if ($x == 0 && $this->bRowHeaders)
{
// row number / column 0 has its own class
// and the 0x0 cell has its own style, too
if ($y==0)
{
$TheHTML .= '<div class="' . $this->ID . 'Crnr"';
if (!empty($TheRow['cols'][$x]['style']))
{
$TheHTML .= 'style="' . $TheRow['cols'][$x]['style'] . '"';
}
$TheHTML .= '>';
if (!empty($TheRow['cols'][$x]['value']))
{
$TheHTML .= $TheRow['cols'][$x]['value'];
}
else
{
$TheHTML .= ' ';
}
}
else
{
$TheHTML .= '<div class="' . $this->ID . 'Col0" ';
if (!empty($TheRow['cols'][$x]['style']))
{
$TheHTML .= 'style="' . $TheRow['cols'][$x]['style'] . '"';
}
else if (!empty($this->ColStyles[$x]) && empty($TheRow['style']))
{
$TheHTML .= 'style="' . $this->ColStyles[$x] . '"';
}
$TheHTML .= '>';
$TheHTML .= $y; // row number
}
}
else
{
// data cells
$TheHTML .= '<div class="' . $this->ID . 'Cell" style="width:' . $this->ColWidths[$x] . '%';
if (!empty($TheRow['cols'][$x]['style']))
{
$TheHTML .= '; ' . $TheRow['cols'][$x]['style'];
}
else if (!empty($this->ColStyles[$x]) && empty($TheRow['style']))
{
$TheHTML .= '; ' . $this->ColStyles[$x];
}
$TheHTML .= '">';
if (!empty($TheRow['cols'][$x]['value']))
{
$TheHTML .= $TheRow['cols'][$x]['value'];
}
else
{
$TheHTML .= ' ';
}
}
$TheHTML .= '</div>';
} // the check for row numbers (col 0)
} // for each column in the row
$TheHTML .= '</div>'; // end of row
} // the check for column header (row 0)
} // for each row in the table
if ($this->debug_mode) {$TheHTML .= PHP_EOL;}
$TheHTML .= "</div></div>";
if ($this->debug_mode)
{
$TheHTML .= PHP_EOL;
$TheHTML .= '<!-- Whisper Table Ends here -->';
$TheHTML .= PHP_EOL;
}
return $TheHTML;
}
/**
* get the style statements necessary for the table, as it sits. See also WriteStyles()
* @return string
* @see WriteStyles()
*/
function GetStyles()
{
$TheHTML = '';
$TheHTML .= PHP_EOL . '<style type="text/css">';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Tbl {width:auto; text-align:left; background-color:inherit; color:inherit}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'OnRow, .' . $this->ID . 'OffRow, .' . $this->ID . 'Row {width:100%; height:22px; margin:0; padding:0}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'OnRow {' . $this->onRowStyle . '}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'OffRow {' . $this->offRowStyle . '}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Row {background-color:inherit; color:inherit}';
// for the row numbers, column 0
if ($this->debug_mode && $this->debug_show_border)
{
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Col0 {float:left; margin:0; padding-right:5px; width:4%; height:22px; text-align:right; background-color:inherit; color:inherit; border:1px blue solid}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Crnr {float:left; margin:0; padding-right:5px; width:4%; height:22px; text-align:right; background-color:white; color:inherit; border:1px blue solid}';
}
else
{
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Col0 {float:left; margin:0; padding-right:5px; width:4%; height:22px; text-align:right; background-color:inherit; color:inherit}';
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Crnr {float:left; margin:0; padding-right:5px; width:4%; height:22px; text-align:right; background-color:white; color:inherit}';
}
$cellClass = 'float:left; margin:0; padding:0; background-color:inherit; color:inherit; height:100%';
if ($this->debug_mode && $this->debug_show_border) {$cellClass .= '; border:1px blue solid';}
$TheHTML .= PHP_EOL . '.' . $this->ID . 'Cell {' . $cellClass . '}';
$TheHTML .= $this->Styles; // any additional user-supplied styles
$TheHTML .= PHP_EOL . '</style>';
return $TheHTML;
}
/**
* write the styles as a .CSS file. Just another option.
* If file name is not supplied, it will write out <tableid>.css to the cwd.
* @param $file optional file name to write the styles out to as .css. DO NOT INCLUDE .css extension! If not provided, table ID is used as default file name
* @see GetStyles()
*/
function WriteStyles($file = '')
{
$fyl = $file;
if (empty($fyl)) {$fyl = strtolower($this->ID) . '.css';}
if (($handle = fopen($fyl, 'w+')))
{
$styles = GetStyles();
fwrite($handle, $styles);
fclose($handle);
}
else
{
SpeakError('could not open/create file "' . $fyl . '"');
}
}
// -------------------------------------------------------------------------------------------------------------------------
// Miscellaneous
//
/**
* expand the rows / columns as necessary according to the latest cell, row or column reference
* also sets default values, styles, etc in unset cells, according to current settings
* Internal, helper function.
* @param integer $row the row being referenced
* @param integer $col the col being referenced
*/
function Expand($row, $col)
{
if ($row >= $this->NumRows || $col >= $this->NumCols)
{
if ($row >= $this->NumRows) {$this->NumRows = $row;}
if ($col >= $this->NumCols) {$this->NumCols = $col;}
}
}
/**
* error handling. Called only for critical, unrecoverable errors
* @param string $msg the error message to be presented
* @param boolean $stop (optional) hault processing at this point if true (default is to stop)
*/
function SpeakError($msg, $stop=true)
{
echo('<div style="text-align:center;background-color:#FF9999;color:$FFFF00"><br/>' . $msg . '<br/>');
if ($this->debug_mode)
{
// <<tbd>> add backtrace
}
echo('</div>');
if ($stop) {exit();}
}
/**
* debug mode on/off. Debug mode is off initially
* @param boolean $mode turns debug mode on (true) or off (false)
* @param boolean $border turns on (true) cell borders. Useful for diagnosing layout difficulties, especially among the different browsers
*/
function SetDebug($mode=false, $border=false)
{
$this->debug_mode = $mode;
$this->debug_show_border = $border;
}
}; // end of class WhisperTable
// -------------------------------------------------------------------------------------------------------------------------
?>