=====Table Action===== >>==See also:== ~-Documentation: TableActionInfo ~-Discussion: WikkaTables and WikkaDevelopment >>This is the development page for the Table action.::c:: ===History=== The original ##Table## action available in Wikka was from IanAndolina's [[http://web.archive.org/web/20041214171813/http://nontroppo.org/wiki/WikiDev nontroppo wiki]] //(archived)//. ''Note: Searching on the web reveals that Ian is not the original author. Credit goes to [[http://web.archive.org/web/20040820214646/http://www.wakkawiki.com/IbuKi Michael Abendroth (IbuKi)]] for being the original author of [[http://web.archive.org/web/20040820215952/http://www.wakkawiki.com/IbukiTableAction IbukiTableAction @ WakkaWiki]].'' The original ##Table## action provides a nice way to create a simple HTML table. This ##Table## action has a number of drawbacks, however: ~1) It is awkward to use for anything but the most simple tables - mainly because it's an action, which is different from the common approach to table markup in many Wikis: Most [[WikiEngine]]s that support tables provide a table **markup** instead of a "plugin"-like solution like this. ~1) Cell contents can't have Wikka markup (if they do, the markup is shown as raw text instead of formatted). ~1) The action does not actually produce **data** table markup (which it should). ===Preliminary solution=== There is an ongoing discussion about providing true table markup in Wikka: ~-WikkaTables ~-WikkaDevelopment Clearly, we need a better solution than the current action, preferably (some kind of) true table markup syntax. However, it would be unwise to release a "preliminary" markup, as it could easily lead to confusion among our user base (as well as needless conversions down the line), and extra work for the developers. Instead, we should first determine what we want to be //able// to do in terms of table markup, and then look if we can find a simpler preliminary solution (as a //subset// of that markup) that still enables us to get there. And any preliminary solution should at least address the problem of ease-of-use **and** generating data table markup. So, until we have come to a clear conclusion about "Wikka table markup", we won't have a preliminary Wikka table markup either. Still, there is a clear (and sometimes pressing) need for an easier way to produce HTML tables from Wikka code. Therefore I've investigated whether it was possible to extend the **//current//** Table action to provide more flexibility and address the major drawbacks at least partially. I was glad to find it wasn't actually all that hard. I'm presenting here a rewrite of the Table action and a minor patch to the main wikka.php file (which could benefit other actions as well). It's far from a perfect solution for producing tables - but it's a lot more flexible and easier to use than the current table action. So I'm hoping this can tide us over until we embark on true table markup. ==Patch for ##./libs/Wakka.class.php##== Two very small changes in ##./libs/Wakka.class.php## are going to provide us with the framework that enables the new Table action to be much easier to use. Essentially, they make it possible to: ~- Write any **action** spanning multiple lines: this is especially handy for all actions that have many, or very long, parameters; ~- Allow the **content** of a parameter to span multiple lines. The second option, while very important for easy maintainability of Table action //content// (particularly, the cell contents), should be approached with caution however: currently (most? all?) actions are not written to take advantage of this. While the new Table action //is// written specifically to make use of this, other actions may actually fail if multi-line parameters are passed to them. Current action code won't fail, but **all** action code will need to be investigated (and maybe patched) if the new capability causes problems. In **##./libs/Wakka.class.php##**, find the **##Action##** function (line 981 in 1.1.6.3). Then replace this line: %%(php) preg_match("/^([A-Za-z0-9]*)\s+(.*)$/", $action, $matches);%%by this: %%(php) preg_match("/^([A-Za-z0-9]*)\s+(.*)$/s", $action, $matches);%% and replace this line: %%(php) preg_match_all("/([A-Za-z0-9]*)=\"(.*)\"/U", $vars_temp, $matches);%%by this: %%(php) preg_match_all("/([A-Za-z0-9]*)=\"(.*)\"/sU", $vars_temp, $matches);%% In both cases, all we do is add an '##s##' after the final '##/##' of the regular expression, which will make it match across multiple lines. The first change allows us to "recognize" an **action** that spans multiple lines (so you can put each parameter on a new line, if desired); the second change allows **parameter content** to span multiple lines (a parameter value must still be enclosed in double quotes to be recognized, though). ""Careful with the latter one: not all actions may be able to handle such multi-line parameter values!!"" ==New Table action== Starting with the current Table action, refactoring, refactoring, refactoring .... many of you won't be surprised that I ended up with a complete rewrite of the table action. It provides a lot more flexibility but is completely backwards-compatible with the current table action. Still, if you want to test only, I'd advise you to store the code under the name of **##table2.php##** rather than ##table.php## (as indicated below): that way you can test without influencing the operation of any current table actions on your Wikka site. Replace **##./actions/table.php##** with the following code (or save it as table2.php for testing): %%(php)'; $out .= '{{table '.$vars['wikka_vars'].'}}'; $out .= sprintf(' '.MISSING_PARAM, 'cells'); $out .= ''; } // all OK, let's go ahead else { // get delimiter first (escape chars that are special chars in REs) if (isset($vars['delimiter'])) { if (1 == strlen($vars['delimiter'])) $lDelim = addcslashes($vars['delimiter'],METACHARS); } elseif (isset($vars['delim'])) { if (1 == strlen($vars['delim'])) $lDelim = addcslashes($vars['delim'],METACHARS); } // process other parameters foreach ($vars as $param => $value) { // sanitize input $value = trim($value); while ($value != strip_tags($value)) $value = strip_tags($value); // parse input switch ($param) { case 'caption': $lCaption = $value; break; case 'columns': case 'cols': if (preg_match('/[0-9]+/',$value)) $lCols = $value; break; case 'border': if (preg_match('/[0-9]+/',$value)) $lBorder = $value; break; case 'cellpadding': if (preg_match('/[0-9]+/',$value)) $lPadding = $value; break; case 'cellspacing': if (preg_match('/[0-9]+/',$value)) $lSpacing = $value; break; case 'style': $lStyle = $value; break; case 'class': $lClass = $value; break; case 'summary': $lSummary = $value; break; case 'cells': // get rid of any surrounding delimiters if (preg_match('/(.*?)['.$lDelim.']+$/s',$value,$matches)) $value = $matches[1]; if (preg_match('/^['.$lDelim.']+(.*)/s',$value,$matches)) $value = $matches[1]; // split contents into array $cells = split($lDelim, $value); break; } } // start table $out = ''."\n"; $iCell = 0; foreach ($cells as $content) { // discard surrounding whitespace $content = trim($content); // start row if (($iCell % $lCols) == 0) $out .= "\n"; // process cells if ($content == EMPTY_CELL || $content == '') { $out .= " \n"; } elseif (preg_match('/={2,5}(.*?)={2,5}/',$content,$matches)) { $out .= ' \n"; } else { $out .= ' \n"; } // end row if ((++$iCell % $lCols) == 0) $out .= "\n"; } // end table $out .= "
 '.trim($this->Format($matches[1]))."'.trim($this->Format($content))."
\n"; } } else { $out = ''; $out .= '{{table}}'; $out .= sprintf(' '.MISSING_PARAM, 'cells'); $out .= ''; } echo $out; ?>%% ===Comments?=== See the TableActionInfo page for documentation and examples [later]. Please try out the various new options, and see if this helps with producing tables (as a //preliminary// solution). Comments and suggestions are welcome, as always. But please take into account that this is definitely not intended as a complete solution, only to tide us over until we get actual table **markup**. ---- ===A workaround for better table headers management=== I modified the table action adding the //header// parameter so a user can specify if he wants a normal table or a table with the first row rendered as ##th## or a table with the first row and the first cell of every row rendered as ##th##. %% {{table columns="3" cellpadding="1" cells="BIG;GREEN;FROGS;yes;yes;no;no;no;###" header="0"}} {{table columns="3" cellpadding="1" cells="BIG;GREEN;FROGS;yes;yes;no;no;no;###" header="1"}} {{table columns="3" cellpadding="1" cells="BIG;GREEN;FROGS;yes;yes;no;no;no;###" header="2"}} %% Go to [[http://wiki.smallpiece.info/WikkaTable my wiki]] to see it in action. This is the modified table action: %%(php) '3', 'cellpadding' => '1', 'cells' => '**BIG**;**GREEN**;**FROGS**;yes;yes;no;no;yes;yes'); // Init: $delimiter=';'; $empty_cell='###'; $row=1; $cellpadding=1; $cellspacing=1; $border=1; $columns=1; $header = 0; // this is the new parameter. the default value is 0 so if no parameter is defined there will be no table header $row_cont = 1; // this is a row counter // $style='border-spacing: 2px;border:2px outset #876;width:auto;margin:0 auto;'; $style=''; if (is_array($vars)) { foreach ($vars as $param => $value) { if ($param == 'style') {$style=$value;} if ($param == 'columns') {$columns=$value;} if ($param == 'header') {$header=$value;} if ($param == 'cellpadding') { $cellpadding=$value; $border=$value; } if ($param == 'cells') $cells = split($delimiter, $value); } $cached_output = "\n"; foreach ($cells as $cell_item) { if ($row == 1) $cached_output .= " \n"; if ($cell_item==$empty_cell) $cell_item='
'; // If we are not in the first row and header is set to 2 and if this is the first cell, then we render it as th if ($header == 2 && $row_cont > 1 && $row == 1 ) $cached_output .= " \n"; // If header is set to 1 or 2 and we are in the first row, then we rendere this row as a table header else if (($header == 1 || $header == 2) && $row_cont == 1) $cached_output .= " \n"; // Else we rendere normal table cells else $cached_output .= " \n"; $row ++; if ($row > $columns) { $row = "1"; $row_cont ++; // Let's count rows number $cached_output .= " \n"; } } $cached_output .= "
".$cell_item."".$cell_item."".$cell_item."
"; echo $this->ReturnSafeHTML($cached_output); } ?>%% -- AlessandroMelandri ---- CategoryDevelopmentActions