@@ -217,18 +217,31 @@ public function renderDataTable(Component\Table\Data $component, RendererInterfa
217217 $ component ->getAdditionalParameters ()
218218 );
219219
220+ // these column counts and index numbers are meant for aria attributes in the html tpl
221+ $ compensate_col_index = 1 ; // aria-colindex expects counting to start with 1, not 0
222+ if ($ component ->hasMultiActions ()) { // adds column with checkbox before first data column which is numbered 1.
223+ $ compensate_col_index += 1 ;
224+ }
225+ $ compensate_col_count = 0 ; // count starts with 1, only needs to be compensated for special columns
226+ if ($ component ->hasMultiActions ()) {
227+ $ compensate_col_count += 1 ;
228+ }
229+ if ($ component ->hasSingleActions ()) { // adds column with action dropdown at the very end
230+ $ compensate_col_count += 1 ;
231+ }
232+
220233 $ id = $ this ->bindJavaScript ($ component );
221234 $ tpl ->setVariable ('ID ' , $ id );
222235 $ tpl ->setVariable ('TITLE ' , $ component ->getTitle ());
223- $ tpl ->setVariable ('COL_COUNT ' , (string ) $ component ->getColumnCount ());
236+ $ tpl ->setVariable ('COL_COUNT ' , (string ) $ component ->getColumnCount () + $ compensate_col_count );
224237 $ tpl ->setVariable ('VIEW_CONTROLS ' , $ default_renderer ->render ($ view_controls ));
225238
226239 $ sortation_signal = null ;
227240 // if the generator is empty, and thus invalid, we render an empty row.
228241 if (!$ rows ->valid ()) {
229242 $ this ->renderFullWidthDataCell ($ component , $ tpl , $ this ->txt ('ui_table_no_records ' ));
230243 } else {
231- $ this ->renderActionsHeader ($ default_renderer , $ component , $ tpl );
244+ $ this ->renderActionsHeader ($ default_renderer , $ component , $ tpl, $ compensate_col_count );
232245 $ this ->appendTableRows ($ tpl , $ rows , $ default_renderer );
233246
234247 if ($ component ->hasMultiActions ()) {
@@ -239,8 +252,8 @@ public function renderDataTable(Component\Table\Data $component, RendererInterfa
239252 $ component ->getMultiActionSignal (),
240253 $ modal ->getShowSignal ()
241254 );
242- $ total_number_of_cols = count ($ component ->getVisibleColumns ()) + 2 ; // + selection column and action dropdown column
243- $ tpl ->setVariable ('COLUMN_COUNT ' , (string ) $ total_number_of_cols );
255+ $ multi_action_col_span = count ($ component ->getVisibleColumns ()) + $ compensate_col_count ;
256+ $ tpl ->setVariable ('MULTI_ACTION_SPAN ' , (string ) $ multi_action_col_span );
244257 $ tpl ->setVariable ('MULTI_ACTION_TRIGGERER ' , $ default_renderer ->render ($ multi_actions_dropdown ));
245258 $ tpl ->setVariable ('MULTI_ACTION_ALL_MODAL ' , $ default_renderer ->render ($ modal ));
246259 }
@@ -255,15 +268,16 @@ public function renderDataTable(Component\Table\Data $component, RendererInterfa
255268 }
256269 }
257270
258- $ this ->renderTableHeader ($ default_renderer , $ component , $ tpl , $ sortation_signal );
271+ $ this ->renderTableHeader ($ default_renderer , $ component , $ tpl , $ sortation_signal, $ compensate_col_index );
259272 return $ tpl ->get ();
260273 }
261274
262275 protected function renderTableHeader (
263276 RendererInterface $ default_renderer ,
264277 Component \Table \Data $ component ,
265278 Template $ tpl ,
266- ?Component \Signal $ sortation_signal
279+ ?Component \Signal $ sortation_signal ,
280+ int $ compensate_col_index ,
267281 ): void {
268282 $ order = $ component ->getOrder ();
269283 $ glyph_factory = $ this ->getUIFactory ()->symbol ()->glyph ();
@@ -276,18 +290,19 @@ protected function renderTableHeader(
276290 $ col_title = $ col ->getTitle ();
277291 if ($ col_id === $ sort_col ) {
278292 if ($ sort_direction === Order::ASC ) {
279- $ sortation = $ this -> txt ( ' order_option_generic_ascending ' );
293+ $ sortation = " ascending " ; // aria-sort should not be translated and always be in English
280294 $ sortation_glyph = $ glyph_factory ->sortAscending ("# " );
281295 $ param_sort_direction = Order::DESC ;
282296 }
283297 if ($ sort_direction === Order::DESC ) {
284- $ sortation = $ this -> txt ( ' order_option_generic_descending ' );
298+ $ sortation = " descending " ; // aria-sort should not be translated and always be in English
285299 $ sortation_glyph = $ glyph_factory ->sortDescending ("# " );
286300 }
287301 }
288302
289303 $ tpl ->setCurrentBlock ('header_cell ' );
290- $ tpl ->setVariable ('COL_INDEX ' , (string ) $ col ->getIndex ());
304+
305+ $ tpl ->setVariable ('COL_INDEX ' , (string ) $ col ->getIndex () + $ compensate_col_index );
291306
292307 if ($ col ->isSortable () && !is_null ($ sortation_signal )) {
293308 $ sort_signal = clone $ sortation_signal ;
@@ -312,10 +327,11 @@ protected function renderTableHeader(
312327 protected function renderActionsHeader (
313328 RendererInterface $ default_renderer ,
314329 Component \Table \Table $ component ,
315- Template $ tpl
330+ Template $ tpl ,
331+ int $ compensate_col_count ,
316332 ): void {
317333 if ($ component ->hasSingleActions ()) {
318- $ tpl ->setVariable ('COL_INDEX_ACTION ' , (string ) count ( $ component ->getColumns ()) );
334+ $ tpl ->setVariable ('COL_INDEX_ACTION ' , (string ) $ component ->getColumnCount () + $ compensate_col_count );
319335 $ tpl ->setVariable ('COL_TITLE_ACTION ' , $ this ->txt ('actions ' ));
320336 }
321337
@@ -330,6 +346,12 @@ protected function renderActionsHeader(
330346 $ tpl ->setVariable ('SELECTION_CONTROL_SELECT ' , $ default_renderer ->render ($ select_all ));
331347 $ tpl ->setVariable ('SELECTION_CONTROL_DESELECT ' , $ default_renderer ->render ($ select_none ));
332348 }
349+
350+ if ($ component instanceof Component \Table \Ordering) {
351+ if (!$ component ->isOrderingDisabled () && !$ component ->hasMultiActions ()) {
352+ $ tpl ->touchBlock ('header_rowselection_cell ' );
353+ }
354+ }
333355 }
334356
335357 /**
@@ -528,9 +550,6 @@ public function renderOrderingRow(Component\Table\OrderingRow $component, Render
528550 $ cell_tpl = $ this ->getTemplate ("tpl.orderingcell.html " , true , true );
529551 $ this ->fillCells ($ component , $ cell_tpl , $ default_renderer );
530552
531- $ drag_handle = $ this ->getUIFactory ()->symbol ()->glyph ()->dragHandle ();
532- $ drag_handle = $ default_renderer ->render ($ drag_handle );
533- $ cell_tpl ->setVariable ('DRAG_HANDLE ' , $ drag_handle );
534553
535554 if ($ component ->isOrderingDisabled ()) {
536555 return $ cell_tpl ->get ();
@@ -570,7 +589,6 @@ protected function fillCells(
570589 }
571590 $ cell_tpl ->setCurrentBlock ('cell ' );
572591 $ cell_tpl ->setVariable ('COL_TYPE ' , strtolower ($ column ->getType ()));
573- $ cell_tpl ->setVariable ('COL_INDEX ' , $ column ->getIndex ());
574592 $ cell_content = $ row ->getCellContent ($ col_id );
575593 if ($ cell_content instanceof Component \Component) {
576594 $ cell_content = $ default_renderer ->render ($ cell_content );
@@ -590,6 +608,14 @@ protected function fillCells(
590608 );
591609 $ cell_tpl ->setVariable ('ACTION_CONTENT ' , $ default_renderer ->render ($ row_actions_dropdown ));
592610 }
611+
612+ if ($ row instanceof Component \Table \OrderingRow) {
613+ if (!$ row ->isOrderingDisabled ()) {
614+ $ drag_handle = $ this ->getUIFactory ()->symbol ()->glyph ()->dragHandle ();
615+ $ drag_handle = $ default_renderer ->render ($ drag_handle );
616+ $ cell_tpl ->setVariable ('DRAG_HANDLE ' , $ drag_handle );
617+ }
618+ }
593619 }
594620
595621 /**
@@ -630,35 +656,50 @@ public function renderOrderingTable(Component\Table\Ordering $component, Rendere
630656 );
631657 }
632658
659+ // these column counts and index numbers are meant for aria attributes in the html tpl
660+ $ compensate_col_index = 1 ; // aria-colindex expects counting to start with 1, not 0
661+ // for column with checkbox and/or drag handle before first data column which is numbered 1.
662+ if ($ component ->hasMultiActions () || !$ component ->isOrderingDisabled ()) {
663+ $ compensate_col_index += 1 ; // checkbox & drag handle
664+ }
665+ if (!$ component ->isOrderingDisabled ()) {
666+ $ compensate_col_index += 1 ; // Position input
667+ }
668+
669+ $ compensate_col_count = 0 ; // count starts with 1, only needs to be compensated for special columns
670+ if ($ component ->hasMultiActions () || !$ component ->isOrderingDisabled ()) {
671+ $ compensate_col_count += 1 ; // checkbox & drag handle
672+ }
673+ if (!$ component ->isOrderingDisabled ()) {
674+ $ compensate_col_count += 1 ; // Position input
675+ }
676+ if ($ component ->hasSingleActions ()) { // adds column with action dropdown at the very end
677+ $ compensate_col_count += 1 ;
678+ }
679+
633680 $ tableid = $ this ->bindJavaScript ($ component ) ?? $ this ->createId ();
634- $ total_number_of_cols = count ($ component ->getVisibleColumns ());
635681
636682 if (!$ component ->isOrderingDisabled ()) {
637- $ total_number_of_cols = $ total_number_of_cols + 1 ;
638683 $ submit = $ this ->getUIFactory ()->button ()->standard ($ this ->txt ('sorting_save ' ), "" )
639684 ->withOnLoadCode (static fn ($ id ) => "document.getElementById(' $ id').addEventListener('click',
640685 function() {document.querySelector('# $ tableid form.c-table-ordering__form').submit();return false;}); " );
641686
642687 $ tpl ->setVariable ('FORM_BUTTONS ' , $ default_renderer ->render ($ submit ));
643688 $ tpl ->setVariable ('POS_INPUT_TITLE ' , $ this ->txt ('table_posinput_col_title ' ));
644- }
645689
646- if (!$ component ->hasMultiActions ()) {
647- $ tpl ->touchBlock ('header_rowselection_ordering_no_multi_actions ' );
648690 }
649691
650692 $ tpl ->setVariable ('ID ' , $ tableid );
651693 $ tpl ->setVariable ('TARGET_URL ' , $ component ->getTargetURL () ? $ component ->getTargetURL ()->__toString () : '# ' );
652694 $ tpl ->setVariable ('TITLE ' , $ component ->getTitle ());
653- $ tpl ->setVariable ('COL_COUNT ' , (string ) $ component ->getColumnCount ());
695+ $ tpl ->setVariable ('COL_COUNT ' , (string ) $ component ->getColumnCount () + $ compensate_col_count );
654696 $ tpl ->setVariable ('VIEW_CONTROLS ' , $ default_renderer ->render ($ view_controls ));
655697
656-
657698 $ columns = $ component ->getVisibleColumns ();
658699 foreach ($ columns as $ col_id => $ col ) {
659700 $ col_title = $ col ->getTitle ();
660701 $ tpl ->setCurrentBlock ('header_cell ' );
661- $ tpl ->setVariable ('COL_INDEX ' , (string ) $ col ->getIndex ());
702+ $ tpl ->setVariable ('COL_INDEX ' , (string ) $ col ->getIndex () + $ compensate_col_index );
662703 $ tpl ->setVariable ('COL_TITLE ' , $ col_title );
663704 $ tpl ->setVariable ('COL_TYPE ' , strtolower ($ col ->getType ()));
664705 $ tpl ->parseCurrentBlock ();
@@ -672,23 +713,26 @@ function() {document.querySelector('#$tableid form.c-table-ordering__form').subm
672713 ->withOrderingDisabled ($ component ->isOrderingDisabled ());
673714 }
674715
675- $ this ->renderActionsHeader ($ default_renderer , $ component , $ tpl );
716+ $ this ->renderActionsHeader ($ default_renderer , $ component , $ tpl, $ compensate_col_count );
676717 $ this ->appendTableRows ($ tpl , $ r , $ default_renderer );
677718
678719 if ($ component ->hasMultiActions ()) {
679- $ total_number_of_cols = $ total_number_of_cols + 2 ;
680720 $ multi_actions = $ component ->getMultiActions ();
681721 $ modal = $ this ->buildMultiActionsAllObjectsModal ($ multi_actions , $ tableid );
682722 $ multi_actions_dropdown = $ this ->buildMultiActionsDropdown (
683723 $ multi_actions ,
684724 $ component ->getMultiActionSignal (),
685725 $ modal ->getShowSignal ()
686726 );
727+
687728 $ tpl ->setVariable ('MULTI_ACTION_TRIGGERER ' , $ default_renderer ->render ($ multi_actions_dropdown ));
688729 $ tpl ->setVariable ('MULTI_ACTION_ALL_MODAL ' , $ default_renderer ->render ($ modal ));
689730 }
731+ if ($ component ->hasMultiActions () || !$ component ->isOrderingDisabled ()) {
732+ $ multi_action_col_span = count ($ component ->getVisibleColumns ()) + $ compensate_col_count ;
733+ $ tpl ->setVariable ('MULTI_ACTION_SPAN ' , (string ) $ multi_action_col_span );
734+ }
690735
691- $ tpl ->setVariable ('COLUMN_COUNT ' , (string ) $ total_number_of_cols );
692736 return $ tpl ->get ();
693737 }
694738
0 commit comments