coral-spectrum/coral-component-table/src/scripts/TableColumn.js
/**
* Copyright 2019 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import {BaseComponent} from '../../../coral-base-component';
import {alignment} from './TableUtil';
import {commons, transform, validate} from '../../../coral-utils';
import {Decorator} from '../../../coral-decorator';
const CLASSNAME = '_coral-Table-column';
/**
Enumeration for {@link TableColumn} sortable direction options.
@typedef {Object} TableColumnSortableDirectionEnum
@property {String} DEFAULT
Default. No sorting applied.
@property {String} ASCENDING
Ascending sort.
@property {String} DESCENDING
Descending sort.
*/
const sortableDirection = {
DEFAULT: 'default',
ASCENDING: 'ascending',
DESCENDING: 'descending'
};
/**
Enumeration for {@link TableColumn} sortable type options.
@typedef {Object} TableColumnSortableTypeEnum
@property {String} ALPHANUMERIC
Alphanumeric type. If sorting is based on {@link TableCell#value}, use {String}.
@property {String} NUMBER
Number type. If sorting is based on {@link TableCell#value}, use {Number}.
@property {String} DATE
Date type. If sorting is based on {@link TableCell#value}, use {Date} in milliseconds.
@property {String} CUSTOM
Custom type. Sorting is based on user defined sorting.
*/
const sortableType = {
ALPHANUMERIC: 'alphanumeric',
NUMBER: 'number',
DATE: 'date',
CUSTOM: 'custom'
};
/**
@class Coral.Table.Column
@classdesc A Table column component
@htmltag coral-table-column
@htmlbasetag col
@extends {HTMLTableColElement}
@extends {BaseComponent}
*/
const TableColumn = Decorator(class extends BaseComponent(HTMLTableColElement) {
/**
The column cells alignment. The alignment should take the {@link i18n} configuration into account.
@type {String}
@default TableColumnAlignmentEnum.LEFT
@htmlattribute alignment
@htmlattributereflected
*/
get alignment() {
return this._alignment || alignment.LEFT;
}
set alignment(value) {
const oldValue = this._alignment;
value = transform.string(value).toLowerCase();
this._alignment = validate.enumeration(alignment)(value) && value || alignment.LEFT;
this._reflectAttribute('alignment', this._alignment);
// Don't trigger on initialization if alignment is LEFT to improve performance
if (!(typeof oldValue === 'undefined' && this._alignment === alignment.LEFT)) {
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_alignmentchanged');
});
}
}
/**
Whether the column has a fixed width.
@type {Boolean}
@default false
@htmlattribute fixedwidth
@htmlattributereflected
*/
get fixedWidth() {
return this._fixedWidth || false;
}
set fixedWidth(value) {
this._fixedWidth = transform.booleanAttr(value);
this._reflectAttribute('fixedwidth', this._fixedWidth);
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_fixedwidthchanged');
});
}
/**
Whether the column is hidden.
@type {Boolean}
@default false
@htmlattribute hidden
@htmlattributereflected
*/
get hidden() {
return this._hidden || false;
}
set hidden(value) {
this._hidden = transform.booleanAttr(value);
this._reflectAttribute('hidden', this._hidden);
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_hiddenchanged');
});
}
/**
Whether the table column is orderable.
Note that this does not affect the underlying data, only presentation.
@type {Boolean}
@default false
@htmlattribute orderable
@htmlattributereflected
*/
get orderable() {
return this._orderable || false;
}
set orderable(value) {
this._orderable = transform.booleanAttr(value);
this._reflectAttribute('orderable', this._orderable);
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_orderablechanged');
});
}
/**
Whether the column is sortable by user interaction.
@type {Boolean}
@default false
@htmlattribute sortable
@htmlattributereflected
*/
get sortable() {
return this._sortable || false;
}
set sortable(value) {
this._sortable = transform.booleanAttr(value);
this._reflectAttribute('sortable', this._sortable);
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_sortablechanged');
});
}
/**
The sorting type. See {@link TableColumnSortableTypeEnum}. If setting to <code>custom</code>, columns won't sort
based on the default table sorting.
Instead, a custom sorting can be performed when triggered by user interaction. This can be defined by listening to
the {@link coral-table:beforecolumnsort} event.
@type {String}
@default TableColumnSortableTypeEnum.ALPHANUMERIC
@htmlattribute sortabletype
@htmlattributereflected
*/
get sortableType() {
return this._sortableType || sortableType.ALPHANUMERIC;
}
set sortableType(value) {
value = transform.string(value).toLowerCase();
this._sortableType = validate.enumeration(sortableType)(value) && value || sortableType.ALPHANUMERIC;
this._reflectAttribute('sortabletype', this._sortableType);
}
/**
The sorting direction. Sorts the column cells based on {@link TableCell#value}.
If not present, the sort is based on the cell text content. See {@link TableColumnSortableDirectionEnum}.
@type {String}
@default TableColumnSortableDirectionEnum.DEFAULT
@htmlattribute sortabledirection
@htmlattributereflected
*/
get sortableDirection() {
return this._sortableDirection || sortableDirection.DEFAULT;
}
set sortableDirection(value) {
value = transform.string(value).toLowerCase();
this._sortableDirection = validate.enumeration(sortableDirection)(value) && value || sortableDirection.DEFAULT;
this._reflectAttribute('sortabledirection', this._sortableDirection);
// Prevent sorting if unnecessary
if (!this._preventSort) {
this._doSort();
window.requestAnimationFrame(() => {
this.trigger('coral-table-column:_sortabledirectionchanged');
});
}
}
/** @private */
_sort() {
let newSortableDirection;
if (this.sortableDirection === sortableDirection.DEFAULT) {
newSortableDirection = sortableDirection.ASCENDING;
} else if (this.sortableDirection === sortableDirection.ASCENDING) {
newSortableDirection = sortableDirection.DESCENDING;
} else if (this.sortableDirection === sortableDirection.DESCENDING) {
newSortableDirection = sortableDirection.DEFAULT;
}
this.trigger('coral-table-column:_beforecolumnsort', {newSortableDirection});
}
/** @private */
_doSort(onInitialization) {
this.trigger('coral-table-column:_sort', {onInitialization, sortableDirection, sortableType});
}
/**
Returns {@link TableColumn} sortable direction options.
@return {TableColumnSortableDirectionEnum}
*/
static get sortableDirection() {
return sortableDirection;
}
/**
Returns {@link TableColumn} sortable type options.
@return {TableColumnSortableTypeEnum}
*/
static get sortableType() {
return sortableType;
}
/**
Returns {@link TableColumn} alignment options.
@return {TableColumnAlignmentEnum}
*/
static get alignment() {
return alignment;
}
static get _attributePropertyMap() {
return commons.extend(super._attributePropertyMap, {
fixedwidth: 'fixedWidth',
sortabletype: 'sortableType',
sortabledirection: 'sortableDirection'
});
}
/** @ignore */
static get observedAttributes() {
return super.observedAttributes.concat([
'fixedwidth',
'hidden',
'alignment',
'orderable',
'sortable',
'sortabletype',
'sortabledirection',
]);
}
/** @ignore */
render() {
super.render();
this.classList.add(CLASSNAME);
// Default reflected attributes
if (!this._sortableType) {
this.sortableType = sortableType.ALPHANUMERIC;
}
if (!this._sortableDirection) {
this.sortableDirection = sortableDirection.DEFAULT;
}
if (!this._alignment) {
this.alignment = alignment.LEFT;
}
}
/**
Triggered when {@link TableColumn#alignment} changed.
@typedef {CustomEvent} coral-table-column:_alignmentchanged
@private
*/
/**
Triggered when {@link TableColumn#fixedWidth} changed.
@typedef {CustomEvent} coral-table-column:_fixedwidthchanged
@private
*/
/**
Triggered when {@link TableColumn#orderable} changed.
@typedef {CustomEvent} coral-table-column:_orderablechanged
@private
*/
/**
Triggered when {@link TableColumn#sortable} changed.
@typedef {CustomEvent} coral-table-column:_sortablechanged
@private
*/
/**
Triggered when {@link TableColumn#sortableDirection} changed.
@typedef {CustomEvent} coral-table-column:_sortabledirectionchanged
@private
*/
/**
Triggered when {@link TableColumn#hidden} changed.
@typedef {CustomEvent} coral-table-column:_hiddenchanged
@private
*/
/**
Triggered before {@link TableColumn#sortableDirection} changed.
@typedef {CustomEvent} coral-table-column:_beforecolumnsort
@private
*/
/**
Triggered when {@link TableColumn#sortableDirection} changed.
@typedef {CustomEvent} coral-table-column:_sort
@private
*/
});
export default TableColumn;