将排序功能与 header 列点击分开的正确方法是什么?

What is the correct way to separate sorting functionality from header clicks on a column?

我有一个制表符 table,其中有一列我想由用户排序table,但我还希望在用户单击该列时出现一个对话框 header 以提供更多信息。

我可以毫无问题地将 headerClick 函数添加到列定义中,并且所有这些都可以正常工作,但问题是,当单击该列时,它还会触发对该列进行排序.

有没有办法将这两个函数分开,以便在单击排序箭头区域(列的右边缘 - 比如说右边的 10%)时进行排序,但在单击列的其余部分时header,出现对话框并取消排序?

我想我可以使用 'e' 参数(鼠标事件 object)中的一些信息来检测单击发生时光标 was/is 的位置,但我不会确定如何取消排序。

一些示例代码:

function headerClickHandler(e, column) {
  // Can the mouse event ('e') be used to detect the location of the cursor and cancel a sort event?
  alert('This column data will be sorted when this dialog closes!');
}

var table = new Tabulator("#example-table", {
    tooltips:true,
    layout:"fitColumns", 
    data:tabledata,
    movableColumns: true,

    columns:[
      {title: "Question Num", formatter:"rownum", align:"center", width:40},
      {title:"Name", field:"name", width:200, headerFilter: true, headerFilterFunc:"regex"},
      {title:"Progress", field:"progress", align:"right", sorter:"number", headerFilter: true, headerFilter:true},
      {title:"Gender", field:"gender", widthGrow:2, headerClick:headerClickHandler},
      {title:"Remove", formatter:"buttonCross", width:40, align:"center", cellClick:function(e, cell){cell.getRow().delete();}}
    ],
});

// Define Test Data
var tabledata = [
{id:1, name:"Oli Bob", progress:-12, gender:"male", rating:1, col:"red", dob:"19/02/1984", car:1, lucky_no:5},
{id:2, name:"Mary May", progress:1.5, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:3, name:"Christine Lobowski", progress:-1.5, gender:"female", rating:0, col:"green", dob:"22/05/1982", car:"true", lucky_no:12},
{id:4, name:"Brendon Philips", progress:10.5, gender:"male", rating:1, col:"orange", dob:"01/08/1980", lucky_no:18},
{id:5, name:"Margret Marmajuke", progress:-10.5, gender:"female", rating:5, col:"yellow", dob:"31/01/1999", lucky_no:33},
{id:6, name:"Frank Harbours", progress:-20, gender:"male", rating:4, col:"red", dob:"12/05/1966", car:1, lucky_no:2},
{id:7, name:"Jamie Newhart", progress:-10.4, gender:"male", rating:3, col:"green", dob:"14/05/1985", car:true, lucky_no:63},
{id:8, name:"Gemma Jane", progress:-10.6, gender:"female", rating:0, col:"red", dob:"22/05/1982", car:"true", lucky_no:72},
{id:9, name:"Emily Sykes", progress:10.4, gender:"female", rating:1, col:"maroon", dob:"11/11/1970", lucky_no:44},
{id:10, name:"James Newman", progress:10.6, gender:"male", rating:5, col:"red", dob:"22/03/1998", lucky_no:9},
{id:11, name:"Martin Barryman", progress:20, gender:"male", rating:5, col:"violet", dob:"04/04/2001"},
{id:12, name:"Jenny Green", progress:56, gender:"female", rating:4, col:"indigo", dob:"12/11/1998", car:true},
{id:13, name:"Alan Francis", progress:90, gender:"male", rating:3, col:"blue", dob:"07/08/1972", car:true},
{id:14, name:"John Phillips", progress:80, gender:"male", rating:1, col:"green", dob:"24/09/1950", car:true},
{id:15, name:"Ed White", progress:70, gender:"male", rating:0, col:"yellow", dob:"19/06/1976"},
{id:16, name:"Paul Branderson", progress:60, gender:"male", rating:5, col:"orange", dob:"01/01/1982"},
{id:18, name:"Emma Netwon", progress:40, gender:"female", rating:4, col:"brown", dob:"07/10/1963", car:true},
{id:19, name:"Hannah Farnsworth", progress:30, gender:"female", rating:1, col:"pink", dob:"11/02/1991"},
{id:20, name:"Victoria Bath", progress:20, gender:"female", rating:2, col:"purple", dob:"22/03/1986"},
];


function headerClickHandler(e, column) {
  // Can the mouse event ('e') be used to detect the location of the cursor and cancel a sort event?
  alert('This column data will be sorted when this dialog closes!');
}

var table = new Tabulator("#example-table", {
    tooltips:true,
    layout:"fitColumns", 
    data:tabledata,
    movableColumns: true,
  
    columns:[
      {title: "Question Num", formatter:"rownum", align:"center", width:40},
      {title:"Name", field:"name", width:200, headerFilter: true, headerFilterFunc:"regex"},
      {title:"Progress", field:"progress", align:"right", sorter:"number", headerFilter: true, headerFilter:true},
      {title:"Gender", field:"gender", widthGrow:2, headerClick:headerClickHandler},
      {title:"Remove", formatter:"buttonCross", width:40, align:"center", cellClick:function(e, cell){cell.getRow().delete();}}
    ],
});
#example-table{
  height:100%;
}
<link href="https://unpkg.com/tabulator-tables@4.5.1/dist/css/tabulator.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/tabulator-tables@4.5.1/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>

添加一个 span 元素来填充您的大部分 TH("sort" 图标除外),并将(z-index)定位在其他所有元素之上。将您的自定义事件处理程序附加到该跨度。在您的处理程序中,preventDefault 和 stopPropagation。当您准备好进行排序时,在 TH(或 Tabulator 侦听的任何元素)上调用 .click()。另外,不要通过 Tabulator 的 API 指定回调(删除所有列 headerClick:headerClickHandler)

以@Ted-Fitzpatrick 的回答为起点,结合来自 的信息,我能够进行以下更改以获得我正在寻找的功能。

function headerClickHandler(e, column) {
  alert('This alert will appear when clicking on the left 90% area of the column header and no sorting will be done!');
}

function customColumnHeaderClicked(e, cell) {
  // The following two lines will block the default sort event from being triggered
  e.stopPropagation();
  e.preventDefault();

  // My header click event handler needed the column reference object normally passed in from Tabulator (not shown in the provided sample).  
  // To fix this, I needed to lookup the column component from information that I did have
  const colRef = table.getColumns().find( e => e.getDefinition().title === cell.getValue());
  headerClickHandler(e, colRef);
}

// The formatter adds the span that allows me to define the click region and handle myself
function customHeaderFormatter(cell, formatterParams, onRendered) {
  const titleElement = document.createElement("span");
  titleElement.style.width='90%';
  titleElement.innerHTML = cell.getValue();
  titleElement.onclick = (e) => customColumnHeaderClicked(e, cell);
  return titleElement; 
}

var table = new Tabulator("#example-table", {
    // ...
    columns:[
      // ...
      {
        // ...
        // headerClick:headerClickHandler // This should no longer be called directly
        titleFormatter: customHeaderFormatter
      },
      // ...
    ],
});

下面是演示上述更改的更新示例代码。

// Define Test Data
var tabledata = [
{id:1, name:"Oli Bob", progress:-12, gender:"male", rating:1, col:"red", dob:"19/02/1984", car:1, lucky_no:5},
{id:2, name:"Mary May", progress:1.5, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:3, name:"Christine Lobowski", progress:-1.5, gender:"female", rating:0, col:"green", dob:"22/05/1982", car:"true", lucky_no:12},
{id:4, name:"Brendon Philips", progress:10.5, gender:"male", rating:1, col:"orange", dob:"01/08/1980", lucky_no:18},
{id:5, name:"Margret Marmajuke", progress:-10.5, gender:"female", rating:5, col:"yellow", dob:"31/01/1999", lucky_no:33},
{id:6, name:"Frank Harbours", progress:-20, gender:"male", rating:4, col:"red", dob:"12/05/1966", car:1, lucky_no:2},
{id:7, name:"Jamie Newhart", progress:-10.4, gender:"male", rating:3, col:"green", dob:"14/05/1985", car:true, lucky_no:63},
{id:8, name:"Gemma Jane", progress:-10.6, gender:"female", rating:0, col:"red", dob:"22/05/1982", car:"true", lucky_no:72},
{id:9, name:"Emily Sykes", progress:10.4, gender:"female", rating:1, col:"maroon", dob:"11/11/1970", lucky_no:44},
{id:10, name:"James Newman", progress:10.6, gender:"male", rating:5, col:"red", dob:"22/03/1998", lucky_no:9},
{id:11, name:"Martin Barryman", progress:20, gender:"male", rating:5, col:"violet", dob:"04/04/2001"},
{id:12, name:"Jenny Green", progress:56, gender:"female", rating:4, col:"indigo", dob:"12/11/1998", car:true},
{id:13, name:"Alan Francis", progress:90, gender:"male", rating:3, col:"blue", dob:"07/08/1972", car:true},
{id:14, name:"John Phillips", progress:80, gender:"male", rating:1, col:"green", dob:"24/09/1950", car:true},
{id:15, name:"Ed White", progress:70, gender:"male", rating:0, col:"yellow", dob:"19/06/1976"},
{id:16, name:"Paul Branderson", progress:60, gender:"male", rating:5, col:"orange", dob:"01/01/1982"},
{id:18, name:"Emma Netwon", progress:40, gender:"female", rating:4, col:"brown", dob:"07/10/1963", car:true},
{id:19, name:"Hannah Farnsworth", progress:30, gender:"female", rating:1, col:"pink", dob:"11/02/1991"},
{id:20, name:"Victoria Bath", progress:20, gender:"female", rating:2, col:"purple", dob:"22/03/1986"},
];


function headerClickHandler(e, column) {
  // Can the mouse event ('e') be used to detect the location of the cursor and cancel a sort event?
  alert('This column data will be sorted when this dialog closes!');
}

function customColumnHeaderClicked(e, cell) {
  e.stopPropagation();
  e.preventDefault();
  const colRef = table.getColumns().find( e => e.getDefinition().title === cell.getValue());
  headerClickHandler(e, colRef);
}

function customHeaderFormatter(cell, formatterParams, onRendered) {
  const titleElement = document.createElement("span");
  titleElement.style.width='90%';
  titleElement.innerHTML = cell.getValue();
  titleElement.onclick = (e) => customColumnHeaderClicked(e, cell);
  return titleElement; 
}

var table = new Tabulator("#example-table", {
    tooltips:true,
    layout:"fitColumns", 
    data:tabledata,
    movableColumns: true,
  
    columns:[
      {title: "Question Num", formatter:"rownum", align:"center", width:40},
      {title:"Name", field:"name", width:200, headerFilter: true, headerFilterFunc:"regex"},
      {title:"Progress", field:"progress", align:"right", sorter:"number", headerFilter: true, headerFilter:true},
      {
        title:"Gender", 
        field:"gender", 
        widthGrow:2, 
        // headerClick:headerClickHandler
        titleFormatter: customHeaderFormatter
      },
      {title:"Remove", formatter:"buttonCross", width:40, align:"center", cellClick:function(e, cell){cell.getRow().delete();}}
    ],
});
#example-table{
  height:100%;
}
<link href="https://unpkg.com/tabulator-tables@4.5.1/dist/css/tabulator.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/tabulator-tables@4.5.1/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>