tips:tableswithrowspans2
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tips:tableswithrowspans2 [2008-08-27 18:35] – 147.47.238.83 | tips:tableswithrowspans2 [2015-08-29 21:38] (current) – Aleksandr | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | =====Tables with rowspans and vertical alignment===== | ||
+ | >I hacked this together in a couple hours last night and it seems to be working correctly. Unfortunately, | ||
+ | |||
+ | By applying the code fixes listed here, you can create tables with rowspans each with their own vertical alignment. This patch does not alter the existing table syntax. To create a rowspan, the " | ||
+ | |||
+ | ====Features at a glance==== | ||
+ | * Compatible with 99.9% of existing DokuWiki tables. (How many tables have content that looks like ''/ | ||
+ | * Supports bidirectional spans. | ||
+ | * Supports '' | ||
+ | * Supports both header and non-header spans. | ||
+ | |||
+ | |||
+ | |||
+ | ====Usage==== | ||
+ | The following code should generate the HTML listed below: | ||
+ | < | ||
+ | ^ ^col 1 ^ col 2 ^ col 3&4^^ | ||
+ | ^row a |a1-b1 | ||
+ | ^row b& | ||
+ | ^/ | ||
+ | ^row d |d1 | d2 | d3| d4 | | ||
+ | </ | ||
+ | |||
+ | This 4x4 table (plus headers) has individual cells at a4, b4, c1, c4, d1, d2, d4, and d4.\\ | ||
+ | The top row and leftmost columns are header cells. c4 is also a header cell.\\ | ||
+ | There are 2 2-cell blocks, the one at row2&3 is bottom aligned and the one at a1-b1 is top aligned.\\ | ||
+ | There is a 6-cell block spanning a2, a3, b2, b3, c2 and c3 which is center aligned. | ||
+ | |||
+ | <code html> | ||
+ | < | ||
+ | <table class=" | ||
+ | < | ||
+ | <th valign=" | ||
+ | <th valign=" | ||
+ | <th class=" | ||
+ | <th class=" | ||
+ | </ | ||
+ | <th valign=" | ||
+ | <td class=" | ||
+ | <td class=" | ||
+ | <td valign=" | ||
+ | </ | ||
+ | <th rowspan=" | ||
+ | <td valign=" | ||
+ | </ | ||
+ | <th valign=" | ||
+ | <th valign=" | ||
+ | </ | ||
+ | <th valign=" | ||
+ | <td class=" | ||
+ | <td class=" | ||
+ | <td class=" | ||
+ | <td valign=" | ||
+ | </tr> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====Known Issues==== | ||
+ | * While you can have leading spaces in ghost columns, trailing spaces are forbidden. | ||
+ | * The colspan code makes sure all rows have the same number of columns but this code doesn' | ||
+ | * The '' | ||
+ | |||
+ | ====Patch Code==== | ||
+ | |||
+ | The patch involves 5 files in the '' | ||
+ | |||
+ | '' | ||
+ | <code php> | ||
+ | // Add this extra line to the indicated class/ | ||
+ | // | ||
+ | class Doku_Parser_Mode_table extends Doku_Parser_Mode { | ||
+ | |||
+ | function postConnect() { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | # | ||
+ | $this-> | ||
+ | // rowspan: | ||
+ | $this-> | ||
+ | // rowspan: | ||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | '' | ||
+ | <code php> | ||
+ | // In this file, we must modify the Doku_Handler and Doku_Handler_Table classes. | ||
+ | // These listings are | ||
+ | class Doku_Handler { | ||
+ | function table($match, | ||
+ | switch ( $state ) { | ||
+ | case DOKU_LEXER_MATCHED: | ||
+ | if ( $match == ' ' ){ | ||
+ | $this-> | ||
+ | } else if ( preg_match('/ | ||
+ | $this-> | ||
+ | } else if ( preg_match('/ | ||
+ | $this-> | ||
+ | } else if ( $match == " | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } else if ( $match == " | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } else if ( $match == ' | ||
+ | $this-> | ||
+ | } else if ( $match == ' | ||
+ | $this-> | ||
+ | // rowspan: | ||
+ | } else if ( substr($match, | ||
+ | $this-> | ||
+ | } else if ( substr($match, | ||
+ | $this-> | ||
+ | } else if ( substr($match, | ||
+ | $this-> | ||
+ | // rowspan: | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | |||
+ | |||
+ | // | ||
+ | class Doku_Handler_Table { | ||
+ | |||
+ | // | ||
+ | function process() { | ||
+ | foreach ( $this-> | ||
+ | switch ( $call[0] ) { | ||
+ | case ' | ||
+ | case ' | ||
+ | // rowspan: | ||
+ | case ' | ||
+ | // rowspan: | ||
+ | $this-> | ||
+ | break; | ||
+ | |||
+ | |||
+ | |||
+ | function tableCell($call) { | ||
+ | if ( !$this-> | ||
+ | $lastCall = end($this-> | ||
+ | | ||
+ | // rowspan: | ||
+ | if (count($call[1]) > 0) { | ||
+ | | ||
+ | } | ||
+ | // A cell call which follows an open cell means an empty cell so span | ||
+ | else if ( $lastCall[0] == ' | ||
+ | // rowspan: | ||
+ | | ||
+ | } | ||
+ | |||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | |||
+ | } else { | ||
+ | |||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | |||
+ | } | ||
+ | |||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | // rowspan: | ||
+ | // new function: finds a call in the tableCalls array | ||
+ | function _findCall($needle, | ||
+ | while (1) { | ||
+ | if ($key < 0 || $key >= count($this-> | ||
+ | return false; | ||
+ | } | ||
+ | | ||
+ | if ($this-> | ||
+ | return $key; | ||
+ | } | ||
+ | | ||
+ | $key += $dir; | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | // rowspan: | ||
+ | |||
+ | function finalizeTable() { | ||
+ | |||
+ | // Add the max cols and rows to the table opening | ||
+ | if ( $this-> | ||
+ | // Adjust to num cols not num col delimeters | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } else { | ||
+ | trigger_error(' | ||
+ | } | ||
+ | |||
+ | $lastRow = 0; | ||
+ | $lastCell = 0; | ||
+ | $toDelete = array(); | ||
+ | |||
+ | // Look for the colspan elements and increment the colspan on the | ||
+ | // previous non-empty opening cell. Once done, delete all the cells | ||
+ | // that contain colspans | ||
+ | foreach ( $this-> | ||
+ | |||
+ | if ( $call[0] == ' | ||
+ | |||
+ | $lastRow = $key; | ||
+ | |||
+ | } else if ( $call[0] == ' | ||
+ | |||
+ | $lastCell = $key; | ||
+ | |||
+ | } else if ( $call[0] == ' | ||
+ | |||
+ | // If the previous element was a cell open, align right | ||
+ | if ( $this-> | ||
+ | $this-> | ||
+ | |||
+ | // If the next element if the close of an element, align either center or left | ||
+ | } else if ( $this-> | ||
+ | if ( $this-> | ||
+ | $this-> | ||
+ | } else { | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | // Now convert the whitespace back to cdata | ||
+ | $this-> | ||
+ | |||
+ | } else if ( $call[0] == ' | ||
+ | |||
+ | $this-> | ||
+ | |||
+ | for($i = $key-2; $i > $lastRow; $i--) { | ||
+ | |||
+ | if ( $this-> | ||
+ | |||
+ | if ( false !== $this-> | ||
+ | $this-> | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $toDelete[] = $key-1; | ||
+ | $toDelete[] = $key; | ||
+ | $toDelete[] = $key+1; | ||
+ | | ||
+ | // rowspan: | ||
+ | } else if ( $call[0] == ' | ||
+ | |||
+ | $this-> | ||
+ | |||
+ | $colofs = $call[1][1]; | ||
+ | $rowstart = $this-> | ||
+ | for($i = $key-2; $i > $rowstart; $i--) { | ||
+ | if ( $this-> | ||
+ | $colofs += $this-> | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | $rowend = $rowstart-1; | ||
+ | while (($prevrow = $this-> | ||
+ | $colsleft = $colofs; | ||
+ | for ($i = $prevrow; $i < $rowend; ++$i) { | ||
+ | if ($this-> | ||
+ | if ($this-> | ||
+ | $colsleft = -1; | ||
+ | } else { | ||
+ | $colsleft -= $this-> | ||
+ | } | ||
+ | } | ||
+ | if ($colsleft == 0) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | break 2; | ||
+ | } else if ($colsleft < 0) { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | $rowend = $prevrow - 1; | ||
+ | } | ||
+ | |||
+ | $toDelete[] = $key-1; | ||
+ | $toDelete[] = $key; | ||
+ | $toDelete[] = $key+1; | ||
+ | } | ||
+ | // rowspan: | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | '' | ||
+ | <code php> | ||
+ | |||
+ | class Doku_Renderer extends DokuWiki_Plugin { | ||
+ | // we just need to add some parameters to these two functions | ||
+ | function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1, $valign = ' | ||
+ | |||
+ | function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1, $valign = ' | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | '' | ||
+ | <code php> | ||
+ | |||
+ | function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1, $valign = ' | ||
+ | $this-> | ||
+ | if ( !is_null($align) ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( !is_null($valign) ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( $rowspan > 1 ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( $colspan > 1 ) { | ||
+ | $this-> | ||
+ | } | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1, $valign = ' | ||
+ | $this-> | ||
+ | if ( !is_null($align) ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( !is_null($valign) ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( $rowspan > 1 ) { | ||
+ | $this-> | ||
+ | } | ||
+ | if ( $colspan > 1 ) { | ||
+ | $this-> | ||
+ | } | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | This version has some errors. | ||
+ | Like lower table : | ||
+ | < | ||
+ | ^ col1 ^ col2 ^ col3 ^ | ||
+ | | 2,1 | 2,2 | 2,3 | | ||
+ | |/\| 3,2 | 3,3 | | ||
+ | |/\|/-\| 4,3 | | ||
+ | |/\|/-\| 5,3 | | ||
+ | |/-\| 6,2 | 6,3 | | ||
+ | | 7,1 | 7,2 | 7,3 | | ||
+ | </ | ||
+ | |||
+ | So I changed(inc/ | ||
+ | <code php> | ||
+ | while (($prevrow = $this-> | ||
+ | $colsleft = $colofs; | ||
+ | for ($i = $prevrow; $i < $rowend; ++$i) { | ||
+ | // patch++ | ||
+ | if ($this-> | ||
+ | $colsleft -= $this-> | ||
+ | } | ||
+ | if ($colsleft == 0 && $this-> | ||
+ | // patch-- | ||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | break 2; | ||
+ | } else if ($colsleft < 0) { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | $rowend = $prevrow - 1; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== Discussion ====== | ||
+ | |||
+ | It's a bit complex to modify the code and is error prone, I wrote an article in http:// |
tips/tableswithrowspans2.txt · Last modified: 2015-08-29 21:38 by Aleksandr