tabulator icon indicating copy to clipboard operation
tabulator copied to clipboard

SelectRange: keybinding-navigation: autoscroll does not work with column groups

Open EduenSarceno opened this issue 6 months ago • 1 comments

Describe the bug SelectRange.js#autoScroll calculates the rect to scroll relative to the nearest column group. This bugs the scrollbar when navigating from the last cell of the current column group to the first cell of the next column group.

Tabulator Info

  • Which version of Tabulator are you using? 6.2.4

Reproducible code

index.html

<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/tabulator.min.css" />
<script src="https://unpkg.com/[email protected]"></script>
<div style="margin: 0.5em 0">
<input type="button" value="prev" id="prev"/>
<input type="button" value="next" id="next"/>
</div>
<div id="tabulator-root"></div>

app.js

(function (global) {
	let tabulator;
	function initialize() {
	  tabulator = new Tabulator("#tabulator-root", {
		columns: [
		  {
			title: "A",
			columns: [
			  { title: "A1", field: "A.1", minWidth: 300 },
			  { title: "A2", field: "A.2", minWidth: 300 },
			  { title: "A3", field: "A.3", minWidth: 300 },
			],
		  },
		  {
			title: "B",
			columns: [
			  { title: "B1", field: "B.1", minWidth: 300 },
			  { title: "B2", field: "B.2", minWidth: 300 },
			  { title: "B3", field: "B.3", minWidth: 300 },
			],
		  },
		],
		width: "100dvw",
		height: "calc(100dvh - 4em)",
		selectableRange: 1,
		selectableRangeColumns: false,
		selectableRangeRows: false,
		editTriggerEvent: "dblclick",
		data: Array(15)
		  .fill(null)
		  .map(() => ({ id: crypto.randomUUID() })),
	  });
	  console.log(tabulator)
	  bind_events();
	}
	initialize();
  
	global.next = next;
	global.prev = prev;
  
	// prettier-ignore
	function next() {
	  tabulator.modules.selectRange.keyNavigate('right', new KeyboardEvent("keydown"))
	}
  

	// prettier-ignore
	function prev() {
	  tabulator.modules.selectRange.keyNavigate('left', new KeyboardEvent("keydown"))
	}
  
	function bind_events() {
	  let elem;
	  elem = document.querySelector("#prev");
	  elem.onclick = prev;
	  elem = document.querySelector("#next");
	  elem.onclick = next;
	}
  })(window);
  

https://jsfiddle.net/mt364Lkv/1/

To Reproduce

A step by step guide to recreate the issue in your JS Fiddle or Codepen:

  1. Go to https://jsfiddle.net/mt364Lkv/1/
  2. Click on any cell
  3. navigate in the table using the arrow keys

output

Expected behavior When the current active range is at the end of group 'A' (at cell 'A3'), if we press the key "right-arrow", the viewport (scrollbar) must be at the first cell of group 'B' (cell 'B1')

Patch

src/js/modules/SelectRange/SelectRange.js

diff --git a/src/js/modules/SelectRange/SelectRange.js b/src/js/modules/SelectRange/SelectRange.js
--- a/src/js/modules/SelectRange/SelectRange.js
+++ b/src/js/modules/SelectRange/SelectRange.js
@@ -693,11 +693,16 @@ export default class SelectRange extends Module {
 		}
 		
 		rect = {
-			left: column.offsetLeft,
-			right: column.offsetLeft + column.offsetWidth,
+			left: 0,
+			right: 0,
 			top: row.offsetTop,
-			bottom: row.offsetTop + row.offsetHeight,
+			bottom: row.offsetTop + row.offsetHeight
 		};
+		// Preconditions: all columns (.tabulator-col) must be relative placed (`position: relative`)
+		for (let col = this.getColumnByRangePos(range.end.col); col && col.type === 'column'; col = col.parent) {
+			rect.left += col.element.offsetLeft
+		}
+		rect.right = rect.left + column.offsetWidth
 		
 		view = {
 			left: tableHolder.scrollLeft,
@@ -705,7 +710,7 @@ export default class SelectRange extends Module {
 			top: tableHolder.scrollTop,
 			bottom:	tableHolder.scrollTop +	tableHolder.offsetHeight - this.table.rowManager.scrollbarWidth,
 		};
-		
+
 		if (rowHeader) {
 			view.left += rowHeader.offsetWidth;
 		}

Live demo at:

https://jsfiddle.net/mt364Lkv/2/

EduenSarceno avatar Aug 21 '24 01:08 EduenSarceno