muonw / muonw-powertable

▦ PowerTable is a Svelte component that turns JSON data into an interactive HTML table. Inspired by DataTables. Powered by Svelte.
https://muonw.github.io/muonw-powertable/
Other
218 stars 13 forks source link

function to scroll to specific row #24

Closed haenf closed 1 year ago

haenf commented 1 year ago

Hi muonw, is there a way to program in javascript a scroll to a specific row. I have clickable cells (see my issue"https://github.com/muonw/muonw-powertable/issues/19") that refer to other cells in other rows. The idea is that you can jump from cell to cell with a scrolling function.

I know the row number and the cell I clicked in, I know the value of the cell I want to scroll to, but I can't find a way to realize the actual scroll in code...

To illustrate it: when I click on 1 the row 2 must scroll to the top of view.

image

muonw-public commented 1 year ago

If you would like the page to scroll to the target row, anchor links might suffice. But if you need JavaScript, scrollIntoView should do it. Of course, you'll need to set the id attribute of the target element to some unique value. If the target row is not in the same page, this alone will not work and you will need to do some processing to first change the page and then scroll. The component itself doesn't have a built-in function for scrolling.

If that was not what you meant and instead you would like the range of the rendered rows change such that the target row would appear at the index that you clicked (like the table below), that might mess with the logic of pagination (in the current version).

Before click After click
1 3
2 [Link] 4 [Target]
3 5
4 [Target] 6
5 7
haenf commented 1 year ago

Anchor links are too static for my purpose. I use scrollIntoView already in the 'non-powertable' html-tables in my application, and it works fine. But in PowerTable I can't make it work...

The problem I try to solve is that when I click a cell in PowerTable the cell gets a background color and everything works fine, except that the refresh of PowerTable sets the view back to the top of the table. So if the cell is in the lower part of the table, it disappears out of sight, which is confusing for the user.

I added a div with an ID to the "rowNr" column (1) and added the row number to the onclick data as well (2).

image

The cellClickHandler calls the scrollToSelected function with the row number as parameter - which is converted to the ID format of the div in the "rowNr" column:

    window.cellClickHandler = (data) => {
        selectedRowNr = data.split('|')[0];
        selectedValue = data.split('|')[1];  
        refreshTable = !refreshTable; 
        scrollToSelected(selectedRowNr);
    }

    function scrollToSelected(rowNr) {

        let rowNrStr = 'row_' + rowNr;

        curRow = document.querySelector("[id=" + CSS.escape(rowNrStr) + "]");

        if (curRow !== null) { 
            // scroll to the selected row
            curRow.scrollIntoView({
                    behavior: 'smooth',
                    block: 'start',
                    inline: "nearest"
                });

            // higlight
            curRow.style.backgroundColor = "rgba(255,250,0,0.35)";
        }
    }

But the curRow stays null, so scrollIntoView doesn't do anything. I suspect the cause of the problem is the way I use the ID in the div, but I can't figure it out... What do I do wrong?

muonw-public commented 1 year ago

[...] everything works fine, except that the refresh of PowerTable sets the view back to the top of the table

I'm not sure what you mean by refresh. How/when is the table being refreshed?

But the curRow stays null, so scrollIntoView doesn't do anything

If curRow is null, it means that you're not getting the element. Simplifying the code can help with troubleshooting: You can hard code an id and try to get the element with that id in cellClickHandler.

window.cellClickHandler = (id) => {
    console.log( document.getElementById(id) );
}

Also, I think you should stop the propagation of the click event, or use a <button> element instead of <a> and style it to look like a link.

haenf commented 1 year ago

The refresh of the table is done after a cell in a row is selected to make the highlight for that cell visible:

window.cellClickHandler = (data) => {
        if (data.split('|').length > 1) {
            selectedRowNr = data.split('|')[0];
            selectedValue = data.split('|')[1];
        }   
        refreshTable = !refreshTable; 
        scrollToSelected(selectedRowNr);
    }

and

{#key refreshTable}
    <div class="MuonW PowerTable ptStyles1">
        <PowerTable {ptData} {ptInstructs} {ptOptions} />
    </div>
{/key}

To highlight the cell:

function parsingFunctions(pageData) { 
    pageData = makeLinkedValue(pageData);
    pageData = setCellStyle(pageData);
    return pageData;
}

and

function setCellStyle(pageData) {

    pageData.forEach((row, rowIndex) => {

        if (selectedValue == stripHtml(row['itemType/property']) && selectedRowNr == rowIndex) {
            row['itemType/property'] = `<div class="green">${row['itemType/property']}</div>`
        }

    });
    return pageData;
}

The cells in the "rowNr" column in the table hold a <div> with the number of the row as id: <div id="row_38"> (for instance).

When I click on that cell, the number of the row is used as parameter for scrollToSelected:

function scrollToSelected(rowNr) {

    let rowNrStr = 'row_' + rowNr;

    curRow = document.querySelector("[id=" + CSS.escape(rowNrStr) + "]");
    console.log(curRow);

    curRow.scrollIntoView({
        behavior: 'instant',
        block: 'start',
        inline: "nearest"
    });
}

The console.log shows that curRow is <div id="row_38"> (I don't know why that didn't work before...). So far all works fine, but the scrollIntoView doesn't do anything... Why? Is there a difference for scrolling of 'plain html tables' and PowerTable? Or something else?

muonw-public commented 1 year ago

While I don't have a solution to get your current code working, I can help you achieve similar results using a different approach. I think refreshing the table and adding event attributes via customParse function are not ideal or necessary. The new release (2.2.0) includes an example that is inspired by your idea of navigating to different rows and offers a working solution with a similar functionality.

https://muonw.github.io/muonw-powertable/examples/example11

haenf commented 1 year ago

Yes, that's exactly what I meant! Thank you for your effort!