@financial-times/o-table
Version:
Provides styling and behvaiour for tables across FT products.
137 lines (123 loc) • 4.48 kB
JavaScript
import CellFormatter from "./CellFormatter.js";
/**
* Construct Intl.Collator if supported.
*
* @access private
* @returns {Intl.Collator | undefined} The Intl.Collator object enables language-sensitive string comparison.
*/
function getIntlCollator() {
if (typeof Intl !== 'undefined' && {}.hasOwnProperty.call(Intl, 'Collator')) {
return new Intl.Collator();
}
}
/**
* An ascending [compare function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters}.
*
* @access private
* @param {string | number} a column a
* @param {string | number} b column b
* @param {Intl.Collator} intlCollator The Intl.Collator object enables language-sensitive string comparison.
* @returns {number} comp
*/
function ascendingSort(a, b, intlCollator) {
if ((typeof a === 'string' || a instanceof String) && (typeof b === 'string' || b instanceof String)) {
return intlCollator ? intlCollator.compare(a, b) : a.localeCompare(b);
} else if (!isNaN(b) && isNaN(a) || a < b) {
return -1;
} else if (!isNaN(a) && isNaN(b) || b < a) {
return 1;
} else {
return 0;
}
}
/**
* A descending [compare function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters}.
*
* @access private
* @param {string | number} a column a
* @param {string | number} b column b
* @param {Intl.Collator} intlCollator The Intl.Collator object enables language-sensitive string comparison.
* @returns {number} comp
*/
function descendingSort(a, b, intlCollator) {
return 0 - ascendingSort.apply(this, [a, b, intlCollator]);
}
/**
* Provides methods to sort table instances.
*/
class TableSorter {
constructor() {
this._cellFormatter = new CellFormatter();
}
/**
* The shared functionality of all `o-table` variants.
*
* @typedef BaseTable
* @access public
* @param {HTMLElement} rootEl - The `o-table` element.
* @param {TableSorter} sorter a TableSorter instance
* @param {object} opts [{}]
* @param {boolean} opts.sortable [true]
* @returns {BaseTable} the new base table
*/
/**
* Sort the given table.
*
* @access public
* @param {BaseTable} table - The table instance to sort.
* @param {number} columnIndex - The index of the table column to sort.
* @param {string} sortOrder - How to sort the column, "ascending" or "descending"
* @param {number} batch [100] - Deprecated. No longer used. How many rows to render at once when sorting.
* @returns {void}
*/
sortRowsByColumn(table, columnIndex, sortOrder, batch) {
const tableHeaderElement = table.getTableHeader(columnIndex);
if (batch) {
// eslint-disable-next-line no-console
console.warn('o-table: The "batch" argument is deprecated and no longer used.');
}
if (['ascending', 'descending'].indexOf(sortOrder) === -1) {
throw new Error(`Sort order "${sortOrder}" is not supported. Must be "ascending" or "descending".`);
}
const intlCollator = getIntlCollator();
const cellFormatter = this._cellFormatter;
const type = tableHeaderElement.getAttribute('data-o-table-data-type') || undefined;
table.tableRows.sort((a, b) => {
let aCol = a.querySelectorAll('td,th:not(.o-table__duplicate-heading)')[columnIndex];
let bCol = b.querySelectorAll('td,th:not(.o-table__duplicate-heading)')[columnIndex];
aCol = cellFormatter.formatCell({ cell: aCol, type });
bCol = cellFormatter.formatCell({ cell: bCol, type });
if (sortOrder === 'ascending') {
return ascendingSort(aCol, bCol, intlCollator);
} else {
return descendingSort(aCol, bCol, intlCollator);
}
});
// Table sorted.
table.sorted({
columnIndex,
sortOrder
});
// Render sorted table rows.
table.renderRowUpdates();
// Update table headings.
window.requestAnimationFrame(() => {
table.tableHeaders.forEach((header) => {
const headerSort = header === tableHeaderElement ? sortOrder : 'none';
header.setAttribute('aria-sort', headerSort);
});
});
}
/**
* Set a custom cell formatter for a given data type.
*
* @param {string} type - The data type to apply the filter function to.
* @param {formatFunction} formatFunction - Callback to format a table cell to a sort value.
* @see {@link CellFormatter~setFormatter} for `formatFunction` details.
* @access public
*/
setCellFormatterForType(type, formatFunction) {
this._cellFormatter.setFormatter(type, formatFunction);
}
}
export default TableSorter;