355 lines
11 KiB
JavaScript
355 lines
11 KiB
JavaScript
/*
|
|
Initialization for Tabulizer
|
|
by Dimitrios Mourloukos
|
|
*/
|
|
|
|
var grid;
|
|
var grid_data = [];
|
|
var grid_row_limit = 500;
|
|
var grid_column_limit = 100;
|
|
var grid_selected_range = new Object;
|
|
|
|
var options = {
|
|
editable: true,
|
|
enableAddRow: true,
|
|
enableCellNavigation: true,
|
|
asyncEditorLoading: false,
|
|
autoEdit: false
|
|
};
|
|
|
|
var columns = [
|
|
{
|
|
id: "selector",
|
|
name: "",
|
|
field: "num",
|
|
width: 30
|
|
}
|
|
];
|
|
|
|
function FormulaEditor(args) {
|
|
var _self = this;
|
|
var _editor = new Slick.Editors.Text(args);
|
|
var _selector;
|
|
|
|
jQuery.extend(this, _editor);
|
|
|
|
function init() {
|
|
// register a plugin to select a range and append it to the textbox
|
|
// since events are fired in reverse order (most recently added are executed first),
|
|
// this will override other plugins like moverows or selection model and will
|
|
// not require the grid to not be in the edit mode
|
|
_selector = new Slick.CellRangeSelector();
|
|
_selector.onCellRangeSelected.subscribe(_self.handleCellRangeSelected);
|
|
args.grid.registerPlugin(_selector);
|
|
}
|
|
|
|
this.destroy = function () {
|
|
_selector.onCellRangeSelected.unsubscribe(_self.handleCellRangeSelected);
|
|
grid.unregisterPlugin(_selector);
|
|
_editor.destroy();
|
|
};
|
|
|
|
this.handleCellRangeSelected = function (e, args) {
|
|
_editor.setValue(
|
|
_editor.getValue() +
|
|
grid.getColumns()[args.range.fromCell].name +
|
|
args.range.fromRow +
|
|
":" +
|
|
grid.getColumns()[args.range.toCell].name +
|
|
args.range.toRow
|
|
);
|
|
};
|
|
|
|
init();
|
|
}
|
|
|
|
function initGrid(data, grid_rows, grid_columns) {
|
|
for (var i = 0; i < grid_column_limit; i++) {
|
|
columns.push({
|
|
id: i,
|
|
name: "Col"+(i+1),
|
|
field: i,
|
|
width: 60,
|
|
editor: FormulaEditor
|
|
});
|
|
}
|
|
|
|
for (var i = 0; i < grid_row_limit; i++) {
|
|
var d = (grid_data[i] = {});
|
|
d["num"] = i+1;
|
|
}
|
|
|
|
grid = new Slick.Grid("#grid", grid_data, columns, options);
|
|
|
|
var selectionModel = new Slick.CellSelectionModel();
|
|
grid.setSelectionModel(selectionModel);
|
|
grid.registerPlugin(new Slick.AutoTooltips());
|
|
|
|
// set keyboard focus on the grid
|
|
grid.getCanvasNode().focus();
|
|
|
|
var copyManager = new Slick.CellCopyManager();
|
|
grid.registerPlugin(copyManager);
|
|
|
|
copyManager.onPasteCells.subscribe(function (e, args) {
|
|
if (args.from.length !== 1 || args.to.length !== 1) {
|
|
throw "This implementation only supports single range copy and paste operations";
|
|
}
|
|
|
|
var from = args.from[0];
|
|
var to = args.to[0];
|
|
var val;
|
|
|
|
// treat differently the cases where the destination area is a single cell or not
|
|
var to_range_length = (to.toRow - to.fromRow) + (to.toCell - to.fromCell);
|
|
var i, j, copy_data = [];
|
|
|
|
for (i = 0; i <= from.toRow - from.fromRow; i++) {
|
|
copy_data[i] = [];
|
|
for (j = 0; j <= from.toCell - from.fromCell; j++) {
|
|
copy_data[i][j] = grid_data[from.fromRow + i][columns[from.fromCell + j].field];
|
|
}
|
|
}
|
|
|
|
if (to_range_length == 0) {
|
|
for (i = 0; i <= from.toRow - from.fromRow; i++) {
|
|
for (j = 0; j <= from.toCell - from.fromCell; j++) {
|
|
grid_data[to.fromRow + i][columns[to.fromCell + j].field] = copy_data[i][j];
|
|
grid.invalidateRow(to.fromRow + i);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i <= from.toRow - from.fromRow; i++) {
|
|
for (j = 0; j <= from.toCell - from.fromCell; j++) {
|
|
if (i <= to.toRow - to.fromRow && j <= to.toCell - to.fromCell) {
|
|
val = copy_data[i][j];
|
|
grid_data[to.fromRow + i][columns[to.fromCell + j].field] = val;
|
|
grid.invalidateRow(to.fromRow + i);
|
|
}
|
|
/*
|
|
if (i <= to.toRow - to.fromRow && j <= to.toCell - to.fromCell) {
|
|
val = grid_data[from.fromRow + i][columns[from.fromCell + j].field];
|
|
grid_data[to.fromRow + i][columns[to.fromCell + j].field] = val;
|
|
grid.invalidateRow(to.fromRow + i);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
grid.render();
|
|
});
|
|
|
|
grid.onAddNewRow.subscribe(function (e, args) {
|
|
var item = args.item;
|
|
var column = args.column;
|
|
grid.invalidateRow(grid_data.length);
|
|
grid_data.push(item);
|
|
grid.updateRowCount();
|
|
grid.render();
|
|
});
|
|
|
|
grid.onContextMenu.subscribe(function (e) {
|
|
e.preventDefault();
|
|
var cell = grid.getCellFromEvent(e);
|
|
jQuery("#gridContextMenu")
|
|
.data("row", cell.row)
|
|
.data("column", cell.cell)
|
|
.css("top", e.pageY)
|
|
.css("left", e.pageX)
|
|
.show();
|
|
|
|
jQuery("body").one("click", function (e) {
|
|
// finally, hide context menu
|
|
jQuery("#gridContextMenu").hide();
|
|
});
|
|
});
|
|
|
|
selectionModel.onSelectedRangesChanged.subscribe(function (e, args) {
|
|
if (args.length == 1) {
|
|
grid_selected_range.fromRow = args[0].fromRow;
|
|
grid_selected_range.toRow = args[0].toRow
|
|
grid_selected_range.fromColumn = args[0].fromCell-1;
|
|
grid_selected_range.toColumn = args[0].toCell-1;
|
|
grid_selected_range.active = 1;
|
|
} else {
|
|
grid_selected_range.active = 0;
|
|
}
|
|
});
|
|
|
|
grid.onKeyDown.subscribe( function (e, args) {
|
|
if ((e.which != 46) || e.ctrlKey) {
|
|
return false;
|
|
}
|
|
|
|
if (grid_selected_range) {
|
|
if (grid_selected_range.active) {
|
|
for (var i = grid_selected_range.fromRow; i <= grid_selected_range.toRow; i++) {
|
|
for (var j = grid_selected_range.fromColumn; j <= grid_selected_range.toColumn; j++) {
|
|
grid_data[i][j] = null;
|
|
}
|
|
grid.invalidateRow(i);
|
|
}
|
|
grid.render();
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
function gridAddRow(row_id, direction) {
|
|
var i, j, d;
|
|
var row_add = grid_row_limit;
|
|
if (direction == 'above') {
|
|
if (row_id>=0) row_add = row_id; else row_add = 0;
|
|
} else {
|
|
if (row_id < grid_row_limit) row_add = row_id + 1; else row_add = grid_row_limit;
|
|
}
|
|
|
|
grid_row_limit++;
|
|
for (i = grid_row_limit; i> row_add; i--) {
|
|
d = (grid_data[i] = {});
|
|
d["num"] = i+1;
|
|
if (grid_data[i-1] != null) {
|
|
for (j=0;j<=grid_column_limit;j++) {
|
|
if (grid_data[i-1][j] !== 'undefined') {
|
|
d[j] = grid_data[i-1][j];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
grid.invalidateRow(i);
|
|
}
|
|
}
|
|
d = (grid_data[row_add] = {});
|
|
d["num"] = row_add+1;
|
|
|
|
/*
|
|
for (j=1;j<=grid_column_limit;j++) {
|
|
d[j] = null;
|
|
}
|
|
*/
|
|
|
|
grid.invalidateRow(row_add);
|
|
|
|
grid.updateRowCount();
|
|
grid.render();
|
|
}
|
|
|
|
function gridAddColumn(column_id, direction) {
|
|
var i, j, d;
|
|
var column_add = grid_column_limit;
|
|
if (direction == 'before') {
|
|
if (column_id>0) column_add = column_id - 1; else column_add = 1;
|
|
} else {
|
|
if (column_id < grid_column_limit) column_add = column_id; else column_add = grid_column_limit;
|
|
}
|
|
|
|
grid_column_limit++;
|
|
for (i = 0; i< grid_row_limit; i++) {
|
|
if (grid_data[i] != null) {
|
|
d = grid_data[i];
|
|
for (j=grid_column_limit;j>column_add;j--) {
|
|
if (typeof grid_data[i][j-1] !== 'undefined') {
|
|
d[j] = grid_data[i][j-1];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
d[column_add] = null;
|
|
for (j=0;j<column_add;j++) {
|
|
if (typeof grid_data[i][j] !== 'undefined') {
|
|
d[j] = grid_data[i][j];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
|
|
grid.invalidateRow(i);
|
|
}
|
|
}
|
|
|
|
grid.updateRowCount();
|
|
grid.render();
|
|
}
|
|
|
|
function gridRemoveRow(row_id) {
|
|
var i, j, d;
|
|
|
|
if (row_id<0) return;
|
|
else if (row_id > grid_row_limit) return;
|
|
else remove_row = row_id;
|
|
|
|
for (i = remove_row; i < grid_row_limit; i++) {
|
|
d = (grid_data[i] = {});
|
|
d["num"] = i+1;
|
|
if (grid_data[i+1] != null) {
|
|
for (j=0;j<grid_column_limit;j++) {
|
|
if (grid_data[i+1][j] !== 'undefined') {
|
|
d[j] = grid_data[i+1][j];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
grid.invalidateRow(i);
|
|
}
|
|
}
|
|
|
|
grid.updateRowCount();
|
|
grid.render();
|
|
}
|
|
|
|
function gridRemoveColumn(column_id) {
|
|
var i, j, d;
|
|
|
|
if (column_id<1) return;
|
|
else if (column_id > grid_column_limit) return;
|
|
else remove_column = column_id-1;
|
|
|
|
for (i = 0; i< grid_row_limit; i++) {
|
|
if (grid_data[i] != null) {
|
|
d = grid_data[i];
|
|
for (j=0;j<remove_column;j++) {
|
|
if (grid_data[i][j] !== 'undefined') {
|
|
d[j] = grid_data[i][j];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
for (j=remove_column;j<grid_column_limit;j++) {
|
|
if (grid_data[i][j+1] !== 'undefined') {
|
|
d[j] = grid_data[i][j+1];
|
|
} else {
|
|
d[j] = null;
|
|
}
|
|
}
|
|
grid.invalidateRow(i);
|
|
}
|
|
}
|
|
|
|
grid.updateRowCount();
|
|
grid.render();
|
|
}
|
|
|
|
jQuery(document).on('click', "#gridContextMenu", function(e) {
|
|
if (!jQuery(e.target).is("li")) {
|
|
return;
|
|
}
|
|
if (!grid.getEditorLock().commitCurrentEdit()) {
|
|
return;
|
|
}
|
|
var row_id = jQuery(this).data("row");
|
|
var column_id = jQuery(this).data("column");
|
|
var selected_action = jQuery(e.target).attr("data");
|
|
switch (selected_action) {
|
|
case "add_row_above": gridAddRow(row_id, "above"); break;
|
|
case "add_row_below": gridAddRow(row_id, "below"); break;
|
|
case "add_column_before": gridAddColumn(column_id, "before"); break;
|
|
case "add_column_after": gridAddColumn(column_id, "after"); break;
|
|
case "remove_row": gridRemoveRow(row_id); break;
|
|
case "remove_column": gridRemoveColumn(column_id); break;
|
|
}
|
|
});
|