Skip to content
This repository was archived by the owner on Jul 25, 2019. It is now read-only.

Commit f9fee9b

Browse files
committed
Merge branch 'feature/undoRedo-enchancement' into develop
Conflicts: src/core.js
2 parents a2bcff9 + 1d495ce commit f9fee9b

11 files changed

+1896
-246
lines changed

Gruntfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ module.exports = function (grunt) {
5757
'src/tableView.js',
5858
'src/helpers.js',
5959
'src/fillHandle.js',
60-
'src/undoRedo.js',
6160
'src/selectionPoint.js',
6261

6362
'src/renderers/textRenderer.js',
@@ -87,6 +86,7 @@ module.exports = function (grunt) {
8786
'src/plugins/manualColumnResize.js',
8887
'src/plugins/observeChanges.js',
8988
'src/plugins/persistentState.js',
89+
'src/plugins/undoRedo.js',
9090

9191
'src/3rdparty/jquery.autoresize.js',
9292
'src/3rdparty/sheetclip.js',

src/core.js

+85-117
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ Handsontable.Core = function (rootElement, userSettings) {
4242
editProxy: false,
4343
isPopulated: null,
4444
scrollable: null,
45-
undoRedo: null,
4645
extensions: {},
4746
colToProp: null,
4847
propToCol: null,
@@ -151,69 +150,103 @@ Handsontable.Core = function (rootElement, userSettings) {
151150
* Creates row at the bottom of the data array
152151
* @param {Number} [index] Optional. Index of the row before which the new row will be inserted
153152
*/
154-
createRow: function (index) {
153+
createRow: function (index, amount) {
155154
var row
156-
, rowCount = instance.countRows();
155+
, colCount = instance.countCols()
156+
, numberOfCreatedRows = 0
157+
, currentIndex;
157158

158-
if (typeof index !== 'number' || index >= rowCount) {
159-
index = rowCount;
159+
if (!amount) {
160+
amount = 1;
160161
}
161162

162-
if (priv.dataType === 'array') {
163-
row = [];
164-
for (var c = 0, clen = instance.countCols(); c < clen; c++) {
165-
row.push(null);
166-
}
167-
}
168-
else if (priv.dataType === 'function') {
169-
row = priv.settings.dataSchema(index);
170-
}
171-
else {
172-
row = $.extend(true, {}, datamap.getSchema());
163+
if (typeof index !== 'number' || index >= instance.countRows()) {
164+
index = instance.countRows();
173165
}
174166

175-
if (index === rowCount) {
176-
GridSettings.prototype.data.push(row);
177-
}
178-
else {
179-
GridSettings.prototype.data.splice(index, 0, row);
167+
currentIndex = index;
168+
while (numberOfCreatedRows < amount && instance.countRows() < priv.settings.maxRows) {
169+
170+
if (priv.dataType === 'array') {
171+
row = [];
172+
for (var c = 0; c < colCount; c++) {
173+
row.push(null);
174+
}
175+
}
176+
else if (priv.dataType === 'function') {
177+
row = priv.settings.dataSchema(index);
178+
}
179+
else {
180+
row = $.extend(true, {}, datamap.getSchema());
181+
}
182+
183+
if (index === instance.countRows()) {
184+
GridSettings.prototype.data.push(row);
185+
}
186+
else {
187+
GridSettings.prototype.data.splice(index, 0, row);
188+
}
189+
190+
numberOfCreatedRows++;
191+
currentIndex++;
180192
}
181193

182-
instance.PluginHooks.run('afterCreateRow', index);
194+
195+
instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows);
183196
instance.forceFullRender = true; //used when data was changed
197+
198+
return numberOfCreatedRows;
184199
},
185200

186201
/**
187202
* Creates col at the right of the data array
188-
* @param {Object} [index] Optional. Index of the column before which the new column will be inserted
203+
* @param {Number} [index] Optional. Index of the column before which the new column will be inserted
204+
* * @param {Number} [amount] Optional.
189205
*/
190-
createCol: function (index) {
206+
createCol: function (index, amount) {
191207
if (priv.dataType === 'object' || priv.settings.columns) {
192208
throw new Error("Cannot create new column. When data source in an object, you can only have as much columns as defined in first data row, data schema or in the 'columns' setting");
193209
}
194-
var r = 0, rlen = instance.countRows()
210+
var rlen = instance.countRows()
195211
, data = GridSettings.prototype.data
196-
, constructor = Handsontable.helper.columnFactory(GridSettings, priv.columnsSettingConflicts);
212+
, constructor
213+
, numberOfCreatedCols = 0
214+
, currentIndex;
215+
216+
if (!amount) {
217+
amount = 1;
218+
}
219+
220+
currentIndex = index;
197221

198-
if (typeof index !== 'number' || index >= instance.countCols()) {
199-
for (; r < rlen; r++) {
200-
if (typeof data[r] === 'undefined') {
201-
data[r] = [];
222+
while (numberOfCreatedCols < amount && instance.countCols() < priv.settings.maxCols){
223+
constructor = Handsontable.helper.columnFactory(GridSettings, priv.columnsSettingConflicts);
224+
if (typeof index !== 'number' || index >= instance.countCols()) {
225+
for (var r = 0; r < rlen; r++) {
226+
if (typeof data[r] === 'undefined') {
227+
data[r] = [];
228+
}
229+
data[r].push(null);
202230
}
203-
data[r].push(null);
231+
// Add new column constructor
232+
priv.columnSettings.push(constructor);
204233
}
205-
// Add new column constructor
206-
priv.columnSettings.push(constructor);
207-
}
208-
else {
209-
for (; r < rlen; r++) {
210-
data[r].splice(index, 0, null);
234+
else {
235+
for (var r = 0 ; r < rlen; r++) {
236+
data[r].splice(currentIndex, 0, null);
237+
}
238+
// Add new column constructor at given index
239+
priv.columnSettings.splice(currentIndex, 0, constructor);
211240
}
212-
// Add new column constructor at given index
213-
priv.columnSettings.splice(index, 0, constructor);
241+
242+
numberOfCreatedCols++;
243+
currentIndex++;
214244
}
215-
instance.PluginHooks.run('afterCreateCol', index);
245+
246+
instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols);
216247
instance.forceFullRender = true; //used when data was changed
248+
249+
return numberOfCreatedCols;
217250
},
218251

219252
/**
@@ -232,6 +265,8 @@ Handsontable.Core = function (rootElement, userSettings) {
232265
// We have to map the physical row ids to logical and than perform removing with (possibly) new row id
233266
var logicRows = this.physicalRowsToLogical(index, amount);
234267

268+
instance.PluginHooks.run('beforeRemoveRow', index, amount);
269+
235270
var newData = GridSettings.prototype.data.filter(function (row, index) {
236271
return logicRows.indexOf(index) == -1;
237272
});
@@ -259,12 +294,16 @@ Handsontable.Core = function (rootElement, userSettings) {
259294
if (typeof index !== 'number') {
260295
index = -amount;
261296
}
297+
298+
instance.PluginHooks.run('beforeRemoveCol', index, amount);
299+
262300
var data = GridSettings.prototype.data;
263301
for (var r = 0, rlen = instance.countRows(); r < rlen; r++) {
264302
data[r].splice(index, amount);
265303
}
266-
instance.PluginHooks.run('afterRemoveCol', index, amount);
267304
priv.columnSettings.splice(index, amount);
305+
306+
instance.PluginHooks.run('afterRemoveCol', index, amount);
268307
instance.forceFullRender = true; //used when data was changed
269308
},
270309

@@ -487,11 +526,8 @@ Handsontable.Core = function (rootElement, userSettings) {
487526

488527
switch (action) {
489528
case "insert_row":
490-
delta = 0;
491-
while (delta < amount && instance.countRows() < priv.settings.maxRows) {
492-
datamap.createRow(index);
493-
delta++;
494-
}
529+
delta = datamap.createRow(index, amount);
530+
495531
if (delta) {
496532
if (priv.selStart.exists() && priv.selStart.row() >= index) {
497533
priv.selStart.row(priv.selStart.row() + delta);
@@ -504,11 +540,8 @@ Handsontable.Core = function (rootElement, userSettings) {
504540
break;
505541

506542
case "insert_col":
507-
delta = 0;
508-
while (delta < amount && instance.countCols() < priv.settings.maxCols) {
509-
datamap.createCol(index);
510-
delta++;
511-
}
543+
delta = datamap.createCol(index, amount);
544+
512545
if (delta) {
513546
if (priv.selStart.exists() && priv.selStart.col() >= index) {
514547
priv.selStart.col(priv.selStart.col() + delta);
@@ -545,14 +578,6 @@ Handsontable.Core = function (rootElement, userSettings) {
545578
break;
546579
}
547580

548-
changes = [];
549-
newData = datamap.getAll();
550-
for (r = 0, rlen = newData.length; r < rlen; r++) {
551-
for (c = 0, clen = newData[r].length; c < clen; c++) {
552-
changes.push([r, c, oldData[r] ? oldData[r][c] : null, newData[r][c]]);
553-
}
554-
}
555-
instance.PluginHooks.run('afterChange', changes, source || action);
556581
if (!keepEmptyRows) {
557582
grid.adjustRowsAndCols(); //makes sure that we did not add rows that will be removed in next refresh
558583
}
@@ -1278,14 +1303,8 @@ Handsontable.Core = function (rootElement, userSettings) {
12781303
selection.selectAll(); //select all cells
12791304
editproxy.setCopyableText();
12801305
event.preventDefault();
1306+
event.stopImmediatePropagation();
12811307
}
1282-
else if (event.keyCode === 89 || (event.shiftKey && event.keyCode === 90)) { //CTRL + Y or CTRL + SHIFT + Z
1283-
priv.undoRedo && priv.undoRedo.redo();
1284-
}
1285-
else if (event.keyCode === 90) { //CTRL + Z
1286-
priv.undoRedo && priv.undoRedo.undo();
1287-
}
1288-
return;
12891308
}
12901309

12911310
var rangeModifier = event.shiftKey ? selection.setRangeEnd : selection.setRangeStart;
@@ -1918,7 +1937,6 @@ Handsontable.Core = function (rootElement, userSettings) {
19181937
instance.render();
19191938
}
19201939
priv.isPopulated = true;
1921-
instance.clearUndo();
19221940
};
19231941

19241942
/**
@@ -1953,15 +1971,6 @@ Handsontable.Core = function (rootElement, userSettings) {
19531971
throw new Error("'cols' setting is no longer supported. do you mean startCols, minCols or maxCols?");
19541972
}
19551973

1956-
if (typeof settings.undo !== "undefined") {
1957-
if (priv.undoRedo && settings.undo === false) {
1958-
priv.undoRedo = null;
1959-
}
1960-
else if (!priv.undoRedo && settings.undo === true) {
1961-
priv.undoRedo = new Handsontable.UndoRedo(instance);
1962-
}
1963-
}
1964-
19651974
for (i in settings) {
19661975
if (i === 'data') {
19671976
continue; //loadData will be triggered later
@@ -2095,46 +2104,6 @@ Handsontable.Core = function (rootElement, userSettings) {
20952104
selection.empty();
20962105
};
20972106

2098-
/**
2099-
* Return true if undo can be performed, false otherwise
2100-
* @public
2101-
*/
2102-
this.isUndoAvailable = function () {
2103-
return priv.undoRedo && priv.undoRedo.isUndoAvailable();
2104-
};
2105-
2106-
/**
2107-
* Return true if redo can be performed, false otherwise
2108-
* @public
2109-
*/
2110-
this.isRedoAvailable = function () {
2111-
return priv.undoRedo && priv.undoRedo.isRedoAvailable();
2112-
};
2113-
2114-
/**
2115-
* Undo last edit
2116-
* @public
2117-
*/
2118-
this.undo = function () {
2119-
priv.undoRedo && priv.undoRedo.undo();
2120-
};
2121-
2122-
/**
2123-
* Redo edit (used to reverse an undo)
2124-
* @public
2125-
*/
2126-
this.redo = function () {
2127-
priv.undoRedo && priv.undoRedo.redo();
2128-
};
2129-
2130-
/**
2131-
* Clears undo history
2132-
* @public
2133-
*/
2134-
this.clearUndo = function () {
2135-
priv.undoRedo && priv.undoRedo.clear();
2136-
};
2137-
21382107
/**
21392108
* Inserts or removes rows and columns
21402109
* @param {String} action See grid.alter for possible values
@@ -2758,7 +2727,6 @@ DefaultSettings.prototype = {
27582727
fillHandle: true,
27592728
fixedRowsTop: 0,
27602729
fixedColumnsLeft: 0,
2761-
undo: true,
27622730
outsideClickDeselects: true,
27632731
enterBeginsEditing: true,
27642732
enterMoves: {row: 1, col: 0},

src/pluginHooks.js

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Handsontable.PluginHookClass = (function () {
88
beforeInit: [],
99
beforeRender: [],
1010
beforeChange: [],
11+
beforeRemoveCol: [],
12+
beforeRemoveRow: [],
1113
beforeValidate: [],
1214
beforeGet: [],
1315
beforeSet: [],

src/plugins/contextMenu.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
"remove_col": {name: "Remove column", disabled: isDisabled},
2525
"hsep3": "---------",
2626
"undo": {name: "Undo", disabled: function () {
27-
return !instance.isUndoAvailable();
27+
return !instance.undoRedo || !instance.isUndoAvailable();
2828
}},
2929
"redo": {name: "Redo", disabled: function () {
30-
return !instance.isRedoAvailable();
30+
return !instance.undoRedo || !instance.isRedoAvailable();
3131
}}
3232
}
3333
, defaultOptions = {

0 commit comments

Comments
 (0)