Version 5.6 Released!

Click to checkout the new features

Release Notes

Range Selection

This release sees the introduction of the new range selection module. This module lets you select a range of cells instead of just a row.

Range selection allows users to select and highlight a block of cells across rows and columns that you can then take action on.

Try some of the following on the table below:

  • Select a range - Click and drag across multiple cells
  • Navigate the table - Click on a cell and use the arrow keys to navigate round the table
  • Expand a range - After selecting a range hold down the shift key and either drag the mouse or use the arrow keys to change the size of the selected range
  • Multiple Ranges - After selecting a range, hold down the crtl key and click and drag to select additional ranges.
  • Programatically Add Ranges - Click the "Select Range" button to programmatically add ranges with the addRange function.

Selection Controls
Loading Example...
Source Code

HTML

<div>
    <button id="select-range">Select Range</button>
</div>

<div id="example-table"></div>

JavaScript

//Build Tabulator
var table = new Tabulator("#example-table", {
    height:"311px",
    selectableRange:true,
    selectableRangeColumns:true,
    selectableRangeRows:true,
    columnDefaults:{
      headerSort:false,
      resizable:"header",
    },
    columns:[
      {resizable: false, frozen: true, hozAlign:"center", formatter: "rownum"},
      {title:"Name", field:"name", width:200},
      {title:"Progress", field:"progress", width:100, hozAlign:"right", sorter:"number"},
      {title:"Gender", field:"gender", width:100},
      {title:"Rating", field:"rating", hozAlign:"center", width:80},
      {title:"Favourite Color", field:"col"},
      {title:"Date Of Birth", field:"dob", hozAlign:"center", sorter:"date"},
      {title:"Driver", field:"car", hozAlign:"center", width:100},
    ],
});

//select row on "select" button click
document.getElementById("select-range").addEventListener("click", function(){
    var topLeft = table.getRows()[3].getCells()[2];
    var bottomRight = table.getRows()[5].getCells()[5];

    table.addRange(topLeft, bottomRight);
});

Compatibility
This module is currently only available with the Virtual renderes and will not work with the Basic renderers

Navigation

The range module allows you to navigate around the table using the arrow keys.

Cell Navigation

When a cell has focus, using any of the arrow keys will cause the selected cell to move one cell in the direction of the arrow key pressed.

Jump Navigation

Holding the ctrl key when pressing an arrow key will cause the focus to skip to the next cell with a value in the direction you are navigating. This will skip any empty cells (if pressent) between the current cell and the next cell with a value.

Expand Navigation

Holding the shift key when pressing an arrow key will expand the current range in the direction of the arrow key pressed.

Jump Expand Navigation

Holding the ctrl and shift keys when pressing an arrow key will expand the current range to the next cell with a value in the direction of the arrow key pressed. This will skip any empty cells (if pressent) between the current cell and the next cell with a value.

Setup

To enable range selection, set the selectableRange option to true

var table = new Tabulator("#example-table", {
	selectableRange:true,
});

The selectableRange option can take one of a several values:

  • false - range selection is disabled
  • true - range selection is enabled, and you can add as many ranges as you want
  • integer - any integer value, this sets the maximum number of ranges that can be selected (when the maximum number of ranges is exceded, the first selected range will be deselected to allow the next range to be selected).

Layout Change
changing the layout or data of the table will result in all ranges being cleared

Selectable Columns

By default you can only select ranges by selecting cells on the table. If you would like to allow the user to select all cells in a column by clicking on the column header, then you can set the selectableRangeColumns option to true

var table = new Tabulator("#example-table", {
  selectableRange:true,
  selectableRangeColumns:true,
});

Header Sorting
You cannot use column header sorting with this option, unless you set the headerSortClickElement option to icon

Selectable Rows

By default you can only select ranges by selecting cells on the table. If you would like to allow the user to select all cells in row by clicking on the first column in a row, then you can set the selectableRangeColumns option to true

var table = new Tabulator("#example-table", {
  selectableRange:true,
  selectableRangeColumns:true,
});

A good idea for a row header is to setup a frozen column with the rownum formatter. An example setup for a row header would be:

var table = new Tabulator("#example-table", {
    columns:[
        {resizable: false, frozen: true, width:40, hozAlign:"center", formatter: "rownum"}, //setup row header for spreadsheet
        ... other columns ...
    ],
});

Header Sorting
You cannot use column header sorting with this option, unless you set the headerSortClickElement option to icon

Selection Management

As well as clicking on a row, you can trigger the selection of a range programmatically.

Range Bounds

When creating or editing an existing range programatically, you woill need to define the bounds for the selected area.

The bounds os of a selection are defined using the top-left and bottom-right cells of a selected area, the system can then calculate the cells contained in this boundry by drawing a rectangle between the two points

Example selected range

In the example above the top left cell with a value of "100" would be the start bound, and the bottom right cell with a value of "red" would be the end bound.

Add Range

To programmatically select a range of cells you can use the addRange function.

To select a range of cells you should call the addRange function, passing in the Cell Components for the top-left and bottom-right bounds of the selection:

    var topLeft = table.getRows()[2].getCells()[1];
    var bottomRight = table.getRows()[5].getCells()[6];

    var range = table.addRange(topLeft, bottomRight);

This will then return the Range Component for the new range.

Get Selected Range Components

To get the Range Component's for all the current ranges you can use the getRanges function.

var ranges = table.getRanges(); //get array of currently selected range components.

This will return an array of Range Components for all the current ranges.

Get Selected Data

To get the data objects for all the selected cell ranges you can use the getRangesData function.

var rangeData = table.getRangesData(); //get array of currently selected data.

This will return an array of range data arrays, with data array per range. Each range data array will contain a series of row data objects with only the props for cells in that range:

[
    [ //range 1
        {name:"Bob Monkhouse", age:83}, //data for selected cells in first row in range
        {name:"Mary May", age:22}, //data for selected cells in second row in range
    ],
    [ //range 2
        {color:"green", country:"England", driver:true}, //data for selected cells in first row in range
        {color:"red", country:"USA", driver:false}, //data for selected cells in second row in range
        {color:"blue", country:"France", driver:true}, //data for selected cells in third row in range
    ],
]

Clear Data

If you want the user to be able to clear the values for all cells in the active range by pressing the backspace or delete keys, then you can enable this behaviour using the selectableRangeClearCells option:

var table = new Tabulator("#example-table", {
      selectableRangeClearCells:true,
});

By default the value of each cell in the range is set to undefined when this option is enabled and the user presses the backspace or delete keys. You can change the value the cells are set to using the selectableRangeClearCellsValue option:

var table = new Tabulator("#example-table", {
      selectableRangeClearCellsValue:"", // set cleared cells to to an empty string
});

Spreadsheet

While not a new feature in its own right, by using the new range selection functionality in addition to the edit and clipboard modules, you can configure Tabulator to function as a spreadsheet.

Try some of the following on the table below:

  • Editing a cell - Double click on a cell or focus on a cell and press the enter key
  • Copy a cell - Click on a cell with a value in, press ctrl+c click on another cell and press ctrl+v
  • Navigate the table - Click on a cell and use the arrow keys to navigate round the table
  • Select a range - Click and drag across multiple cells
  • Expand a range - After selecting a range hold down the shift key and either drag the mouse or use the arrow keys to change the size of the selected range
  • Copy a range - After selecting a range, press ctrl+c then click on a different cell and press ctrl+v to paste the range starting from that cell
  • Paste to fill - Select a cell or range with values in, press ctrl+c then select a different size range (more than one cell) and press ctrl+v. Notice how it pastes the data to fill the range, either duplicating rows and columns as needed, or hiding data that wont fit.
  • Duplicating a column - Click on a column header to select a whole column, press ctrl+c, click into another column header and press ctrl+v
  • Duplicating a row - Click on a row header to select a whole row, press ctrl+c, click into another row header and press ctrl+v

Selection Controls
Loading Example...
Source Code

HTML

<div id="example-table"></div>

JavaScript

//create an empty spreadsheet of columns and rows
var example_table_range;

var exampleData = [];
var exampleColumns = [
  {resizable: false, frozen: true, width:40, hozAlign:"center", formatter: "rownum", editor:false}, //setup row header for spreadsheet
];

//build initial row with correct column setup
var exampleRow = {};

var start = "a";

for(let j = 0; j < 24; j++){
    key = String.fromCharCode(start.charCodeAt(0) + j);
    exampleRow[key] = "";
    exampleColumns.push({title: key.toUpperCase(), field:key});
}

//add 50 blank rows to the spreadsheet
for(let i = 0; i < 50; i++){
  exampleData.push(Object.assign({}, exampleRow));
}    
    
//Build Tabulator
var table = new Tabulator("#example-table", {
    height:"311px",
    data:exampleData,

    //enable range selection
    selectableRange:1,
    selectableRangeColumns:true,
    selectableRangeRows:true,
    selectableRangeClearCells:true,

    //change edit trigger mode to make cell navigation smoother
    editTriggerEvent:"dblclick",

    //configure clipboard to allow copy and paste of range format data
    clipboard:true,
    clipboardCopyStyled:false,
    clipboardCopyConfig:{
        columnHeaders:false,
    },
    clipboardCopyRowRange:"range",
    clipboardPasteParser:"range",
    clipboardPasteAction:"range",

    //setup cells to work as a spreadsheet
    columnDefaults:{
        headerSort:false,
        headerHozAlign:"center",
        editor:"input",
        resizable:"header",
        width:100,
    },
    columns:exampleColumns,
});

Components

Row Range Lookup

With the addition of the selectable range module, a new Row Range Lookup option of range has been added, to allow you to use the selected ranges in other table functions

var table = new Tabulator("#example-table", {
    clipboardCopyRowRange:"range", //copy selected ranges to the clipboard
});

This new range lookup option can be used in any table setup option that accepts row range lookups as a value.

Range Component

The addition of the selectable range module also sees the creation of a new type of component object, the range component, this can be used to manipulate the cells selected in a given range. Full details for the range component options can be found in the Range Component Documentation

These component objects are returned from table functions like getRanges or from range based events.

var ranges = table.getRanges(); //get array of currently selected range components.
table.on("rangeAdded", function(range){
    //range - range component for the selected range
});

Update Range Bounds

You can update the bounds for an existing range using the setBounds function, passing in the Cell Components for the top-left and bottom-right bounds of the selection:

    var topLeft = table.getRows()[2].getCells()[1];
    var bottomRight = table.getRows()[5].getCells()[6];

    range.setBounds(topLeft, bottomRight);

Update Range Start

You can change the top left start edge of an existing range using the setStartBound function, passing in the Cell Component for the top left bound of the selection:

    var topLeft = table.getRows()[2].getCells()[1];

    range.setStartBound(topLeft);

Update Range End

You can change the bottom right ending edge of an existing range using the setEndBound function, passing in the Cell Component for the bottom right bound of the selection:

    var bottomRight = table.getRows()[5].getCells()[6];

    range.setEndBound(bottomRight);

Remove Range

You can remove a range by calling the remove function on the range:

range.remove();

Get Element

You can retrieve the bounding rectagle element for a range by calling the getElement function on the range:

var element = range.getElement();

Get Data

You can retrieve the cell data for a range by calling the getData function on the range:

var data = range.getData();

This will return a range data array, which is structured as a series of row data objects with only the props for cells in that range:

[
    {color:"green", country:"England", driver:true}, //data for selected cells in first row in range
    {color:"red", country:"USA", driver:false}, //data for selected cells in second row in range
    {color:"blue", country:"France", driver:true}, //data for selected cells in third row in range
]

Clear Values

You can clear the value of every cell in a range by calling the clearValues function on the range:

var data = range.clearValues();

This will set the value of every cell in the range to the value of the selectableRangeClearCellsValue table option, which is set to undefined by default.

Get All Cells

You can retrieve all the Cell Components in a range by calling the getCells function on the range:

var cells = range.getCells();

This will return a array of Cell Components

Get With Structure

You can retrieve a structured map of all the Cell Components in a range by calling the getStructuredCells function on the range:

var cells = range.getStructuredCells();

This will return a array of row arrays, with each row array containing the Cell Components in order for that row:

[
    [Component, Component, Component], //first row
    [Component, Component, Component], //second row
    [Component, Component, Component], //third row
]

Get Rows

You can retrieve all the Row Components in a range by calling the getRows function on the range:

var rows = range.getRows();

This will return a array of Row Components

Get Columns

You can retrieve all the Column Components in a range by calling the getColumns function on the range:

var columns = range.getColumns();

This will return a array of Column Components

Get Bounds

You can retrieve the bounds of a range by calling the getBounds function on the range:

var bounds = range.getBounds();

This will return an object containing two Cell Components, for the two bounds of the range

{
    start:Component, //the cell component at the top left of the range
    end:Component, //the cell component at the bottom right of the range
}

Get Top Edge

You can find the position number for the top row of the range by calling the getTopEdge function on the range:

var topPosition = range.getTopEdge();

Get Bottom Edge

You can find the position number for the bottom row of the range by calling the getBottomEdge function on the range:

var bottomPosition = range.getBottomEdge();

Get Left Edge

You can find the position number for the left column of the range by calling the getLeftEdge function on the range:

var leftPosition = range.getLeftEdge();

Get Right Edge

You can find the position number for the right column of the range by calling the getRightEdge function on the range:

var rightPosition = range.getRightEdge();

Row Component

Get Ranges

You can retreive all ranges that overlap a row by calling the getRanges function:

var ranges = row.getRanges();

This will return an array of Range Components for any ranges that overlap the row. If no ranges overlap the row, an empty array will be returned.

Column Component

Get Ranges

You can retreive all ranges that overlap a column by calling the getRanges function:

var ranges = column.getRanges();

This will return an array of Range Components for any ranges that overlap the column. If no ranges overlap the column, an empty array will be returned.

Cell Component

You can retreive all ranges that overlap a cell by calling the getRanges function:

var ranges = cell.getRanges();

This will return an array of Range Components for any ranges that overlap the cell. If no ranges overlap the cell, an empty array will be returned.

Editing

Edit Trigger Event

The new editTriggerEvent option lets you choose which type of interaction event will trigger an edit on a cell.

var table = new Tabulator("#example-table", {
    editTriggerEvent:"dblclick", //trigger edit on double click
});

This option can take one of three values:

  • focus - trigger edit when the cell has focus (default)
  • click - trigger edit on single click on cell
  • dblclick - trigger edit on double click on cell

This option does not affect navigation behavior, cells edits will still be triggered when they are navigated to through arrow keys or tabs.

Validators

Alphanumeric Validator

The new alphanumeric validator allows values that are explicitly numbers and letters with no symbols or spaces

{title:"Example", field:"example", validator:"alphanumeric"}

Clipboard

The clipboard module has had several updates to add intergration with the new range selection module

Copy Row Range

The clipboardCopyRowRange option, now accepts the range value to allow copying of cell ranges from the table

var table = new Tabulator("#example-table", {
    clipboardCopyRowRange:"range", //change default selector to selected
});

Range Paste Parser

The clipboardPasteParser option, now accepts the range value to allow pasting of cell ranges to the table

var table = new Tabulator("#example-table", {
    clipboardPasteParser:"range", //use the range parser
});

Range Paste Action

The clipboardPasteAction option, now accepts the range value to allow pasting of cell ranges to the table

var table = new Tabulator("#example-table", {
    clipboardPasteAction:"range", //use the range paste action
});

Events

Range

The addition of the selectable range module also includes a number of new events.

Range Added

The rangeAdded event is triggered when a range is initialy selected, either by the user or programmatically.

table.on("rangeAdded", function(range){
    //range - range component for the selected range
});

Range Changed

The rangeChanged event is triggered when a the bounds of an existing range are changed.

table.on("rangeChanged", function(range){
    //range - range component for the selected range
});

Range Removed

The rangeRemoved event is triggered when a range is removed from the table.

table.on("rangeRemoved", function(range){
    //range - range component for the selected range
});

Internal Events

Edit

New internal events have been added to allow overriding of the default blur behaviour of edited cells.

Key Type Arguments Response Notes
edit-blur confirm cell returning true will prevent the default blur behaviour Dispatched when an edit is about to blur the cell focus, to give the opertunity to preven or override this behaviour

Menu

New internal events have been added to help track when a menu is opened or closed

Key Type Arguments Response Notes
menu-opened dispatch menu, popup A new menu has been opened
menu-closed dispatch menu, popup A menu has been closed

Keybinding

A new internal event has been added to help track when a range navigation keybining is triggered

Key Type Arguments Response Notes
keybinding-nav-range dispatch trigger event, direction, jump, expand A range navigation action has been triggered by a keybinding

Column

New internal events have been added to track when a column has finished being deleted.

Key Type Arguments Response Notes
column-deleted dispatch column Column has been deleted

Alert

New internal events have been added to track when alerts open and close

Key Type Arguments Response Notes
alert-show dispatch type An alert has been opened
alert-hide dispatch type An alert has been hidden

Clipboard

New internal events have been added to allow handling of clipboard paste events.

Key Type Arguments Response Notes
clipboard-paste confirm paste event returning true will prevent the paste event from being handled by the cliboard module A user has pasted content into the table

keybindings

Range Keybindings

A number of new default keybindings have been added to aid in range navigation of the table:

Action Default Key Combination (keycode) Function
rangeJumpUp ctrl + up ("ctrl + 38") OR meta(cmd) + up ("meta + 38") Navigate range cursor up to next cell with value
rangeJumpDown ctrl + down ("ctrl + 40") OR meta(cmd) + down ("meta + 40") Navigate range cursor down to next cell with value
rangeJumpLeft ctrl + left ("ctrl + 37") OR meta(cmd) + left ("meta + 37") Navigate range cursor left to next cell with value
rangeJumpRight ctrl + left ("ctrl + 39") OR meta(cmd) + left ("meta + 39") Navigate range cursor left to next cell with value
rangeExpandUp shift + up ("ctrl + 38") Expand active range up one row
rangeExpandDown shift + down ("ctrl + 40") Expand active range down one row
rangeExpandLeft shift + left ("ctrl + 37") Expand active range left one column
rangeExpandRight shift + right ("ctrl + 39") Expand active range right one column
rangeExpandJumpUp ctrl + shift + up ("ctrl + shift + 38") OR meta(cmd) + shift + up ("meta + shift + 38") Expand active range up to next cell with value
rangeExpandJumpDown ctrl + shift + down ("ctrl + shift + 40") OR meta(cmd) + shift + down ("meta + shift + 40") Expand active range down to next cell with value
rangeExpandJumpLeft ctrl + shift + left ("ctrl + shift + 37") OR meta(cmd) + shift + left ("meta + shift + 37") Expand active range left to next cell with value
rangeExpandJumpRight ctrl + shift + right ("ctrl + shift + 39") OR meta(cmd) + shift + right ("meta + shift + 39") Expand active range right to next cell with value

Row Selection

With the addition of the range selection module, all row selection options have now been renamed for clarity.

Enable Row Selection

Anywhere you used the selectable option:

var table = new Tabulator("#example-table", {
    selectable:true, //make rows selectable
});

You should now use the selectableRows option:

var table = new Tabulator("#example-table", {
    selectableRows:true, //make rows selectable
});

Rolling Row Selection

Anywhere you used the selectableRollingSelection option:

var table = new Tabulator("#example-table", {
    selectableRollingSelection:false, //disable rolling selection
});

You should now use the selectableRowsRollingSelection option:

var table = new Tabulator("#example-table", {
    selectableRowsRollingSelection:false, //disable rolling selection
});

Range Mode

Anywhere you used the selectablePersistence option:

var table = new Tabulator("#example-table", {
    selectableRangeMode:"click", //select row range on click
});

You should now use the selectableRowsRangeMode option:

var table = new Tabulator("#example-table", {
    selectableRowsRangeMode:"click", //select row range on click
});

Persistent Selection

Anywhere you used the selectablePersistence option:

var table = new Tabulator("#example-table", {
    selectablePersistence:false, //disable selection peristence
});

You should now use the selectableRowsPersistence option:

var table = new Tabulator("#example-table", {
    selectableRowsPersistence:false, //disable selection peristence
});

Persistent Selection

Anywhere you used the selectableCheck option:

var table = new Tabulator("#example-table", {
    selectableCheck:function(row){
        //row - row component
        return row.getData().age > 18; //allow selection of rows where the age is greater than 18
    },
});

You should now use the selectableRowsCheck option:

var table = new Tabulator("#example-table", {
    selectableRowsCheck:function(row){
        //row - row component
        return row.getData().age > 18; //allow selection of rows where the age is greater than 18
    }
});

CSS Styling

CSS Classes

A number of new CSS classes have been added to the table with the new range selection module

Class Element Description
tabulator-rangesApplied to the table container when range selection is enabled
tabulator-range-highlightApplied to a column header or row when a cell in that column is included in a range
tabulator-range-selectedApplied to a column header or row header when that entier row or column is included in a range
tabulator-range-row-headerApplied to the row header cell for a row
tabulator-range-overlayThe containing element for all range area overlays
tabulator-rangeThe overlayed area graphic for a range
tabulator-range-activeApplied to the active range overlay area
tabulator-range-activeApplied to the active range overlay area

SASS Variables

A number of new SASS Variables have been added to the table with the new range selection module

Variable Default Value Description
rangeBorderColor#2975DDRange selection border colour
rangeHandleColor#2975DDRange selection handle colour
rangeHeaderSelectedBackground#3876CARange column header selected backgroud Colour
rangeHeaderSelectedTextColor#FFFFCARange column header selected text Colour
rangeHeaderHighlightBackground#D6D6CARange column header highlighted backgroud Colour
rangeHeaderTextHighlightBackground#0000CARange column header highlighted text Colour

Bug Fixes

v5.6.0 Release

The following minor updates and bugfixes have been made:

  • Updating a column definition to freeze a column now works successfully
  • Toggling the visibility of a frozen column will no longer cause a visual glitch
  • Column resizing now works for frozen columns
  • Table resize functionality now works correctly on mobile devices when the edit module is not installed
  • Column header vertical alignment is recalculated after initial data load
  • Top column calcks and frozen rows will now correctly render when scrolled horizontally
  • Alerts poping up while moving columns now cancle the column move
  • History actions now correctly clear and restore the empty table placeholder
  • The placeholder is now correctly positioned on tables using the basic renderer
  • The selectRow and deselectRow functions now correctly handle rows with an index of 0
  • Fixed missing getTable function on psuedo cell component used in export module

v5.6.1 Release

The following minor updates and bugfixes have been made:

  • Fixed issues with rendering in range selection module when no row header defined
  • Fixed regression in frozen columns module when frozen columns are initially hidden
  • Fix issue in time and datetime editors where 24 hour times were not being handled correctly
  • You can now use the editableTitle and movableColumns options together without dragging the mouse in the title input causing the column to be moved
  • Using events after calling the setHeight function will no longer result console warnings
  • Fixed regression that caused text areas to not resize on table resize, introduced during performance improvements in v5.5
  • Editors can now only trigger success or cancel calls once (if validation passes) to prevent duplicate events

Donate