utils.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { isUndefined } from '../../helpers/mixed';
  2. import { isObject } from '../../helpers/object';
  3. import { isRightClick } from '../../helpers/dom/event';
  4. export const ASC_SORT_STATE = 'asc';
  5. export const DESC_SORT_STATE = 'desc';
  6. export const HEADER_SPAN_CLASS = 'colHeader';
  7. /**
  8. * Get if column state is valid.
  9. *
  10. * @param {Number} columnState Particular column state.
  11. * @returns {Boolean}
  12. */
  13. function isValidColumnState(columnState) {
  14. if (isUndefined(columnState)) {
  15. return false;
  16. }
  17. const { column, sortOrder } = columnState;
  18. return Number.isInteger(column) && [ASC_SORT_STATE, DESC_SORT_STATE].includes(sortOrder);
  19. }
  20. /**
  21. * Get if all sorted columns states are valid.
  22. *
  23. * @param {Array} sortStates
  24. * @returns {Boolean}
  25. */
  26. export function areValidSortStates(sortStates) {
  27. if (Array.isArray(sortStates) === false || sortStates.every(columnState => isObject(columnState)) === false) {
  28. return false;
  29. }
  30. const sortedColumns = sortStates.map(({ column }) => column);
  31. const indexOccursOnlyOnce = new Set(sortedColumns).size === sortedColumns.length;
  32. return indexOccursOnlyOnce && sortStates.every(isValidColumnState);
  33. }
  34. /**
  35. * Get next sort order for particular column. The order sequence looks as follows: 'asc' -> 'desc' -> undefined -> 'asc'
  36. *
  37. * @param {String|undefined} sortOrder sort order (`asc` for ascending, `desc` for descending and undefined for not sorted).
  38. * @returns {String|undefined} Next sort order (`asc` for ascending, `desc` for descending and undefined for not sorted).
  39. */
  40. export function getNextSortOrder(sortOrder) {
  41. if (sortOrder === DESC_SORT_STATE) {
  42. return;
  43. } else if (sortOrder === ASC_SORT_STATE) {
  44. return DESC_SORT_STATE;
  45. }
  46. return ASC_SORT_STATE;
  47. }
  48. /**
  49. * Get `span` DOM element inside `th` DOM element.
  50. *
  51. * @param {Element} TH th HTML element.
  52. * @returns {Element | null}
  53. */
  54. export function getHeaderSpanElement(TH) {
  55. const headerSpanElement = TH.querySelector(`.${HEADER_SPAN_CLASS}`);
  56. return headerSpanElement;
  57. }
  58. /**
  59. *
  60. * Get if handled header is first level column header.
  61. *
  62. * @param {Number} column Visual column index.
  63. * @param {Element} TH th HTML element.
  64. * @returns {Boolean}
  65. */
  66. export function isFirstLevelColumnHeader(column, TH) {
  67. if (column < 0 || !TH.parentNode) {
  68. return false;
  69. }
  70. const TRs = TH.parentNode.parentNode.childNodes;
  71. const headerLevel = Array.from(TRs).indexOf(TH.parentNode) - TRs.length;
  72. if (headerLevel !== -1) {
  73. return false;
  74. }
  75. return true;
  76. }
  77. /**
  78. * Get if header was clicked properly. Click on column header and NOT done by right click return `true`.
  79. *
  80. * @param {Number} row Visual row index.
  81. * @param {Number} column Visual column index.
  82. * @param {Event} clickEvent Click event.
  83. * @returns {Boolean}
  84. */
  85. export function wasHeaderClickedProperly(row, column, clickEvent) {
  86. return row === -1 && column >= 0 && isRightClick(clickEvent) === false;
  87. }