Hi, you find a file attached, which contains my changes for a new class (formated tables). It's a tar file, and it consists of 1. diff.txt: the diff to the current cvs version (changes in CHANGES and Documentation.sgml) 2. php/html/fmt_table.inc 3. sgml/05-fmt_tables.sgml 4. stuff/fmt_table.html (sample html output) Perhaps someone with write access to the repository could commit it for me. Thanks to Holger Bahr for help and to Matt Wong for his proposal (perhaps you could send some details of your solution) Michael -- GMX - Die Kommunikationsplattform im Internet. http://www.gmx.net
diff.txt 100644 0 0 3102 7263020534 10603 0 ustar root root ? doc/sgml/05-fmt_table.sgml ? php/html/fmt_table.inc ? stuff/fmt_table.html Index: CHANGES =================================================================== RCS file: /repository/php-lib/CHANGES,v retrieving revision 1.187 diff -u -r1.187 CHANGES --- CHANGES 2001/01/05 09:30:21 1.187 +++ CHANGES 2001/04/05 07:39:58 @@ -1,5 +1,12 @@ $Id: CHANGES,v 1.187 2001/01/05 09:30:21 max Exp $ +04-Mar-2001 + - Added class fmt_table.inc; + - added class documentation 05-fmt_table.sgml; + - changed documentation.sgml in order to include fmt_table.sgml; + - put fmt_table.html into stuff directory (sample html output of Fmt_Table) + 05-Jan-2001 max - Added user4.inc with User class that works with session4* session implementations. Index: doc/sgml/documentation.sgml =================================================================== RCS file: /repository/php-lib/doc/sgml/documentation.sgml,v retrieving revision 1.11 diff -u -r1.11 documentation.sgml --- doc/sgml/documentation.sgml 2000/02/24 23:33:02 1.11 +++ doc/sgml/documentation.sgml 2001/04/05 07:39:59 @@ -36,6 +36,7 @@ <!ENTITY f05widget SYSTEM "05-widget.sgml"> <!ENTITY f05sqlquery SYSTEM "05-sql_query.sgml"> <!ENTITY f05table SYSTEM "05-table.sgml"> + <!ENTITY f05fmttable SYSTEM "05-fmt_table.sgml"> <!ENTITY f05menu SYSTEM "05-menu.sgml"> <!ENTITY f05menu2 SYSTEM "05-menu2.sgml"> <!ENTITY f05form SYSTEM "05-form.sgml"> @@ -93,6 +94,7 @@ &f05widget; &f05sqlquery; &f05table; +&f05fmttable; &f05menu; &f05menu2; &f05form; doc/sgml/05-fmt_table.sgml 100644 44 144 17431 7262646274 14463 0 ustar adabas users <sect1>Fmt_Table <p> The Fmt_Table class is an extension of Table that allows you to pass content sensitive formating information to your html output. <p> The Fmt_Table class can be used to <itemize> <item>span rows, e.g. concatenate all rows with the same content; <item>span columns, e.g. concatenate fields in certain rows; <item>wrap the content of a cell with html tags, dependent on the value of this or other cells in the specific row, e.g. if the value is less than the one of the other column, you want to show it with red font color; <item>put html code into the opening tag of a cell, dependent on the value of this or other cells in the specific row, e.g. you want a different background color for some values. </itemize> For the user the main extension to Table is the function <tt/add_format()/, which takes the specific format conditions and format instructions for a column, an array of columns or, if desired, for all columns. Imagine a table that contains two numerical columns ,'expected' and 'obtained'. The following code will assign a different font color to those values in the 'obtained' column, which are less than the values in the 'expected' column. <p> <tscreen><code> $t->add_format(array('cols'=>'obtained' , 'conds'=>"([expected] > [])", 'formats'=>"<font color='red'>[]</font>")); </code></tscreen> <p> An empty pair of square brackets is a placeholder for the value of the column in question ( resp. for the html presentation of this value). The <tt/cols/ key of the format array also takes an array with a collection of column names or the special value <tt/ALL_COLUMNS/. If several columns are concerned, the placeholder always points to the value of each single column, which is traversed. <p> The <tt/conds/ key also might contain an array with several conditional expressions. In that case an array with a fitting number of format instructions has to be assigned to the <tt/formats/ key. Please see the example below. <p> The default for the <tt/conds/ key is <tt/true/, that means, all rows will hit. <p> The <tt/formats/ value(s) can contain the special <tt/met/ tag (my escape tag) for those values, that are directed to the cell opening tag. For example, a <tt/<met colspan=2>/ will span two columns together. In that case you need to apply the special expression <tt/<met MET_SKIP>/ in the column to be skipped, in order to assure a fitting number of columns in the row, where the <tt/colspan/ is applied. <p> The <tt/met/ tag is also the right place for text alignment and background color information. <p> <sect2>Additional instance variables <p> <table> <tabular ca=""> extrahtml<colsep>Takes html assignments for the table opening tag.<rowsep> suppress_empty<colsep>If set true, empty cells are filled with the <tt/&nbsp;/ special char (some explorers neglect the cell frame for empty cells). Default is <tt/false/<rowsep> row_span<colsep>Takes a field name or an array of field names which are concatenated (in case of identical values in consecutive rows).<rowsep> </tabular> <caption>Additional accessible instance variables.Only variables and functions additional to the Table class are listed. Please refer to the Table class documentation for further information. </caption> </table> <sect2>Additional instance methods <p> <descrip> <tag>add_format($ary)</tag> <p> Will add format conditions and format instructions to the table. The array <tt/$ary/ shall consist of the keys <itemize> <item><tt/cols/ (value is a field name, an array of field names or the special value <tt/ALL_COLUMNS/), <item><tt/conds/ (value is a conditional expression or an array of conditional expressions, which probably will involve the value of the cell(s), for which the format applies) and finally <item><tt/formats/, which will contain a format instruction (or an array of format instructions), which is applied to the cell in case of succesful validation of <tt/conds/. </itemize> <sect2>Example <p> Since the functionality of this class is best explained with approbiate data, the data objects for this example are outlined. The example makes use of the DB_Sql class of phplib. <p> <tscreen><code> // sql, that goes into the database first; // your sql-loader might expect a semi-colon after each command // drop table sales // create table sales ( category varchar (32), product varchar (32), expected fixed (5,2), obtained fixed (5,2) ) // insert into sales values ('sports','hoola hoops',103.56, 0) // insert into sales values ('sports','mountain bikes',155.88, 87.22) // insert into sales values ('sports','surf boards',106.56, 106.56) // insert into sales values ('entertainment','books',75.65, 109.44) // insert into sales values ('entertainment','videos',99.88, 82.34) // create view sales_view as select 10 as order1, 10 as order2, category, product, expected, obtained, obtained - expected as difference from sales union select 10 as order1, 20 as order2, category, '' as product, sum (expected) as expected, sum (obtained) as obtained, sum (obtained - expected) as difference from sales group by category union select 20 as order1, 10 as order2, '' as category, '' as product, sum (expected) as expected, sum (obtained) as obtained, sum (obtained - expected) as difference from sales // grant select on sales_view to wwwrun // commit </code></tscreen> <p> A view object is used for the computation of our provisional and final results. Here also the help fields <tt/order1/ and <tt/order2/ are introduced, that will constitute the proper order of details and results and will serve as an hook to some format conditions. The user <tt/wwwrun/ is the database user account for the DB_Sql class to access the database. The dedicated part of your php script may look like this: <tscreen><code> require("fmt_table.inc"); $db = new DB_Sql_1; $q = " select * from sales_view " . " order by order1, category, order2, product"; $db->query($q); $t = new Fmt_Table; $t->heading = "on"; $t->suppress_empty = true; $t->extrahtml = "border width = 100%"; $t->fields=array("category","product","expected","obtained","difference"); $t->add_format(array('cols'=>"obtained" , 'conds'=>array("(([]==0)or([expected]==[]))", "([expected] < [])", "([expected] > [])"), 'formats'=>array("<font color='blue'>[]</font>", "<font color='green'>[]</font>", "<font color='red'>[]</font>"))); $t->add_format(array('cols'=>"category", 'conds'=>"[order1] == 20", 'formats'=>"<met colspan=2 align='right'>Overall sum:")); $t->add_format(array('cols'=>"product", 'conds'=>"[order1] == 20", 'formats'=>"<met MET_SKIP>")); $t->add_format(array('cols'=>"product", 'conds'=>"[order2] == 20", 'formats'=>"<met align='right'>Sum of [category]:")); $t->add_format(array('cols'=>"difference", 'conds'=>"[obtained] == 0", 'formats'=>"<i>No Sales</i>")); $t->add_format(array('cols'=>"ALL_COLUMNS", 'conds'=>"[order1] == 20", 'formats'=>"<met bgcolor='pink'><b>[]</b>")); $t->add_format(array("cols"=>"ALL_COLUMNS", "conds"=>"[order2] == 20", "formats"=>"<met bgcolor='lightyellow'><b>[]</b>")); $t->row_span = "category"; $t->show_result($db); </code></tscreen> For an impression on how the html output does look like, see the file <tt/fmt_table.html/ in the <tt/stuff/ directory of the php-lib installation. php/html/fmt_table.inc 100644 44 144 26117 7262632704 14066 0 ustar adabas users <?php /************************************************************************ * class Fmt_Table extends Table { * extra functionality for content sensitive formating of cells; * all additional formating information is done in html instead of css; * Copyright (c) 2000,2001 by Michael Kuehne [EMAIL PROTECTED] * ************************************************************************/ class Fmt_Table extends Table { var $extrahtml; var $col_func = array(); var $suppress_empty=false; var $row_span = false; var $span_ary = array(); var $headline_wrap; /************************************************************************ * function show_headline($headline){ * extra function for display of a headline above the table * ************************************************************************/ function show_headline($headline){ printf ($this->headline_wrap, $headline); } /************************************************************************ * function table_open($class=""){ * prints table header with extra html * ************************************************************************/ function table_open($class=""){ printf("<table $this->extrahtml %s>\n", $class?" class=$class":""); } /************************************************************************ * function show_info($db, $class =""){ * shows a query result (only 1 dataset allowed) as rotated table; * usefull for header information in 1:n - relations * ************************************************************************/ function show_info($db, $class =""){ if ($db->num_rows() > 1) { echo ("error in function show_info: more than 1 dataset!"); return; } $db->next_record(); $ary = array(); $ary_inv = array(); $ary[] = $db->Record; while(list($key,$val) = each($ary[0])){ if (is_numeric($key)){continue;} if ($this->verify_array($this->map_cols)){ reset($this->map_cols); while(list($mkey, $name) = each($this->map_cols)) { if ($mkey == $key){ $key = $name; $found = 1; break; } } } $t_ary["Attrib"] = $key; $t_ary["Value"] = $val; $ary_inv[] = $t_ary; } $this->show($ary_inv, $class); } /************************************************************************ * function load_into_array($db) * loads query result into array; necessary, since we work here * with the table::show() function instead of table::show_result() * ************************************************************************/ function load_into_array($db) { if (!$this->verify_db($db)) return 0; $ary = array(); while ($db->next_record()){ $ary[] = $db->Record; } reset ($ary); return $ary; } /************************************************************************ * function span ($ary) { * checks results in the row(s) to span and prepares an array with * the approbiate spanning information * ************************************************************************/ function span ($ary) { if (!$this->row_span) { return 0 ; } $cols = is_array ($this->row_span) ? $this->row_span : array ($this->row_span); $this->span_ary = $ary; while (list ($colkey, $col) = each ($cols)){ reset ($this->span_ary); $distval = ""; $distkey = 0; $num_distrow = 0; $row = 0; while (list ($rowkey, $rowval) = each ($this->span_ary)) { $row++; $num_distrow++; if ($rowval [$col] == $distval) { $this->span_ary[$rowkey][$col] = -1; } else { $this->span_ary [$distkey] [$col] = $num_distrow; $num_distrow = 0; $distkey = $row - 1; $distval = $rowval [$col]; } } } } /************************************************************************ * function add_format ($ary) { * used for passing format information to the col_func - array * ************************************************************************/ function add_format ($ary) { if (!is_array($ary)) return false; $ary['conds']=$ary['conds']?$ary['conds']:true; $this->col_func[] = $ary; } /************************************************************************ * function show_result($db, $class="") { * similar functionality like table::show_result * ************************************************************************/ function show_result($db, $class="") { if (!$this->verify_db($db)) return 0; $ary = $this->load_into_array($db); $this->show($ary, $class); } /************************************************************************ * function show($ary, $class=""){ * contains additional functionality; calls table::show() * ************************************************************************/ function show($ary, $class=""){ if (!$this->verify_2d_array($ary)) return 0; $this->span ($ary); while (list($rowkey, $rowval) = each ($ary)){ while (list ($cellkey, $cellval) = each ($rowval)){ if (is_array($this->col_func)){ reset($this->col_func); while (list($funckey,$funcval) = each($this->col_func)){ if (($cellkey != '0') and (($funcval['cols'] == "ALL_COLUMNS") or (strcmp($cellkey,$funcval['cols'])== 0) or (is_array($funcval['cols']) and in_array($cellkey, $funcval['cols'])))){ $AryCondition = $funcval['conds']; $AryFormatExpression = $funcval['formats']; if (!is_array($AryCondition)){ $AryCondition = array($AryCondition); $AryFormatExpression = array($AryFormatExpression); } while (list($condkey, $Condition) = each ($AryCondition)){ $Condition = ereg_replace ("\[\]", '$cellval', $Condition); if (ereg("(\[(.*)\])",$Condition, $regs)) $Condition = ereg_replace ("(\[.*\])", $rowval[$regs[2]], $Condition); eval("\$f = ($Condition);"); if ($f){ $expstr = "\"$AryFormatExpression[$condkey]\""; $expstr = ereg_replace ("\[\]", "\$cellval", $expstr); if (ereg("(\[(.*)\])",$expstr, $regs)) $expstr = ereg_replace ("(\[.*\])", $rowval[$regs[2]], $expstr); eval("\$cellval = ($expstr);"); break; } } } } $ary[$rowkey][$cellkey] = sprintf("%s", $cellval); } if ($this->suppress_empty and strlen(strip_tags($cellval)) == 0){ $ary[$rowkey][$cellkey].= sprintf(" " ); } } } reset ($ary); $rows = 0; $this->table_open($class); if ($this->show_table_heading_row($ary, $class)) $rows = $this->show_table_rows($ary, $class); $this->table_close($class); return $rows; } /************************************************************************ * function table_cell($row, $col, $key, $val, $class="") * contains additional functionality; calls table::table_cell() * ************************************************************************/ function table_cell($row, $col, $key, $val, $class="") { if ($this->row_span) { $cols = is_array ($this->row_span) ? $this->row_span : array ($this->row_span); if (in_array ($key, $cols)) { $nbrows = $this->span_ary [$row] [$key]; if ($nbrows == -1) return; else { $extra .= " rowspan=$nbrows valign=top "; } } } if (preg_match_all("|<met(.*)>|Ui",$val, $regs, PREG_PATTERN_ORDER)){ while (list($regkey, $regval) = each($regs[1])){ if (ereg('MET_SKIP',$regval)) { return; } $extra .= " $regval"; } } $this->table_cell_open($class, $extra); printf("%s", $val); $this->table_cell_close($class); } /************************************************************************ * function table_cell_open($class="", $extra="") * outputs html tag for table cell open + additional html * ************************************************************************/ function table_cell_open($class="", $extra="") { printf(" <td %s%s>", $extra, $class?" class=$class":""); } /************************************************************************ * function table_heading_cell($col, $val, $class="") { * checks whether column will be shown, outputs html for * table heading cell + extra html * ************************************************************************/ function table_heading_cell($col, $val, $class="") { //Check for column name remapping if ($this->verify_array($this->map_cols)) { reset($this->map_cols); while(list($key, $name) = each($this->map_cols)) { if ($key == $val) { $val = $name; $found = 1; break; } } } if (preg_match_all("|<met(.*)>|Ui",$val, $regs, PREG_PATTERN_ORDER)){ while (list($regkey, $regval) = each($regs[1])){ if (ereg('MET_SKIP',$regval)) { return; } $extra .= "$regval"; } } $this->table_heading_cell_open($class, $extra); printf("%s", $val); $this->table_heading_cell_close($class); } /************************************************************************ * function table_heading_cell_open($class="", $extra="") { * outputs opening tag for table heading cell + extra html * ************************************************************************/ function table_heading_cell_open($class="", $extra="") { printf(" <th %s%s>", $extra, $class?" class=$class":""); } /************************************************************************ * function table_heading_row_add_extra($data, $class=""){ * outputs an additional heading cell * overload ************************************************************************/ function table_heading_row_add_extra($data, $class=""){ $this->table_heading_cell(0, " ", $class); } /************************************************************************ * function table_row_add_extra($row, $row_key, $data, $class=""){ * outputs an additional cell * overload ************************************************************************/ function table_row_add_extra($row, $row_key, $data, $class=""){ $this->table_cell($row, $col, $key, $data, $class=""); } } ?>