@@ -307,7 +307,14 @@ code-body: yes
307307\end
308308
309309\function tf.get.table.width() [<stateTiddlerPrefix>addsuffix[parent-size]get[text]addsuffix[px]]
310- \function tf.get.max.column.width() [range<columns>!match<colIndex>!match<nextColIndex>] :reduce[addprefix<stateTiddlerPrefix>get[text]!prefix[Infinity]else<cellWidth>add<accumulator>] +[subtract[100]] :map[abs<currentTiddler>subtract<tf.get.min.column.width.percentage>addsuffix[%]]
310+
311+ \function tf.get.max.column.width()
312+ [range<columns>!match<colIndex>!match<nextColIndex>]
313+ :reduce[addprefix<stateTiddlerPrefix>get[text]!prefix[Infinity]else<cellWidth>add<accumulator>]
314+ :and[subtract[100]]
315+ :map[abs<currentTiddler>subtract<tf.get.min.column.width.percentage>addsuffix[%]]
316+ \end
317+
311318\function tf.get.min.column.width.percentage() [tf.convert.px.to.percentage<tf.get.table.width>,[50px]addsuffix[%]]
312319\function tf.get.max.column.width.percentage() [<colIndex>!match<columns>then<tf.get.table.width>!is[blank]then<tf.get.max.column.width>]
313320
@@ -330,19 +337,240 @@ code-body: yes
330337</$let>
331338\end
332339
333- \procedure resizable-table(columns:"", rows:"", columnFilter:"", rowFilter:"", tableHeight:"auto", class:"", headerClass:"", cellClass:"", stateTiddlerPrefix:"$:/state/resizable-table/col-")
340+ \procedure resizable-table-content-inner(filter)
341+ \whitespace trim
342+ <%if [<editable>match[yes]] %>
343+ <$let state={{{ [[$:/state/edit-cell-]addsuffix<colIndex>addsuffix[-]addsuffix<row>addsuffix[-]addsuffix<qualify>] }}}>
344+ <%if [<state>get[text]!match[yes]] [<state>is[missing]] %>
345+ <div style.display="flex">
346+ <div style.flex="1">
347+ <$wikify name="content" text="""<$text text={{{ [subfilter<filter>get<field>] }}}/>""">
348+ <<content>>
349+ </$wikify>
350+ </div>
351+ <div>
352+ <$button class="tc-btn-invisible" set=<<state>> setTo="yes" actions=<<resizable-table-content-create-tiddler-actions>>>
353+ {{$:/core/images/edit-button}}
354+ </$button>
355+ </div>
356+ </div>
357+ <% else %>
358+ <div style.display="flex">
359+ <div style.flex="1">
360+ <$edit-text tag="input" tiddler={{{ [subfilter<filter>] }}} focus="yes" class="tc-width-100"/>
361+ </div>
362+ <div>
363+ <$button class="tc-btn-invisible" set=<<state>> setTo="no">
364+ {{$:/core/images/done-button}}
365+ </$button>
366+ </div>
367+ </div>
368+ <% endif %>
369+ </$let>
370+ <% else %>
371+ <$wikify name="content" text="""<$text text={{{ [subfilter<filter>get<field>] }}}/>""">
372+ <<content>>
373+ </$wikify>
374+ <% endif %>
375+ \end
376+
377+ \procedure resizable-table-content(filter,tableArea)
378+ <%if [<wikitextTable>is[blank]] %>
379+ <$transclude $variable="resizable-table-content-inner" filter=<<filter>>/>
380+ <%elseif [<tableArea>match[header]] %>
381+ <$let tableHeader={{{ [<wikitextTable>splitregexp[\n]suffix[|h]] }}} tableHeaderCell={{{ [<tableHeader>split[|]butfirst[]butlast[]nth<colIndex>] }}}>
382+ <$wikify name="content" text=<<tableHeaderCell>>>
383+ <<content>>
384+ </$wikify>
385+ </$let>
386+ <%elseif [<tableArea>match[rows]] %>
387+ <$let tableRow={{{ [<wikitextTable>splitregexp[\n]!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]nth<rowIndex>] }}} tableRowCell={{{ [<tableRow>split[|]butfirst[]butlast[]nth<colIndex>] }}}>
388+ <$wikify name="content" text=<<tableRowCell>>>
389+ <<content>>
390+ </$wikify>
391+ </$let>
392+ <%elseif [<tableArea>match[footer]] %>
393+ <$let tableFooter={{{ [<wikitextTable>splitregexp[\n]suffix[|f]] }}} tableFooterCell={{{ [<tableFooter>split[|]butfirst[]butlast[]nth<colIndex>] }}}>
394+ <$wikify name="content" text=<<tableFooterCell>>>
395+ <<content>>
396+ </$wikify>
397+ </$let>
398+ <% endif %>
399+ \end
400+
401+
402+ <!-- Replace every cell value except ">" or "<" by "1" -->
403+ \function fn.row.value-to-1()
404+ [all[]]
405+ :map[<currentTiddler>!regexp[>|<]then[1]else<currentTiddler>]
406+ :map[<currentTiddler>match[<]then<index>match[0]then[1]else<currentTiddler>]
407+ :map[<currentTiddler>match[>]then<index>match<columnsMinusOne>then[1]else<currentTiddler>]
408+ +[join[ ]]
409+ \end
410+
411+
412+ <!-- Replace every cell value except "~" by "1" -->
413+ \function fn.col.value-to-1()
414+ [all[]]
415+ :map[<currentTiddler>!match[~]then[1]else<currentTiddler>]
416+ :map[<currentTiddler>match[~]then<index>match[0]then[1]else<currentTiddler>]
417+ +[join[ ]]
418+ \end
419+
420+
421+ <!-- Counts the occurrences of "c" in string "s" -->
422+ \function fn.nb(c,s)
423+ [<s>split<c>count[]subtract[1]]
424+ \end
425+
426+
427+ <!-- Replaces sequences of "from" characters by "to" characters -->
428+ \function fn.expand.cell(from,to)
429+ [fn.nb<from>,<cell>!match[0]]
430+ :map:flat[range<currentTiddler>]
431+ :map[<to>]
432+ +[join[]]
433+ \end
434+
435+
436+ <!-- Returns <<cell>> length -->
437+ \function fn.cell.ln() [<cell>split[]count[]]
438+
439+
440+ <!-- Computes current <<cell>> weight -->
441+ \function fn.compute.row.cell(cell)
442+ =[fn.expand.cell[>],[0 ]]
443+ =[fn.cell.ln[]]
444+ =[fn.expand.cell[<],[ 0]]
445+ +[join[]]
446+ \end
447+
448+
449+ <!-- Computes current <<cell>> weight -->
450+ \function fn.compute.col.cell(cell)
451+ =[fn.cell.ln[]]
452+ =[fn.expand.cell[~],[ 0]]
453+ +[join[]]
454+ \end
455+
456+
457+ <!-- Computes current <<row>> weights -->
458+ \function fn.compute.row(row)
459+ =[<row>split[|]]
460+ :map:flat[fn.compute.row.cell<currentTiddler>]
461+ +[join[ ]]
462+ \end
463+
464+
465+ <!-- Computes current <<col>> weights -->
466+ \function fn.compute.col(col)
467+ =[<col>split[|]]
468+ :map:flat[fn.compute.col.cell<currentTiddler>]
469+ +[join[ ]]
470+ \end
471+
472+
473+ <!-- Sanitizes input (not perfect, but you get the idea... -->
474+ \function fn.sanitize()
475+ [all[]]
476+ :map[<currentTiddler>search-replace:g[||],[|x|]search-replace:g:regexp[\|\s+\|],[|x|]]
477+ \end
478+
479+
480+ <!-- Replaces actual cell values by "1"s -->
481+ \function fn.get.row.ones()
482+ [all[]]
483+ :map[<currentTiddler>split[|]butfirst[]butlast[]trim[]fn.row.value-to-1[]enlist-input:raw[]join[|]]
484+ \end
485+
486+
487+ <!-- Replaces actual cell values by "1"s -->
488+ \function fn.get.col.ones()
489+ [all[]]
490+ :map[<currentTiddler>split[|]trim[]butfirst[]butlast[]fn.col.value-to-1[]enlist-input:raw[]join[|]]
491+ \end
492+
493+
494+ <!-- Collapse cells (">|1" becomes ">1" -->
495+ \function fn.row.collapse()
496+ [all[]]
497+ :map[<currentTiddler>search-replace:g[>|],[>]search-replace:g[|<],[<]]
498+ \end
499+
500+
501+ <!-- Collapse cells ("1|~" becomes "1~" -->
502+ \function fn.col.collapse()
503+ [all[]]
504+ :map[<currentTiddler>search-replace:g[|~],[~]]
505+ \end
506+
507+
508+ \function tf.exclude.header.caption.classes.footer() [!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]]
509+ \function tf.is.header() [suffix[|h]]
510+
511+
512+ <!-- Maps a table to its colspans -->
513+ \function row.map(table,fn)
514+ [<table>splitregexp[\n]function<fn>] :and[nth<rowIndex>]
515+ :map[<currentTiddler>fn.sanitize[]]
516+ :map[<currentTiddler>fn.get.row.ones[>|<]]
517+ :map[<currentTiddler>fn.row.collapse[]]
518+ :map[fn.compute.row<currentTiddler>]
519+ \end
520+
521+
522+ <!-- Maps a table to its rowspans -->
523+ \function col.map(table,fn)
524+ [<table>splitregexp[\n]function<fn>split[|]butfirst[]butlast[]join[ ]enlist-input:raw[]]
525+ :map:flat[<index>remainder<columns>match<previousColIndex>then<currentTiddler>]
526+ :and[!match[]join[|]] :and[addprefix[|]addsuffix[|]]
527+ :map[<currentTiddler>fn.sanitize[]]
528+ :map[<currentTiddler>fn.get.col.ones[]]
529+ :map[<currentTiddler>fn.col.collapse[]]
530+ :map[fn.compute.col<currentTiddler>]
531+ \end
532+
533+
534+ \function tf.get.colspan() [row.map<wikitextTable>,[tf.exclude.header.caption.classes.footer]split[ ]!match[]nth<colIndex>]
535+ \function tf.get.rowspan() [col.map<wikitextTable>,[tf.exclude.header.caption.classes.footer]split[ ]!match[]nth<rowIndex>]
536+
537+
538+ \function tf.row.split.regexp() [<wikitextTable>splitregexp[\n]!is[blank]]
539+ \function tf.row.split.regexp.count.columns() [function[tf.row.split.regexp]!suffix[|c]!suffix[|k]nth[1]split[|]butfirst[]butlast[]count[]]
540+ \function tf.row.split.regexp.count.rows() [function[tf.row.split.regexp]!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]count[]]
541+ \function tf.row.split.regexp.has.header() [function[tf.row.split.regexp]suffix[|h]then[yes]]
542+ \function tf.row.split.regexp.has.footer() [function[tf.row.split.regexp]suffix[|f]then[yes]]
543+ \function tf.row.split.regexp.get.caption() [function[tf.row.split.regexp]suffix[|c]split[|]butfirst[]butlast[]first[]]
544+
545+
546+ \procedure resizable-table(columns:"", rows:"", columnFilter:"", rowFilter:"", footerFilter:"", field:"text", editable:"no", tableHeight:"auto", class:"", headerClass:"", cellClass:"", stateTiddlerPrefix:"$:/state/resizable-table/", caption:"", wikitextTable:"")
334547\whitespace trim
335- <$let cellWidth={{{ [[100]divide<columns>addsuffix[%]] }}}>
548+ <$let
549+ columns={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp.count.columns>] :else[<wikitextTable>is[blank]then<columns>] :else[[0]] }}}
550+ rows={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp.count.rows>] :else[<wikitextTable>is[blank]then<rows>] :else[[0]] }}}
551+ cellWidth={{{ [[100]divide<columns>addsuffix[%]] }}}
552+ stateTiddlerPrefix={{{ [<stateTiddlerPrefix>addsuffix<columns>addsuffix<qualify>addsuffix[/]addsuffix[col-]] }}}
553+ hasHeader={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp.has.header>] :else[[no]] }}}
554+ hasFooter={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp.has.footer>] :else[[no]] }}}
555+ caption={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp.get.caption>] :else[<caption>!is[blank]] :else[[]] }}}
556+ wikitextClasses={{{ [<wikitextTable>!is[blank]then<tf.row.split.regexp>suffix[|k]split[|]butfirst[]butlast[]first[]] }}}
557+ columnsMinusOne={{{ [<columns>subtract[1]] }}}
558+ >
336559 <div class={{{ tc-resizable-table-wrapper [<class>] +[join[ ]] }}} style.height=<<tableHeight>> style.width="100%">
337- <table class="tc-resizable-table" style.width="100%">
338- <%if [<columns>!is[blank]] %>
560+ <table class={{{ tc-resizable-table evenRow [<wikitextClasses>] +[join[ ]] }}} style.width="100%">
561+ <%if [<caption>!is[blank]] %>
562+ <caption>
563+ <<caption>>
564+ </caption>
565+ <% endif %>
566+ <%if [<wikitextTable>is[blank]then<columns>!is[blank]then<columnFilter>!is[blank]] [<wikitextTable>!is[blank]then<hasHeader>match[yes]] %>
339567 <thead>
340568 <tr class={{{ tc-resizable-table-header [<headerClass>] +[join[ ]] }}}>
341569 <$list filter="[range<columns>]" variable="column" counter="colIndex">
342- <$let nextColIndex={{{ [<colIndex>add[1]] }}}>
570+ <$let nextColIndex={{{ [<colIndex>add[1]] }}} row="0" >
343571 <th style.position="relative" style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}}>
344572 <div class="tc-resizable-table-cell" style.width="100%">
345- <$text text=<<colIndex>> />
573+ <$transclude $variable="resizable-table-content" filter=<<columnFilter>> tableArea="header" />
346574 </div>
347575 <%if [<colIndex>!match<columns>] %>
348576 <$resizer
@@ -363,39 +591,76 @@ code-body: yes
363591 </tr>
364592 </thead>
365593 <% endif %>
366- <%if [<rows>!is[blank]] %>
594+ <%if [<wikitextTable>is[blank]then< rows>!is[blank]then<rowFilter>!is[blank]] [<wikitextTable >!is[blank]] %>
367595 <tbody>
368- <$list filter="[range<rows>]" variable="row">
369- <tr class={{{ tc-resizable-table-row [<cellClass>] +[join[ ]] }}}>
596+ <$list filter="[range<rows>]" variable="row" counter="rowIndex" >
597+ <tr class={{{ tc-resizable-table-row [<rowIndex>remainder[2]match[1]then[evenRow]else[oddRow]] [< cellClass>] +[join[ ]] }}}>
370598 <$list filter="[range<columns>]" variable="column" counter="colIndex">
371- <td style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}}>
372- <div class="tc-resizable-table-cell" style.width="100%">
373- <$text text={{{ [<row>addsuffix[ - ]addsuffix<colIndex>] }}}/>
374- </div>
375- </td>
599+ <$let
600+ previousColIndex={{{ [<colIndex>subtract[1]] }}}
601+ nextColIndex={{{ [<colIndex>add[1]] }}}
602+ colspan={{{ [<wikitextTable>!is[blank]then<tf.get.colspan>] :else[[1]] }}}
603+ rowspan={{{ [<wikitextTable>!is[blank]then<tf.get.rowspan>] :else[[1]] }}}
604+ >
605+ <%if [<colspan>!match[0]then<rowspan>!match[0]] %>
606+ <td style.position="relative" style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}} colspan=<<colspan>> rowspan=<<rowspan>>>
607+ <div class="tc-resizable-table-cell" style.width="100%">
608+ <$transclude $variable="resizable-table-content" filter=<<rowFilter>> tableArea="rows"/>
609+ </div>
610+ <%if [<colIndex>!match<columns>] %>
611+ <$resizer
612+ class="tc-table-column-resizer"
613+ direction="horizontal"
614+ min=<<tf.get.min.column.width.percentage>>
615+ max=<<tf.get.max.column.width.percentage>>
616+ default=<<cellWidth>>
617+ unit="px"
618+ element="parent.parent"
619+ onBeforeResizeStart=<<resizable-table-on-before-resize-start-actions>>
620+ onResize=<<resizable-table-on-resize-actions>>
621+ />
622+ <% endif %>
623+ </td>
624+ <% endif %>
625+ </$let>
376626 </$list>
377627 </tr>
378628 </$list>
379629 </tbody>
380630 <% endif %>
631+ <%if [<wikitextTable>is[blank]then<footerFilter>!is[blank]] [<wikitextTable>!is[blank]then<hasFooter>match[yes]] %>
632+ <tfoot>
633+ <tr class="evenRow">
634+ <$list filter="[range<columns>]" variable="column" counter="colIndex">
635+ <$let nextColIndex={{{ [<colIndex>add[1]] }}} row={{{ [<rows>add[1]] }}}>
636+ <td style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}}>
637+ <div class="tc-resizable-table-cell" style.width="100%">
638+ <$transclude $variable="resizable-table-content" filter=<<footerFilter>> tableArea="footer"/>
639+ </div>
640+ </td>
641+ </$let>
642+ </$list>
643+ </tr>
644+ </tfoot>
645+ <% endif %>
381646 </table>
382647 </div>
383648</$let>
384649\end
385650
386- \procedure resizable-table-flexbox(columns:"", rows:"", columnFilter:"", rowFilter:"", tableHeight:"auto", class:"", headerClass:"", cellClass:"", stateTiddlerPrefix:"$:/state/resizable-table-flex/col- ")
651+ \procedure resizable-table-flexbox(columns:"", rows:"", columnFilter:"", rowFilter:"", editable:"no", tableHeight:"auto", class:"", headerClass:"", cellClass:"", stateTiddlerPrefix:"$:/state/resizable-table-flex/", wikitextTable:" ")
387652\whitespace trim
388- <$let cellWidth={{{ [[100]divide<columns>addsuffix[%]] }}}>
653+ <$let cellWidth={{{ [[100]divide<columns>addsuffix[%]] }}} stateTiddlerPrefix={{{ [<stateTiddlerPrefix>addsuffix<columns>addsuffix<qualify>addsuffix[/]addsuffix[col-]] }}} >
389654 <div class={{{ tc-resizable-table-flexbox-wrapper [<class>] +[join[ ]] }}} style.height=<<tableHeight>> style.width="100%" style.display="flex" style.flex-direction="column">
390- <%if [<columns>!is[blank]] %>
655+ <%if [<columns>!is[blank]then<columnFilter>!is[blank] ] %>
391656 <div class={{{ tc-resizable-table-flexbox-header [<headerClass>] +[join[ ]] }}} style.display="flex">
392657 <$list filter="[range<columns>]" variable="column" counter="colIndex">
393658 <$let
394659 nextColIndex={{{ [<colIndex>add[1]] }}}
395660 columnZIndex={{{ [<columns>subtract<colIndex>add[1]] }}}
396661 >
397662 <div style.position="relative" style.z-index=<<columnZIndex>> style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}} style.padding="8px" style.font-weight="bold">
398- <$text text={{{ [[Column ]addsuffix<colIndex>] }}} />
663+ <$transclude $variable="resizable-table-content" filter=<<columnFilter>> />
399664 <%if [<colIndex>!match<columns>] %>
400665 <$resizer
401666 class="tc-table-column-resizer-flexbox"
@@ -416,14 +681,14 @@ code-body: yes
416681 <% endif %>
417682 <%if [<rows>!is[blank]] %>
418683 <div class="tc-resizable-table-flexbox-body" style.flex="1" style.overflow="auto">
419- <$list filter="[range<rows>]" variable="row">
684+ <$list filter="[range<rows>]" variable="row" counter="rowIndex" >
420685 <div class={{{ tc-resizable-table-flexbox-row [<cellClass>] +[join[ ]] }}} style.display="flex">
421686 <$list filter="[range<columns>]" variable="column" counter="colIndex">
422687 <$let
423688 nextColIndex={{{ [<colIndex>add[1]] }}}
424689 columnZIndex={{{ [<columns>subtract<colIndex>add[1]] }}}>
425690 <div style.position="relative" style.z-index=<<columnZIndex>> style.min-width=<<tf.get.min.column.width.percentage>> style.max-width=<<tf.get.max.column.width.percentage>> style.width={{{ [<stateTiddlerPrefix>addsuffix<colIndex>get[text]!prefix[Infinity]] :else[<cellWidth>] }}} style.padding="8px" style.word-wrap="break-word" style.overflow-wrap="break-word">
426- <$text text={{{ [<row>addsuffix[ - ]addsuffix<colIndex>] }}} />
691+ <$transclude $variable="resizable-table-content" filter=<<rowFilter>> />
427692 </div>
428693 </$let>
429694 </$list>
0 commit comments