Search code examples
javascripttabulator

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


I have a Tabulator table with a column that I want to be sortable by the user, but I also want to have a dialog appear when the user clicks on the column header to provide additional information.

I have no problem adding the headerClick function to the column definition and have all of that working, but the problem is, when the column is clicked, it also triggers the sorting to happen on that column.

Is there a way to separate these two functions so that when clicking on the sort arrow region (the right edge of the column - say the right 10%) the sorting occurs, but when clicking on the rest of the column header, the dialog appears and the sort is canceled?

I think I can use some information in the 'e' argument (a mouse event object) to detect where the cursor was/is when the click occurred, but I'm not sure how to cancel the sort.

Some sample code:

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/[email protected]/dist/css/tabulator.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/[email protected]/dist/js/tabulator.min.js"></script>
<div id="example-table"></div>


Solution

  • Add a span element that fills most of your TH (except for the "sort" icon), and is positioned (z-index) on top of everything else. Attach your custom event handler to that span. In your handler, preventDefault and stopPropagation. When you're ready for the sort, call .click() on the TH (or whatever element Tabulator listens for). Also, don't specify a callback via Tabulator's API (remove all of the columns headerClick:headerClickHandler)