You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

filterRows.js 5.9 KiB

2 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import { isNumber, stripHTML } from './utils';
  2. import CellManager from './cellmanager';
  3. export default function filterRows(rows, filters) {
  4. let filteredRowIndices = [];
  5. if (Object.keys(filters).length === 0) {
  6. return rows.map(row => row.meta.rowIndex);
  7. }
  8. for (let colIndex in filters) {
  9. const keyword = filters[colIndex];
  10. const filteredRows = filteredRowIndices.length ?
  11. filteredRowIndices.map(i => rows[i]) :
  12. rows;
  13. const cells = filteredRows.map(row => row[colIndex]);
  14. let filter = guessFilter(keyword);
  15. let filterMethod = getFilterMethod(rows, filter);
  16. if (filterMethod) {
  17. filteredRowIndices = filterMethod(filter.text, cells);
  18. } else {
  19. filteredRowIndices = cells.map(cell => cell.rowIndex);
  20. }
  21. }
  22. return filteredRowIndices;
  23. };
  24. function getFilterMethod(rows, filter) {
  25. const getFormattedValue = cell => {
  26. let formatter = CellManager.getCustomCellFormatter(cell);
  27. if (formatter && cell.content) {
  28. cell.html = formatter(cell.content, rows[cell.rowIndex], cell.column, rows[cell.rowIndex]);
  29. return stripHTML(cell.html);
  30. }
  31. return cell.content || '';
  32. };
  33. const stringCompareValue = cell =>
  34. String(stripHTML(cell.html || '') || getFormattedValue(cell)).toLowerCase();
  35. const numberCompareValue = cell => parseFloat(cell.content);
  36. const getCompareValues = (cell, keyword) => {
  37. if (cell.column.compareValue) {
  38. const compareValues = cell.column.compareValue(cell, keyword);
  39. if (compareValues && Array.isArray(compareValues)) return compareValues;
  40. }
  41. // check if it can be converted to number
  42. const float = numberCompareValue(cell);
  43. if (!isNaN(float)) {
  44. return [float, keyword];
  45. }
  46. return [stringCompareValue(cell), keyword];
  47. };
  48. let filterMethodMap = {
  49. contains(keyword, cells) {
  50. return cells
  51. .filter(cell => {
  52. const hay = stringCompareValue(cell);
  53. const needle = (keyword || '').toLowerCase();
  54. return !needle || hay.includes(needle);
  55. })
  56. .map(cell => cell.rowIndex);
  57. },
  58. greaterThan(keyword, cells) {
  59. return cells
  60. .filter(cell => {
  61. const [compareValue, keywordValue] = getCompareValues(cell, keyword);
  62. return compareValue > keywordValue;
  63. })
  64. .map(cell => cell.rowIndex);
  65. },
  66. lessThan(keyword, cells) {
  67. return cells
  68. .filter(cell => {
  69. const [compareValue, keywordValue] = getCompareValues(cell, keyword);
  70. return compareValue < keywordValue;
  71. })
  72. .map(cell => cell.rowIndex);
  73. },
  74. equals(keyword, cells) {
  75. return cells
  76. .filter(cell => {
  77. const value = parseFloat(cell.content);
  78. return value === keyword;
  79. })
  80. .map(cell => cell.rowIndex);
  81. },
  82. notEquals(keyword, cells) {
  83. return cells
  84. .filter(cell => {
  85. const value = parseFloat(cell.content);
  86. return value !== keyword;
  87. })
  88. .map(cell => cell.rowIndex);
  89. },
  90. range(rangeValues, cells) {
  91. return cells
  92. .filter(cell => {
  93. const values1 = getCompareValues(cell, rangeValues[0]);
  94. const values2 = getCompareValues(cell, rangeValues[1]);
  95. const value = values1[0];
  96. return value >= values1[1] && value <= values2[1];
  97. })
  98. .map(cell => cell.rowIndex);
  99. },
  100. containsNumber(keyword, cells) {
  101. return cells
  102. .filter(cell => {
  103. let number = parseFloat(keyword, 10);
  104. let string = keyword;
  105. let hayNumber = numberCompareValue(cell);
  106. let hayString = stringCompareValue(cell);
  107. return number === hayNumber || hayString.includes(string);
  108. })
  109. .map(cell => cell.rowIndex);
  110. }
  111. };
  112. return filterMethodMap[filter.type];
  113. }
  114. function guessFilter(keyword = '') {
  115. if (keyword.length === 0) return {};
  116. let compareString = keyword;
  117. if (['>', '<', '='].includes(compareString[0])) {
  118. compareString = keyword.slice(1);
  119. } else if (compareString.startsWith('!=')) {
  120. compareString = keyword.slice(2);
  121. }
  122. if (keyword.startsWith('>')) {
  123. if (compareString) {
  124. return {
  125. type: 'greaterThan',
  126. text: compareString.trim()
  127. };
  128. }
  129. }
  130. if (keyword.startsWith('<')) {
  131. if (compareString) {
  132. return {
  133. type: 'lessThan',
  134. text: compareString.trim()
  135. };
  136. }
  137. }
  138. if (keyword.startsWith('=')) {
  139. if (isNumber(compareString)) {
  140. return {
  141. type: 'equals',
  142. text: Number(keyword.slice(1).trim())
  143. };
  144. }
  145. }
  146. if (isNumber(compareString)) {
  147. return {
  148. type: 'containsNumber',
  149. text: compareString
  150. };
  151. }
  152. if (keyword.startsWith('!=')) {
  153. if (isNumber(compareString)) {
  154. return {
  155. type: 'notEquals',
  156. text: Number(keyword.slice(2).trim())
  157. };
  158. }
  159. }
  160. if (keyword.split(':').length === 2) {
  161. compareString = keyword.split(':');
  162. return {
  163. type: 'range',
  164. text: compareString.map(v => v.trim())
  165. };
  166. }
  167. return {
  168. type: 'contains',
  169. text: compareString.toLowerCase()
  170. };
  171. }