d09b155484f04a60914e0a854adcaa9343846e9cdedd8e4db1a40339b8f4ad74ee7ddff13dc464010cc843c01a2d1c84e50fb769c185c547171a097117a383 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  2. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  3. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  4. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  5. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  7. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  8. import moment from 'moment';
  9. import { addClass, hasClass, removeClass } from './../../helpers/dom/element';
  10. import { arrayMap, arrayReduce } from './../../helpers/array';
  11. import { isEmpty } from './../../helpers/mixed';
  12. import { hasOwnProperty } from './../../helpers/object';
  13. import BasePlugin from './../_base';
  14. import { registerPlugin } from './../../plugins';
  15. import mergeSort from './../../utils/sortingAlgorithms/mergeSort';
  16. import Hooks from './../../pluginHooks';
  17. Hooks.getSingleton().register('beforeColumnSort');
  18. Hooks.getSingleton().register('afterColumnSort');
  19. // TODO: Implement mixin arrayMapper to ColumnSorting plugin.
  20. /**
  21. * @plugin ColumnSorting
  22. *
  23. * @description
  24. * This plugin sorts the view by a column (but does not sort the data source!).
  25. * To enable the plugin, set the `columnSorting` property to either:
  26. * * a boolean value (`true`/`false`),
  27. * * an object defining the initial sorting order (see the example below).
  28. *
  29. * @example
  30. * ```js
  31. * ...
  32. * // as boolean
  33. * columnSorting: true
  34. * ...
  35. * // as a object with initial order (sort ascending column at index 2)
  36. * columnSorting: {
  37. * column: 2,
  38. * sortOrder: true, // true = ascending, false = descending, undefined = original order
  39. * sortEmptyCells: true // true = the table sorts empty cells, false = the table moves all empty cells to the end of the table
  40. * }
  41. * ...
  42. * ```
  43. * @dependencies ObserveChanges
  44. */
  45. var ColumnSorting = function (_BasePlugin) {
  46. _inherits(ColumnSorting, _BasePlugin);
  47. function ColumnSorting(hotInstance) {
  48. _classCallCheck(this, ColumnSorting);
  49. var _this2 = _possibleConstructorReturn(this, (ColumnSorting.__proto__ || Object.getPrototypeOf(ColumnSorting)).call(this, hotInstance));
  50. _this2.sortIndicators = [];
  51. _this2.lastSortedColumn = null;
  52. _this2.sortEmptyCells = false;
  53. return _this2;
  54. }
  55. /**
  56. * Check if the plugin is enabled in the handsontable settings.
  57. *
  58. * @returns {Boolean}
  59. */
  60. _createClass(ColumnSorting, [{
  61. key: 'isEnabled',
  62. value: function isEnabled() {
  63. return !!this.hot.getSettings().columnSorting;
  64. }
  65. /**
  66. * Enable plugin for this Handsontable instance.
  67. */
  68. }, {
  69. key: 'enablePlugin',
  70. value: function enablePlugin() {
  71. var _this3 = this;
  72. if (this.enabled) {
  73. return;
  74. }
  75. this.setPluginOptions();
  76. var _this = this;
  77. this.hot.sortIndex = [];
  78. this.hot.sort = function () {
  79. var args = Array.prototype.slice.call(arguments);
  80. return _this.sortByColumn.apply(_this, _toConsumableArray(args));
  81. };
  82. if (typeof this.hot.getSettings().observeChanges === 'undefined') {
  83. this.enableObserveChangesPlugin();
  84. }
  85. this.addHook('afterTrimRow', function (row) {
  86. return _this3.sort();
  87. });
  88. this.addHook('afterUntrimRow', function (row) {
  89. return _this3.sort();
  90. });
  91. this.addHook('modifyRow', function (row) {
  92. return _this3.translateRow(row);
  93. });
  94. this.addHook('unmodifyRow', function (row) {
  95. return _this3.untranslateRow(row);
  96. });
  97. this.addHook('afterUpdateSettings', function () {
  98. return _this3.onAfterUpdateSettings();
  99. });
  100. this.addHook('afterGetColHeader', function (col, TH) {
  101. return _this3.getColHeader(col, TH);
  102. });
  103. this.addHook('afterOnCellMouseDown', function (event, target) {
  104. return _this3.onAfterOnCellMouseDown(event, target);
  105. });
  106. this.addHook('afterCreateRow', function () {
  107. _this.afterCreateRow.apply(_this, arguments);
  108. });
  109. this.addHook('afterRemoveRow', function () {
  110. _this.afterRemoveRow.apply(_this, arguments);
  111. });
  112. this.addHook('afterInit', function () {
  113. return _this3.sortBySettings();
  114. });
  115. this.addHook('afterLoadData', function () {
  116. _this3.hot.sortIndex = [];
  117. if (_this3.hot.view) {
  118. _this3.sortBySettings();
  119. }
  120. });
  121. if (this.hot.view) {
  122. this.sortBySettings();
  123. }
  124. _get(ColumnSorting.prototype.__proto__ || Object.getPrototypeOf(ColumnSorting.prototype), 'enablePlugin', this).call(this);
  125. }
  126. /**
  127. * Disable plugin for this Handsontable instance.
  128. */
  129. }, {
  130. key: 'disablePlugin',
  131. value: function disablePlugin() {
  132. this.hot.sort = void 0;
  133. _get(ColumnSorting.prototype.__proto__ || Object.getPrototypeOf(ColumnSorting.prototype), 'disablePlugin', this).call(this);
  134. }
  135. /**
  136. * afterUpdateSettings callback.
  137. *
  138. * @private
  139. */
  140. }, {
  141. key: 'onAfterUpdateSettings',
  142. value: function onAfterUpdateSettings() {
  143. this.sortBySettings();
  144. }
  145. }, {
  146. key: 'sortBySettings',
  147. value: function sortBySettings() {
  148. var sortingSettings = this.hot.getSettings().columnSorting;
  149. var loadedSortingState = this.loadSortingState();
  150. var sortingColumn = void 0;
  151. var sortingOrder = void 0;
  152. if (typeof loadedSortingState === 'undefined') {
  153. sortingColumn = sortingSettings.column;
  154. sortingOrder = sortingSettings.sortOrder;
  155. } else {
  156. sortingColumn = loadedSortingState.sortColumn;
  157. sortingOrder = loadedSortingState.sortOrder;
  158. }
  159. if (typeof sortingColumn === 'number') {
  160. this.lastSortedColumn = sortingColumn;
  161. this.sortByColumn(sortingColumn, sortingOrder);
  162. }
  163. }
  164. /**
  165. * Set sorted column and order info
  166. *
  167. * @param {number} col Sorted column index.
  168. * @param {boolean|undefined} order Sorting order (`true` for ascending, `false` for descending).
  169. */
  170. }, {
  171. key: 'setSortingColumn',
  172. value: function setSortingColumn(col, order) {
  173. if (typeof col == 'undefined') {
  174. this.hot.sortColumn = void 0;
  175. this.hot.sortOrder = void 0;
  176. return;
  177. } else if (this.hot.sortColumn === col && typeof order == 'undefined') {
  178. if (this.hot.sortOrder === false) {
  179. this.hot.sortOrder = void 0;
  180. } else {
  181. this.hot.sortOrder = !this.hot.sortOrder;
  182. }
  183. } else {
  184. this.hot.sortOrder = typeof order === 'undefined' ? true : order;
  185. }
  186. this.hot.sortColumn = col;
  187. }
  188. }, {
  189. key: 'sortByColumn',
  190. value: function sortByColumn(col, order) {
  191. this.setSortingColumn(col, order);
  192. if (typeof this.hot.sortColumn == 'undefined') {
  193. return;
  194. }
  195. var allowSorting = this.hot.runHooks('beforeColumnSort', this.hot.sortColumn, this.hot.sortOrder);
  196. if (allowSorting !== false) {
  197. this.sort();
  198. }
  199. this.updateOrderClass();
  200. this.updateSortIndicator();
  201. this.hot.runHooks('afterColumnSort', this.hot.sortColumn, this.hot.sortOrder);
  202. this.hot.render();
  203. this.saveSortingState();
  204. }
  205. /**
  206. * Save the sorting state
  207. */
  208. }, {
  209. key: 'saveSortingState',
  210. value: function saveSortingState() {
  211. var sortingState = {};
  212. if (typeof this.hot.sortColumn != 'undefined') {
  213. sortingState.sortColumn = this.hot.sortColumn;
  214. }
  215. if (typeof this.hot.sortOrder != 'undefined') {
  216. sortingState.sortOrder = this.hot.sortOrder;
  217. }
  218. if (hasOwnProperty(sortingState, 'sortColumn') || hasOwnProperty(sortingState, 'sortOrder')) {
  219. this.hot.runHooks('persistentStateSave', 'columnSorting', sortingState);
  220. }
  221. }
  222. /**
  223. * Load the sorting state.
  224. *
  225. * @returns {*} Previously saved sorting state.
  226. */
  227. }, {
  228. key: 'loadSortingState',
  229. value: function loadSortingState() {
  230. var storedState = {};
  231. this.hot.runHooks('persistentStateLoad', 'columnSorting', storedState);
  232. return storedState.value;
  233. }
  234. /**
  235. * Update sorting class name state.
  236. */
  237. }, {
  238. key: 'updateOrderClass',
  239. value: function updateOrderClass() {
  240. var orderClass = void 0;
  241. if (this.hot.sortOrder === true) {
  242. orderClass = 'ascending';
  243. } else if (this.hot.sortOrder === false) {
  244. orderClass = 'descending';
  245. }
  246. this.sortOrderClass = orderClass;
  247. }
  248. }, {
  249. key: 'enableObserveChangesPlugin',
  250. value: function enableObserveChangesPlugin() {
  251. var _this = this;
  252. this.hot._registerTimeout(setTimeout(function () {
  253. _this.hot.updateSettings({
  254. observeChanges: true
  255. });
  256. }, 0));
  257. }
  258. /**
  259. * Default sorting algorithm.
  260. *
  261. * @param {Boolean} sortOrder Sorting order - `true` for ascending, `false` for descending.
  262. * @param {Object} columnMeta Column meta object.
  263. * @returns {Function} The comparing function.
  264. */
  265. }, {
  266. key: 'defaultSort',
  267. value: function defaultSort(sortOrder, columnMeta) {
  268. return function (a, b) {
  269. if (typeof a[1] == 'string') {
  270. a[1] = a[1].toLowerCase();
  271. }
  272. if (typeof b[1] == 'string') {
  273. b[1] = b[1].toLowerCase();
  274. }
  275. if (a[1] === b[1]) {
  276. return 0;
  277. }
  278. if (isEmpty(a[1])) {
  279. if (isEmpty(b[1])) {
  280. return 0;
  281. }
  282. if (columnMeta.columnSorting.sortEmptyCells) {
  283. return sortOrder ? -1 : 1;
  284. }
  285. return 1;
  286. }
  287. if (isEmpty(b[1])) {
  288. if (isEmpty(a[1])) {
  289. return 0;
  290. }
  291. if (columnMeta.columnSorting.sortEmptyCells) {
  292. return sortOrder ? 1 : -1;
  293. }
  294. return -1;
  295. }
  296. if (isNaN(a[1]) && !isNaN(b[1])) {
  297. return sortOrder ? 1 : -1;
  298. } else if (!isNaN(a[1]) && isNaN(b[1])) {
  299. return sortOrder ? -1 : 1;
  300. } else if (!(isNaN(a[1]) || isNaN(b[1]))) {
  301. a[1] = parseFloat(a[1]);
  302. b[1] = parseFloat(b[1]);
  303. }
  304. if (a[1] < b[1]) {
  305. return sortOrder ? -1 : 1;
  306. }
  307. if (a[1] > b[1]) {
  308. return sortOrder ? 1 : -1;
  309. }
  310. return 0;
  311. };
  312. }
  313. /**
  314. * Date sorting algorithm
  315. * @param {Boolean} sortOrder Sorting order (`true` for ascending, `false` for descending).
  316. * @param {Object} columnMeta Column meta object.
  317. * @returns {Function} The compare function.
  318. */
  319. }, {
  320. key: 'dateSort',
  321. value: function dateSort(sortOrder, columnMeta) {
  322. return function (a, b) {
  323. if (a[1] === b[1]) {
  324. return 0;
  325. }
  326. if (isEmpty(a[1])) {
  327. if (isEmpty(b[1])) {
  328. return 0;
  329. }
  330. if (columnMeta.columnSorting.sortEmptyCells) {
  331. return sortOrder ? -1 : 1;
  332. }
  333. return 1;
  334. }
  335. if (isEmpty(b[1])) {
  336. if (isEmpty(a[1])) {
  337. return 0;
  338. }
  339. if (columnMeta.columnSorting.sortEmptyCells) {
  340. return sortOrder ? 1 : -1;
  341. }
  342. return -1;
  343. }
  344. var aDate = moment(a[1], columnMeta.dateFormat);
  345. var bDate = moment(b[1], columnMeta.dateFormat);
  346. if (!aDate.isValid()) {
  347. return 1;
  348. }
  349. if (!bDate.isValid()) {
  350. return -1;
  351. }
  352. if (bDate.isAfter(aDate)) {
  353. return sortOrder ? -1 : 1;
  354. }
  355. if (bDate.isBefore(aDate)) {
  356. return sortOrder ? 1 : -1;
  357. }
  358. return 0;
  359. };
  360. }
  361. /**
  362. * Numeric sorting algorithm.
  363. *
  364. * @param {Boolean} sortOrder Sorting order (`true` for ascending, `false` for descending).
  365. * @param {Object} columnMeta Column meta object.
  366. * @returns {Function} The compare function.
  367. */
  368. }, {
  369. key: 'numericSort',
  370. value: function numericSort(sortOrder, columnMeta) {
  371. return function (a, b) {
  372. var parsedA = parseFloat(a[1]);
  373. var parsedB = parseFloat(b[1]);
  374. // Watch out when changing this part of code!
  375. // Check below returns 0 (as expected) when comparing empty string, null, undefined
  376. if (parsedA === parsedB || isNaN(parsedA) && isNaN(parsedB)) {
  377. return 0;
  378. }
  379. if (columnMeta.columnSorting.sortEmptyCells) {
  380. if (isEmpty(a[1])) {
  381. return sortOrder ? -1 : 1;
  382. }
  383. if (isEmpty(b[1])) {
  384. return sortOrder ? 1 : -1;
  385. }
  386. }
  387. if (isNaN(parsedA)) {
  388. return 1;
  389. }
  390. if (isNaN(parsedB)) {
  391. return -1;
  392. }
  393. if (parsedA < parsedB) {
  394. return sortOrder ? -1 : 1;
  395. } else if (parsedA > parsedB) {
  396. return sortOrder ? 1 : -1;
  397. }
  398. return 0;
  399. };
  400. }
  401. /**
  402. * Perform the sorting.
  403. */
  404. }, {
  405. key: 'sort',
  406. value: function sort() {
  407. if (typeof this.hot.sortOrder == 'undefined') {
  408. this.hot.sortIndex.length = 0;
  409. return;
  410. }
  411. var colMeta = this.hot.getCellMeta(0, this.hot.sortColumn);
  412. var emptyRows = this.hot.countEmptyRows();
  413. var sortFunction = void 0;
  414. var nrOfRows = void 0;
  415. this.hot.sortingEnabled = false; // this is required by translateRow plugin hook
  416. this.hot.sortIndex.length = 0;
  417. if (typeof colMeta.columnSorting.sortEmptyCells === 'undefined') {
  418. colMeta.columnSorting = { sortEmptyCells: this.sortEmptyCells };
  419. }
  420. if (this.hot.getSettings().maxRows === Number.POSITIVE_INFINITY) {
  421. nrOfRows = this.hot.countRows() - this.hot.getSettings().minSpareRows;
  422. } else {
  423. nrOfRows = this.hot.countRows() - emptyRows;
  424. }
  425. for (var i = 0, ilen = nrOfRows; i < ilen; i++) {
  426. this.hot.sortIndex.push([i, this.hot.getDataAtCell(i, this.hot.sortColumn)]);
  427. }
  428. if (colMeta.sortFunction) {
  429. sortFunction = colMeta.sortFunction;
  430. } else {
  431. switch (colMeta.type) {
  432. case 'date':
  433. sortFunction = this.dateSort;
  434. break;
  435. case 'numeric':
  436. sortFunction = this.numericSort;
  437. break;
  438. default:
  439. sortFunction = this.defaultSort;
  440. }
  441. }
  442. mergeSort(this.hot.sortIndex, sortFunction(this.hot.sortOrder, colMeta));
  443. // Append spareRows
  444. for (var _i = this.hot.sortIndex.length; _i < this.hot.countRows(); _i++) {
  445. this.hot.sortIndex.push([_i, this.hot.getDataAtCell(_i, this.hot.sortColumn)]);
  446. }
  447. this.hot.sortingEnabled = true; // this is required by translateRow plugin hook
  448. }
  449. /**
  450. * Update indicator states.
  451. */
  452. }, {
  453. key: 'updateSortIndicator',
  454. value: function updateSortIndicator() {
  455. if (typeof this.hot.sortOrder == 'undefined') {
  456. return;
  457. }
  458. var colMeta = this.hot.getCellMeta(0, this.hot.sortColumn);
  459. this.sortIndicators[this.hot.sortColumn] = colMeta.sortIndicator;
  460. }
  461. /**
  462. * `modifyRow` hook callback. Translates physical row index to the sorted row index.
  463. *
  464. * @param {Number} row Row index.
  465. * @returns {Number} Sorted row index.
  466. */
  467. }, {
  468. key: 'translateRow',
  469. value: function translateRow(row) {
  470. if (this.hot.sortingEnabled && typeof this.hot.sortOrder !== 'undefined' && this.hot.sortIndex && this.hot.sortIndex.length && this.hot.sortIndex[row]) {
  471. return this.hot.sortIndex[row][0];
  472. }
  473. return row;
  474. }
  475. /**
  476. * Translates sorted row index to physical row index.
  477. *
  478. * @param {Number} row Sorted row index.
  479. * @returns {number} Physical row index.
  480. */
  481. }, {
  482. key: 'untranslateRow',
  483. value: function untranslateRow(row) {
  484. if (this.hot.sortingEnabled && this.hot.sortIndex && this.hot.sortIndex.length) {
  485. for (var i = 0; i < this.hot.sortIndex.length; i++) {
  486. if (this.hot.sortIndex[i][0] == row) {
  487. return i;
  488. }
  489. }
  490. }
  491. }
  492. /**
  493. * `afterGetColHeader` callback. Adds column sorting css classes to clickable headers.
  494. *
  495. * @private
  496. * @param {Number} col Column index.
  497. * @param {Element} TH TH HTML element.
  498. */
  499. }, {
  500. key: 'getColHeader',
  501. value: function getColHeader(col, TH) {
  502. if (col < 0 || !TH.parentNode) {
  503. return false;
  504. }
  505. var headerLink = TH.querySelector('.colHeader');
  506. var colspan = TH.getAttribute('colspan');
  507. var TRs = TH.parentNode.parentNode.childNodes;
  508. var headerLevel = Array.prototype.indexOf.call(TRs, TH.parentNode);
  509. headerLevel -= TRs.length;
  510. if (!headerLink) {
  511. return;
  512. }
  513. if (this.hot.getSettings().columnSorting && col >= 0 && headerLevel === -1) {
  514. addClass(headerLink, 'columnSorting');
  515. }
  516. removeClass(headerLink, 'descending');
  517. removeClass(headerLink, 'ascending');
  518. if (this.sortIndicators[col]) {
  519. if (col === this.hot.sortColumn) {
  520. if (this.sortOrderClass === 'ascending') {
  521. addClass(headerLink, 'ascending');
  522. } else if (this.sortOrderClass === 'descending') {
  523. addClass(headerLink, 'descending');
  524. }
  525. }
  526. }
  527. }
  528. /**
  529. * Check if any column is in a sorted state.
  530. *
  531. * @returns {Boolean}
  532. */
  533. }, {
  534. key: 'isSorted',
  535. value: function isSorted() {
  536. return typeof this.hot.sortColumn != 'undefined';
  537. }
  538. /**
  539. * `afterCreateRow` callback. Updates the sorting state after a row have been created.
  540. *
  541. * @private
  542. * @param {Number} index
  543. * @param {Number} amount
  544. */
  545. }, {
  546. key: 'afterCreateRow',
  547. value: function afterCreateRow(index, amount) {
  548. if (!this.isSorted()) {
  549. return;
  550. }
  551. for (var i = 0; i < this.hot.sortIndex.length; i++) {
  552. if (this.hot.sortIndex[i][0] >= index) {
  553. this.hot.sortIndex[i][0] += amount;
  554. }
  555. }
  556. for (var _i2 = 0; _i2 < amount; _i2++) {
  557. this.hot.sortIndex.splice(index + _i2, 0, [index + _i2, this.hot.getSourceData()[index + _i2][this.hot.sortColumn + this.hot.colOffset()]]);
  558. }
  559. this.saveSortingState();
  560. }
  561. /**
  562. * `afterRemoveRow` hook callback.
  563. *
  564. * @private
  565. * @param {Number} index
  566. * @param {Number} amount
  567. */
  568. }, {
  569. key: 'afterRemoveRow',
  570. value: function afterRemoveRow(index, amount) {
  571. if (!this.isSorted()) {
  572. return;
  573. }
  574. var removedRows = this.hot.sortIndex.splice(index, amount);
  575. removedRows = arrayMap(removedRows, function (row) {
  576. return row[0];
  577. });
  578. function countRowShift(logicalRow) {
  579. // Todo: compare perf between reduce vs sort->each->brake
  580. return arrayReduce(removedRows, function (count, removedLogicalRow) {
  581. if (logicalRow > removedLogicalRow) {
  582. count++;
  583. }
  584. return count;
  585. }, 0);
  586. }
  587. this.hot.sortIndex = arrayMap(this.hot.sortIndex, function (logicalRow, physicalRow) {
  588. var rowShift = countRowShift(logicalRow[0]);
  589. if (rowShift) {
  590. logicalRow[0] -= rowShift;
  591. }
  592. return logicalRow;
  593. });
  594. this.saveSortingState();
  595. }
  596. /**
  597. * Set options by passed settings
  598. *
  599. * @private
  600. */
  601. }, {
  602. key: 'setPluginOptions',
  603. value: function setPluginOptions() {
  604. var columnSorting = this.hot.getSettings().columnSorting;
  605. if ((typeof columnSorting === 'undefined' ? 'undefined' : _typeof(columnSorting)) === 'object') {
  606. this.sortEmptyCells = columnSorting.sortEmptyCells || false;
  607. } else {
  608. this.sortEmptyCells = false;
  609. }
  610. }
  611. /**
  612. * `onAfterOnCellMouseDown` hook callback.
  613. *
  614. * @private
  615. * @param {Event} event Event which are provided by hook.
  616. * @param {CellCoords} coords Coords of the selected cell.
  617. */
  618. }, {
  619. key: 'onAfterOnCellMouseDown',
  620. value: function onAfterOnCellMouseDown(event, coords) {
  621. if (coords.row > -1) {
  622. return;
  623. }
  624. if (hasClass(event.realTarget, 'columnSorting')) {
  625. // reset order state on every new column header click
  626. if (coords.col !== this.lastSortedColumn) {
  627. this.hot.sortOrder = true;
  628. }
  629. this.lastSortedColumn = coords.col;
  630. this.sortByColumn(coords.col);
  631. }
  632. }
  633. }]);
  634. return ColumnSorting;
  635. }(BasePlugin);
  636. registerPlugin('columnSorting', ColumnSorting);
  637. export default ColumnSorting;