fd7476d24a0a9706db600f3c43f5bb11d77b9e437b31dedcff8b04c66b74d8783575915553633ca177dec2dbd617ed6d5e1b7bf0acdbcbd298959f76a8be6f 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. import Hooks from './../../pluginHooks';
  2. import {registerPlugin} from './../../plugins';
  3. import {stopImmediatePropagation} from './../../helpers/dom/event';
  4. import {CellCoords, CellRange, Table} from './../../3rdparty/walkontable/src';
  5. function CellInfoCollection() {
  6. var collection = [];
  7. collection.getInfo = function(row, col) {
  8. for (var i = 0, ilen = this.length; i < ilen; i++) {
  9. if (this[i].row <= row && this[i].row + this[i].rowspan - 1 >= row &&
  10. this[i].col <= col && this[i].col + this[i].colspan - 1 >= col) {
  11. return this[i];
  12. }
  13. }
  14. };
  15. collection.setInfo = function(info) {
  16. for (var i = 0, ilen = this.length; i < ilen; i++) {
  17. if (this[i].row === info.row && this[i].col === info.col) {
  18. this[i] = info;
  19. return;
  20. }
  21. }
  22. this.push(info);
  23. };
  24. collection.removeInfo = function(row, col) {
  25. for (var i = 0, ilen = this.length; i < ilen; i++) {
  26. if (this[i].row === row && this[i].col === col) {
  27. this.splice(i, 1);
  28. break;
  29. }
  30. }
  31. };
  32. return collection;
  33. }
  34. /**
  35. * Plugin used to merge cells in Handsontable.
  36. *
  37. * @private
  38. * @plugin MergeCells
  39. * @class MergeCells
  40. */
  41. function MergeCells(mergeCellsSetting) {
  42. this.mergedCellInfoCollection = new CellInfoCollection();
  43. if (Array.isArray(mergeCellsSetting)) {
  44. for (var i = 0, ilen = mergeCellsSetting.length; i < ilen; i++) {
  45. this.mergedCellInfoCollection.setInfo(mergeCellsSetting[i]);
  46. }
  47. }
  48. }
  49. /**
  50. * @param cellRange (CellRange)
  51. */
  52. MergeCells.prototype.canMergeRange = function(cellRange) {
  53. // is more than one cell selected
  54. return !cellRange.isSingle();
  55. };
  56. MergeCells.prototype.mergeRange = function(cellRange) {
  57. if (!this.canMergeRange(cellRange)) {
  58. return;
  59. }
  60. // normalize top left corner
  61. var topLeft = cellRange.getTopLeftCorner();
  62. var bottomRight = cellRange.getBottomRightCorner();
  63. var mergeParent = {};
  64. mergeParent.row = topLeft.row;
  65. mergeParent.col = topLeft.col;
  66. // TD has rowspan == 1 by default. rowspan == 2 means spread over 2 cells
  67. mergeParent.rowspan = bottomRight.row - topLeft.row + 1;
  68. mergeParent.colspan = bottomRight.col - topLeft.col + 1;
  69. this.mergedCellInfoCollection.setInfo(mergeParent);
  70. };
  71. MergeCells.prototype.mergeOrUnmergeSelection = function(cellRange) {
  72. var info = this.mergedCellInfoCollection.getInfo(cellRange.from.row, cellRange.from.col);
  73. if (info) {
  74. // unmerge
  75. this.unmergeSelection(cellRange.from);
  76. } else {
  77. // merge
  78. this.mergeSelection(cellRange);
  79. }
  80. };
  81. MergeCells.prototype.mergeSelection = function(cellRange) {
  82. this.mergeRange(cellRange);
  83. };
  84. MergeCells.prototype.unmergeSelection = function(cellRange) {
  85. var info = this.mergedCellInfoCollection.getInfo(cellRange.row, cellRange.col);
  86. this.mergedCellInfoCollection.removeInfo(info.row, info.col);
  87. };
  88. MergeCells.prototype.applySpanProperties = function(TD, row, col) {
  89. var info = this.mergedCellInfoCollection.getInfo(row, col);
  90. if (info) {
  91. if (info.row === row && info.col === col) {
  92. TD.setAttribute('rowspan', info.rowspan);
  93. TD.setAttribute('colspan', info.colspan);
  94. } else {
  95. TD.removeAttribute('rowspan');
  96. TD.removeAttribute('colspan');
  97. TD.style.display = 'none';
  98. }
  99. } else {
  100. TD.removeAttribute('rowspan');
  101. TD.removeAttribute('colspan');
  102. }
  103. };
  104. MergeCells.prototype.modifyTransform = function(hook, currentSelectedRange, delta) {
  105. var sameRowspan = function(merged, coords) {
  106. if (coords.row >= merged.row && coords.row <= (merged.row + merged.rowspan - 1)) {
  107. return true;
  108. }
  109. return false;
  110. },
  111. sameColspan = function(merged, coords) {
  112. if (coords.col >= merged.col && coords.col <= (merged.col + merged.colspan - 1)) {
  113. return true;
  114. }
  115. return false;
  116. },
  117. getNextPosition = function(newDelta) {
  118. return new CellCoords(currentSelectedRange.to.row + newDelta.row, currentSelectedRange.to.col + newDelta.col);
  119. };
  120. var newDelta = {
  121. row: delta.row,
  122. col: delta.col,
  123. };
  124. if (hook == 'modifyTransformStart') {
  125. /* eslint-disable block-scoped-var */
  126. var nextPosition;
  127. if (!this.lastDesiredCoords) {
  128. this.lastDesiredCoords = new CellCoords(null, null);
  129. }
  130. var currentPosition = new CellCoords(currentSelectedRange.highlight.row, currentSelectedRange.highlight.col),
  131. // if current position's parent is a merged range, returns it
  132. mergedParent = this.mergedCellInfoCollection.getInfo(currentPosition.row, currentPosition.col),
  133. currentRangeContainsMerge; // if current range contains a merged range
  134. for (var i = 0, mergesLength = this.mergedCellInfoCollection.length; i < mergesLength; i++) {
  135. var range = this.mergedCellInfoCollection[i];
  136. range = new CellCoords(range.row + range.rowspan - 1, range.col + range.colspan - 1);
  137. if (currentSelectedRange.includes(range)) {
  138. currentRangeContainsMerge = true;
  139. break;
  140. }
  141. }
  142. if (mergedParent) { // only merge selected
  143. let mergeTopLeft = new CellCoords(mergedParent.row, mergedParent.col);
  144. let mergeBottomRight = new CellCoords(mergedParent.row + mergedParent.rowspan - 1, mergedParent.col + mergedParent.colspan - 1);
  145. let mergeRange = new CellRange(mergeTopLeft, mergeTopLeft, mergeBottomRight);
  146. if (!mergeRange.includes(this.lastDesiredCoords)) {
  147. this.lastDesiredCoords = new CellCoords(null, null); // reset outdated version of lastDesiredCoords
  148. }
  149. newDelta.row = this.lastDesiredCoords.row ? this.lastDesiredCoords.row - currentPosition.row : newDelta.row;
  150. newDelta.col = this.lastDesiredCoords.col ? this.lastDesiredCoords.col - currentPosition.col : newDelta.col;
  151. if (delta.row > 0) { // moving down
  152. newDelta.row = mergedParent.row + mergedParent.rowspan - 1 - currentPosition.row + delta.row;
  153. } else if (delta.row < 0) { // moving up
  154. newDelta.row = currentPosition.row - mergedParent.row + delta.row;
  155. }
  156. if (delta.col > 0) { // moving right
  157. newDelta.col = mergedParent.col + mergedParent.colspan - 1 - currentPosition.col + delta.col;
  158. } else if (delta.col < 0) { // moving left
  159. newDelta.col = currentPosition.col - mergedParent.col + delta.col;
  160. }
  161. }
  162. nextPosition = new CellCoords(currentSelectedRange.highlight.row + newDelta.row, currentSelectedRange.highlight.col + newDelta.col);
  163. var nextParentIsMerged = this.mergedCellInfoCollection.getInfo(nextPosition.row, nextPosition.col);
  164. if (nextParentIsMerged) { // skipping the invisible cells in the merge range
  165. this.lastDesiredCoords = nextPosition;
  166. newDelta = {
  167. row: nextParentIsMerged.row - currentPosition.row,
  168. col: nextParentIsMerged.col - currentPosition.col
  169. };
  170. }
  171. } else if (hook == 'modifyTransformEnd') {
  172. for (let i = 0, mergesLength = this.mergedCellInfoCollection.length; i < mergesLength; i++) {
  173. let currentMerge = this.mergedCellInfoCollection[i];
  174. let mergeTopLeft = new CellCoords(currentMerge.row, currentMerge.col);
  175. let mergeBottomRight = new CellCoords(currentMerge.row + currentMerge.rowspan - 1, currentMerge.col + currentMerge.colspan - 1);
  176. let mergedRange = new CellRange(mergeTopLeft, mergeTopLeft, mergeBottomRight);
  177. let sharedBorders = currentSelectedRange.getBordersSharedWith(mergedRange);
  178. if (mergedRange.isEqual(currentSelectedRange)) { // only the merged range is selected
  179. currentSelectedRange.setDirection('NW-SE');
  180. } else if (sharedBorders.length > 0) {
  181. var mergeHighlighted = (currentSelectedRange.highlight.isEqual(mergedRange.from));
  182. if (sharedBorders.indexOf('top') > -1) { // if range shares a border with the merged section, change range direction accordingly
  183. if (currentSelectedRange.to.isSouthEastOf(mergedRange.from) && mergeHighlighted) {
  184. currentSelectedRange.setDirection('NW-SE');
  185. } else if (currentSelectedRange.to.isSouthWestOf(mergedRange.from) && mergeHighlighted) {
  186. currentSelectedRange.setDirection('NE-SW');
  187. }
  188. } else if (sharedBorders.indexOf('bottom') > -1) {
  189. if (currentSelectedRange.to.isNorthEastOf(mergedRange.from) && mergeHighlighted) {
  190. currentSelectedRange.setDirection('SW-NE');
  191. } else if (currentSelectedRange.to.isNorthWestOf(mergedRange.from) && mergeHighlighted) {
  192. currentSelectedRange.setDirection('SE-NW');
  193. }
  194. }
  195. }
  196. nextPosition = getNextPosition(newDelta);
  197. var
  198. withinRowspan = sameRowspan(currentMerge, nextPosition),
  199. withinColspan = sameColspan(currentMerge, nextPosition);
  200. if (currentSelectedRange.includesRange(mergedRange) && (mergedRange.includes(nextPosition) ||
  201. withinRowspan || withinColspan)) { // if next step overlaps a merged range, jump past it
  202. if (withinRowspan) {
  203. if (newDelta.row < 0) {
  204. newDelta.row -= currentMerge.rowspan - 1;
  205. } else if (newDelta.row > 0) {
  206. newDelta.row += currentMerge.rowspan - 1;
  207. }
  208. }
  209. if (withinColspan) {
  210. if (newDelta.col < 0) {
  211. newDelta.col -= currentMerge.colspan - 1;
  212. } else if (newDelta.col > 0) {
  213. newDelta.col += currentMerge.colspan - 1;
  214. }
  215. }
  216. }
  217. }
  218. }
  219. if (newDelta.row !== 0) {
  220. delta.row = newDelta.row;
  221. }
  222. if (newDelta.col !== 0) {
  223. delta.col = newDelta.col;
  224. }
  225. };
  226. MergeCells.prototype.shiftCollection = function(direction, index, count) {
  227. var shiftVector = [0, 0];
  228. switch (direction) {
  229. case 'right':
  230. shiftVector[0] += 1;
  231. break;
  232. case 'left':
  233. shiftVector[0] -= 1;
  234. break;
  235. case 'down':
  236. shiftVector[1] += 1;
  237. break;
  238. case 'up':
  239. shiftVector[1] -= 1;
  240. break;
  241. default:
  242. break;
  243. }
  244. for (var i = 0; i < this.mergedCellInfoCollection.length; i++) {
  245. var currentMerge = this.mergedCellInfoCollection[i];
  246. if (direction === 'right' || direction === 'left') {
  247. if (index <= currentMerge.col) {
  248. currentMerge.col += shiftVector[0];
  249. }
  250. } else if (index <= currentMerge.row) {
  251. currentMerge.row += shiftVector[1];
  252. }
  253. }
  254. };
  255. var beforeInit = function() {
  256. var instance = this;
  257. var mergeCellsSetting = instance.getSettings().mergeCells;
  258. if (mergeCellsSetting) {
  259. if (!instance.mergeCells) {
  260. instance.mergeCells = new MergeCells(mergeCellsSetting);
  261. }
  262. }
  263. };
  264. var afterInit = function() {
  265. var instance = this;
  266. if (instance.mergeCells) {
  267. /**
  268. * Monkey patch Table.prototype.getCell to return TD for merged cell parent if asked for TD of a cell that is
  269. * invisible due to the merge. This is not the cleanest solution but there is a test case for it (merged cells scroll) so feel free to refactor it!
  270. */
  271. instance.view.wt.wtTable.getCell = function(coords) {
  272. if (instance.getSettings().mergeCells) {
  273. var mergeParent = instance.mergeCells.mergedCellInfoCollection.getInfo(coords.row, coords.col);
  274. if (mergeParent) {
  275. coords = mergeParent;
  276. }
  277. }
  278. return Table.prototype.getCell.call(this, coords);
  279. };
  280. }
  281. };
  282. var afterUpdateSettings = function() {
  283. var instance = this;
  284. var mergeCellsSetting = instance.getSettings().mergeCells;
  285. if (mergeCellsSetting) {
  286. if (instance.mergeCells) {
  287. instance.mergeCells.mergedCellInfoCollection = new CellInfoCollection();
  288. if (Array.isArray(mergeCellsSetting)) {
  289. for (var i = 0, ilen = mergeCellsSetting.length; i < ilen; i++) {
  290. instance.mergeCells.mergedCellInfoCollection.setInfo(mergeCellsSetting[i]);
  291. }
  292. }
  293. } else {
  294. instance.mergeCells = new MergeCells(mergeCellsSetting);
  295. }
  296. } else if (instance.mergeCells) { // it doesn't actually turn off the plugin, just resets the settings. Need to refactor.
  297. instance.mergeCells.mergedCellInfoCollection = new CellInfoCollection();
  298. }
  299. };
  300. var onBeforeKeyDown = function(event) {
  301. if (!this.mergeCells) {
  302. return;
  303. }
  304. var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;
  305. if (ctrlDown) {
  306. if (event.keyCode === 77) { // CTRL + M
  307. this.mergeCells.mergeOrUnmergeSelection(this.getSelectedRange());
  308. this.render();
  309. stopImmediatePropagation(event);
  310. }
  311. }
  312. };
  313. var addMergeActionsToContextMenu = function(defaultOptions) {
  314. if (!this.getSettings().mergeCells) {
  315. return;
  316. }
  317. defaultOptions.items.push({name: '---------'});
  318. defaultOptions.items.push({
  319. key: 'mergeCells',
  320. name() {
  321. var sel = this.getSelected();
  322. var info = this.mergeCells.mergedCellInfoCollection.getInfo(sel[0], sel[1]);
  323. if (info) {
  324. return 'Unmerge cells';
  325. }
  326. return 'Merge cells';
  327. },
  328. callback() {
  329. this.mergeCells.mergeOrUnmergeSelection(this.getSelectedRange());
  330. this.render();
  331. },
  332. disabled() {
  333. return this.selection.selectedHeader.corner;
  334. },
  335. });
  336. };
  337. var afterRenderer = function(TD, row, col, prop, value, cellProperties) {
  338. if (this.mergeCells) {
  339. this.mergeCells.applySpanProperties(TD, row, col);
  340. }
  341. };
  342. var modifyTransformFactory = function(hook) {
  343. return function(delta) {
  344. var mergeCellsSetting = this.getSettings().mergeCells;
  345. if (mergeCellsSetting) {
  346. var currentSelectedRange = this.getSelectedRange();
  347. this.mergeCells.modifyTransform(hook, currentSelectedRange, delta);
  348. if (hook === 'modifyTransformEnd') {
  349. // sanitize "from" (core.js will sanitize to)
  350. var totalRows = this.countRows();
  351. var totalCols = this.countCols();
  352. if (currentSelectedRange.from.row < 0) {
  353. currentSelectedRange.from.row = 0;
  354. } else if (currentSelectedRange.from.row > 0 && currentSelectedRange.from.row >= totalRows) {
  355. currentSelectedRange.from.row = currentSelectedRange.from - 1;
  356. }
  357. if (currentSelectedRange.from.col < 0) {
  358. currentSelectedRange.from.col = 0;
  359. } else if (currentSelectedRange.from.col > 0 && currentSelectedRange.from.col >= totalCols) {
  360. currentSelectedRange.from.col = totalCols - 1;
  361. }
  362. }
  363. }
  364. };
  365. };
  366. /**
  367. * While selecting cells with keyboard or mouse, make sure that rectangular area is expanded to the extent of the merged cell
  368. * @param coords
  369. */
  370. var beforeSetRangeEnd = function(coords) {
  371. this.lastDesiredCoords = null; // unset lastDesiredCoords when selection is changed with mouse
  372. var mergeCellsSetting = this.getSettings().mergeCells;
  373. if (mergeCellsSetting) {
  374. var selRange = this.getSelectedRange();
  375. selRange.highlight = new CellCoords(selRange.highlight.row, selRange.highlight.col); // clone in case we will modify its reference
  376. selRange.to = coords;
  377. var rangeExpanded = false;
  378. do {
  379. rangeExpanded = false;
  380. for (var i = 0, ilen = this.mergeCells.mergedCellInfoCollection.length; i < ilen; i++) {
  381. var cellInfo = this.mergeCells.mergedCellInfoCollection[i];
  382. var mergedCellTopLeft = new CellCoords(cellInfo.row, cellInfo.col);
  383. var mergedCellBottomRight = new CellCoords(cellInfo.row + cellInfo.rowspan - 1, cellInfo.col + cellInfo.colspan - 1);
  384. var mergedCellRange = new CellRange(mergedCellTopLeft, mergedCellTopLeft, mergedCellBottomRight);
  385. if (selRange.expandByRange(mergedCellRange)) {
  386. coords.row = selRange.to.row;
  387. coords.col = selRange.to.col;
  388. rangeExpanded = true;
  389. }
  390. }
  391. } while (rangeExpanded);
  392. }
  393. };
  394. /**
  395. * Returns correct coordinates for merged start / end cells in selection for area borders
  396. * @param corners
  397. * @param className
  398. */
  399. var beforeDrawAreaBorders = function(corners, className) {
  400. if (className && className == 'area') {
  401. var mergeCellsSetting = this.getSettings().mergeCells;
  402. if (mergeCellsSetting) {
  403. var selRange = this.getSelectedRange();
  404. var startRange = new CellRange(selRange.from, selRange.from, selRange.from);
  405. var stopRange = new CellRange(selRange.to, selRange.to, selRange.to);
  406. for (var i = 0, ilen = this.mergeCells.mergedCellInfoCollection.length; i < ilen; i++) {
  407. var cellInfo = this.mergeCells.mergedCellInfoCollection[i];
  408. var mergedCellTopLeft = new CellCoords(cellInfo.row, cellInfo.col);
  409. var mergedCellBottomRight = new CellCoords(cellInfo.row + cellInfo.rowspan - 1, cellInfo.col + cellInfo.colspan - 1);
  410. var mergedCellRange = new CellRange(mergedCellTopLeft, mergedCellTopLeft, mergedCellBottomRight);
  411. if (startRange.expandByRange(mergedCellRange)) {
  412. corners[0] = startRange.from.row;
  413. corners[1] = startRange.from.col;
  414. }
  415. if (stopRange.expandByRange(mergedCellRange)) {
  416. corners[2] = stopRange.from.row;
  417. corners[3] = stopRange.from.col;
  418. }
  419. }
  420. }
  421. }
  422. };
  423. var afterGetCellMeta = function(row, col, cellProperties) {
  424. var mergeCellsSetting = this.getSettings().mergeCells;
  425. if (mergeCellsSetting) {
  426. var mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(row, col);
  427. if (mergeParent && (mergeParent.row != row || mergeParent.col != col)) {
  428. cellProperties.copyable = false;
  429. }
  430. }
  431. };
  432. var afterViewportRowCalculatorOverride = function(calc) {
  433. var mergeCellsSetting = this.getSettings().mergeCells;
  434. if (mergeCellsSetting) {
  435. var colCount = this.countCols();
  436. var mergeParent;
  437. for (var c = 0; c < colCount; c++) {
  438. mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(calc.startRow, c);
  439. if (mergeParent) {
  440. if (mergeParent.row < calc.startRow) {
  441. calc.startRow = mergeParent.row;
  442. return afterViewportRowCalculatorOverride.call(this, calc); // recursively search upwards
  443. }
  444. }
  445. mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(calc.endRow, c);
  446. if (mergeParent) {
  447. var mergeEnd = mergeParent.row + mergeParent.rowspan - 1;
  448. if (mergeEnd > calc.endRow) {
  449. calc.endRow = mergeEnd;
  450. return afterViewportRowCalculatorOverride.call(this, calc); // recursively search upwards
  451. }
  452. }
  453. }
  454. }
  455. };
  456. var afterViewportColumnCalculatorOverride = function(calc) {
  457. var mergeCellsSetting = this.getSettings().mergeCells;
  458. if (mergeCellsSetting) {
  459. var rowCount = this.countRows();
  460. var mergeParent;
  461. for (var r = 0; r < rowCount; r++) {
  462. mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(r, calc.startColumn);
  463. if (mergeParent) {
  464. if (mergeParent.col < calc.startColumn) {
  465. calc.startColumn = mergeParent.col;
  466. return afterViewportColumnCalculatorOverride.call(this, calc); // recursively search upwards
  467. }
  468. }
  469. mergeParent = this.mergeCells.mergedCellInfoCollection.getInfo(r, calc.endColumn);
  470. if (mergeParent) {
  471. var mergeEnd = mergeParent.col + mergeParent.colspan - 1;
  472. if (mergeEnd > calc.endColumn) {
  473. calc.endColumn = mergeEnd;
  474. return afterViewportColumnCalculatorOverride.call(this, calc); // recursively search upwards
  475. }
  476. }
  477. }
  478. }
  479. };
  480. var isMultipleSelection = function(isMultiple) {
  481. if (isMultiple && this.mergeCells) {
  482. var mergedCells = this.mergeCells.mergedCellInfoCollection,
  483. selectionRange = this.getSelectedRange();
  484. for (var group in mergedCells) {
  485. if (selectionRange.highlight.row == mergedCells[group].row &&
  486. selectionRange.highlight.col == mergedCells[group].col &&
  487. selectionRange.to.row == mergedCells[group].row + mergedCells[group].rowspan - 1 &&
  488. selectionRange.to.col == mergedCells[group].col + mergedCells[group].colspan - 1) {
  489. return false;
  490. }
  491. }
  492. }
  493. return isMultiple;
  494. };
  495. function modifyAutofillRange(select, drag) {
  496. var mergeCellsSetting = this.getSettings().mergeCells;
  497. if (!mergeCellsSetting || this.selection.isMultiple()) {
  498. return;
  499. }
  500. var info = this.mergeCells.mergedCellInfoCollection.getInfo(select[0], select[1]);
  501. if (info) {
  502. select[0] = info.row;
  503. select[1] = info.col;
  504. select[2] = info.row + info.rowspan - 1;
  505. select[3] = info.col + info.colspan - 1;
  506. }
  507. }
  508. function onAfterCreateCol(col, count) {
  509. if (this.mergeCells) {
  510. this.mergeCells.shiftCollection('right', col, count);
  511. }
  512. }
  513. function onAfterRemoveCol(col, count) {
  514. if (this.mergeCells) {
  515. this.mergeCells.shiftCollection('left', col, count);
  516. }
  517. }
  518. function onAfterCreateRow(row, count) {
  519. if (this.mergeCells) {
  520. this.mergeCells.shiftCollection('down', row, count);
  521. }
  522. }
  523. function onAfterRemoveRow(row, count) {
  524. if (this.mergeCells) {
  525. this.mergeCells.shiftCollection('up', row, count);
  526. }
  527. }
  528. const hook = Hooks.getSingleton();
  529. hook.add('beforeInit', beforeInit);
  530. hook.add('afterInit', afterInit);
  531. hook.add('afterUpdateSettings', afterUpdateSettings);
  532. hook.add('beforeKeyDown', onBeforeKeyDown);
  533. hook.add('modifyTransformStart', modifyTransformFactory('modifyTransformStart'));
  534. hook.add('modifyTransformEnd', modifyTransformFactory('modifyTransformEnd'));
  535. hook.add('beforeSetRangeEnd', beforeSetRangeEnd);
  536. hook.add('beforeDrawBorders', beforeDrawAreaBorders);
  537. hook.add('afterIsMultipleSelection', isMultipleSelection);
  538. hook.add('afterRenderer', afterRenderer);
  539. hook.add('afterContextMenuDefaultOptions', addMergeActionsToContextMenu);
  540. hook.add('afterGetCellMeta', afterGetCellMeta);
  541. hook.add('afterViewportRowCalculatorOverride', afterViewportRowCalculatorOverride);
  542. hook.add('afterViewportColumnCalculatorOverride', afterViewportColumnCalculatorOverride);
  543. hook.add('modifyAutofillRange', modifyAutofillRange);
  544. hook.add('afterCreateCol', onAfterCreateCol);
  545. hook.add('afterRemoveCol', onAfterRemoveCol);
  546. hook.add('afterCreateRow', onAfterCreateRow);
  547. hook.add('afterRemoveRow', onAfterRemoveRow);
  548. export default MergeCells;