shieldRows.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import BasePlugin from '../_base';
  2. import { arrayEach } from '../../helpers/array';
  3. import { rangeEach } from '../../helpers/number';
  4. import { registerPlugin } from '../../plugins';
  5. import { mixin } from '../../helpers/object';
  6. import arrayMapper from '../../mixins/arrayMapper';
  7. class Mapper {
  8. constructor(shieldRows) {
  9. this.shieldRows = shieldRows;
  10. }
  11. createMap(length) {
  12. let rowOffset = 0;
  13. const originLength = length ? this._arrayMap.length : length;
  14. this._arrayMap.length = 0;
  15. rangeEach(originLength - 1, (itemIndex) => {
  16. if (this.shieldRows.isShield(itemIndex)) {
  17. rowOffset += 1;
  18. } else {
  19. this._arrayMap[itemIndex - rowOffset] = itemIndex;
  20. }
  21. });
  22. }
  23. destroy() {
  24. this._arrayMap = null;
  25. }
  26. }
  27. mixin(Mapper, arrayMapper);
  28. class TrimRows extends BasePlugin {
  29. constructor(hotInstance) {
  30. super(hotInstance);
  31. this.trimmedRows = [];
  32. this.removedRows = [];
  33. this.rowsMapper = new Mapper(this);
  34. }
  35. isEnabled() {
  36. return !!this.hot.getSettings().trimRows;
  37. }
  38. enablePlugin() {
  39. if (this.enabled) {
  40. return;
  41. }
  42. const settings = this.hot.getSettings().trimRows;
  43. if (Array.isArray(settings)) {
  44. this.trimmedRows = settings;
  45. }
  46. this.rowsMapper.createMap(this.hot.countSourceRows());
  47. this.addHook('modifyRow', (row, source) => this.onModifyRow(row, source));
  48. this.addHook('unmodifyRow', (row, source) => this.onUnmodifyRow(row, source));
  49. this.addHook('beforeCreateRow', (index, amount, source) => this.onBeforeCreateRow(index, amount, source));
  50. this.addHook('afterCreateRow', (index, amount) => this.onAfterCreateRow(index, amount));
  51. this.addHook('beforeRemoveRow', (index, amount) => this.onBeforeRemoveRow(index, amount));
  52. this.addHook('afterRemoveRow', () => this.onAfterRemoveRow());
  53. this.addHook('afterLoadData', firstRun => this.onAfterLoadData(firstRun));
  54. super.enablePlugin();
  55. }
  56. updatePlugin() {
  57. const settings = this.hot.getSettings().trimRows;
  58. if (Array.isArray(settings)) {
  59. this.disablePlugin();
  60. this.enablePlugin();
  61. }
  62. super.updatePlugin();
  63. }
  64. disablePlugin() {
  65. this.trimmedRows = [];
  66. this.removedRows.length = 0;
  67. this.rowsMapper.clearMap();
  68. super.disablePlugin();
  69. }
  70. trimRows(rows) {
  71. arrayEach(rows, (row) => {
  72. const physicalRow = parseInt(row, 10);
  73. if (!this.isShield(physicalRow)) {
  74. this.trimmedRows.push(physicalRow);
  75. }
  76. });
  77. this.hot.runHooks('skipLengthCache', 100);
  78. this.rowsMapper.createMap(this.hot.countSourceRows());
  79. this.hot.runHooks('afterTrimRow', rows);
  80. }
  81. trimRow(...row) {
  82. this.trimRows(row);
  83. }
  84. untrimRows(rows) {
  85. arrayEach(rows, (row) => {
  86. const physicalRow = parseInt(row, 10);
  87. if (this.isShield(physicalRow)) {
  88. this.trimmedRows.splice(this.trimmedRows.indexOf(physicalRow), 1);
  89. }
  90. });
  91. this.hot.runHooks('skipLengthCache', 100);
  92. this.rowsMapper.createMap(this.hot.countSourceRows());
  93. this.hot.runHooks('afterUntrimRow', rows);
  94. }
  95. untrimRow(...row) {
  96. this.untrimRows(row);
  97. }
  98. isShield(row) {
  99. return this.trimmedRows.indexOf(row) > -1;
  100. }
  101. untrimAll() {
  102. this.untrimRows([].concat(this.trimmedRows));
  103. }
  104. onModifyRow(row, source) {
  105. let physicalRow = row;
  106. if (source !== this.pluginName) {
  107. physicalRow = this.rowsMapper.getValueByIndex(physicalRow);
  108. }
  109. return physicalRow;
  110. }
  111. onUnmodifyRow(row, source) {
  112. let visualRow = row;
  113. if (source !== this.pluginName) {
  114. visualRow = this.rowsMapper.getIndexByValue(visualRow);
  115. }
  116. return visualRow;
  117. }
  118. onBeforeCreateRow(index, amount, source) {
  119. return !(this.isEnabled() && this.trimmedRows.length > 0 && source === 'auto');
  120. }
  121. onAfterCreateRow(index, amount) {
  122. this.rowsMapper.shiftItems(index, amount);
  123. }
  124. onBeforeRemoveRow(index, amount) {
  125. this.removedRows.length = 0;
  126. if (index !== false) {
  127. // Collect physical row index.
  128. rangeEach(index, index + amount - 1, (removedIndex) => {
  129. this.removedRows.push(this.hot.runHooks('modifyRow', removedIndex, this.pluginName));
  130. });
  131. }
  132. }
  133. onAfterRemoveRow() {
  134. this.rowsMapper.unshiftItems(this.removedRows);
  135. }
  136. onAfterLoadData(firstRun) {
  137. if (!firstRun) {
  138. this.rowsMapper.createMap(this.hot.countSourceRows());
  139. }
  140. }
  141. destroy() {
  142. this.rowsMapper.destroy();
  143. super.destroy();
  144. }
  145. }
  146. registerPlugin('trimRows', TrimRows);
  147. export default TrimRows;