DataTables:如果标题中有复选框和弹出控件,如何避免列排序?

时间:2014-09-13 21:55:09

标签: jquery twitter-bootstrap datatables

我有一个DataTables表,在某些标题列中有复选框和弹出窗口。 (另外我也使用FixedColumn和ColReorder插件)。我在jsfiddle中的模型是在底部

我的问题是,如果用户尝试检查复选框或按下弹出窗口,则排序事件将接管所有内容。 jsfiddle页面无法正常运行,因为在我的应用程序中,我收到了复选框点击的事件,但当时为时已太晚,排序也会发生。 排序图标只是标题单元格的背景CSS,而排序事件是由DataTables为整个标题单元格注册的。

计划解决这个问题:

  1. 注册处理程序并尝试阻止Datatables自己的处理程序的运行。截至目前,如果我还为标题单元格注册事件处理程序,我只会在DataTable的处理程序之后获取事件,事件按注册顺序传递。我还为复选框和弹出窗口本身注册了处理程序,但这些也只在DataTables的处理程序(冒泡)之后提供。 这可能只有在我能以某种方式在DataTables自己的处理程序之前注册我的处理程序时才能工作,但我还没有找到一个切入点来做到这一点。当事件被注册时,应该已经生成了表DOM。现在我看到太晚了,我只能注册。
  2. 找到我可以取消DataTables排序的API调用点。订单活动(http://datatables.net/reference/event/order)似乎是在事后,我没有看到取消的方式。
  3. 在某些时候,我重新构建了非固定列标题以包含两行:顶行用于排序,底部包含我的checbox和弹出控件。这似乎有效,但事实证明它不适用于ColReorder插件。我需要这个插件,它只重新排序标题的顶行,底部停留在那里。如果我能解决这个问题,那也是一个解决方案。
  4. http://jsfiddle.net/csabatoth/pgue1sf5/8/

    var initPage = function () {
        var columnsArray = [
            { "title": "index", "class": "dt-center" },
            { "title": "lastname", "class": "dt-head-center dt-body-left" },
            { "title": "firstname", "class": "dt-head-center dt-body-left" },
            { "title": '<div>foo1</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-head-center dt-body-left" },
            { "title": '<div>foo2</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
            { "title": '<div>foo3</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
            { "title": '<div>foo4</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
            { "title": '<div>bar1</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
            { "title": '<div>bar2</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" },
            { "title": '<div>bar3</div><input type="checkbox" class="filterchk" checked="checked">&nbsp;<select class="paramsel"><option value="1" selected="selected"/><option value="2"/><option value="3"/></select>', "class": "dt-center rulecolumn" }
        ];
    
        var dataArray = [
            [ 1, "aaa", "rrr", "x", "x", "x", "x", "x", "x", "x" ],
            [ 2, "bbb", "qqq", "x", "x", "x", "x", "x", "x", "x" ],
            [ 3, "ccc", "ppp", "x", "x", "x", "x", "x", "x", "x" ],
            [ 4, "ddd", "ooo", "x", "x", "x", "x", "x", "x", "x" ],
            [ 5, "eee", "nnn", "x", "x", "x", "x", "x", "x", "x" ],
            [ 6, "fff", "mmm", "x", "x", "x", "x", "x", "x", "x" ],
            [ 7, "ggg", "lll", "x", "x", "x", "x", "x", "x", "x" ],
            [ 8, "hhh", "kkk", "x", "x", "x", "x", "x", "x", "x" ],
            [ 9, "iii", "jjj", "x", "x", "x", "x", "x", "x", "x" ]
        ];
    
        viewModel.table = $('#MyTable').DataTable({
            dom: "Rrtip",
            autoWidth: false,
            deferRender: true,
            info: true,
            lengthChange: false,
            ordering: true,
            orderMulti: true,
            orderFixed: {
                pre: [0, 'asc'],
                post: [1, 'asc']
            },
            paging: true,
            pagingType: "full_numbers",
            renderer: "bootstrap",
            processing: true,
            scrollX: true,
            scrollY: false,
            searching: false,
            columns: columnsArray,
            data: dataArray,
            initComplete: function (settings, json) {
                viewModel.attachTableEventHandlers();
            },
            displayLength: 5,
            colReorder: {
                fixedColumnsLeft: 3,
                fixedColumnsRight: 0
            }
        });
        new $.fn.dataTable.FixedColumns(viewModel.table, {
            leftColumns: 3
        });
    

3 个答案:

答案 0 :(得分:8)

我只阅读了问题的标题及其前3行(所以我希望它有所帮助),但是如果您需要的只是停止点击的传播,即使是位于里面的点击复选框也是如此您应该将onclick="event.stopPropagation()"添加到该复选框,或者更好的是可以在IE(旧)和其他浏览器上运行的函数

//taken from my yadcf plugin, you can call it in your code like this:
//yadcf.stopPropagation(event)
function stopPropagation(evt) {
    if (evt.stopPropagation !== undefined) {
        evt.stopPropagation();
    } else {
        evt.cancelBubble = true;
    }
}

并在您的复选框中添加onclick="stopPropagation(event)"

对于您的选择,您还应添加onmousedown="...",使其如下所示:

<select onclick="event.stopPropagation()"  
        onmousedown="event.stopPropagation()"

这是working jsfiddle,我只修复了第一个复选框/选择

答案 1 :(得分:1)

重申我的尝试:

  1. 我无法阻止DataTables注册到该点击事件或劫持该点击。
  2. 我也找不到API,我可以阻止它。
  3. 复杂的标题首先看起来是一个很好的解决方案,直到我意识到它不能与ColReorder一起使用。
  4. 所以我能想到的唯一方法就是深呼吸并破解DataTables本身:

    function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
    {
        return;
    

    所以我将return语句添加到函数体的开头。这将阻止收听者的附着。我将不可访问的代码留在返回下面,以尽可能减少修改。 这个修改的问题:

    1. 每次升级DataTables时,我都需要重复这个黑客攻击。
    2. 我也需要在最小化版本上执行hack: function Ka(a,b,c,d){return;var e=a.aoColumns[c];Ta(b ...
    3. 既然点击不起作用,我需要附加我自己的听众,如果点击不在输入元素上,则以编程方式调用排序。

      $('.dataTables_scrollHead thead th').on('click', function (e) {
          if ($(e.target).hasClass("yadcf-filter-reset-button") || $(e.target).hasClass("paramchk") || $(e.target).hasClass("paramsel") || $(e.target).is("option"))
              return;
          var colIdxStr = $(this).attr("data-column-index");
          var colIdx = parseInt(colIdxStr, 10);
          viewModel.sortColumn(colIdx, e.shiftKey);
      });
      
    4. 你在这里看到的是yacdf过滤器或弹出窗口(&#34;选项&#34;)或标有&#34; paramsel&#34;的编辑框的组合。由我上课或复选框标有&#34; paramchk&#34; class by将收到点击事件,我不会排序。但是否则我需要以编程方式排序。如果按下shift键,以下代码甚至会尝试支持多列排序。

      viewModel.sortColumn = function (colIdx, shiftPressed) {
          var order = viewModel.table.order();
          var direction = "";
          for (var i = 0; i < order.length; i++) {
              if (order[i][0] == colIdx) {
                  direction = order[i][1];
                  break;
              }
          }
          if (direction === "")
              direction = "desc";
          else if (direction === "desc")
              direction = "asc";
          else
              direction = "";
          if (shiftPressed) {
              order.push([colIdx, direction]);
              viewModel.table.order(order).draw();
          } else {
              viewModel.table.order([colIdx, direction]).draw();
          }
      }
      

      另一个需要的部分是使用列索引装饰标题单元格:

      viewModel.table = $('#reportTable').DataTable({
          ...
          headerCallback: function (thead, data, start, end, display) {
              $(thead).find("th").each(function (thindex, thelement) {
                  $(thelement).attr("data-column-index", thindex);
              });
          }
      });
      

      最后这一切都很复杂,请不要犹豫告诉我它是否可以变得更简单,或者你知道任何优雅或其他解决方案。

答案 2 :(得分:0)

不确定这是否有帮助,但是我也遇到类似的情况-我的标题包含一个下拉按钮,该按钮会打开一个带滑块的.dropdown-pane窗格元素。滑块的每次移动都会引起列排序。 我很拼命,写了近100行试图解除绑定并覆盖此行为。最后,我要么使用preventDefault()禁用排序和滑块,(显然,这不是解决方案),否则什么都不起作用。 出乎意料的是,经过数小时的错误和尝试,我发现这可行:

$('.dropdown-pane').click(function() {
return false;
});