ExamplesPlaygroundReference Source

coral-spectrum/coral-component-table/src/scripts/TableColumn.js

  1. /**
  2. * Copyright 2019 Adobe. All rights reserved.
  3. * This file is licensed to you under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License. You may obtain a copy
  5. * of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Unless required by applicable law or agreed to in writing, software distributed under
  8. * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
  9. * OF ANY KIND, either express or implied. See the License for the specific language
  10. * governing permissions and limitations under the License.
  11. */
  12.  
  13. import {BaseComponent} from '../../../coral-base-component';
  14. import {alignment} from './TableUtil';
  15. import {commons, transform, validate} from '../../../coral-utils';
  16. import {Decorator} from '../../../coral-decorator';
  17.  
  18. const CLASSNAME = '_coral-Table-column';
  19.  
  20. /**
  21. Enumeration for {@link TableColumn} sortable direction options.
  22.  
  23. @typedef {Object} TableColumnSortableDirectionEnum
  24.  
  25. @property {String} DEFAULT
  26. Default. No sorting applied.
  27. @property {String} ASCENDING
  28. Ascending sort.
  29. @property {String} DESCENDING
  30. Descending sort.
  31. */
  32. const sortableDirection = {
  33. DEFAULT: 'default',
  34. ASCENDING: 'ascending',
  35. DESCENDING: 'descending'
  36. };
  37.  
  38. /**
  39. Enumeration for {@link TableColumn} sortable type options.
  40.  
  41. @typedef {Object} TableColumnSortableTypeEnum
  42.  
  43. @property {String} ALPHANUMERIC
  44. Alphanumeric type. If sorting is based on {@link TableCell#value}, use {String}.
  45. @property {String} NUMBER
  46. Number type. If sorting is based on {@link TableCell#value}, use {Number}.
  47. @property {String} DATE
  48. Date type. If sorting is based on {@link TableCell#value}, use {Date} in milliseconds.
  49. @property {String} CUSTOM
  50. Custom type. Sorting is based on user defined sorting.
  51. */
  52. const sortableType = {
  53. ALPHANUMERIC: 'alphanumeric',
  54. NUMBER: 'number',
  55. DATE: 'date',
  56. CUSTOM: 'custom'
  57. };
  58.  
  59. /**
  60. @class Coral.Table.Column
  61. @classdesc A Table column component
  62. @htmltag coral-table-column
  63. @htmlbasetag col
  64. @extends {HTMLTableColElement}
  65. @extends {BaseComponent}
  66. */
  67. const TableColumn = Decorator(class extends BaseComponent(HTMLTableColElement) {
  68. /**
  69. The column cells alignment. The alignment should take the {@link i18n} configuration into account.
  70.  
  71. @type {String}
  72. @default TableColumnAlignmentEnum.LEFT
  73. @htmlattribute alignment
  74. @htmlattributereflected
  75. */
  76. get alignment() {
  77. return this._alignment || alignment.LEFT;
  78. }
  79.  
  80. set alignment(value) {
  81. const oldValue = this._alignment;
  82.  
  83. value = transform.string(value).toLowerCase();
  84. this._alignment = validate.enumeration(alignment)(value) && value || alignment.LEFT;
  85. this._reflectAttribute('alignment', this._alignment);
  86.  
  87. // Don't trigger on initialization if alignment is LEFT to improve performance
  88. if (!(typeof oldValue === 'undefined' && this._alignment === alignment.LEFT)) {
  89. window.requestAnimationFrame(() => {
  90. this.trigger('coral-table-column:_alignmentchanged');
  91. });
  92. }
  93. }
  94.  
  95. /**
  96. Whether the column has a fixed width.
  97.  
  98. @type {Boolean}
  99. @default false
  100. @htmlattribute fixedwidth
  101. @htmlattributereflected
  102. */
  103. get fixedWidth() {
  104. return this._fixedWidth || false;
  105. }
  106.  
  107. set fixedWidth(value) {
  108. this._fixedWidth = transform.booleanAttr(value);
  109. this._reflectAttribute('fixedwidth', this._fixedWidth);
  110.  
  111. window.requestAnimationFrame(() => {
  112. this.trigger('coral-table-column:_fixedwidthchanged');
  113. });
  114. }
  115.  
  116. /**
  117. Whether the column is hidden.
  118.  
  119. @type {Boolean}
  120. @default false
  121. @htmlattribute hidden
  122. @htmlattributereflected
  123. */
  124. get hidden() {
  125. return this._hidden || false;
  126. }
  127.  
  128. set hidden(value) {
  129. this._hidden = transform.booleanAttr(value);
  130. this._reflectAttribute('hidden', this._hidden);
  131.  
  132. window.requestAnimationFrame(() => {
  133. this.trigger('coral-table-column:_hiddenchanged');
  134. });
  135. }
  136.  
  137. /**
  138. Whether the table column is orderable.
  139. Note that this does not affect the underlying data, only presentation.
  140.  
  141. @type {Boolean}
  142. @default false
  143. @htmlattribute orderable
  144. @htmlattributereflected
  145. */
  146. get orderable() {
  147. return this._orderable || false;
  148. }
  149.  
  150. set orderable(value) {
  151. this._orderable = transform.booleanAttr(value);
  152. this._reflectAttribute('orderable', this._orderable);
  153.  
  154. window.requestAnimationFrame(() => {
  155. this.trigger('coral-table-column:_orderablechanged');
  156. });
  157. }
  158.  
  159. /**
  160. Whether the column is sortable by user interaction.
  161.  
  162. @type {Boolean}
  163. @default false
  164. @htmlattribute sortable
  165. @htmlattributereflected
  166. */
  167. get sortable() {
  168. return this._sortable || false;
  169. }
  170.  
  171. set sortable(value) {
  172. this._sortable = transform.booleanAttr(value);
  173. this._reflectAttribute('sortable', this._sortable);
  174.  
  175. window.requestAnimationFrame(() => {
  176. this.trigger('coral-table-column:_sortablechanged');
  177. });
  178. }
  179.  
  180. /**
  181. The sorting type. See {@link TableColumnSortableTypeEnum}. If setting to <code>custom</code>, columns won't sort
  182. based on the default table sorting.
  183. Instead, a custom sorting can be performed when triggered by user interaction. This can be defined by listening to
  184. the {@link coral-table:beforecolumnsort} event.
  185.  
  186. @type {String}
  187. @default TableColumnSortableTypeEnum.ALPHANUMERIC
  188. @htmlattribute sortabletype
  189. @htmlattributereflected
  190. */
  191. get sortableType() {
  192. return this._sortableType || sortableType.ALPHANUMERIC;
  193. }
  194.  
  195. set sortableType(value) {
  196. value = transform.string(value).toLowerCase();
  197. this._sortableType = validate.enumeration(sortableType)(value) && value || sortableType.ALPHANUMERIC;
  198. this._reflectAttribute('sortabletype', this._sortableType);
  199. }
  200.  
  201. /**
  202. The sorting direction. Sorts the column cells based on {@link TableCell#value}.
  203. If not present, the sort is based on the cell text content. See {@link TableColumnSortableDirectionEnum}.
  204.  
  205. @type {String}
  206. @default TableColumnSortableDirectionEnum.DEFAULT
  207. @htmlattribute sortabledirection
  208. @htmlattributereflected
  209. */
  210. get sortableDirection() {
  211. return this._sortableDirection || sortableDirection.DEFAULT;
  212. }
  213.  
  214. set sortableDirection(value) {
  215. value = transform.string(value).toLowerCase();
  216. this._sortableDirection = validate.enumeration(sortableDirection)(value) && value || sortableDirection.DEFAULT;
  217. this._reflectAttribute('sortabledirection', this._sortableDirection);
  218.  
  219. // Prevent sorting if unnecessary
  220. if (!this._preventSort) {
  221. this._doSort();
  222.  
  223. window.requestAnimationFrame(() => {
  224. this.trigger('coral-table-column:_sortabledirectionchanged');
  225. });
  226. }
  227. }
  228.  
  229. /** @private */
  230. _sort() {
  231. let newSortableDirection;
  232. if (this.sortableDirection === sortableDirection.DEFAULT) {
  233. newSortableDirection = sortableDirection.ASCENDING;
  234. } else if (this.sortableDirection === sortableDirection.ASCENDING) {
  235. newSortableDirection = sortableDirection.DESCENDING;
  236. } else if (this.sortableDirection === sortableDirection.DESCENDING) {
  237. newSortableDirection = sortableDirection.DEFAULT;
  238. }
  239.  
  240. this.trigger('coral-table-column:_beforecolumnsort', {newSortableDirection});
  241. }
  242.  
  243. /** @private */
  244. _doSort(onInitialization) {
  245. this.trigger('coral-table-column:_sort', {onInitialization, sortableDirection, sortableType});
  246. }
  247.  
  248. /**
  249. Returns {@link TableColumn} sortable direction options.
  250.  
  251. @return {TableColumnSortableDirectionEnum}
  252. */
  253. static get sortableDirection() {
  254. return sortableDirection;
  255. }
  256.  
  257. /**
  258. Returns {@link TableColumn} sortable type options.
  259.  
  260. @return {TableColumnSortableTypeEnum}
  261. */
  262. static get sortableType() {
  263. return sortableType;
  264. }
  265.  
  266. /**
  267. Returns {@link TableColumn} alignment options.
  268.  
  269. @return {TableColumnAlignmentEnum}
  270. */
  271. static get alignment() {
  272. return alignment;
  273. }
  274.  
  275. static get _attributePropertyMap() {
  276. return commons.extend(super._attributePropertyMap, {
  277. fixedwidth: 'fixedWidth',
  278. sortabletype: 'sortableType',
  279. sortabledirection: 'sortableDirection'
  280. });
  281. }
  282.  
  283. /** @ignore */
  284. static get observedAttributes() {
  285. return super.observedAttributes.concat([
  286. 'fixedwidth',
  287. 'hidden',
  288. 'alignment',
  289. 'orderable',
  290. 'sortable',
  291. 'sortabletype',
  292. 'sortabledirection',
  293. ]);
  294. }
  295.  
  296. /** @ignore */
  297. render() {
  298. super.render();
  299.  
  300. this.classList.add(CLASSNAME);
  301.  
  302. // Default reflected attributes
  303. if (!this._sortableType) {
  304. this.sortableType = sortableType.ALPHANUMERIC;
  305. }
  306. if (!this._sortableDirection) {
  307. this.sortableDirection = sortableDirection.DEFAULT;
  308. }
  309. if (!this._alignment) {
  310. this.alignment = alignment.LEFT;
  311. }
  312. }
  313.  
  314. /**
  315. Triggered when {@link TableColumn#alignment} changed.
  316.  
  317. @typedef {CustomEvent} coral-table-column:_alignmentchanged
  318.  
  319. @private
  320. */
  321.  
  322. /**
  323. Triggered when {@link TableColumn#fixedWidth} changed.
  324.  
  325. @typedef {CustomEvent} coral-table-column:_fixedwidthchanged
  326.  
  327. @private
  328. */
  329.  
  330. /**
  331. Triggered when {@link TableColumn#orderable} changed.
  332.  
  333. @typedef {CustomEvent} coral-table-column:_orderablechanged
  334.  
  335. @private
  336. */
  337.  
  338. /**
  339. Triggered when {@link TableColumn#sortable} changed.
  340.  
  341. @typedef {CustomEvent} coral-table-column:_sortablechanged
  342.  
  343. @private
  344. */
  345.  
  346. /**
  347. Triggered when {@link TableColumn#sortableDirection} changed.
  348.  
  349. @typedef {CustomEvent} coral-table-column:_sortabledirectionchanged
  350.  
  351. @private
  352. */
  353.  
  354. /**
  355. Triggered when {@link TableColumn#hidden} changed.
  356.  
  357. @typedef {CustomEvent} coral-table-column:_hiddenchanged
  358.  
  359. @private
  360. */
  361.  
  362. /**
  363. Triggered before {@link TableColumn#sortableDirection} changed.
  364.  
  365. @typedef {CustomEvent} coral-table-column:_beforecolumnsort
  366.  
  367. @private
  368. */
  369.  
  370. /**
  371. Triggered when {@link TableColumn#sortableDirection} changed.
  372.  
  373. @typedef {CustomEvent} coral-table-column:_sort
  374.  
  375. @private
  376. */
  377. });
  378.  
  379. export default TableColumn;