Infinite Scroll: Scroll to Row # not currently loaded in the DOM

Infinite Scroll: Scroll to Row # not currently loaded in the DOM

DanielpDanielp Posts: 7Questions: 3Answers: 0

Hi,

I'm using DataTables, Editor, and Scroller on a page using Server Side Infinite Scroll. I can use the following to scroll to row number 80 and selected it as long as the table row is currently in the DOM.

table_data.row(80).scrollTo();
table_data.row(80).select();

However, If I try going to row number 90 nothing happens as row number 90 is not currently loaded into the DOM.

table_data.row(90).scrollTo();
table_data.row(90).select();

I have looked all over the forums and stackoverflow and I have found nothing that works or addresses my situation.

I need to be able to jump to or scroll to a result row regardless if it is currently loaded into the DOM or not. Are there any pointers you have give?

Thanks.

-Daniel

Answers

  • allanallan Posts: 52,508Questions: 1Answers: 8,014 Site admin

    Hi Daniel,

    Server Side Infinite Scroll

    There is no such thing as infinite scroll in DataTables I'm afraid. Could you give me a link to the page you are working on so I can take a look at the configuration and also see what the error is?

    One thing you need to be really careful with when using server-side processing is that it is asynchronous - so if your scrollTo command requires that new data be loaded, you need to wait for that data to be loaded before you can select it (draw could be used for that for example).

    However, if it isn't even loading row 90, there is something else going on.

    Allan

  • DanielpDanielp Posts: 7Questions: 3Answers: 0

    Allan,

    Maybe I'm not using the right nomenclature when I say "Server Side Infinite Scroll".

    I'm talking about using DataTables, Editor, and Scroller like I outlined in this previous post where I found a bug: https://datatables.net/forums/discussion/32538 and you had a nightly patch for it.

    So I have a large result set (25K rows) and "Scroller" creates a "view window" that is a subset (it looks like it is just the first 80 rows in my case) of the whole result.

    Using UI I can just slide down to the row I want to display and DataTables will fetch everything and display the record I want. I can go from 1 to 25K with no issues when using the UI slider.

    I want to programmatically scroll to the record in the result set. I can use the following to scroll to row number 80 and selected it, but if the row number exceeds 80 it does not fetch and scroll to the row.

    table_data.row(80).scrollTo();
    table_data.row(80).select();

    However, I need to be able to jump to or scroll to a row number regardless if it is currently fetched into the DOM or not. I hope you understand what I am getting at. I have found code that will scroll me to the last record but I wnat to go to any row in the result set.

    Thanks.

    -Daniel

  • faizu88faizu88 Posts: 2Questions: 1Answers: 0

    Brother!
    Better try this.

    $('#example').DataTable().scroller().scrollToRow(81);

  • allanallan Posts: 52,508Questions: 1Answers: 8,014 Site admin

    That line appears to work okay on this example.

    Do you have a link to a test case that shows the issue please?

    Allan

  • DanielpDanielp Posts: 7Questions: 3Answers: 0

    faizu88 thanks that worked perfect!

    However, table_data.row(#).select() does not work when I call it after I call scroller().scrollToRow(#)

    Any ideas?

    P.S. I have a much more detailed post but this stupid CMS lost 20 minutes worth of typing work when I hit preview...

  • allanallan Posts: 52,508Questions: 1Answers: 8,014 Site admin

    However, table_data.row(#).select() does not work when I call it after I call scroller().scrollToRow(#)

    Is the data loading asynchronous in your table (very likely if using server-side processing)? If so, that is likely the issue - you will need to select the row after the data has loaded - since otherwise the row doesn't exist on the client-side and thus can't be selected.

    Allan

  • DanielpDanielp Posts: 7Questions: 3Answers: 0

    Allen,

    That was part of my post that got lost.

    I was looking for a postback or something I could hook into that would trigger the selection after the scroller().scrollToRow(#) is done updating.

    I did try the .on('page' postback but that did not work.

    -Daniel

  • allanallan Posts: 52,508Questions: 1Answers: 8,014 Site admin

    Try listening for draw - for example you could use:

    table
      .one( 'draw', function () {
        ... select
      } )
      .scroller().scrollToRow( ... );
    

    Assuming that the row id specified is in the new display, I think that should work.

    Allan

  • DanielpDanielp Posts: 7Questions: 3Answers: 0

    Hi Allan,

    I hate to keep coming back here but I keep running into issues with scrolling to a row and highlighting it. Again I'm using Client Server mode and this time I'm cutting and pasting all my code here for your review.

    This is for a CSV File Import "Wizard" and the idea is to scroll to and highlight the next row of data where there is a validation issue.

    The callback function validate_data_callback is where I'm running into issues.

    The issue I'm still dealing with is the scrolling to a row #ID (in this case the next error record) does not behave consistently or in what I would think is an intuitive manor.

    For example if you have deleted too many records previously and try and scroll to the next highlighted record it scrolls too far ahead by exactly the number of rows you have deleted.

    I think this has to do with the DataTables API using two different index attributes for scrolling and for selecting/highlighting that get out of sync when deleting records.

    Another issue this is driving me crazy is if I tell it to scroll to an #ID that is already in the DOM then it then scrolls backwards to an #ID number I didn't specify. This whole thing should not be this hard, but I keep running into one thing after another.

    Any guidance would be helpful. I have been using JavaScript and JQuery for years and I can normally figure things out, but I'm just not getting it here.

    -Daniel

            var table_layout;
            var table_data;
            var editor_layout;
            var editor_data;
            var options = {};
            var error_list;
    
        
            var keys = Object.keys(options);
    
            $(document).ready(function(){
    
            editor_layout = new $.fn.dataTable.Editor({
                table: '#layout',
                ajax: {'url': layout_crud_url,'cache': true},
                idSrc: 'id',
                fields: [
                { name: 'csv_order',
                  data: 'csv_order',
                  label: 'Column#' },
                { name: 'csv_name',
                  data: 'db_name',
                  label: 'Column Name' },
                { name: 'display_name',
                  data: 'display_name',
                  label: 'Masked Name' },
                { name: 'user_datatype',
                  data: 'user_datatype',
                  type:  'select', 
                  options: Object.keys(options),
                  label: 'Data Type' },
                { name: 'user_dataformat',
                  data: 'user_dataformat',
                  type:  "select",
                  options: [],
                  label: 'Data Format' },
                ],
            });
    
            table_layout = $('#layout').DataTable({
                dom: 'tp',
                ajax: {'url': get_layout_url,'cache': true},
                pageLength: 15,
                columns: [
                { data: 'csv_order', orderable: false },
                { data: 'csv_name', orderable: false },
                { data: 'display_name', orderable: false },
                { data: 'user_datatype', orderable: false },
                { data: 'user_dataformat', orderable: false },
                ],
                });
    
                editor_layout.dependent( 'user_datatype', function (val) {
                if (val != null) {
                    editor_layout.field('user_dataformat').update(options[val]);
                }
                });
    
                $("select").selectmenu({
                select: function(e){
                    $(e.target).trigger('blur');
                }
                });
    
                // Activate an inline edit on click of a table cell
                $('#layout').on( 'click', 'tbody td:not(:first-child, :nth-child(2))', function (e) {
                editor_layout.inline( this, { onBlur: 'submit' } );
                });
    
                $('#layout').on( 'submitComplete', function (e) {
                editor_data.fnReloadAjax();
                editor_data.fnDraw();
                });
    
            editor_data = new $.fn.dataTable.Editor({
                table: '#staging',
                ajax: {'url': data_crud_url,'cache': true},
                idSrc: 'id',
                fields: [
                            { name: 'c0',
                  data: 'c0',
                  label: 'CrimeDate' },
                            { name: 'c1',
                  data: 'c1',
                  label: 'CrimeTime' },
                            { name: 'c2',
                  data: 'c2',
                  label: 'CrimeCode' },
                            { name: 'c3',
                  data: 'c3',
                  label: 'Location' },
                            { name: 'c4',
                  data: 'c4',
                  label: 'Description' },
                  label: 'Total Incidents' },
                            ],
            });
    
            table_data = $('#staging').DataTable({
                rowId: 'id',
                dom: 'BrtSip',
                serverSide: true,
                scrollY: 300,
                deferRender: true,
                scroller: true,
                scrollCollapse: false,
                ajax: {'url': get_data_url,'type': 'POST','cache': true},
                pageLength: 20,
                columns: [
                {
                data: null,
                defaultContent: '',
                className: 'select-checkbox',
                orderable: false
                },
                            { data: 'c0', orderable: false },
                            { data: 'c1', orderable: false },
                            { data: 'c2', orderable: false },
                            { data: 'c3', orderable: false },
                            { data: 'c4', orderable: false },
                            ],
                select: {
                style:    'os',
                selector: 'td:first-child'
                },
                buttons: [
                { extend: 'edit',   editor: editor_data },
                { extend: 'remove', editor: editor_data },
                ],
            });
    
            // Activate an inline edit on click of a table cell
            $('#staging').on( 'click', 'tbody td:not(:first-child)', function (e) {
                //editor_data.inline( this );
            });
    
                $("#edit_layout").button()
                .click(function() {
                    $("#div_edit_layout").show();
                    $("#div_edit_data").hide();
                    $("#edit_layout").button("refresh");
                    $("#edit_data").button("refresh");
                });
    
                $("#edit_data").button()
                .click(function() {
                    $("#div_edit_layout").hide();
                    $("#div_edit_data").show();
                    $("#edit_layout").button("refresh");
                    $("#edit_data").button("refresh");
                });
    
                $("#validate_data").button()
                .click(function() {
                    validate_data();
                });
    
                $("#div_edit_layout").show();
                $("#div_edit_data").hide();
                $("#edit_layout").button("refresh");
                $("#edit_data").button("refresh");
    
            });
    
            function validate_data()
            {
                    table_data.rows(".selected").deselect();
                error_list = null;
                    var searchParm = [];
                    $.get(validate_data_url, searchParm, validate_data_callback, 'text');
                    return;
        
            }
    
            function validate_data_callback(data) {
                console.log(data.toString());
                try {
                error_list = $.parseJSON(data);
                if (error_list.validation_error_row_id != null) {
                    if ($('#'+parseInt(error_list.validation_error_row_id)).length) {
                    console.log('found');
                    table_data.row('#'+parseInt(error_list.validation_error_row_id)).select();
                    table_data.row('#'+parseInt(error_list.validation_error_row_id)).scrollTo();
                    }else{
                    console.log('notfound');
                    $('#staging').one( {"draw.dt": function() {setTimeout(function() {
                            var rowindex = table_data.row('#'+parseInt(error_list.validation_error_row_id)).index();
                            table_data.row('#'+parseInt(error_list.validation_error_row_id)).select();
                            //table_data.row('#'+parseInt(error_list.validation_error_row_id)).scrollTo();
                        },600);}} );
                    table_data.scroller().scrollToRow(parseInt(error_list.validation_error_row_id));
                    }
                    $("#div_edit_layout").hide();
                    $("#div_edit_data").show();
                    $("#edit_layout").button("refresh");
                    $("#edit_data").button("refresh");
                }else{
                    alert(error_list.validation_error_message);
                }
                } catch (e) {
                error_list = null;
                alert(e)
                }
            }
    
        </script> 
    
  • allanallan Posts: 52,508Questions: 1Answers: 8,014 Site admin

    Are you able to give me a link to a page (http://live.datatables.net or JSFiddle if you can't host your own code) so I can debug the issue directly.

    I realise this is frustrating and I apologies for any bugs in the software. Scroller add an awful lot of complexity...

    I'm a little concerned about line 191 in the above code giving that it might overlap with something else trying to do basically the same thing.

    Allan

This discussion has been closed.