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;
 | |
|     }
 | |
| });
 |