← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:10 2015

Filename/var/www/foswiki11/lib/Foswiki/Plugins/TablePlugin/Core.pm
StatementsExecuted 625 statements in 9.43ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
511671µs1.77msFoswiki::Plugins::TablePlugin::Core::::handlerFoswiki::Plugins::TablePlugin::Core::handler
621205µs205µsFoswiki::Plugins::TablePlugin::Core::::_mergeHashesFoswiki::Plugins::TablePlugin::Core::_mergeHashes
111174µs311µsFoswiki::Plugins::TablePlugin::Core::::_parseAttributesFoswiki::Plugins::TablePlugin::Core::_parseAttributes
511110µs327µsFoswiki::Plugins::TablePlugin::Core::::_resetReusedVariablesFoswiki::Plugins::TablePlugin::Core::_resetReusedVariables
135165µs96µsFoswiki::Plugins::TablePlugin::Core::::_debugFoswiki::Plugins::TablePlugin::Core::_debug
2323147µs47µsFoswiki::Plugins::TablePlugin::Core::::_storeAttributeFoswiki::Plugins::TablePlugin::Core::_storeAttribute
11129µs383µsFoswiki::Plugins::TablePlugin::Core::::_initDefaultsFoswiki::Plugins::TablePlugin::Core::_initDefaults
66122µs22µsFoswiki::Plugins::TablePlugin::Core::::_arrayRefFromParamFoswiki::Plugins::TablePlugin::Core::_arrayRefFromParam
11121µs155µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@11Foswiki::Plugins::TablePlugin::Core::BEGIN@11
11116µs29µsFoswiki::Plugins::TablePlugin::::BEGIN@3 Foswiki::Plugins::TablePlugin::BEGIN@3
11114µs30µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@1728Foswiki::Plugins::TablePlugin::Core::BEGIN@1728
11112µs23µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@1730Foswiki::Plugins::TablePlugin::Core::BEGIN@1730
11111µs11µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@10Foswiki::Plugins::TablePlugin::Core::BEGIN@10
11111µs327µsFoswiki::Plugins::TablePlugin::Core::::_parseDefaultAttributesFoswiki::Plugins::TablePlugin::Core::_parseDefaultAttributes
11110µs17µsFoswiki::Plugins::TablePlugin::::BEGIN@4 Foswiki::Plugins::TablePlugin::BEGIN@4
2219µs16µsFoswiki::Plugins::TablePlugin::Core::::_debugDataFoswiki::Plugins::TablePlugin::Core::_debugData
1116µs6µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@8Foswiki::Plugins::TablePlugin::Core::BEGIN@8
1116µs14µsFoswiki::Plugins::TablePlugin::Core::::_initFoswiki::Plugins::TablePlugin::Core::_init
2214µs4µsFoswiki::Plugins::TablePlugin::Core::::_cleanParamValueFoswiki::Plugins::TablePlugin::Core::_cleanParamValue
1114µs4µsFoswiki::Plugins::TablePlugin::Core::::BEGIN@9Foswiki::Plugins::TablePlugin::Core::BEGIN@9
0000s0sFoswiki::Plugins::TablePlugin::Core::::__ANON__[:1012]Foswiki::Plugins::TablePlugin::Core::__ANON__[:1012]
0000s0sFoswiki::Plugins::TablePlugin::Core::::__ANON__[:481]Foswiki::Plugins::TablePlugin::Core::__ANON__[:481]
0000s0sFoswiki::Plugins::TablePlugin::Core::::__ANON__[:486]Foswiki::Plugins::TablePlugin::Core::__ANON__[:486]
0000s0sFoswiki::Plugins::TablePlugin::Core::::_addDefaultStylesFoswiki::Plugins::TablePlugin::Core::_addDefaultStyles
0000s0sFoswiki::Plugins::TablePlugin::Core::::_addHeadStylesFoswiki::Plugins::TablePlugin::Core::_addHeadStyles
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendColNumberCssClassFoswiki::Plugins::TablePlugin::Core::_appendColNumberCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendFirstColumnCssClassFoswiki::Plugins::TablePlugin::Core::_appendFirstColumnCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendLastColumnCssClassFoswiki::Plugins::TablePlugin::Core::_appendLastColumnCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendLastRowCssClassFoswiki::Plugins::TablePlugin::Core::_appendLastRowCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendRowNumberCssClassFoswiki::Plugins::TablePlugin::Core::_appendRowNumberCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendSortedAscendingCssClassFoswiki::Plugins::TablePlugin::Core::_appendSortedAscendingCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendSortedCssClassFoswiki::Plugins::TablePlugin::Core::_appendSortedCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendSortedDescendingCssClassFoswiki::Plugins::TablePlugin::Core::_appendSortedDescendingCssClass
0000s0sFoswiki::Plugins::TablePlugin::Core::::_appendToClassListFoswiki::Plugins::TablePlugin::Core::_appendToClassList
0000s0sFoswiki::Plugins::TablePlugin::Core::::_convertStringToDateFoswiki::Plugins::TablePlugin::Core::_convertStringToDate
0000s0sFoswiki::Plugins::TablePlugin::Core::::_convertStringToNumberFoswiki::Plugins::TablePlugin::Core::_convertStringToNumber
0000s0sFoswiki::Plugins::TablePlugin::Core::::_createCssStylesFoswiki::Plugins::TablePlugin::Core::_createCssStyles
0000s0sFoswiki::Plugins::TablePlugin::Core::::_getCurrentSortDirectionFoswiki::Plugins::TablePlugin::Core::_getCurrentSortDirection
0000s0sFoswiki::Plugins::TablePlugin::Core::::_getDefaultSortDirectionFoswiki::Plugins::TablePlugin::Core::_getDefaultSortDirection
0000s0sFoswiki::Plugins::TablePlugin::Core::::_getImageTextForSortingFoswiki::Plugins::TablePlugin::Core::_getImageTextForSorting
0000s0sFoswiki::Plugins::TablePlugin::Core::::_getIncludeParamsFoswiki::Plugins::TablePlugin::Core::_getIncludeParams
0000s0sFoswiki::Plugins::TablePlugin::Core::::_getNewSortDirectionFoswiki::Plugins::TablePlugin::Core::_getNewSortDirection
0000s0sFoswiki::Plugins::TablePlugin::Core::::_headerRowCountFoswiki::Plugins::TablePlugin::Core::_headerRowCount
0000s0sFoswiki::Plugins::TablePlugin::Core::::_parseTableSpecificTableAttributesFoswiki::Plugins::TablePlugin::Core::_parseTableSpecificTableAttributes
0000s0sFoswiki::Plugins::TablePlugin::Core::::_processTableRowFoswiki::Plugins::TablePlugin::Core::_processTableRow
0000s0sFoswiki::Plugins::TablePlugin::Core::::_setSortTypeForCellsFoswiki::Plugins::TablePlugin::Core::_setSortTypeForCells
0000s0sFoswiki::Plugins::TablePlugin::Core::::_stripHtmlFoswiki::Plugins::TablePlugin::Core::_stripHtml
0000s0sFoswiki::Plugins::TablePlugin::Core::::_writeStyleToHeadFoswiki::Plugins::TablePlugin::Core::_writeStyleToHead
0000s0sFoswiki::Plugins::TablePlugin::Core::::addDefaultSizeUnitFoswiki::Plugins::TablePlugin::Core::addDefaultSizeUnit
0000s0sFoswiki::Plugins::TablePlugin::Core::::emitTableFoswiki::Plugins::TablePlugin::Core::emitTable
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3231µs243µs
# spent 29µs (16+14) within Foswiki::Plugins::TablePlugin::BEGIN@3 which was called: # once (16µs+14µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 3
use strict;
# spent 29µs making 1 call to Foswiki::Plugins::TablePlugin::BEGIN@3 # spent 14µs making 1 call to strict::import
4234µs224µs
# spent 17µs (10+7) within Foswiki::Plugins::TablePlugin::BEGIN@4 which was called: # once (10µs+7µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 4
use warnings;
# spent 17µs making 1 call to Foswiki::Plugins::TablePlugin::BEGIN@4 # spent 7µs making 1 call to warnings::import
5
6package Foswiki::Plugins::TablePlugin::Core;
7
8226µs16µs
# spent 6µs within Foswiki::Plugins::TablePlugin::Core::BEGIN@8 which was called: # once (6µs+0s) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 8
use Foswiki::Func;
# spent 6µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@8
9222µs14µs
# spent 4µs within Foswiki::Plugins::TablePlugin::Core::BEGIN@9 which was called: # once (4µs+0s) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 9
use Foswiki::Plugins::TablePlugin ();
# spent 4µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@9
10243µs111µs
# spent 11µs within Foswiki::Plugins::TablePlugin::Core::BEGIN@10 which was called: # once (11µs+0s) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 10
use Foswiki::Time;
# spent 11µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@10
1126.57ms2290µs
# spent 155µs (21+135) within Foswiki::Plugins::TablePlugin::Core::BEGIN@11 which was called: # once (21µs+135µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 11
use Error qw(:try);
# spent 155µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@11 # spent 135µs making 1 call to Error::import
12
131300nsmy @curTable;
141100nsmy $translationToken;
151100nsmy $insideTABLE;
161100nsmy $currTablePre;
171100nsmy $didWriteDefaultStyle;
181100nsmy $defaultAttrs; # to write generic table CSS
191100nsmy $tableSpecificAttrs; # to write table specific table CSS
201100nsmy $combinedTableAttrs; # default and specific table attributes
211800nsmy $styles = {}; # hash of default and specific styles
221600nsmy @messages = ();
23
24# not yet refactored:
251100nsmy $tableCount;
261100nsmy $sortCol;
271100nsmy $MAX_SORT_COLS;
281100nsmy $requestedTable;
291100nsmy $up;
301100nsmy $sortTablesInText;
311100nsmy $sortAttachments;
321100nsmy $sortColFromUrl;
3310smy $url;
3410smy $currentSortDirection;
3510smy @rowspan;
36
371500nsmy $HEAD_ID_DEFAULT_STYLE =
38 'TABLEPLUGIN_default'; # this name is part of the API, do not change
391200nsmy $HEAD_ID_SPECIFIC_STYLE =
40 'TABLEPLUGIN_specific'; # this name is part of the API, do not change
41
4212µsmy $PATTERN_TABLE = qr/%TABLE(?:{(.*?)})?%/;
4314µs13µsmy $URL_ICON =
# spent 3µs making 1 call to Foswiki::Func::getPubUrlPath
44 Foswiki::Func::getPubUrlPath() . '/'
45 . $Foswiki::cfg{SystemWebName}
46 . '/DocumentGraphics/';
4719µs1237µsmy $GIF_TABLE_SORT_ASCENDING = CGI::img(
# spent 237µs making 1 call to CGI::AUTOLOAD
48 {
49 src => $URL_ICON . 'tablesortup.gif',
50 border => 0,
51 width => 11,
52 height => 13,
53 alt => 'Sorted ascending',
54 title => 'Sorted ascending'
55 }
56);
57
5815µs159µsmy $GIF_TABLE_SORT_DESCENDING = CGI::img(
# spent 59µs making 1 call to CGI::img
59 {
60 src => $URL_ICON . 'tablesortdown.gif',
61 border => 0,
62 width => 11,
63 height => 13,
64 alt => 'Sorted descending',
65 title => 'Sorted descending'
66 }
67);
68
6914µs157µsmy $GIF_TABLE_SORT_BOTH = CGI::img(
# spent 57µs making 1 call to CGI::img
70 {
71 src => $URL_ICON . 'tablesortdiamond.gif',
72 border => 0,
73 width => 11,
74 height => 13,
75 alt => 'Sort',
76 title => 'Sort'
77 }
78);
7914µs1210µsmy $CHAR_SORT_ASCENDING = CGI::span( { class => 'tableSortIcon tableSortUp' },
# spent 210µs making 1 call to CGI::AUTOLOAD
80 $GIF_TABLE_SORT_ASCENDING );
8113µs136µsmy $CHAR_SORT_DESCENDING =
# spent 36µs making 1 call to CGI::span
82 CGI::span( { class => 'tableSortIcon tableSortDown' },
83 $GIF_TABLE_SORT_DESCENDING );
8412µs128µsmy $CHAR_SORT_BOTH =
# spent 28µs making 1 call to CGI::span
85 CGI::span( { class => 'tableSortIcon tableSortUp' }, $GIF_TABLE_SORT_BOTH );
86
8711µsmy $SORT_DIRECTION = {
88 'ASCENDING' => 0,
89 'DESCENDING' => 1,
90 'NONE' => 2,
91};
92
9312µsmy $PATTERN_ATTRIBUTE_SIZE = qr'([0-9]+)(px|%)*'o;
94
951300nsmy $TABLE_RULES = {};
9613µs$TABLE_RULES->{all}->{TD} = $TABLE_RULES->{all}->{TH} =
97 $TABLE_RULES->{data_all}->{TD} = $TABLE_RULES->{header_all}->{TH} =
98 'border-style:solid';
9912µs$TABLE_RULES->{none}->{TD} = $TABLE_RULES->{none}->{TH} =
100 $TABLE_RULES->{data_none}->{TD} = $TABLE_RULES->{header_none}->{TH} =
101 'border-style:none';
10212µs$TABLE_RULES->{cols}->{TD} = $TABLE_RULES->{cols}->{TH} =
103 $TABLE_RULES->{data_cols}->{TD} = $TABLE_RULES->{header_cols}->{TH} =
104 'border-style:none solid';
10512µs$TABLE_RULES->{rows}->{TD} = $TABLE_RULES->{rows}->{TH} =
106 $TABLE_RULES->{data_rows}->{TD} = $TABLE_RULES->{header_rows}->{TH} =
107 'border-style:solid none';
1081500ns$TABLE_RULES->{groups}->{TD} = 'border-style:none';
1091500ns$TABLE_RULES->{groups}->{TH} = 'border-style:solid none';
110
1111200nsmy $TABLE_FRAME = {};
1121400ns$TABLE_FRAME->{void} = 'border-style:none';
1131400ns$TABLE_FRAME->{above} = 'border-style:solid none none none';
1141300ns$TABLE_FRAME->{below} = 'border-style:none none solid none';
1151400ns$TABLE_FRAME->{lhs} = 'border-style:none none none solid';
1161300ns$TABLE_FRAME->{rhs} = 'border-style:none solid none none';
1171300ns$TABLE_FRAME->{hsides} = 'border-style:solid none solid none';
1181300ns$TABLE_FRAME->{vsides} = 'border-style:none solid none solid';
1191700ns$TABLE_FRAME->{box} = 'border-style:solid';
1201300ns$TABLE_FRAME->{border} = 'border-style:solid';
121
122
# spent 14µs (6+8) within Foswiki::Plugins::TablePlugin::Core::_init which was called: # once (6µs+8µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 70 of /var/www/foswiki11/lib/Foswiki/Plugins/TablePlugin.pm
sub _init {
1231900ns18µs _debug("_init");
# spent 8µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_debug
1241400ns $translationToken = "\0";
125
126 # the maximum number of columns we will handle
1271200ns $MAX_SORT_COLS = 10000;
1281200ns $didWriteDefaultStyle = 0;
1291100ns $tableCount = 0;
1301200ns $currTablePre = '';
1311300ns $combinedTableAttrs = {};
1321200ns $tableSpecificAttrs = {};
13313µs $styles = {};
134}
135
136# called one time
137
# spent 383µs (29+355) within Foswiki::Plugins::TablePlugin::Core::_initDefaults which was called: # once (29µs+355µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1896
sub _initDefaults {
1381800ns15µs _debug('_initDefaults');
# spent 5µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_debug
13912µs $defaultAttrs = {
140 headerrows => 0,
141 footerrows => 0,
142 sort => 1,
143 class => 'foswikiTable',
144 sortAllTables => $sortTablesInText,
145 };
146117µs1327µs _parseDefaultAttributes(
147 %{Foswiki::Plugins::TablePlugin::pluginAttributes} );
148
14915µs122µs $combinedTableAttrs = _mergeHashes( {}, $defaultAttrs );
# spent 22µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_mergeHashes
150}
151
152sub _addDefaultStyles {
153 return if $Foswiki::Plugins::TablePlugin::writtenToHead;
154 $Foswiki::Plugins::TablePlugin::writtenToHead = 1;
155
156 # create CSS styles tables in general
157 my ( $id, @styles ) = _createCssStyles( 1, $defaultAttrs );
158 _addHeadStyles( $HEAD_ID_DEFAULT_STYLE, @styles ) if scalar @styles;
159}
160
161
# spent 327µs (110+217) within Foswiki::Plugins::TablePlugin::Core::_resetReusedVariables which was called 5 times, avg 65µs/call: # 5 times (110µs+217µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1934, avg 65µs/call
sub _resetReusedVariables {
16256µs535µs _debug('_resetReusedVariables');
# spent 35µs making 5 calls to Foswiki::Plugins::TablePlugin::Core::_debug, avg 7µs/call
16352µs $currTablePre = '';
164556µs5182µs $combinedTableAttrs = _mergeHashes( {}, $defaultAttrs );
# spent 182µs making 5 calls to Foswiki::Plugins::TablePlugin::Core::_mergeHashes, avg 36µs/call
16553µs $tableSpecificAttrs = {};
16651µs $sortCol = 0;
167521µs @messages = ();
168}
169
170=pod
171
172=cut
173
174
# spent 47µs within Foswiki::Plugins::TablePlugin::Core::_storeAttribute which was called 23 times, avg 2µs/call: # once (5µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 379 # once (3µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 384 # once (3µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 319 # once (3µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 253 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 364 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 359 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 274 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 376 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 382 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 365 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 320 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 324 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 366 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 361 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 377 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 322 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 378 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 323 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 367 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 392 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 370 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 389 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 373
sub _storeAttribute {
1752312µs my ( $inAttrName, $inValue, $inCollection ) = @_;
176
177233µs if ( !$inCollection ) {
178 _debug('_storeAttribute -- missing inCollection!');
179 return;
180 }
1812350µs return if !defined $inValue;
182102µs return if !defined $inAttrName || $inAttrName eq '';
1831039µs $inCollection->{$inAttrName} = $inValue;
184}
185
186=pod
187
188=cut
189
190
# spent 327µs (11+316) within Foswiki::Plugins::TablePlugin::Core::_parseDefaultAttributes which was called: # once (11µs+316µs) by Foswiki::Plugins::TablePlugin::Core::_initDefaults at line 146
sub _parseDefaultAttributes {
19114µs my (%params) = @_;
192
1931900ns15µs _debug('_parseDefaultAttributes');
# spent 5µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_debug
194
19514µs1311µs _parseAttributes( 0, $defaultAttrs, \%params );
196}
197
198=pod
199
200=cut
201
202sub _parseTableSpecificTableAttributes {
203 my (%params) = @_;
204
205 _debug('_parseTableSpecificTableAttributes');
206
207 _parseAttributes( 1, $tableSpecificAttrs, \%params );
208
209 # remove default values from hash
210 while ( my ( $key, $value ) = each %{$tableSpecificAttrs} ) {
211 delete $tableSpecificAttrs->{$key}
212 if $defaultAttrs->{$key} && $value eq $defaultAttrs->{$key};
213 }
214 $combinedTableAttrs =
215 _mergeHashes( $combinedTableAttrs, $tableSpecificAttrs );
216 _debugData( 'combinedTableAttrs', $combinedTableAttrs );
217
218 # create CSS styles for this table only
219 my ( $id, @styles ) = _createCssStyles( 0, $tableSpecificAttrs );
220 _debugData( "after _createCssStyles, id=$id; styles", \@styles );
221
222 _addHeadStyles( $id, @styles ) if scalar @styles;
223
224 return $currTablePre . '<nop>';
225}
226
227=pod
228
229=cut
230
231
# spent 311µs (174+137) within Foswiki::Plugins::TablePlugin::Core::_parseAttributes which was called: # once (174µs+137µs) by Foswiki::Plugins::TablePlugin::Core::_parseDefaultAttributes at line 195
sub _parseAttributes {
2321500ns my ( $isTableSpecific, $inCollection, $inParams ) = @_;
233
23412µs111µs _debugData( "isTableSpecific=$isTableSpecific; _parseAttributes=",
# spent 11µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_debugData
235 $inParams );
236
237 # include topic to read definitions
2381400ns if ( $inParams->{include} ) {
239 my ( $includeParams, $message ) =
240 _getIncludeParams( $inParams->{include} );
241
242 if ($includeParams) {
243 $inParams = $includeParams;
244 }
245 if ($message) {
246 push( @messages, $message );
247 }
248 }
249
250 # table attributes
251 # some will be used for css styling as well
252
25314µs219µs _storeAttribute( 'generateInlineMarkup',
# spent 16µs making 1 call to Foswiki::Func::isTrue # spent 3µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_storeAttribute
254 Foswiki::Func::isTrue( $inParams->{inlinemarkup} ),
255 $inCollection )
256 if defined $inParams->{inlinemarkup};
257
258 # sort attributes
2591400ns if ( defined $inParams->{sort} ) {
260 my $sort = Foswiki::Func::isTrue( $inParams->{sort} );
261 _storeAttribute( 'sort', $sort, $inCollection );
262 _storeAttribute( 'sortAllTables', $sort, $inCollection );
263 }
2641300ns if ( defined( $inParams->{initsort} )
265 and int( $inParams->{initsort} ) > 0 )
266 {
267 _storeAttribute( 'initSort', $inParams->{initsort}, $inCollection );
268
269 # override sort attribute: we are sorting after all
270 _storeAttribute( 'sort', 1, $inCollection );
271 }
272
2731600ns if ( $inParams->{initdirection} ) {
27412µs12µs _storeAttribute( 'initDirection', $SORT_DIRECTION->{'ASCENDING'},
275 $inCollection )
276 if $inParams->{initdirection} =~ /^down$/i;
27711µs _storeAttribute( 'initDirection', $SORT_DIRECTION->{'DESCENDING'},
278 $inCollection )
279 if $inParams->{initdirection} =~ /^up$/i;
280 }
281
282 # Don't allow sort requests when rendering for static use.
283 # Force sort=off but allow initsort / initdirection
28412µs15µs my $context = Foswiki::Func::getContext();
# spent 5µs making 1 call to Foswiki::Func::getContext
2851400ns if ( $context->{static} ) {
286 delete $inCollection->{sortAllTables};
287 }
288
289 # If EditTablePlugin is installed and we are editing a table,
290 # the CGI parameter 'sort' is defined as "off" to disable all
291 # header sorting ((Item5135)
29211µs16µs my $cgi = Foswiki::Func::getCgiQuery();
# spent 6µs making 1 call to Foswiki::Func::getCgiQuery
29312µs116µs my $urlParamSort = $cgi->param('sort');
# spent 16µs making 1 call to Foswiki::Request::param
2941200ns if ( $urlParamSort && $urlParamSort =~ /^off$/oi ) {
295 delete $inCollection->{sortAllTables};
296 }
297
298 # If EditTablePlugin is installed and we are editing a table, the
299 # 'disableallsort' TABLE parameter is added to disable initsort and header
300 # sorting in the table that is being edited. (Item5135)
30112µs15µs if ( Foswiki::Func::isTrue( $inParams->{disableallsort} ) ) {
# spent 5µs making 1 call to Foswiki::Func::isTrue
302 $inCollection->{sortAllTables} = 0;
303 delete $inCollection->{initSort};
304 }
305
3061200ns if ($isTableSpecific) {
307
308 _storeAttribute( 'summary', $inParams->{summary}, $inCollection );
309 my $id =
310 defined $inParams->{id}
311 ? $inParams->{id}
312 : 'table'
313 . $Foswiki::Plugins::TablePlugin::topic
314 . ( $tableCount + 1 );
315 _storeAttribute( 'id', $id, $inCollection );
316 _storeAttribute( 'headerrows', $inParams->{headerrows}, $inCollection );
317 _storeAttribute( 'footerrows', $inParams->{footerrows}, $inCollection );
318 }
31911µs13µs _storeAttribute( 'border', $inParams->{tableborder}, $inCollection );
32012µs12µs _storeAttribute( 'tableBorderColor', $inParams->{tablebordercolor},
321 $inCollection );
32212µs12µs _storeAttribute( 'cellpadding', $inParams->{cellpadding}, $inCollection );
32312µs12µs _storeAttribute( 'cellspacing', $inParams->{cellspacing}, $inCollection );
32412µs12µs _storeAttribute( 'frame', $inParams->{tableframe}, $inCollection );
325
326 # tablerules css settings
3271400ns my @tableRulesList = ();
3281500ns if ( $inParams->{tablerules} ) {
329
330 # store tablerules as array, so that headerrules and datarules
331 # can be appended to that list
33212µs12µs my $param = _cleanParamValue( $inParams->{tablerules} );
3331900ns if ($param) {
334 push( @tableRulesList, $param );
335 }
336 }
3371600ns if ( $inParams->{headerrules} ) {
33811µs12µs my $param = _cleanParamValue( $inParams->{headerrules} );
3391400ns if ($param) {
3401700ns $param = "header_$param";
3411400ns push( @tableRulesList, $param );
342 }
343 }
3441400ns if ( $inParams->{datarules} ) {
345 my $param = _cleanParamValue( $inParams->{datarules} );
346 if ($param) {
347 $param = "data_$param";
348 push( @tableRulesList, $param );
349 }
350 }
3511800ns $inCollection->{tableRules} = \@tableRulesList if scalar @tableRulesList;
352
353 # use 'rules' as table attribute only (not to define css styles)
354 # but set to
3551600ns my $rules =
356 ( defined $inParams->{headerrules} || defined $inParams->{datarules} )
357 ? 'none'
358 : $inParams->{tablerules};
3591900ns12µs _storeAttribute( 'rules', $rules, $inCollection );
360
36112µs12µs _storeAttribute( 'width', $inParams->{tablewidth}, $inCollection );
362
363 # css attributes
36411µs12µs _storeAttribute( 'headerColor', $inParams->{headercolor}, $inCollection );
36511µs12µs _storeAttribute( 'headerBg', $inParams->{headerbg}, $inCollection );
36612µs12µs _storeAttribute( 'cellBorder', $inParams->{cellborder}, $inCollection );
36713µs23µs _storeAttribute( 'headerAlignListRef',
368 _arrayRefFromParam( $inParams->{headeralign} ),
369 $inCollection );
37012µs23µs _storeAttribute( 'dataAlignListRef',
371 _arrayRefFromParam( $inParams->{dataalign} ),
372 $inCollection );
37312µs22µs _storeAttribute( 'columnWidthsListRef',
374 _arrayRefFromParam( $inParams->{columnwidths} ),
375 $inCollection );
37611µs12µs _storeAttribute( 'vAlign', $inParams->{valign} || 'top', $inCollection );
37712µs12µs _storeAttribute( 'dataVAlign', $inParams->{datavalign}, $inCollection );
37812µs12µs _storeAttribute( 'headerVAlign', $inParams->{headervalign}, $inCollection );
37911µs15µs _storeAttribute( 'headerBgSorted',
380 $inParams->{headerbgsorted} || $inParams->{headerbg},
381 $inCollection );
38212µs26µs _storeAttribute( 'dataBgListRef', _arrayRefFromParam( $inParams->{databg} ),
383 $inCollection );
38412µs215µs _storeAttribute(
385 'dataBgSortedListRef',
386 _arrayRefFromParam( $inParams->{databgsorted} || $inParams->{databg} ),
387 $inCollection
388 );
38913µs23µs _storeAttribute( 'dataColorListRef',
390 _arrayRefFromParam( $inParams->{datacolor} ),
391 $inCollection );
39212µs12µs _storeAttribute( 'tableCaption', $inParams->{caption}, $inCollection );
393
394 # remove empty attributes
395115µs while ( my ( $key, $value ) = each %{$inCollection} ) {
396 delete $inCollection->{$key} if !defined $value || $value eq '';
397 }
398
39915µs15µs _debugData( '_parseAttributes result:', $inCollection );
# spent 5µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_debugData
400}
401
402=pod
403
404_getIncludeParams( $includeTopic ) -> \%params
405
406From $includeTopic read the first TABLE tag and return its parameters.
407
408=cut
409
410sub _getIncludeParams {
411 my ($inIncludeTopic) = @_;
412
413 my ( $includeWeb, $includeTopic ) =
414 Foswiki::Func::normalizeWebTopicName( $Foswiki::Plugins::TablePlugin::web,
415 $inIncludeTopic );
416
417 _debug("_getIncludeParams:$inIncludeTopic");
418 _debug("\t includeTopic=$includeTopic") if $includeTopic;
419
420 if ( !Foswiki::Func::topicExists( $includeWeb, $includeTopic ) ) {
421 _debug("TablePlugin: included topic $inIncludeTopic does not exist.");
422 return ( undef,
423'%MAKETEXT{"Warning: \'include\' topic <nop>[_1] does not exist!" args="'
424 . "$includeWeb.$includeTopic"
425 . '"}%' );
426 }
427 else {
428
429 my $text = Foswiki::Func::readTopicText( $includeWeb, $includeTopic );
430
431 if ( $text =~ m/$PATTERN_TABLE/s ) {
432 _debug("\t PATTERN_TABLE=$PATTERN_TABLE; 1=$1");
433 my $paramString = $1;
434
435 if ( $includeWeb ne $Foswiki::Plugins::TablePlugin::web
436 || $includeTopic ne $Foswiki::Plugins::TablePlugin::topic )
437 {
438
439 # expand common vars, except oneself to prevent recursion
440 $paramString =
441 Foswiki::Func::expandCommonVariables( $paramString,
442 $includeTopic, $includeWeb );
443 }
444 my %params = Foswiki::Func::extractParameters($paramString);
445 return ( \%params, undef );
446 }
447 else {
448 return ( undef,
449'%MAKETEXT{"Warning: table definition in \'include\' topic [_1] does not exist!" args="'
450 . "$includeWeb.$includeTopic"
451 . '"}%' );
452 }
453 }
454}
455
456=pod
457
458_convertStringToDate ( $text ) -> $number
459
460Convert text to number if syntactically possible, otherwise return undef.
461Assumes that the text has been stripped from HTML markup.
462
463=cut
464
465sub _convertStringToDate {
466 my ($text) = @_;
467
468 return undef if !defined $text;
469 return undef if $text eq '';
470 return undef if ( $text =~ /^\s*$/ );
471
472 my $date = undef;
473
474 if ( $text =~ /^\s*-?[0-9]+(\.[0-9])*\s*$/ ) {
475 _debug("\t this is a number");
476 }
477 else {
478 try {
479 $date = Foswiki::Time::parseTime($text);
480 _debug("\t is a date");
481 }
482 catch Error::Simple with {
483
484 # nope, wasn't a date
485 _debug("\t $text is not a date");
486 };
487 }
488
489 return $date;
490}
491
492=pod
493
494_convertStringToNumber ( $text ) -> $number
495
496Convert text to number if syntactically possible, otherwise return undef.
497Assumes that the text has been stripped from HTML markup.
498
499=cut
500
501sub _convertStringToNumber {
502 my ($text) = @_;
503
504 return undef if !defined $text;
505 return undef if $text eq '';
506 return undef if ( $text =~ /^\s*$/ );
507
508 # very course testing on IP (could in fact be anything with n.n. syntax
509 if (
510 $text =~ m/
511 ^
512 \s* # any space
513 (?: # don't need to capture
514 [0-9]+ # digits
515 \. # dot
516 ) #
517 {2,} # repeat more than once: exclude decimal numbers
518 .*? # any string
519 $
520 /x
521 )
522 {
523 _debug("\t $text looks like an IP address, or something similar");
524
525 # should be sorted by text
526 return undef;
527 }
528
529 if (
530 $text =~ m/
531 ^
532 \s* # any space
533 ( #
534 -* # possible minus
535 [0-9]+ # digits
536 \.* # possible decimal
537 [0-9]* # possible fracture digits
538 ) # end capture of number
539 .*$ # any string
540 /x
541 )
542 {
543
544 _debug("\t $1 is a number");
545
546 # make sure to return a number, not a string
547 return $1 * 1.0;
548 }
549 return undef;
550}
551
552sub _processTableRow {
553 my ( $thePre, $theRow ) = @_;
554
555 $currTablePre = $thePre || '';
556 my $span = 0;
557 my $l1 = 0;
558 my $l2 = 0;
559
560 if ( !$insideTABLE ) {
561 @curTable = ();
562 @rowspan = ();
563
564 $tableCount++;
565 $currentSortDirection = $SORT_DIRECTION->{'NONE'};
566
567 if ( defined $requestedTable
568 && $requestedTable == $tableCount
569 && defined $sortColFromUrl )
570 {
571 $sortCol = $sortColFromUrl;
572 $sortCol = 0 unless ( $sortCol =~ m/^[0-9]+$/ );
573 $sortCol = $MAX_SORT_COLS if ( $sortCol > $MAX_SORT_COLS );
574 $currentSortDirection = _getCurrentSortDirection($up);
575 }
576 elsif ( defined $combinedTableAttrs->{initSort} ) {
577 $sortCol = $combinedTableAttrs->{initSort} - 1;
578 $sortCol = $MAX_SORT_COLS if ( $sortCol > $MAX_SORT_COLS );
579 $currentSortDirection =
580 _getCurrentSortDirection( $combinedTableAttrs->{initDirection} );
581 }
582 }
583
584 $theRow =~ s/\t/ /go; # change tabs to space
585 $theRow =~ s/\s*$//o; # remove trailing spaces
586 $theRow =~
587 s/(\|\|+)/'colspan'.$translationToken.length($1)."\|"/geo; # calc COLSPAN
588 my $colCount = 0;
589 my @row = ();
590 $span = 0;
591 my $value = '';
592
593 foreach ( split( /\|/, $theRow ) ) {
594 my $attr = {};
595 $span = 1;
596
597 #AS 25-5-01 Fix to avoid matching also single columns
598 if (s/colspan$translationToken([0-9]+)//) {
599 $span = $1;
600 $attr->{colspan} = $span;
601 }
602 s/^\s+$/ &nbsp; /o;
603 ( $l1, $l2 ) = ( 0, 0 );
604 if (/^(\s*).*?(\s*)$/) {
605 $l1 = length($1);
606 $l2 = length($2);
607 }
608 if ( $l1 >= 2 ) {
609 if ( $l2 <= 1 ) {
610 $attr->{align} = 'right';
611 }
612 else {
613 $attr->{align} = 'center';
614 }
615 }
616 if ( $span <= 2 ) {
617 $attr->{class} =
618 _appendColNumberCssClass( $attr->{class}, $colCount );
619 }
620
621 # html attribute: (column) width
622 if ( $combinedTableAttrs->{generateInlineMarkup}
623 && defined $combinedTableAttrs->{columnWidthsListRef} )
624 {
625 my @columnWidths = @{ $combinedTableAttrs->{columnWidthsListRef} };
626 if ( defined $columnWidths[$colCount]
627 && $columnWidths[$colCount]
628 && $span <= 2 )
629 {
630 $attr->{width} = $columnWidths[$colCount];
631 }
632 }
633
634 # END html attribute
635
636 if (/^(\s|<[^>]*>)*\^(\s|<[^>]*>)*$/) { # row span above
637 $rowspan[$colCount]++;
638 push @row, { text => $value, type => 'Y' };
639 }
640 else {
641 for ( my $col = $colCount ; $col < ( $colCount + $span ) ; $col++ )
642 {
643 if ( defined( $rowspan[$col] ) && $rowspan[$col] ) {
644 my $nRows = scalar(@curTable);
645 my $rspan = $rowspan[$col] + 1;
646 if ( $rspan > 1 ) {
647 $curTable[ $nRows - $rspan ][$col]->{attrs}->{rowspan}
648 = $rspan;
649 }
650 undef( $rowspan[$col] );
651 }
652 }
653
654 if (
655 (
656 (
657 defined $requestedTable
658 && $requestedTable == $tableCount
659 )
660 || defined $combinedTableAttrs->{initSort}
661 )
662 && defined $sortCol
663 && $colCount == $sortCol
664 )
665 {
666
667 # CSS class name
668 if ( $currentSortDirection == $SORT_DIRECTION->{'ASCENDING'} ) {
669 $attr->{class} =
670 _appendSortedAscendingCssClass( $attr->{class} );
671 }
672 if ( $currentSortDirection == $SORT_DIRECTION->{'DESCENDING'} )
673 {
674 $attr->{class} =
675 _appendSortedDescendingCssClass( $attr->{class} );
676 }
677 }
678
679 my $type = '';
680 if (/^\s*\*(.*)\*\s*$/) {
681 $value = $1;
682 $type = 'th';
683
684 # html attribute: align
685 if ( $combinedTableAttrs->{generateInlineMarkup}
686 && defined $combinedTableAttrs->{headerAlignListRef} )
687 {
688 my @headerAlign =
689 @{ $combinedTableAttrs->{headerAlignListRef} };
690 if (@headerAlign) {
691 my $align =
692 @headerAlign[ $colCount % ( $#headerAlign + 1 ) ];
693 $attr->{align} = $align;
694 }
695 }
696
697 # END html attribute
698
699 # html attribute: valign
700 if ( $combinedTableAttrs->{generateInlineMarkup} ) {
701 if ( defined $combinedTableAttrs->{headerVAlign} ) {
702 $attr->{valign} = $combinedTableAttrs->{headerVAlign};
703 }
704 elsif ( defined $combinedTableAttrs->{vAlign} ) {
705 $attr->{valign} = $combinedTableAttrs->{vAlign};
706 }
707 }
708
709 # END html attribute
710 }
711 else {
712 if (/^\s*(.*?)\s*$/) { # strip white spaces
713 $_ = $1;
714 }
715 $value = $_;
716 $type = 'td';
717
718 # html attribute: align
719 if ( $combinedTableAttrs->{generateInlineMarkup}
720 && defined $combinedTableAttrs->{dataAlignListRef} )
721 {
722 my @dataAlign =
723 @{ $combinedTableAttrs->{dataAlignListRef} };
724 if (@dataAlign) {
725 my $align =
726 @dataAlign[ $colCount % ( $#dataAlign + 1 ) ];
727 $attr->{align} = $align;
728 }
729 }
730
731 # END html attribute
732
733 # html attribute: valign
734 if ( $combinedTableAttrs->{generateInlineMarkup} ) {
735 if ( defined $combinedTableAttrs->{dataVAlign} ) {
736 $attr->{valign} = $combinedTableAttrs->{dataVAlign};
737 }
738 elsif ( defined $combinedTableAttrs->{vAlign} ) {
739 $attr->{valign} = $combinedTableAttrs->{vAlign};
740 }
741 }
742
743 # END html attribute
744 }
745
746 push @row, { text => $value, attrs => $attr, type => $type };
747 }
748 while ( $span > 1 ) {
749 push @row, { text => $value, type => 'X' };
750 $colCount++;
751 $span--;
752 }
753 $colCount++;
754 }
755 push @curTable, \@row;
756 return $currTablePre
757 . '<nop>'; # Avoid Foswiki converting empty lines to new paras
758}
759
760sub _headerRowCount {
761 my ($table) = @_;
762
763 my $headerCount = 0;
764 my $footerCount = 0;
765 my $endheader = 0;
766
767 # All cells in header are headings?
768 foreach my $row (@$table) {
769 my $isHeader = 1;
770 foreach my $cell (@$row) {
771 if ( $cell->{type} ne 'th' ) {
772 $isHeader = 0;
773 $endheader = 1;
774 $footerCount = 0 if $footerCount;
775 }
776 }
777 unless ($endheader) {
778 $headerCount++ if $isHeader;
779 }
780 else {
781 $footerCount++ if $isHeader;
782 }
783 }
784
785 # Some cells came after the footer - so there isn't one.
786 $footerCount = 0 if ( $endheader > 1 );
787
788 return ( $headerCount, $footerCount );
789}
790
791=pod
792
793_setSortTypeForCells ( $col, \@table )
794
795Sets a sort key for each cell.
796
797=cut
798
799sub _setSortTypeForCells {
800 my ( $col, $table ) = @_;
801
802 foreach my $row ( @{$table} ) {
803
804 my $rowText = _stripHtml( $row->[$col]->{text} );
805
806 my $num = _convertStringToNumber($rowText);
807 my $date = _convertStringToDate($rowText);
808
809 $row->[$col]->{sortText} = '';
810 $row->[$col]->{number} = 0;
811 $row->[$col]->{dateString} = '';
812
813 if ( defined $date ) {
814
815 # date has just converted to a number
816 $row->[$col]->{number} = $date;
817
818 # add dateString value in case dates are equal
819 $row->[$col]->{dateString} = $rowText;
820 }
821 elsif ( defined $num ) {
822 $row->[$col]->{number} = $num;
823
824# when sorting mixed numbers and text, make the text sort value as low as possible
825 $row->[$col]->{sortText} = ' ';
826 }
827 else {
828 $row->[$col]->{sortText} = lc $rowText;
829 }
830
831 }
832}
833
834# Remove HTML from text so it can be sorted
835sub _stripHtml {
836 my ($text) = @_;
837
838 return undef if !defined $text;
839 $text =~
840 s/\[\[[^\]]+\]\[([^\]]+)\]\]/$1/go; # extract label from [[...][...]] link
841
842 my $orgtext =
843 $text; # in case we will have removed all contents with stripping html
844 $text =~ s/<[^>]+>//go; # strip HTML
845 $text =~ s/\&nbsp;/ /go;
846 $text = _getImageTextForSorting($orgtext) if ( $text eq '' );
847 $text =~ s/[\[\]\*\|=_\&\<\>]/ /g; # remove Wiki formatting chars
848 $text =~ s/^ *//go; # strip leading space space
849
850 return $text;
851}
852
853=pod
854
855Retrieve text data from an image html tag to be used for sorting.
856First try the alt tag string. If not available, return the url string.
857If not available, return the original string.
858
859=cut
860
861sub _getImageTextForSorting {
862 my ($text) = @_;
863
864 # try to see _if_ there is any img data for sorting
865 my $hasImageTag = ( $text =~ m/\<\s*img([^>]+)>/ );
866 return $text if ( !$hasImageTag );
867
868 # first try to get the alt text
869 my $key = 'alt';
870 $text =~ m/$key=\s*[\"\']([^\"\']*)/;
871 return $1 if ( $1 ne '' );
872
873 # else
874
875 # no alt text; use the url
876 $key = 'url';
877 $text =~ m/$key=\s*[\"\']([^\"\']*)/;
878 return $1 if ( $1 ne '' );
879
880 # else
881
882 return $text;
883}
884
885=pod
886
887Appends $className to $classList, separated by a space.
888
889=cut
890
891sub _appendToClassList {
892 my ( $classList, $className ) = @_;
893 $classList = $classList ? $classList .= ' ' : '';
894 $classList .= $className;
895 return $classList;
896}
897
898sub _appendSortedCssClass {
899 my ($classList) = @_;
900
901 return _appendToClassList( $classList, 'foswikiSortedCol' );
902}
903
904sub _appendRowNumberCssClass {
905 my ( $classList, $colListName, $rowNum ) = @_;
906
907 my $rowClassName = 'foswikiTableRow' . $colListName . $rowNum;
908 return _appendToClassList( $classList, $rowClassName );
909}
910
911sub _appendColNumberCssClass {
912 my ( $classList, $colNum ) = @_;
913
914 my $colClassName = 'foswikiTableCol' . $colNum;
915 return _appendToClassList( $classList, $colClassName );
916}
917
918sub _appendFirstColumnCssClass {
919 my ($classList) = @_;
920
921 return _appendToClassList( $classList, 'foswikiFirstCol' );
922}
923
924sub _appendLastColumnCssClass {
925 my ($classList) = @_;
926
927 return _appendToClassList( $classList, 'foswikiLastCol' );
928}
929
930sub _appendLastRowCssClass {
931 my ($classList) = @_;
932
933 return _appendToClassList( $classList, 'foswikiLast' );
934}
935
936sub _appendSortedAscendingCssClass {
937 my ($classList) = @_;
938
939 return _appendToClassList( $classList, 'foswikiSortedAscendingCol' );
940}
941
942sub _appendSortedDescendingCssClass {
943 my ($classList) = @_;
944
945 return _appendToClassList( $classList, 'foswikiSortedDescendingCol' );
946}
947
948# The default sort direction.
949sub _getDefaultSortDirection {
950 return $SORT_DIRECTION->{'ASCENDING'};
951}
952
953# Gets the current sort direction.
954sub _getCurrentSortDirection {
955 my ($currentDirection) = @_;
956 $currentDirection = $SORT_DIRECTION->{'ASCENDING'}
957 unless defined $currentDirection && $currentDirection =~ m/[0-2]+/;
958 $currentDirection ||= _getDefaultSortDirection();
959 return $currentDirection;
960}
961
962# Gets the new sort direction (needed for sort button) based on the current sort
963# direction.
964sub _getNewSortDirection {
965 my ($currentDirection) = @_;
966 if ( !defined $currentDirection ) {
967 return _getDefaultSortDirection();
968 }
969 my $newDirection;
970 if ( $currentDirection == $SORT_DIRECTION->{'ASCENDING'} ) {
971 $newDirection = $SORT_DIRECTION->{'DESCENDING'};
972 }
973 elsif ( $currentDirection == $SORT_DIRECTION->{'DESCENDING'} ) {
974 $newDirection = $SORT_DIRECTION->{'NONE'};
975 }
976 elsif ( $currentDirection == $SORT_DIRECTION->{'NONE'} ) {
977 $newDirection = $SORT_DIRECTION->{'ASCENDING'};
978 }
979 else {
980 $newDirection = _getDefaultSortDirection();
981 }
982
983 return $newDirection;
984}
985
986=pod
987
988_createCssStyles( $writeDefaults, $inAttrs ) -> ($id, @styles)
989
990Explicitly set styles override html styling (in this file marked with comment '# html attribute').
991
992=cut
993
994sub _createCssStyles {
995 my ( $writeDefaults, $inAttrs ) = @_;
996
997 _debug("_createCssStyles; writeDefaults=$writeDefaults");
998
999 my $_styles = {};
1000 my $setAttribute = sub {
1001 my ( $tableSelector, $type, $rule ) = @_;
1002
1003 return if !$rule;
1004 $type ||= '#'; # for table selector only, if no type
1005 my $storedType = $_styles->{$tableSelector}->{$type} || '';
1006 if ( !defined $storedType ) {
1007 @{ $_styles->{$tableSelector}->{$type} } = ();
1008 }
1009 if ( $rule ne $storedType ) {
1010 push @{ $_styles->{$tableSelector}->{$type} }, $rule;
1011 }
1012 };
1013
1014 if ( $writeDefaults && !$didWriteDefaultStyle ) {
1015 my $tableSelector = '.foswikiTable';
1016 my $attr = 'padding-left:.3em; vertical-align:text-bottom';
1017 &$setAttribute( $tableSelector, '.tableSortIcon img', $attr );
1018
1019 if ( $inAttrs->{cellpadding} ) {
1020 my $attr =
1021 'padding:' . addDefaultSizeUnit( $inAttrs->{cellpadding} );
1022 &$setAttribute( $tableSelector, 'td', $attr );
1023 &$setAttribute( $tableSelector, 'th', $attr );
1024 }
1025 }
1026
1027 my $tableSelector;
1028 my $id;
1029 if ($writeDefaults) {
1030 $id = 'default';
1031 $tableSelector = ".foswikiTable";
1032 }
1033 else {
1034 $id = $inAttrs->{id};
1035 $tableSelector = ".foswikiTable#$id";
1036 }
1037
1038 # tablerules
1039 if ( $inAttrs->{tableRules} ) {
1040 my @rules = @{ $inAttrs->{tableRules} };
1041
1042 my $attr_td;
1043 my $attr_th;
1044 foreach my $rule (@rules) {
1045 $attr_td = $TABLE_RULES->{$rule}->{TD}
1046 if $TABLE_RULES->{$rule}->{TD};
1047 $attr_th = $TABLE_RULES->{$rule}->{TH}
1048 if $TABLE_RULES->{$rule}->{TH};
1049 }
1050 &$setAttribute( $tableSelector, 'th', $attr_th );
1051 &$setAttribute( $tableSelector, 'td', $attr_td );
1052 }
1053
1054 # tableframe
1055 if ( $inAttrs->{frame} ) {
1056 my $attr = $TABLE_FRAME->{ $inAttrs->{frame} };
1057 &$setAttribute( $tableSelector, '', $attr );
1058 }
1059
1060 # tableborder
1061 if ( defined $inAttrs->{border} ) {
1062 my $tableBorderWidth = $inAttrs->{border} || 0;
1063 my $attr = 'border-width:' . addDefaultSizeUnit($tableBorderWidth);
1064 &$setAttribute( $tableSelector, '', $attr );
1065 }
1066
1067 # tableBorderColor
1068 if ( defined $inAttrs->{tableBorderColor} ) {
1069 my $attr;
1070 $attr = 'border-color:' . $inAttrs->{tableBorderColor};
1071 &$setAttribute( $tableSelector, '', $attr );
1072 $attr = 'border-top-color:' . $inAttrs->{tableBorderColor};
1073 &$setAttribute( $tableSelector, '', $attr );
1074 $attr = 'border-bottom-color:' . $inAttrs->{tableBorderColor};
1075 &$setAttribute( $tableSelector, '', $attr );
1076 $attr = 'border-left-color:' . $inAttrs->{tableBorderColor};
1077 &$setAttribute( $tableSelector, '', $attr );
1078 $attr = 'border-right-color:' . $inAttrs->{tableBorderColor};
1079 &$setAttribute( $tableSelector, '', $attr );
1080 }
1081
1082 # cellSpacing
1083 if ( defined $inAttrs->{cellspacing} ) {
1084
1085 # do not use border-collapse:collapse
1086 my $attr = 'border-collapse:separate';
1087 &$setAttribute( $tableSelector, '', $attr );
1088 }
1089
1090 # cellpadding
1091 if ( defined $inAttrs->{cellpadding} ) {
1092 my $attr = 'padding:' . addDefaultSizeUnit( $inAttrs->{cellpadding} );
1093 &$setAttribute( $tableSelector, 'td', $attr );
1094 &$setAttribute( $tableSelector, 'th', $attr );
1095 }
1096
1097 # cellborder
1098 if ( defined $inAttrs->{cellBorder} ) {
1099 my $cellBorderWidth = $inAttrs->{cellBorder} || 0;
1100 my $attr = 'border-width:' . addDefaultSizeUnit($cellBorderWidth);
1101 &$setAttribute( $tableSelector, 'td', $attr );
1102 &$setAttribute( $tableSelector, 'th', $attr );
1103 }
1104
1105 # tablewidth
1106 if ( defined $inAttrs->{width} ) {
1107 my $width = addDefaultSizeUnit( $inAttrs->{width} );
1108 my $attr = 'width:' . $width;
1109 &$setAttribute( $tableSelector, '', $attr );
1110 }
1111
1112 # valign
1113 if ( defined $inAttrs->{vAlign} ) {
1114 my $attr = 'vertical-align:' . $inAttrs->{vAlign};
1115 &$setAttribute( $tableSelector, 'td', $attr );
1116 &$setAttribute( $tableSelector, 'th', $attr );
1117 }
1118
1119 # headerVAlign
1120 if ( defined $inAttrs->{headerVAlign} ) {
1121 my $attr = 'vertical-align:' . $inAttrs->{headerVAlign};
1122 &$setAttribute( $tableSelector, 'th', $attr );
1123 }
1124
1125 # dataVAlign
1126 if ( defined $inAttrs->{dataVAlign} ) {
1127 my $attr = 'vertical-align:' . $inAttrs->{dataVAlign};
1128 &$setAttribute( $tableSelector, 'td', $attr );
1129 }
1130
1131 # headerbg
1132 if ( defined $inAttrs->{headerBg} ) {
1133 my $color =
1134 ( $inAttrs->{headerBg} =~ /none/i )
1135 ? 'transparent'
1136 : $inAttrs->{headerBg};
1137 my $attr = 'background-color:' . $color;
1138 &$setAttribute( $tableSelector, 'th', $attr );
1139 }
1140
1141 # headerbgsorted
1142 if ( defined $inAttrs->{headerBgSorted} ) {
1143 my $color =
1144 ( $inAttrs->{headerBgSorted} =~ /none/i )
1145 ? 'transparent'
1146 : $inAttrs->{headerBgSorted};
1147 my $attr = 'background-color:' . $color;
1148 &$setAttribute( $tableSelector, 'th.foswikiSortedCol', $attr );
1149 }
1150
1151 # headercolor
1152 if ( defined $inAttrs->{headerColor} ) {
1153 my $attr = 'color:' . $inAttrs->{headerColor};
1154 &$setAttribute( $tableSelector, 'th', $attr );
1155 &$setAttribute( $tableSelector, 'th a:link', $attr );
1156 &$setAttribute( $tableSelector, 'th a:visited', $attr );
1157 &$setAttribute( $tableSelector, 'th a:xhover', $attr )
1158 ; # just to make sorting work: hover should be last. below we will remove the x again.
1159 if ( defined $inAttrs->{headerBg} ) {
1160 my $hoverBackgroundColor = $inAttrs->{headerBg};
1161 $attr = 'background-color:' . $hoverBackgroundColor;
1162 &$setAttribute( $tableSelector, 'th a:xhover', $attr );
1163 }
1164 }
1165
1166 # databg (array)
1167 if ( defined $inAttrs->{dataBgListRef} ) {
1168 my @dataBg = @{ $inAttrs->{dataBgListRef} };
1169 my $noneColor = ( $dataBg[0] =~ /none/i ) ? 'transparent' : '';
1170 my $count = 0;
1171 foreach my $color (@dataBg) {
1172 $color = $noneColor if $noneColor;
1173 next if !$color;
1174 my $rowSelector = 'foswikiTableRow' . 'dataBg' . $count;
1175 my $attr = "background-color:$color";
1176 &$setAttribute( $tableSelector, "tr.$rowSelector td", $attr );
1177 $count++;
1178 }
1179 }
1180
1181 # databgsorted (array)
1182 if ( defined $inAttrs->{dataBgSortedListRef} ) {
1183 my @dataBgSorted = @{ $inAttrs->{dataBgSortedListRef} };
1184 my $noneColor = ( $dataBgSorted[0] =~ /none/i ) ? 'transparent' : '';
1185 my $count = 0;
1186 foreach my $color (@dataBgSorted) {
1187 $color = $noneColor if $noneColor;
1188 next if !$color;
1189 my $rowSelector = 'foswikiTableRow' . 'dataBg' . $count;
1190 my $attr = "background-color:$color";
1191 &$setAttribute( $tableSelector,
1192 "tr.$rowSelector td.foswikiSortedCol", $attr );
1193 $count++;
1194 }
1195 }
1196
1197 # datacolor (array)
1198 if ( defined $inAttrs->{dataColorListRef} ) {
1199 my @dataColor = @{ $inAttrs->{dataColorListRef} };
1200 unless ( $dataColor[0] =~ /none/i ) {
1201 my $count = 0;
1202 foreach my $color (@dataColor) {
1203 next if !$color;
1204 my $rowSelector = 'foswikiTableRow' . 'dataColor' . $count;
1205 my $attr = "color:$color";
1206 &$setAttribute( $tableSelector, "tr.$rowSelector td", $attr );
1207 $count++;
1208 }
1209 }
1210 }
1211
1212 # columnwidths
1213 if ( defined $inAttrs->{columnWidthsListRef} ) {
1214 my @columnWidths = @{ $inAttrs->{columnWidthsListRef} };
1215 my $count = 0;
1216 foreach my $width (@columnWidths) {
1217 next if !$width;
1218 $width = addDefaultSizeUnit($width);
1219 my $colSelector = 'foswikiTableCol';
1220 $colSelector .= $count;
1221 my $attr = 'width:' . $width;
1222 &$setAttribute( $tableSelector, "td.$colSelector", $attr );
1223 &$setAttribute( $tableSelector, "th.$colSelector", $attr );
1224 $count++;
1225 }
1226 }
1227
1228 # headeralign
1229 if ( defined $inAttrs->{headerAlignListRef} ) {
1230 my @headerAlign = @{ $inAttrs->{headerAlignListRef} };
1231 if ( scalar @headerAlign == 1 ) {
1232 my $align = $headerAlign[0];
1233 my $attr = 'text-align:' . $align;
1234 &$setAttribute( $tableSelector, 'th', $attr );
1235 }
1236 else {
1237 my $count = 0;
1238 foreach my $align (@headerAlign) {
1239 next if !$align;
1240 my $colSelector = 'foswikiTableCol';
1241 $colSelector .= $count;
1242 my $attr = 'text-align:' . $align;
1243 &$setAttribute( $tableSelector, "th.$colSelector", $attr );
1244 $count++;
1245 }
1246 }
1247 }
1248
1249 # dataAlign
1250 if ( defined $inAttrs->{dataAlignListRef} ) {
1251 my @dataAlign = @{ $inAttrs->{dataAlignListRef} };
1252 if ( scalar @dataAlign == 1 ) {
1253 my $align = $dataAlign[0];
1254 my $attr = 'text-align:' . $align;
1255 &$setAttribute( $tableSelector, 'td', $attr );
1256 }
1257 else {
1258 my $count = 0;
1259 foreach my $align (@dataAlign) {
1260 next if !$align;
1261 my $colSelector = 'foswikiTableCol';
1262 $colSelector .= $count;
1263 my $attr = 'text-align:' . $align;
1264 &$setAttribute( $tableSelector, "td.$colSelector", $attr );
1265 $count++;
1266 }
1267 }
1268 }
1269
1270 my @styles = ();
1271 foreach my $tableSelector ( sort keys %{$_styles} ) {
1272 foreach my $selector ( sort keys %{ $_styles->{$tableSelector} } ) {
1273 my $selectors =
1274 join( '; ', @{ $_styles->{$tableSelector}->{$selector} } );
1275 $selector =~ s/xhover/hover/go; # remove sorting hack
1276 # TODO: optimize by combining identical rules
1277 if ( $selector eq '#' ) {
1278 push @styles, "$tableSelector {$selectors}";
1279 }
1280 else {
1281 push @styles, "$tableSelector $selector {$selectors}";
1282 }
1283 }
1284 }
1285
1286 return ( $id, @styles );
1287}
1288
1289sub _addHeadStyles {
1290 my ( $inId, @inStyles ) = @_;
1291
1292 return if !scalar @inStyles;
1293
1294 $styles->{seendIds}->{$inId} = 1;
1295 if ( $inId eq $HEAD_ID_DEFAULT_STYLE ) {
1296 $styles->{$HEAD_ID_DEFAULT_STYLE}->{'default'} = \@inStyles;
1297 _writeStyleToHead( $HEAD_ID_DEFAULT_STYLE,
1298 $styles->{$HEAD_ID_DEFAULT_STYLE} );
1299 }
1300 else {
1301 $styles->{$HEAD_ID_SPECIFIC_STYLE}->{$inId} = \@inStyles;
1302 _writeStyleToHead( $HEAD_ID_SPECIFIC_STYLE,
1303 $styles->{$HEAD_ID_SPECIFIC_STYLE} );
1304 }
1305}
1306
1307sub _writeStyleToHead {
1308 my ( $inId, $inStyles ) = @_;
1309
1310 my @allStyles = ();
1311 foreach my $id ( sort keys %{$inStyles} ) {
1312 push @allStyles, @{ $inStyles->{$id} };
1313 }
1314 my $styleText = join( "\n", @allStyles );
1315
1316 my $header = <<EOS;
1317<style type="text/css" media="all">
1318$styleText
1319</style>
1320EOS
1321 $header =~ s/(.*?)\s*$/$1/; # remove last newline
1322 Foswiki::Func::addToHEAD( $inId, $header, $HEAD_ID_DEFAULT_STYLE );
1323}
1324
1325=pod
1326
1327StaticMethod addDefaultSizeUnit ($text) -> $text
1328
1329Adds size unit 'px' if this is missing from the size text.
1330
1331=cut
1332
1333sub addDefaultSizeUnit {
1334 my ($inSize) = @_;
1335
1336 my $unit = '';
1337 if ( $inSize =~ m/$PATTERN_ATTRIBUTE_SIZE/ ) {
1338 $unit = 'px' if !$2;
1339 }
1340 return "$inSize$unit";
1341}
1342
1343sub emitTable {
1344
1345 _addDefaultStyles();
1346
1347 _debug('emitTable');
1348
1349 #Validate headerrows/footerrows and modify if out of range
1350 if ( $combinedTableAttrs->{headerrows} > scalar @curTable ) {
1351 $combinedTableAttrs->{headerrows} =
1352 scalar @curTable; # limit header to size of table!
1353 }
1354 if ( $combinedTableAttrs->{headerrows} + $combinedTableAttrs->{footerrows} >
1355 @curTable )
1356 {
1357 $combinedTableAttrs->{footerrows} = scalar @curTable -
1358 $combinedTableAttrs->{headerrows}; # and footer to whatever is left
1359 }
1360
1361 my $sortThisTable =
1362 ( !defined $combinedTableAttrs->{sortAllTables}
1363 || $combinedTableAttrs->{sortAllTables} == 0 )
1364 ? 0
1365 : $combinedTableAttrs->{sort};
1366
1367 if ( $combinedTableAttrs->{headerrows} == 0 ) {
1368 my ( $headerRowCount, $footerRowCount ) = _headerRowCount( \@curTable );
1369
1370 # override default setting with calculated header count
1371 $combinedTableAttrs->{headerrows} = $headerRowCount;
1372 $combinedTableAttrs->{footerrows} = $footerRowCount;
1373 }
1374
1375 my $tableTagAttributes = {};
1376 $tableTagAttributes->{class} = $combinedTableAttrs->{class};
1377 $tableTagAttributes->{border} = $combinedTableAttrs->{border};
1378 $tableTagAttributes->{cellspacing} = $combinedTableAttrs->{cellspacing};
1379 $tableTagAttributes->{cellpadding} = $combinedTableAttrs->{cellpadding};
1380 $tableTagAttributes->{id} = $combinedTableAttrs->{id}
1381 || undef;
1382 $tableTagAttributes->{summary} = $combinedTableAttrs->{summary};
1383 $tableTagAttributes->{frame} = $combinedTableAttrs->{frame};
1384 $tableTagAttributes->{rules} = $combinedTableAttrs->{rules};
1385 $tableTagAttributes->{width} = $combinedTableAttrs->{width};
1386
1387 # remove empty attributes
1388 while ( my ( $key, $value ) = each %{$tableTagAttributes} ) {
1389 delete $tableTagAttributes->{$key} if !defined $value || $value eq '';
1390 }
1391
1392 my $text = $currTablePre . CGI::start_table($tableTagAttributes);
1393 $text .= $currTablePre . CGI::caption( $combinedTableAttrs->{tableCaption} )
1394 if $combinedTableAttrs->{tableCaption};
1395
1396 # count the number of cols to prevent looping over non-existing columns
1397 my $maxCols = 0;
1398
1399 # Flush out any remaining rowspans
1400 for ( my $i = 0 ; $i < @rowspan ; $i++ ) {
1401 if ( defined( $rowspan[$i] ) && $rowspan[$i] ) {
1402 my $nRows = scalar(@curTable);
1403 my $rspan = $rowspan[$i] + 1;
1404 my $r = $nRows - $rspan;
1405 $curTable[$r][$i]->{attrs} ||= {};
1406 if ( $rspan > 1 ) {
1407 $curTable[$r][$i]->{attrs}->{rowspan} = $rspan;
1408 }
1409 }
1410 }
1411
1412 if (
1413 (
1414 $sortThisTable
1415 && defined $sortCol
1416 && defined $requestedTable
1417 && $requestedTable == $tableCount
1418 )
1419 || defined $combinedTableAttrs->{initSort}
1420 )
1421 {
1422
1423 # DG 08 Aug 2002: Allow multi-line headers
1424 my @header = splice( @curTable, 0, $combinedTableAttrs->{headerrows} );
1425
1426 # DG 08 Aug 2002: Skip sorting any trailers as well
1427 my @trailer = ();
1428 if ( $combinedTableAttrs->{footerrows}
1429 && scalar(@curTable) > $combinedTableAttrs->{footerrows} )
1430 {
1431 @trailer = splice( @curTable, -$combinedTableAttrs->{footerrows} );
1432 }
1433
1434 # Count the maximum number of columns of this table
1435 for my $row ( 0 .. $#curTable ) {
1436 my $thisRowMaxColCount = 0;
1437 for my $col ( 0 .. $#{ $curTable[$row] } ) {
1438 $thisRowMaxColCount++;
1439 }
1440 $maxCols = $thisRowMaxColCount
1441 if ( $thisRowMaxColCount > $maxCols );
1442 }
1443
1444 # Handle multi-row labels by killing rowspans in sorted tables
1445 for my $row ( 0 .. $#curTable ) {
1446 for my $col ( 0 .. $#{ $curTable[$row] } ) {
1447
1448 # SMELL: why do we need to specify a rowspan of 1?
1449 $curTable[$row][$col]->{attrs}->{rowspan} = 1;
1450 if ( $curTable[$row][$col]->{type} eq 'Y' ) {
1451 $curTable[$row][$col]->{text} =
1452 $curTable[ $row - 1 ][$col]->{text};
1453 $curTable[$row][$col]->{type} = 'td';
1454 }
1455 }
1456 }
1457
1458 # url requested sort on column beyond end of table. Force to last column
1459 $sortCol = 0 unless ( $sortCol =~ m/^[0-9]+$/ );
1460 $sortCol = $maxCols - 1 if ( $sortCol >= $maxCols );
1461
1462 # only get the column type if within bounds
1463 if ( $sortCol < $maxCols ) {
1464 _setSortTypeForCells( $sortCol, \@curTable );
1465 }
1466
1467 _debug("currentSortDirection:$currentSortDirection");
1468
1469 if ( $combinedTableAttrs->{sort}
1470 && $currentSortDirection == $SORT_DIRECTION->{'ASCENDING'} )
1471 {
1472 @curTable = sort {
1473 $a->[$sortCol]->{sortText} cmp $b->[$sortCol]->{sortText}
1474 || $a->[$sortCol]->{number} <=> $b->[$sortCol]->{number}
1475 || $a->[$sortCol]->{dateString}
1476 cmp $b->[$sortCol]->{dateString}
1477 } @curTable;
1478 }
1479 elsif ($combinedTableAttrs->{sort}
1480 && $currentSortDirection == $SORT_DIRECTION->{'DESCENDING'} )
1481 {
1482 @curTable = sort {
1483 $b->[$sortCol]->{sortText} cmp $a->[$sortCol]->{sortText}
1484 || $b->[$sortCol]->{number} <=> $a->[$sortCol]->{number}
1485 || $b->[$sortCol]->{dateString}
1486 cmp $a->[$sortCol]->{dateString}
1487 } @curTable;
1488 }
1489
1490 # DG 08 Aug 2002: Cleanup after the header/trailer splicing
1491 # this is probably awfully inefficient - but how big is a table?
1492 @curTable = ( @header, @curTable, @trailer );
1493 } # if defined $sortCol ...
1494
1495 my $rowCount = 0;
1496 my $numberOfRows = scalar(@curTable);
1497 my $dataColorCount = 0;
1498
1499 my @headerRowList = ();
1500 my @bodyRowList = ();
1501 my @footerRowList = ();
1502
1503 my $isPastHeaderRows = 0;
1504 my $singleIndent = "\n\t";
1505 my $doubleIndent = "\n\t\t";
1506 my $tripleIndent = "\n\t\t\t";
1507
1508 # Only *one* row of the table has sort links, and it will either
1509 # be the last row in the header or the first row in the footer.
1510 my $sortLinksWritten = 0;
1511
1512 foreach my $row (@curTable) {
1513 my $rowtext = '';
1514 my $colCount = 0;
1515
1516 # keep track of header cells: if all cells are header cells, do not
1517 # update the data color count
1518 my $headerCellCount = 0;
1519 my $numberOfCols = scalar(@$row);
1520 my $writingSortLinks = 0;
1521
1522 foreach my $fcell (@$row) {
1523
1524 # check if cell exists
1525 next if ( !$fcell || !$fcell->{type} );
1526
1527 my $tableAnchor = '';
1528 next
1529 if ( $fcell->{type} eq 'X' )
1530 ; # data was there so sort could work with col spanning
1531 my $type = $fcell->{type};
1532 my $cell = $fcell->{text};
1533 my $attr = $fcell->{attrs} || {};
1534
1535 my $newDirection;
1536 my $isSorted = 0;
1537
1538 if (
1539 $currentSortDirection != $SORT_DIRECTION->{'NONE'}
1540 && defined $sortCol
1541 && $colCount == $sortCol
1542
1543 # Removing the line below hides the marking of sorted columns
1544 # until the user clicks on a header (KJL)
1545 # && defined $requestedTable && $requestedTable == $tableCount
1546 # && $sortType ne ''
1547 )
1548 {
1549 $isSorted = 1;
1550 $newDirection = _getNewSortDirection($currentSortDirection);
1551 }
1552 else {
1553 $newDirection = _getDefaultSortDirection();
1554 }
1555
1556 if ( $type eq 'th' ) {
1557 $headerCellCount++;
1558
1559 # html attribute: bgcolor
1560 if ( $combinedTableAttrs->{generateInlineMarkup}
1561 && defined $combinedTableAttrs->{headerBg} )
1562 {
1563 $attr->{bgcolor} = $combinedTableAttrs->{headerBg}
1564 unless ( $combinedTableAttrs->{headerBg} =~ /none/i );
1565 }
1566
1567 # END html attribute
1568
1569 if ($isSorted) {
1570 if ( $currentSortDirection ==
1571 $SORT_DIRECTION->{'ASCENDING'} )
1572 {
1573 $tableAnchor = $CHAR_SORT_ASCENDING;
1574 }
1575 if ( $currentSortDirection ==
1576 $SORT_DIRECTION->{'DESCENDING'} )
1577 {
1578 $tableAnchor = $CHAR_SORT_DESCENDING;
1579 }
1580
1581 # html attribute: (sorted header cell) bgcolor
1582 # overrides earlier set bgcolor
1583 if ( $combinedTableAttrs->{generateInlineMarkup}
1584 && defined $combinedTableAttrs->{headerBgSorted} )
1585 {
1586 $attr->{bgcolor} = $combinedTableAttrs->{headerBgSorted}
1587 unless (
1588 $combinedTableAttrs->{headerBgSorted} =~ /none/i );
1589 }
1590
1591 # END html attribute
1592 }
1593
1594 if (
1595 defined $sortCol
1596 && $colCount == $sortCol
1597 && defined $requestedTable
1598 && $requestedTable == $tableCount
1599 && ( $combinedTableAttrs->{headerrows}
1600 || $combinedTableAttrs->{footerrows} )
1601 )
1602 {
1603
1604 $tableAnchor =
1605 CGI::a( { name => 'sorted_table' }, '<!-- -->' )
1606 . $tableAnchor;
1607 }
1608
1609 # html attribute: headercolor (font style)
1610 if ( $combinedTableAttrs->{generateInlineMarkup}
1611 && defined $combinedTableAttrs->{headerColor} )
1612 {
1613 my $fontStyle =
1614 { color => $combinedTableAttrs->{headerColor} };
1615 $cell = CGI::font( $fontStyle, $cell );
1616 }
1617
1618 # END html attribute
1619
1620 if (
1621 $sortThisTable
1622 && (
1623 ( $rowCount == $combinedTableAttrs->{headerrows} - 1 )
1624 || ( !$combinedTableAttrs->{headerrows}
1625 && $rowCount ==
1626 $numberOfRows - $combinedTableAttrs->{footerrows} )
1627 )
1628 && ( $writingSortLinks || !$sortLinksWritten )
1629 )
1630 {
1631 $writingSortLinks = 1;
1632 my $linkAttributes = {
1633 href => $url
1634 . 'sortcol='
1635 . $colCount
1636 . ';table='
1637 . $tableCount . ';up='
1638 . $newDirection
1639 . '#sorted_table',
1640 rel => 'nofollow',
1641 title => 'Sort by this column'
1642 };
1643
1644 if ( $cell =~ /\[\[|href/o ) {
1645 $cell .= CGI::a( $linkAttributes, $CHAR_SORT_BOTH )
1646 . $tableAnchor;
1647 }
1648 else {
1649 $cell = CGI::a( $linkAttributes, $cell ) . $tableAnchor;
1650 }
1651 }
1652
1653 }
1654 else {
1655
1656 $type = 'td' unless $type eq 'Y';
1657
1658 # html attribute: bgcolor
1659 if ( $combinedTableAttrs->{generateInlineMarkup} ) {
1660 if ( $isSorted
1661 && defined $combinedTableAttrs->{dataBgSortedListRef} )
1662 {
1663 my @dataBg =
1664 @{ $combinedTableAttrs->{dataBgSortedListRef} };
1665
1666 unless ( $dataBg[0] =~ /none/ ) {
1667 $attr->{bgcolor} =
1668 $dataBg[ $dataColorCount % ( $#dataBg + 1 ) ];
1669 }
1670 }
1671 elsif ( defined $combinedTableAttrs->{dataBgListRef} ) {
1672 my @dataBg = @{ $combinedTableAttrs->{dataBgListRef} };
1673 unless ( $dataBg[0] =~ /none/i ) {
1674 $attr->{bgcolor} =
1675 $dataBg[ $dataColorCount % ( $#dataBg + 1 ) ];
1676 }
1677 }
1678 }
1679
1680 # END html attribute
1681
1682 # html attribute: datacolor (font style)
1683 if ( $combinedTableAttrs->{generateInlineMarkup}
1684 && defined $combinedTableAttrs->{dataColorListRef} )
1685 {
1686 my @dataColor =
1687 @{ $combinedTableAttrs->{dataColorListRef} };
1688 my $color =
1689 $dataColor[ $dataColorCount % ( $#dataColor + 1 ) ];
1690 unless ( $color =~ /^(none)$/i ) {
1691 my $cellAttrs = { color => $color };
1692 $cell = CGI::font( $cellAttrs, ' ' . $cell . ' ' );
1693 }
1694 }
1695
1696 # END html attribute
1697
1698 } ###if( $type eq 'th' )
1699
1700 if ($isSorted) {
1701 $attr->{class} = _appendSortedCssClass( $attr->{class} );
1702 }
1703
1704 if ($writingSortLinks) {
1705 $sortLinksWritten = 1;
1706 }
1707
1708 my $isLastRow = ( $rowCount == $numberOfRows - 1 );
1709 if ( $attr->{rowspan} ) {
1710 $isLastRow =
1711 ( ( $rowCount + ( $attr->{rowspan} - 1 ) ) ==
1712 $numberOfRows - 1 );
1713 }
1714
1715 # CSS class name
1716 $attr->{class} = _appendFirstColumnCssClass( $attr->{class} )
1717 if $colCount == 0;
1718 my $isLastCol = ( $colCount == $numberOfCols - 1 );
1719 $attr->{class} = _appendLastColumnCssClass( $attr->{class} )
1720 if $isLastCol;
1721
1722 $attr->{class} = _appendLastRowCssClass( $attr->{class} )
1723 if $isLastRow;
1724
1725 $colCount++;
1726 next if ( $type eq 'Y' );
1727 my $fn = 'CGI::' . $type;
1728254µs246µs
# spent 30µs (14+16) within Foswiki::Plugins::TablePlugin::Core::BEGIN@1728 which was called: # once (14µs+16µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 1728
no strict 'refs';
# spent 30µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@1728 # spent 16µs making 1 call to strict::unimport
1729 $rowtext .= "$tripleIndent" . &$fn( $attr, " $cell " );
173021.27ms233µs
# spent 23µs (12+10) within Foswiki::Plugins::TablePlugin::Core::BEGIN@1730 which was called: # once (12µs+10µs) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 1730
use strict 'refs';
# spent 23µs making 1 call to Foswiki::Plugins::TablePlugin::Core::BEGIN@1730 # spent 10µs making 1 call to strict::import
1731 } # foreach my $fcell ( @$row )
1732
1733 # assign css class names to tr
1734 # based on settings: dataBg, dataBgSorted
1735 my $trClassName = '';
1736
1737 # just 2 css names is too limited, but we will keep it for compatibility
1738 # with existing style sheets
1739 my $rowTypeName =
1740 ( $rowCount % 2 ) ? 'foswikiTableEven' : 'foswikiTableOdd';
1741 $trClassName = _appendToClassList( $trClassName, $rowTypeName );
1742
1743 if ( $combinedTableAttrs->{dataBgSortedListRef} ) {
1744 my @dataBgSorted = @{ $combinedTableAttrs->{dataBgSortedListRef} };
1745 my $modRowNum = $dataColorCount % ( $#dataBgSorted + 1 );
1746 $trClassName =
1747 _appendRowNumberCssClass( $trClassName, 'dataBgSorted',
1748 $modRowNum );
1749 }
1750 if ( $combinedTableAttrs->{dataBgListRef} ) {
1751 my @dataBg = @{ $combinedTableAttrs->{dataBgListRef} };
1752 my $modRowNum = $dataColorCount % ( $#dataBg + 1 );
1753 $trClassName =
1754 _appendRowNumberCssClass( $trClassName, 'dataBg', $modRowNum );
1755 }
1756 if ( $combinedTableAttrs->{dataColorListRef} ) {
1757 my @dataColor = @{ $combinedTableAttrs->{dataColorListRef} };
1758 my $modRowNum = $dataColorCount % ( $#dataColor + 1 );
1759 $trClassName =
1760 _appendRowNumberCssClass( $trClassName, 'dataColor', $modRowNum );
1761 }
1762 $rowtext .= $doubleIndent;
1763 my $rowHTML =
1764 $doubleIndent . CGI::Tr( { class => $trClassName }, $rowtext );
1765
1766 my $isHeaderRow =
1767 $rowCount <
1768 $combinedTableAttrs->{headerrows}; #( $headerCellCount == $colCount );
1769 my $isFooterRow =
1770 ( ( $numberOfRows - $rowCount ) <=
1771 $combinedTableAttrs->{footerrows} );
1772
1773 if ( !$isHeaderRow && !$isFooterRow ) {
1774
1775 # don't include non-adjacent header rows to the top block of header rows
1776 $isPastHeaderRows = 1;
1777 }
1778
1779 if ($isFooterRow) {
1780 push @footerRowList, $rowHTML;
1781 }
1782 elsif ( $isHeaderRow && !$isPastHeaderRows ) {
1783 push( @headerRowList, $rowHTML );
1784 }
1785 else {
1786 push @bodyRowList, $rowHTML;
1787 $dataColorCount++;
1788 }
1789
1790 if ($isHeaderRow) {
1791
1792 # reset data color count to start with first color after
1793 # each table heading
1794 $dataColorCount = 0;
1795 }
1796
1797 $rowCount++;
1798 } # foreach my $row ( @curTable )
1799
1800 my $thead =
1801 "$singleIndent<thead>"
1802 . join( "", @headerRowList )
1803 . "$singleIndent</thead>";
1804 $text .= $currTablePre . $thead if scalar @headerRowList;
1805
1806 my $tfoot =
1807 "$singleIndent<tfoot>"
1808 . join( "", @footerRowList )
1809 . "$singleIndent</tfoot>";
1810 $text .= $currTablePre . $tfoot if scalar @footerRowList;
1811
1812 my $tbody;
1813 if ( scalar @bodyRowList ) {
1814 $tbody =
1815 "$singleIndent<tbody>"
1816 . join( "", @bodyRowList )
1817 . "$singleIndent</tbody>";
1818 }
1819 else {
1820
1821 # A HTML table requires a body, which cannot be empty (Item8991).
1822 # So we provide one, but prevent it from being displayed.
1823 $tbody =
1824"$singleIndent<tbody>$doubleIndent<tr style=\"display:none;\">$tripleIndent<td></td>$doubleIndent</tr>$singleIndent</tbody>\n";
1825 }
1826
1827 if ( scalar @messages ) {
1828 $text =
1829 '<span class="foswikiAlert">'
1830 . Foswiki::Func::expandCommonVariables( join( "\n", @messages ) )
1831 . '</span>' . "\n"
1832 . $text;
1833 }
1834
1835 $text .= $currTablePre . $tbody;
1836 $text .= $currTablePre . CGI::end_table() . "\n";
1837
1838 return $text;
1839}
1840
1841
# spent 1.77ms (671µs+1.09) within Foswiki::Plugins::TablePlugin::Core::handler which was called 5 times, avg 353µs/call: # 5 times (671µs+1.09ms) by Foswiki::Plugins::TablePlugin::preRenderingHandler at line 73 of /var/www/foswiki11/lib/Foswiki/Plugins/TablePlugin.pm, avg 353µs/call
sub handler {
1842 ### my ( $text, $removed ) = @_;
1843
1844514µs544µs _debug('handler');
# spent 44µs making 5 calls to Foswiki::Plugins::TablePlugin::Core::_debug, avg 9µs/call
1845
184652µs unless ($Foswiki::Plugins::TablePlugin::initialised) {
18471200ns $insideTABLE = 0;
1848
1849 # Even if $tableCount is initialized already at plugin init
1850 # we need to reset it again each time preRenderingHandler
1851 # calls this handler sub. Important for initialiseWhenRender API
18521200ns $tableCount = 0;
1853
185411µs18µs my $cgi = Foswiki::Func::getCgiQuery();
# spent 8µs making 1 call to Foswiki::Func::getCgiQuery
18551200ns return unless $cgi;
1856
1857 # Copy existing values
18581300ns my ( @origSort, @origTable, @origUp );
185913µs122µs @origSort = $cgi->param('sortcol');
# spent 22µs making 1 call to Foswiki::Request::param
186012µs113µs @origTable = $cgi->param('table');
# spent 13µs making 1 call to Foswiki::Request::param
186111µs112µs @origUp = $cgi->param('up'); # NOTE: internal parameter
# spent 12µs making 1 call to Foswiki::Request::param
186215µs19µs $cgi->delete( 'sortcol', 'table', 'up' );
# spent 9µs making 1 call to Foswiki::Request::delete
186315µs1151µs $url = $cgi->url( -absolute => 1, -path => 1 ) . '?';
# spent 151µs making 1 call to Foswiki::Request::url
186412µs162µs my $queryString = $cgi->query_string();
# spent 62µs making 1 call to Foswiki::Request::queryString
18651700ns $url .= $queryString . ';' if $queryString;
1866
1867 # Restore parameters, so we don't interfere on the remaining execution
18681300ns $cgi->param( -name => 'sortcol', -value => \@origSort ) if @origSort;
18691200ns $cgi->param( -name => 'table', -value => \@origTable ) if @origTable;
18701200ns $cgi->param( -name => 'up', -value => \@origUp ) if @origUp;
1871
187211µs113µs $sortColFromUrl =
# spent 13µs making 1 call to Foswiki::Request::param
1873 $cgi->param('sortcol'); # zero based: 0 is first column
18741100ns if ( defined $sortColFromUrl && $sortColFromUrl !~ m/^[0-9]+$/ ) {
1875 $sortColFromUrl = 0;
1876 }
1877
187811µs112µs $requestedTable = $cgi->param('table');
# spent 12µs making 1 call to Foswiki::Request::param
18791400ns $requestedTable = 0
1880 unless ( defined $requestedTable && $requestedTable =~ m/^[0-9]+$/ );
1881
188211µs111µs $up = $cgi->param('up');
# spent 11µs making 1 call to Foswiki::Request::param
1883
18841200ns $sortTablesInText = 0;
18851100ns $sortAttachments = 0;
188612µs128µs my $tmp = Foswiki::Func::getPreferencesValue('TABLEPLUGIN_SORT')
# spent 28µs making 1 call to Foswiki::Func::getPreferencesValue
1887 || 'all';
188812µs if ( !$tmp || $tmp =~ /^all$/oi ) {
18891200ns $sortTablesInText = 1;
18901300ns $sortAttachments = 1;
1891 }
1892 elsif ( $tmp =~ /^attachments$/oi ) {
1893 $sortAttachments = 1;
1894 }
1895
189612µs1383µs _initDefaults(); # first time
# spent 383µs making 1 call to Foswiki::Plugins::TablePlugin::Core::_initDefaults
189711µs $Foswiki::Plugins::TablePlugin::initialised = 1;
1898 }
1899
190054µs $insideTABLE = 0;
1901
190257µs my $defaultSort = $combinedTableAttrs->{sortAllTables};
1903
190452µs my $acceptable = $combinedTableAttrs->{sortAllTables};
19055222µs my @lines = split( /\r?\n/, $_[0] );
190656µs for (@lines) {
1907223240µs if (
1908s/$PATTERN_TABLE/_parseTableSpecificTableAttributes(Foswiki::Func::extractParameters($1))/se
1909 )
1910 {
1911 $acceptable = 1;
1912 }
1913 elsif (s/^(\s*)\|(.*\|\s*)$/_processTableRow($1,$2)/eo) {
1914 $insideTABLE = 1;
1915 }
1916 elsif ($insideTABLE) {
1917 $_ = emitTable() . $_;
1918 $insideTABLE = 0;
1919
1920 $combinedTableAttrs->{sortAllTables} = $defaultSort;
1921 $acceptable = $defaultSort;
1922
1923 # prepare for next table
1924 _resetReusedVariables();
1925 }
1926 }
1927562µs $_[0] = join( "\n", @lines );
1928
192952µs if ($insideTABLE) {
1930 $_[0] .= emitTable();
1931 }
1932
1933 # prepare for next table
1934547µs5327µs _resetReusedVariables();
# spent 327µs making 5 calls to Foswiki::Plugins::TablePlugin::Core::_resetReusedVariables, avg 65µs/call
1935}
1936
1937=pod
1938
1939_mergeHashes (\%a, \%b ) -> \%merged
1940
1941Merges 2 hash references.
1942
1943=cut
1944
1945
# spent 205µs within Foswiki::Plugins::TablePlugin::Core::_mergeHashes which was called 6 times, avg 34µs/call: # 5 times (182µs+0s) by Foswiki::Plugins::TablePlugin::Core::_resetReusedVariables at line 164, avg 36µs/call # once (22µs+0s) by Foswiki::Plugins::TablePlugin::Core::_initDefaults at line 149
sub _mergeHashes {
194664µs my ( $A, $B ) = @_;
1947
194866µs my %merged = ();
1949611µs while ( my ( $k, $v ) = each(%$A) ) {
1950 $merged{$k} = $v;
1951 }
19526169µs while ( my ( $k, $v ) = each(%$B) ) {
1953 $merged{$k} = $v;
1954 }
1955627µs return \%merged;
1956}
1957
1958=pod
1959
1960=cut
1961
1962
# spent 4µs within Foswiki::Plugins::TablePlugin::Core::_cleanParamValue which was called 2 times, avg 2µs/call: # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 332 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 338
sub _cleanParamValue {
19632700ns my ($inValue) = @_;
1964
19652200ns return undef if !$inValue;
1966
19672800ns $inValue =~ s/ //go; # remove spaces
1968210µs return $inValue;
1969}
1970
1971=pod
1972
1973=cut
1974
1975
# spent 22µs within Foswiki::Plugins::TablePlugin::Core::_arrayRefFromParam which was called 6 times, avg 4µs/call: # once (12µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 384 # once (4µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 382 # once (2µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 367 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 370 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 389 # once (1µs+0s) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 373
sub _arrayRefFromParam {
197663µs my ($inValue) = @_;
1977
1978612µs return undef if !$inValue;
1979
19802600ns $inValue =~ s/ //go; # remove spaces
1981213µs my @list = split( /,/, $inValue );
198227µs return \@list;
1983}
1984
1985=pod
1986
1987Shorthand debugging call.
1988
1989=cut
1990
1991
# spent 96µs (65+31) within Foswiki::Plugins::TablePlugin::Core::_debug which was called 13 times, avg 7µs/call: # 5 times (32µs+12µs) by Foswiki::Plugins::TablePlugin::Core::handler at line 1844, avg 9µs/call # 5 times (22µs+13µs) by Foswiki::Plugins::TablePlugin::Core::_resetReusedVariables at line 162, avg 7µs/call # once (5µs+3µs) by Foswiki::Plugins::TablePlugin::Core::_init at line 123 # once (3µs+2µs) by Foswiki::Plugins::TablePlugin::Core::_initDefaults at line 138 # once (3µs+2µs) by Foswiki::Plugins::TablePlugin::Core::_parseDefaultAttributes at line 193
sub _debug {
19921357µs1331µs return Foswiki::Plugins::TablePlugin::debug( 'TablePlugin::Core', @_ );
# spent 31µs making 13 calls to Foswiki::Plugins::TablePlugin::debug, avg 2µs/call
1993}
1994
1995
# spent 16µs (9+8) within Foswiki::Plugins::TablePlugin::Core::_debugData which was called 2 times, avg 8µs/call: # once (6µs+5µs) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 234 # once (3µs+2µs) by Foswiki::Plugins::TablePlugin::Core::_parseAttributes at line 399
sub _debugData {
199629µs28µs return Foswiki::Plugins::TablePlugin::debugData( 'TablePlugin::Core', @_ );
# spent 8µs making 2 calls to Foswiki::Plugins::TablePlugin::debugData, avg 4µs/call
1997}
1998
1999125µs1;
2000__END__