manualColumnMove.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. 'use strict';
  2. exports.__esModule = true;
  3. 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; }; }();
  4. 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); } };
  5. var _base = require('./../_base.js');
  6. var _base2 = _interopRequireDefault(_base);
  7. var _pluginHooks = require('./../../pluginHooks');
  8. var _pluginHooks2 = _interopRequireDefault(_pluginHooks);
  9. var _array = require('./../../helpers/array');
  10. var _element = require('./../../helpers/dom/element');
  11. var _number = require('./../../helpers/number');
  12. var _eventManager = require('./../../eventManager');
  13. var _eventManager2 = _interopRequireDefault(_eventManager);
  14. var _plugins = require('./../../plugins');
  15. var _columnsMapper = require('./columnsMapper');
  16. var _columnsMapper2 = _interopRequireDefault(_columnsMapper);
  17. var _backlight = require('./ui/backlight');
  18. var _backlight2 = _interopRequireDefault(_backlight);
  19. var _guideline = require('./ui/guideline');
  20. var _guideline2 = _interopRequireDefault(_guideline);
  21. var _src = require('./../../3rdparty/walkontable/src');
  22. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  23. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  24. 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; }
  25. 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; }
  26. _pluginHooks2.default.getSingleton().register('beforeColumnMove');
  27. _pluginHooks2.default.getSingleton().register('afterColumnMove');
  28. _pluginHooks2.default.getSingleton().register('unmodifyCol');
  29. var privatePool = new WeakMap();
  30. var CSS_PLUGIN = 'ht__manualColumnMove';
  31. var CSS_SHOW_UI = 'show-ui';
  32. var CSS_ON_MOVING = 'on-moving--columns';
  33. var CSS_AFTER_SELECTION = 'after-selection--columns';
  34. /**
  35. * @plugin ManualColumnMove
  36. *
  37. * @description
  38. * This plugin allows to change columns order.
  39. *
  40. * API:
  41. * - moveColumn - move single column to the new position.
  42. * - moveColumns - move many columns (as an array of indexes) to the new position.
  43. *
  44. * If you want apply visual changes, you have to call manually the render() method on the instance of Handsontable.
  45. *
  46. * UI components:
  47. * - backlight - highlight of selected columns.
  48. * - guideline - line which shows where rows has been moved.
  49. *
  50. * @class ManualColumnMove
  51. * @plugin ManualColumnMove
  52. */
  53. var ManualColumnMove = function (_BasePlugin) {
  54. _inherits(ManualColumnMove, _BasePlugin);
  55. function ManualColumnMove(hotInstance) {
  56. _classCallCheck(this, ManualColumnMove);
  57. /**
  58. * Set up WeakMap of plugin to sharing private parameters;
  59. */
  60. var _this = _possibleConstructorReturn(this, (ManualColumnMove.__proto__ || Object.getPrototypeOf(ManualColumnMove)).call(this, hotInstance));
  61. privatePool.set(_this, {
  62. columnsToMove: [],
  63. countCols: 0,
  64. fixedColumns: 0,
  65. pressed: void 0,
  66. disallowMoving: void 0,
  67. target: {
  68. eventPageX: void 0,
  69. coords: void 0,
  70. TD: void 0,
  71. col: void 0
  72. }
  73. });
  74. /**
  75. * List of last removed row indexes.
  76. *
  77. * @type {Array}
  78. */
  79. _this.removedColumns = [];
  80. /**
  81. * Object containing visual row indexes mapped to data source indexes.
  82. *
  83. * @type {RowsMapper}
  84. */
  85. _this.columnsMapper = new _columnsMapper2.default(_this);
  86. /**
  87. * Event Manager object.
  88. *
  89. * @type {Object}
  90. */
  91. _this.eventManager = new _eventManager2.default(_this);
  92. /**
  93. * Backlight UI object.
  94. *
  95. * @type {Object}
  96. */
  97. _this.backlight = new _backlight2.default(hotInstance);
  98. /**
  99. * Guideline UI object.
  100. *
  101. * @type {Object}
  102. */
  103. _this.guideline = new _guideline2.default(hotInstance);
  104. return _this;
  105. }
  106. /**
  107. * Check if plugin is enabled.
  108. *
  109. * @returns {Boolean}
  110. */
  111. _createClass(ManualColumnMove, [{
  112. key: 'isEnabled',
  113. value: function isEnabled() {
  114. return !!this.hot.getSettings().manualColumnMove;
  115. }
  116. /**
  117. * Enable the plugin.
  118. */
  119. }, {
  120. key: 'enablePlugin',
  121. value: function enablePlugin() {
  122. var _this2 = this;
  123. if (this.enabled) {
  124. return;
  125. }
  126. this.addHook('beforeOnCellMouseDown', function (event, coords, TD, blockCalculations) {
  127. return _this2.onBeforeOnCellMouseDown(event, coords, TD, blockCalculations);
  128. });
  129. this.addHook('beforeOnCellMouseOver', function (event, coords, TD, blockCalculations) {
  130. return _this2.onBeforeOnCellMouseOver(event, coords, TD, blockCalculations);
  131. });
  132. this.addHook('afterScrollVertically', function () {
  133. return _this2.onAfterScrollVertically();
  134. });
  135. this.addHook('modifyCol', function (row, source) {
  136. return _this2.onModifyCol(row, source);
  137. });
  138. this.addHook('beforeRemoveCol', function (index, amount) {
  139. return _this2.onBeforeRemoveCol(index, amount);
  140. });
  141. this.addHook('afterRemoveCol', function (index, amount) {
  142. return _this2.onAfterRemoveCol(index, amount);
  143. });
  144. this.addHook('afterCreateCol', function (index, amount) {
  145. return _this2.onAfterCreateCol(index, amount);
  146. });
  147. this.addHook('afterLoadData', function (firstTime) {
  148. return _this2.onAfterLoadData(firstTime);
  149. });
  150. this.addHook('unmodifyCol', function (column) {
  151. return _this2.onUnmodifyCol(column);
  152. });
  153. this.registerEvents();
  154. // TODO: move adding plugin classname to BasePlugin.
  155. (0, _element.addClass)(this.hot.rootElement, CSS_PLUGIN);
  156. _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'enablePlugin', this).call(this);
  157. }
  158. /**
  159. * Updates the plugin to use the latest options you have specified.
  160. */
  161. }, {
  162. key: 'updatePlugin',
  163. value: function updatePlugin() {
  164. this.disablePlugin();
  165. this.enablePlugin();
  166. this.onAfterPluginsInitialized();
  167. _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'updatePlugin', this).call(this);
  168. }
  169. /**
  170. * Disable plugin for this Handsontable instance.
  171. */
  172. }, {
  173. key: 'disablePlugin',
  174. value: function disablePlugin() {
  175. var pluginSettings = this.hot.getSettings().manualColumnMove;
  176. if (Array.isArray(pluginSettings)) {
  177. this.columnsMapper.clearMap();
  178. }
  179. (0, _element.removeClass)(this.hot.rootElement, CSS_PLUGIN);
  180. this.unregisterEvents();
  181. this.backlight.destroy();
  182. this.guideline.destroy();
  183. _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'disablePlugin', this).call(this);
  184. }
  185. /**
  186. * Move a single column.
  187. *
  188. * @param {Number} column Visual column index to be moved.
  189. * @param {Number} target Visual column index being a target for the moved column.
  190. */
  191. }, {
  192. key: 'moveColumn',
  193. value: function moveColumn(column, target) {
  194. this.moveColumns([column], target);
  195. }
  196. /**
  197. * Move multiple columns.
  198. *
  199. * @param {Array} columns Array of visual column indexes to be moved.
  200. * @param {Number} target Visual column index being a target for the moved columns.
  201. */
  202. }, {
  203. key: 'moveColumns',
  204. value: function moveColumns(columns, target) {
  205. var _this3 = this;
  206. var priv = privatePool.get(this);
  207. var beforeColumnHook = this.hot.runHooks('beforeColumnMove', columns, target);
  208. priv.disallowMoving = !beforeColumnHook;
  209. if (beforeColumnHook !== false) {
  210. // first we need to rewrite an visual indexes to logical for save reference after move
  211. (0, _array.arrayEach)(columns, function (column, index, array) {
  212. array[index] = _this3.columnsMapper.getValueByIndex(column);
  213. });
  214. // next, when we have got an logical indexes, we can move columns
  215. (0, _array.arrayEach)(columns, function (column, index) {
  216. var actualPosition = _this3.columnsMapper.getIndexByValue(column);
  217. if (actualPosition !== target) {
  218. _this3.columnsMapper.moveColumn(actualPosition, target + index);
  219. }
  220. });
  221. // after moving we have to clear columnsMapper from null entries
  222. this.columnsMapper.clearNull();
  223. }
  224. this.hot.runHooks('afterColumnMove', columns, target);
  225. }
  226. /**
  227. * Correct the cell selection after the move action. Fired only when action was made with a mouse.
  228. * That means that changing the column order using the API won't correct the selection.
  229. *
  230. * @private
  231. * @param {Number} startColumn Visual column index for the start of the selection.
  232. * @param {Number} endColumn Visual column index for the end of the selection.
  233. */
  234. }, {
  235. key: 'changeSelection',
  236. value: function changeSelection(startColumn, endColumn) {
  237. var selection = this.hot.selection;
  238. var lastRowIndex = this.hot.countRows() - 1;
  239. selection.setRangeStartOnly(new _src.CellCoords(0, startColumn));
  240. selection.setRangeEnd(new _src.CellCoords(lastRowIndex, endColumn), false);
  241. }
  242. /**
  243. * Get the sum of the widths of columns in the provided range.
  244. *
  245. * @private
  246. * @param {Number} from Visual column index.
  247. * @param {Number} to Visual column index.
  248. * @returns {Number}
  249. */
  250. }, {
  251. key: 'getColumnsWidth',
  252. value: function getColumnsWidth(from, to) {
  253. var width = 0;
  254. for (var i = from; i < to; i++) {
  255. var columnWidth = 0;
  256. if (i < 0) {
  257. columnWidth = this.hot.view.wt.wtTable.getColumnWidth(i) || 0;
  258. } else {
  259. columnWidth = this.hot.view.wt.wtTable.getStretchedColumnWidth(i) || 0;
  260. }
  261. width += columnWidth;
  262. }
  263. return width;
  264. }
  265. /**
  266. * Load initial settings when persistent state is saved or when plugin was initialized as an array.
  267. *
  268. * @private
  269. */
  270. }, {
  271. key: 'initialSettings',
  272. value: function initialSettings() {
  273. var pluginSettings = this.hot.getSettings().manualColumnMove;
  274. if (Array.isArray(pluginSettings)) {
  275. this.moveColumns(pluginSettings, 0);
  276. } else if (pluginSettings !== void 0) {
  277. this.persistentStateLoad();
  278. }
  279. }
  280. /**
  281. * Check if the provided column is in the fixedColumnsLeft section.
  282. *
  283. * @private
  284. * @param {Number} column Visual column index to check.
  285. * @returns {Boolean}
  286. */
  287. }, {
  288. key: 'isFixedColumnsLeft',
  289. value: function isFixedColumnsLeft(column) {
  290. return column < this.hot.getSettings().fixedColumnsLeft;
  291. }
  292. /**
  293. * Save the manual column positions to the persistent state.
  294. *
  295. * @private
  296. */
  297. }, {
  298. key: 'persistentStateSave',
  299. value: function persistentStateSave() {
  300. this.hot.runHooks('persistentStateSave', 'manualColumnMove', this.columnsMapper._arrayMap);
  301. }
  302. /**
  303. * Load the manual column positions from the persistent state.
  304. *
  305. * @private
  306. */
  307. }, {
  308. key: 'persistentStateLoad',
  309. value: function persistentStateLoad() {
  310. var storedState = {};
  311. this.hot.runHooks('persistentStateLoad', 'manualColumnMove', storedState);
  312. if (storedState.value) {
  313. this.columnsMapper._arrayMap = storedState.value;
  314. }
  315. }
  316. /**
  317. * Prepare array of indexes based on actual selection.
  318. *
  319. * @private
  320. * @returns {Array}
  321. */
  322. }, {
  323. key: 'prepareColumnsToMoving',
  324. value: function prepareColumnsToMoving(start, end) {
  325. var selectedColumns = [];
  326. (0, _number.rangeEach)(start, end, function (i) {
  327. selectedColumns.push(i);
  328. });
  329. return selectedColumns;
  330. }
  331. /**
  332. * Update the UI visual position.
  333. *
  334. * @private
  335. */
  336. }, {
  337. key: 'refreshPositions',
  338. value: function refreshPositions() {
  339. var priv = privatePool.get(this);
  340. var firstVisible = this.hot.view.wt.wtTable.getFirstVisibleColumn();
  341. var lastVisible = this.hot.view.wt.wtTable.getLastVisibleColumn();
  342. var wtTable = this.hot.view.wt.wtTable;
  343. var scrollableElement = this.hot.view.wt.wtOverlays.scrollableElement;
  344. var scrollLeft = typeof scrollableElement.scrollX === 'number' ? scrollableElement.scrollX : scrollableElement.scrollLeft;
  345. var tdOffsetLeft = this.hot.view.THEAD.offsetLeft + this.getColumnsWidth(0, priv.coordsColumn);
  346. var mouseOffsetLeft = priv.target.eventPageX - (priv.rootElementOffset - (scrollableElement.scrollX === void 0 ? scrollLeft : 0));
  347. var hiderWidth = wtTable.hider.offsetWidth;
  348. var tbodyOffsetLeft = wtTable.TBODY.offsetLeft;
  349. var backlightElemMarginLeft = this.backlight.getOffset().left;
  350. var backlightElemWidth = this.backlight.getSize().width;
  351. var rowHeaderWidth = 0;
  352. if (priv.rootElementOffset + wtTable.holder.offsetWidth + scrollLeft < priv.target.eventPageX) {
  353. if (priv.coordsColumn < priv.countCols) {
  354. priv.coordsColumn++;
  355. }
  356. }
  357. if (priv.hasRowHeaders) {
  358. rowHeaderWidth = this.hot.view.wt.wtOverlays.leftOverlay.clone.wtTable.getColumnHeader(-1).offsetWidth;
  359. }
  360. if (this.isFixedColumnsLeft(priv.coordsColumn)) {
  361. tdOffsetLeft += scrollLeft;
  362. }
  363. tdOffsetLeft += rowHeaderWidth;
  364. if (priv.coordsColumn < 0) {
  365. // if hover on rowHeader
  366. if (priv.fixedColumns > 0) {
  367. priv.target.col = 0;
  368. } else {
  369. priv.target.col = firstVisible > 0 ? firstVisible - 1 : firstVisible;
  370. }
  371. } else if (priv.target.TD.offsetWidth / 2 + tdOffsetLeft <= mouseOffsetLeft) {
  372. var newCoordsCol = priv.coordsColumn >= priv.countCols ? priv.countCols - 1 : priv.coordsColumn;
  373. // if hover on right part of TD
  374. priv.target.col = newCoordsCol + 1;
  375. // unfortunately first column is bigger than rest
  376. tdOffsetLeft += priv.target.TD.offsetWidth;
  377. if (priv.target.col > lastVisible) {
  378. this.hot.scrollViewportTo(void 0, lastVisible + 1, void 0, true);
  379. }
  380. } else {
  381. // elsewhere on table
  382. priv.target.col = priv.coordsColumn;
  383. if (priv.target.col <= firstVisible && priv.target.col >= priv.fixedColumns) {
  384. this.hot.scrollViewportTo(void 0, firstVisible - 1);
  385. }
  386. }
  387. if (priv.target.col <= firstVisible && priv.target.col >= priv.fixedColumns) {
  388. this.hot.scrollViewportTo(void 0, firstVisible - 1);
  389. }
  390. var backlightLeft = mouseOffsetLeft;
  391. var guidelineLeft = tdOffsetLeft;
  392. if (mouseOffsetLeft + backlightElemWidth + backlightElemMarginLeft >= hiderWidth) {
  393. // prevent display backlight on the right side of the table
  394. backlightLeft = hiderWidth - backlightElemWidth - backlightElemMarginLeft;
  395. } else if (mouseOffsetLeft + backlightElemMarginLeft < tbodyOffsetLeft + rowHeaderWidth) {
  396. // prevent display backlight on the left side of the table
  397. backlightLeft = tbodyOffsetLeft + rowHeaderWidth + Math.abs(backlightElemMarginLeft);
  398. }
  399. if (tdOffsetLeft >= hiderWidth - 1) {
  400. // prevent display guideline outside the table
  401. guidelineLeft = hiderWidth - 1;
  402. } else if (guidelineLeft === 0) {
  403. // guideline has got `margin-left: -1px` as default
  404. guidelineLeft = 1;
  405. } else if (scrollableElement.scrollX !== void 0 && priv.coordsColumn < priv.fixedColumns) {
  406. guidelineLeft -= priv.rootElementOffset <= scrollableElement.scrollX ? priv.rootElementOffset : 0;
  407. }
  408. this.backlight.setPosition(null, backlightLeft);
  409. this.guideline.setPosition(null, guidelineLeft);
  410. }
  411. /**
  412. * This method checks arrayMap from columnsMapper and updates the columnsMapper if it's necessary.
  413. *
  414. * @private
  415. */
  416. }, {
  417. key: 'updateColumnsMapper',
  418. value: function updateColumnsMapper() {
  419. var countCols = this.hot.countSourceCols();
  420. var columnsMapperLen = this.columnsMapper._arrayMap.length;
  421. if (columnsMapperLen === 0) {
  422. this.columnsMapper.createMap(countCols || this.hot.getSettings().startCols);
  423. } else if (columnsMapperLen < countCols) {
  424. var diff = countCols - columnsMapperLen;
  425. this.columnsMapper.insertItems(columnsMapperLen, diff);
  426. } else if (columnsMapperLen > countCols) {
  427. var maxIndex = countCols - 1;
  428. var columnsToRemove = [];
  429. (0, _array.arrayEach)(this.columnsMapper._arrayMap, function (value, index, array) {
  430. if (value > maxIndex) {
  431. columnsToRemove.push(index);
  432. }
  433. });
  434. this.columnsMapper.removeItems(columnsToRemove);
  435. }
  436. }
  437. /**
  438. * Bind the events used by the plugin.
  439. *
  440. * @private
  441. */
  442. }, {
  443. key: 'registerEvents',
  444. value: function registerEvents() {
  445. var _this4 = this;
  446. this.eventManager.addEventListener(document.documentElement, 'mousemove', function (event) {
  447. return _this4.onMouseMove(event);
  448. });
  449. this.eventManager.addEventListener(document.documentElement, 'mouseup', function () {
  450. return _this4.onMouseUp();
  451. });
  452. }
  453. /**
  454. * Unbind the events used by the plugin.
  455. *
  456. * @private
  457. */
  458. }, {
  459. key: 'unregisterEvents',
  460. value: function unregisterEvents() {
  461. this.eventManager.clear();
  462. }
  463. /**
  464. * Change the behavior of selection / dragging.
  465. *
  466. * @private
  467. * @param {MouseEvent} event
  468. * @param {CellCoords} coords
  469. * @param {HTMLElement} TD
  470. * @param {Object} blockCalculations
  471. */
  472. }, {
  473. key: 'onBeforeOnCellMouseDown',
  474. value: function onBeforeOnCellMouseDown(event, coords, TD, blockCalculations) {
  475. var wtTable = this.hot.view.wt.wtTable;
  476. var isHeaderSelection = this.hot.selection.selectedHeader.cols;
  477. var selection = this.hot.getSelectedRange();
  478. var priv = privatePool.get(this);
  479. var isSortingElement = event.realTarget.className.indexOf('columnSorting') > -1;
  480. if (!selection || !isHeaderSelection || priv.pressed || event.button !== 0 || isSortingElement) {
  481. priv.pressed = false;
  482. priv.columnsToMove.length = 0;
  483. (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI]);
  484. return;
  485. }
  486. var guidelineIsNotReady = this.guideline.isBuilt() && !this.guideline.isAppended();
  487. var backlightIsNotReady = this.backlight.isBuilt() && !this.backlight.isAppended();
  488. if (guidelineIsNotReady && backlightIsNotReady) {
  489. this.guideline.appendTo(wtTable.hider);
  490. this.backlight.appendTo(wtTable.hider);
  491. }
  492. var from = selection.from,
  493. to = selection.to;
  494. var start = Math.min(from.col, to.col);
  495. var end = Math.max(from.col, to.col);
  496. if (coords.row < 0 && coords.col >= start && coords.col <= end) {
  497. blockCalculations.column = true;
  498. priv.pressed = true;
  499. priv.target.eventPageX = event.pageX;
  500. priv.coordsColumn = coords.col;
  501. priv.target.TD = TD;
  502. priv.target.col = coords.col;
  503. priv.columnsToMove = this.prepareColumnsToMoving(start, end);
  504. priv.hasRowHeaders = !!this.hot.getSettings().rowHeaders;
  505. priv.countCols = this.hot.countCols();
  506. priv.fixedColumns = this.hot.getSettings().fixedColumnsLeft;
  507. priv.rootElementOffset = (0, _element.offset)(this.hot.rootElement).left;
  508. var countColumnsFrom = priv.hasRowHeaders ? -1 : 0;
  509. var topPos = wtTable.holder.scrollTop + wtTable.getColumnHeaderHeight(0) + 1;
  510. var fixedColumns = coords.col < priv.fixedColumns;
  511. var scrollableElement = this.hot.view.wt.wtOverlays.scrollableElement;
  512. var wrapperIsWindow = scrollableElement.scrollX ? scrollableElement.scrollX - priv.rootElementOffset : 0;
  513. var mouseOffset = event.layerX - (fixedColumns ? wrapperIsWindow : 0);
  514. var leftOffset = Math.abs(this.getColumnsWidth(start, coords.col) + mouseOffset);
  515. this.backlight.setPosition(topPos, this.getColumnsWidth(countColumnsFrom, start) + leftOffset);
  516. this.backlight.setSize(this.getColumnsWidth(start, end + 1), wtTable.hider.offsetHeight - topPos);
  517. this.backlight.setOffset(null, leftOffset * -1);
  518. (0, _element.addClass)(this.hot.rootElement, CSS_ON_MOVING);
  519. } else {
  520. (0, _element.removeClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
  521. priv.pressed = false;
  522. priv.columnsToMove.length = 0;
  523. }
  524. }
  525. /**
  526. * 'mouseMove' event callback. Fired when pointer move on document.documentElement.
  527. *
  528. * @private
  529. * @param {MouseEvent} event `mousemove` event properties.
  530. */
  531. }, {
  532. key: 'onMouseMove',
  533. value: function onMouseMove(event) {
  534. var priv = privatePool.get(this);
  535. if (!priv.pressed) {
  536. return;
  537. }
  538. // callback for browser which doesn't supports CSS pointer-event: none
  539. if (event.realTarget === this.backlight.element) {
  540. var width = this.backlight.getSize().width;
  541. this.backlight.setSize(0);
  542. setTimeout(function () {
  543. this.backlight.setPosition(width);
  544. });
  545. }
  546. priv.target.eventPageX = event.pageX;
  547. this.refreshPositions();
  548. }
  549. /**
  550. * 'beforeOnCellMouseOver' hook callback. Fired when pointer was over cell.
  551. *
  552. * @private
  553. * @param {MouseEvent} event `mouseover` event properties.
  554. * @param {CellCoords} coords Cell coordinates where was fired event.
  555. * @param {HTMLElement} TD Cell represented as HTMLElement.
  556. * @param {Object} blockCalculations Object which contains information about blockCalculation for row, column or cells.
  557. */
  558. }, {
  559. key: 'onBeforeOnCellMouseOver',
  560. value: function onBeforeOnCellMouseOver(event, coords, TD, blockCalculations) {
  561. var selectedRange = this.hot.getSelectedRange();
  562. var priv = privatePool.get(this);
  563. if (!selectedRange || !priv.pressed) {
  564. return;
  565. }
  566. if (priv.columnsToMove.indexOf(coords.col) > -1) {
  567. (0, _element.removeClass)(this.hot.rootElement, CSS_SHOW_UI);
  568. } else {
  569. (0, _element.addClass)(this.hot.rootElement, CSS_SHOW_UI);
  570. }
  571. blockCalculations.row = true;
  572. blockCalculations.column = true;
  573. blockCalculations.cell = true;
  574. priv.coordsColumn = coords.col;
  575. priv.target.TD = TD;
  576. }
  577. /**
  578. * `onMouseUp` hook callback.
  579. *
  580. * @private
  581. */
  582. }, {
  583. key: 'onMouseUp',
  584. value: function onMouseUp() {
  585. var priv = privatePool.get(this);
  586. priv.coordsColumn = void 0;
  587. priv.pressed = false;
  588. priv.backlightWidth = 0;
  589. (0, _element.removeClass)(this.hot.rootElement, [CSS_ON_MOVING, CSS_SHOW_UI, CSS_AFTER_SELECTION]);
  590. if (this.hot.selection.selectedHeader.cols) {
  591. (0, _element.addClass)(this.hot.rootElement, CSS_AFTER_SELECTION);
  592. }
  593. if (priv.columnsToMove.length < 1 || priv.target.col === void 0 || priv.columnsToMove.indexOf(priv.target.col) > -1) {
  594. return;
  595. }
  596. this.moveColumns(priv.columnsToMove, priv.target.col);
  597. this.persistentStateSave();
  598. this.hot.render();
  599. this.hot.view.wt.wtOverlays.adjustElementsSize(true);
  600. if (!priv.disallowMoving) {
  601. var selectionStart = this.columnsMapper.getIndexByValue(priv.columnsToMove[0]);
  602. var selectionEnd = this.columnsMapper.getIndexByValue(priv.columnsToMove[priv.columnsToMove.length - 1]);
  603. this.changeSelection(selectionStart, selectionEnd);
  604. }
  605. priv.columnsToMove.length = 0;
  606. }
  607. /**
  608. * `afterScrollHorizontally` hook callback. Fired the table was scrolled horizontally.
  609. *
  610. * @private
  611. */
  612. }, {
  613. key: 'onAfterScrollVertically',
  614. value: function onAfterScrollVertically() {
  615. var wtTable = this.hot.view.wt.wtTable;
  616. var headerHeight = wtTable.getColumnHeaderHeight(0) + 1;
  617. var scrollTop = wtTable.holder.scrollTop;
  618. var posTop = headerHeight + scrollTop;
  619. this.backlight.setPosition(posTop);
  620. this.backlight.setSize(null, wtTable.hider.offsetHeight - posTop);
  621. }
  622. /**
  623. * `afterCreateCol` hook callback.
  624. *
  625. * @private
  626. * @param {Number} index Index of the created column.
  627. * @param {Number} amount Amount of created columns.
  628. */
  629. }, {
  630. key: 'onAfterCreateCol',
  631. value: function onAfterCreateCol(index, amount) {
  632. this.columnsMapper.shiftItems(index, amount);
  633. }
  634. /**
  635. * On before remove column listener.
  636. *
  637. * @private
  638. * @param {Number} index Column index.
  639. * @param {Number} amount Defines how many columns removed.
  640. */
  641. }, {
  642. key: 'onBeforeRemoveCol',
  643. value: function onBeforeRemoveCol(index, amount) {
  644. var _this5 = this;
  645. this.removedColumns.length = 0;
  646. if (index !== false) {
  647. // Collect physical row index.
  648. (0, _number.rangeEach)(index, index + amount - 1, function (removedIndex) {
  649. _this5.removedColumns.push(_this5.hot.runHooks('modifyCol', removedIndex, _this5.pluginName));
  650. });
  651. }
  652. }
  653. /**
  654. * `afterRemoveCol` hook callback.
  655. *
  656. * @private
  657. * @param {Number} index Index of the removed column.
  658. * @param {Number} amount Amount of removed columns.
  659. */
  660. }, {
  661. key: 'onAfterRemoveCol',
  662. value: function onAfterRemoveCol(index, amount) {
  663. this.columnsMapper.unshiftItems(this.removedColumns);
  664. }
  665. /**
  666. * `afterLoadData` hook callback.
  667. *
  668. * @private
  669. * @param {Boolean} firstTime True if that was loading data during the initialization.
  670. */
  671. }, {
  672. key: 'onAfterLoadData',
  673. value: function onAfterLoadData(firstTime) {
  674. this.updateColumnsMapper();
  675. }
  676. /**
  677. * 'modifyRow' hook callback.
  678. *
  679. * @private
  680. * @param {Number} column Visual column index.
  681. * @returns {Number} Modified column index.
  682. */
  683. }, {
  684. key: 'onModifyCol',
  685. value: function onModifyCol(column, source) {
  686. if (source !== this.pluginName) {
  687. // ugly fix for try to insert new, needed columns after pasting data
  688. var columnInMapper = this.columnsMapper.getValueByIndex(column);
  689. column = columnInMapper === null ? column : columnInMapper;
  690. }
  691. return column;
  692. }
  693. /**
  694. * 'unmodifyCol' hook callback.
  695. *
  696. * @private
  697. * @param {Number} column Visual column index.
  698. * @returns {Number} Logical column index.
  699. */
  700. }, {
  701. key: 'onUnmodifyCol',
  702. value: function onUnmodifyCol(column) {
  703. var indexInMapper = this.columnsMapper.getIndexByValue(column);
  704. return indexInMapper === null ? column : indexInMapper;
  705. }
  706. /**
  707. * `afterPluginsInitialized` hook callback.
  708. *
  709. * @private
  710. */
  711. }, {
  712. key: 'onAfterPluginsInitialized',
  713. value: function onAfterPluginsInitialized() {
  714. this.updateColumnsMapper();
  715. this.initialSettings();
  716. this.backlight.build();
  717. this.guideline.build();
  718. }
  719. /**
  720. * Destroy plugin instance.
  721. */
  722. }, {
  723. key: 'destroy',
  724. value: function destroy() {
  725. this.backlight.destroy();
  726. this.guideline.destroy();
  727. _get(ManualColumnMove.prototype.__proto__ || Object.getPrototypeOf(ManualColumnMove.prototype), 'destroy', this).call(this);
  728. }
  729. }]);
  730. return ManualColumnMove;
  731. }(_base2.default);
  732. (0, _plugins.registerPlugin)('ManualColumnMove', ManualColumnMove);
  733. exports.default = ManualColumnMove;