如何在 .draw() 之后保持 jQuery DataTables 滚动位置

Posted

技术标签:

【中文标题】如何在 .draw() 之后保持 jQuery DataTables 滚动位置【英文标题】:How to maintain jQuery DataTables scroll position after .draw() 【发布时间】:2015-02-24 03:44:57 【问题描述】:

我正在将 jQuery Datatables 插件用于小表(12 行)。一些<input type="text" ... 字段允许编辑。当输入字段失去焦点时,我需要验证其值并可能更改字段值。如果不发出 .draw() 之后,我无法让 DataTables 识别修改后的输入字段值,但这会导致表格滚动到表格顶部。

有没有办法在发出 .draw() 后保持当前滚动位置?

$('#mytable').on('blur', 'input', function (e) 

    var inputFieldId = this.id;
    var inputFieldVal = $(this).val();

     ... perform validation of field value ... 

    $('#mytable').DataTable().rows().invalidate().draw();
);

编辑

我看到有人试图做与我相同的事情,他们表示以下代码对他们有用。这似乎是完成我需要的一种非常简单的方法,但我自己总是得到 scrollTop = 0 。有人知道我如何获取当前选定行的行索引吗?

var scrollPos = $(".dataTables_scrollBody").scrollTop();
$('#mytable').DataTable().rows().invalidate().draw(false);
$(".dataTables_scrollBody").scrollTop(scrollPos);

【问题讨论】:

对不起,我没有看到您的更改,您的代码是正确的,但请尝试使用 scrollTo() $(".dataTables_scrollBody").scrollTo('#IDROW')。其中 'IDROW' 是 ROW 的 ID,或者只是您更改的输入的 ID 万一你有多个具有相同className的dataTables,你应该使用ID选择器$("#divContrainer1 > .dataTables_scrollBody").scrollTop() 是的,你可以这样做。有一个肮脏的黑客,但你可以。在下面寻找我的答案。 【参考方案1】:
var table = $('table#example').DataTable(
    "preDrawCallback": function (settings) 
        pageScrollPos = $('div.dataTables_scrollBody').scrollTop();
    ,
    "drawCallback": function (settings) 
        $('div.dataTables_scrollBody').scrollTop(pageScrollPos);
    
);

这似乎对我有用。我只需要在绘制表格后找到div.dataTables_scrollBody

【讨论】:

正确答案。 节省了我的时间。谢谢 我认为这是一个更好的答案。对我很有用。这是一个简单的即插即用,你就完成了。如果在选择滚动体之前添加表格 ID,会更安全。 $('table#example div.dataTables_scrollBody').scrollTop(); 我发现当我使用粘性标题时,有时会在页面顶部添加另一个表格标题。如果我将drawCallback 包装在setTimeout 中并将其设置为一个小的间隔,它将避免它。 tableConfig.drawCallback = () => setTimeout(() => $('div.dataTables_scrollBody').scrollTop(pageScrollPos);, 50);【参考方案2】:

只是想在此处添加此内容,尽管情况略有不同 - 它适用于我的情况,并且可能对到达这里寻找答案的其他一些人有用。

我正在使用服务器端处理并使用table.ajax.reload() 每 10 秒刷新一次表数据。这个函数接受一个参数来保持当前的分页值,但不能保持滚动位置。该解决方案与 OP 提到的解决方案非常相似,并在回调中设置滚动位置。不知道为什么它对他不起作用,但这是我成功使用的间隔代码:

setInterval( function () 
    scrollPos = $(".dataTables_scrollBody").scrollTop();
    myTable.ajax.reload(function() 
        $(".dataTables_scrollBody").scrollTop(scrollPos);
    ,false);
, 10000 );

【讨论】:

非常简单的解决方案【参考方案3】:

我使用 DataTables 1.10 解决的方法是使用preDrawCallBack 保存 ScrollTop 位置,然后使用DrawCallback 设置它。

var pageScrollPos = 0;

var table = $('#example').DataTable(
  "preDrawCallback": function (settings) 
    pageScrollPos = $('body').scrollTop();
  ,
  "drawCallback": function (settings) 
    $('body').scrollTop(pageScrollPos);
  
);

【讨论】:

【参考方案4】:

如果您将page 参数传递给绘图函数,表格将不会滚动移动,但会从.DataTable 源重新读取。例如。在“保存”更新 DataTable 的数据之后:

$("your-selector").DataTable().row(t_itemid).invalidate();
$("your-selector").DataTable().row(t_itemid).draw('page');

注意:我在 DataTable 实例化中使用了 id 列,这使得直接处理单行变得容易。但我相信page 参数会给出想要的结果。

【讨论】:

$table.draw('page') 比其他任何解决方案都好用。直接设置 scrollTop 会滚动,但也会使数据表对象失去对其所在位置的跟踪,并且其他控件会误报数据,例如正在显示的开始/结束行等 非常适合我。【参考方案5】:

我不认为你可以这样做,但你可以使用回调函数来代替:

$(document).ready(function() 
    var selected = [];

    $("#example").dataTable(
        "processing": true,
        "serverSide": true,
        "ajax": "scripts/ids-arrays.php",
        "rowCallback": function( row, data ) 
            if ( $.inArray(data.DT_RowId, selected) !== -1 ) 
                $(row).addClass('selected');
            
        
    );

    $('#example tbody').on('click', 'tr', function () 
        var id = this.id;
        var index = $.inArray(id, selected);

        if ( index === -1 ) 
            selected.push( id );
         else 
            selected.splice( index, 1 );
        

        $(this).toggleClass('selected');
     );
 );

参考:https://datatables.net/examples/server_side/select_rows.html

【讨论】:

谢谢。我使用有人说为他们工作的解决方案编辑了我的帖子,但我的 scrollTop 始终等于 0。您在编辑的示例中看到任何优点吗?我想我需要将 scrollTop 设置为当前选定的行索引,但是鉴于我的事件触发器,我不确定如何获取当前行索引。我还没有尝试过你的例子,因为我不完全理解它是如何工作的。 您可以为您的行元素之一添加 ID 属性,然后是 $('body').scrollTo('#target');编辑元素后。如果我的解释不够清楚,请告诉我。【参考方案6】:

这个黑客怎么样?不涉及scrollTop()先打开jquery.dataTables.js 找这行,去掉:

divBodyEl.scrollTop = 0

然后将以下代码放在您的 draw()/clear() 调用之前:

var $tbl=$('#my_table_id');
if (!document.getElementById('twrapper')) $tbl.wrap( '<div id="twrapper" style="display:block; height:'+$tbl.height()+'px;"></div>' );
else $('#twrapper').css('height',$tbl.height()+'px');

我花了一些时间才弄清楚这一点。

【讨论】:

【参考方案7】:

以下代码在 Datatables 服务器端重新加载时保留滚动位置。

var table =  $('#mytable').DataTable();

var start_row = table.scroller.page()['start'];

table.ajax.reload(function () 

    table.scroller().scrollToRow(start_row, false);

, false);

【讨论】:

以上是关于如何在 .draw() 之后保持 jQuery DataTables 滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

如何将SpriteBatch.draw()等效为Sprite.draw()?

如何从jquery更新datatable对象

如何在 jQuery 弹跳下“保持”元素?

使用重载方法等待

JS / Canvas - 如何仅在按下键时更新 draw() 函数?

cocos2d-x 2.0下怎样让BOX2D DEBUG DRAW的方法笔记