slickgrid ( nsunleo-slickgrid ) 8 區域選擇與複製粘貼

區域選擇
區域選擇是通過插件CellRangeSelector實現的,默認不支援跨凍結列進行選擇,修正了選擇,支援跨凍結列,程式碼如下,通過判斷選擇的起點和終點所落在的凍結範圍進行計算,如從左往右進行複製,此時需要判拷貝的列數是否超過了凍結列,如果超過凍結了,此時需要在右側(canvas)中進行繪製,否則在原canvas中繪製。從右往左邏輯同。
 function show(range, cfg) {
      var canvas = cfg.canvas;
      var start = cfg.start;
      var end = cfg.end;
      var from = grid.getCellNodeBox(range.fromRow, range.fromCell);
      var to = grid.getCellNodeBox(range.toRow, range.toCell);
 
      // range left to right 
      var directLR = start <= end;
      // frozenColumn temp var 
      var frozenColumn = grid.getOptions().frozenColumn;
 
      var lR = false;
      // lR true condition
      if (directLR) {
        lR = start <= frozenColumn && end > frozenColumn;
      } else {
        lR = start > frozenColumn && end <= frozenColumn;
      }
 
      if (!_elem) {
        _elem = $(“<div></div>”, { css: options.selectionCss })
          .addClass(options.selectionCssClass)
          .css(“position”, “absolute”)
          .appendTo(grid.getActiveCanvasNode());
        _borderWidth = _elem.css(“border-left-width”);
      }
 
      // lr ,create new element .
      if (lR && !_rElem) {
        _rElem = $(“<div></div>”, { css: options.selectionCss })
          .addClass(options.selectionCssClass)
          .css(“position”, “absolute”)
          .appendTo(canvas);
      }
 
      // ! lr ,remove _rElem
      if (!lR && _rElem) {
        _rElem.remove();
        _rElem = null;
      }
 
      var temp = lR && directLR ? _rElem : _elem;
      var lWidth = lR ? directLR ? canvas.width() : to.right – 2 : (to.right – from.left – 2);
      var lLeft = lR && !directLR ? 0 : (from.left – 1);
      //console.log(“DIRECT_LR:” + directLR + ” FROM_L:” + from.left + ” TO_L:” + to.left + ” FROM_R:” + from.right + ” TO_R” + to.right + ” START:” + start + ” END:” + end + ” LWIDTH:” + lWidth)
      if (_elem) {
        _elem.css(“border-right-width”, lR ? directLR ? “0px” : _borderWidth : _borderWidth);
        _elem.css(“border-left-width”, lR ? directLR ? _borderWidth : “0px” : _borderWidth);
        _elem.css({
          top: from.top – 1,
          left: lLeft,
          height: to.bottom – from.top – 2,
          width: lWidth
        });
      }
 
      if (_rElem) {
        var rLeft = directLR ? 0 : from.left;
        var rWidth = !directLR ? canvas.width() : (to.right – 2);
        //console.log(“RWIDTH:” + rWidth + ” RLEFT:” + rLeft);
        _rElem.css(“border-left-width”, lR ? directLR ? “0px” : _borderWidth : _borderWidth);
        _rElem.css(“border-right-width”, lR ? directLR ? _borderWidth : “0px” : _borderWidth);
        _rElem.css({
          top: from.top – 1,
          left: rLeft,
          height: to.bottom – from.top – 2,
          width: rWidth
        });
      }
 
      return temp;
    }
 
拷貝粘貼的實現:
獲取選中的數據,監聽ctrl + c 和 ctrl + v 事件進行攔截,是通過CellExternalFullCopyManager插件實現的(支援跨凍結列拷貝、粘貼)。
當監聽到ctrl + c 的時候,先攔截事件,並將選中區域的數據轉換成數據保存在臨時的text中,並且選中text的值,之後將text刪除,此時粘貼板上已經有複製的值。
當監聽到ctrl + v 的時候,首先判斷是否有自定義的攔截,如果有自定義攔截,執行自定義攔截,否則執行默認粘貼方法。
  • 默認粘貼支援兩種模式,一種是選擇了區域,此時粘貼會在選擇區域內進行粘貼;
  • 另一種模式是僅指定了起點,按照複製的區域,從頂點開始粘貼後續區域。
 function _decodeTabularDataExt(_grid, ta) {
            var columns = _grid.getColumns();
            var clippeds = toRow(_grid, ta);
 
            document.body.removeChild(ta);
 
            var ranges = _grid.getSelectionModel().getSelectedRanges();
            if (ranges && ranges[0] && !((ranges[0].fromCell – ranges[0].toCell == 0) && (ranges[0].fromRow – ranges[0].toRow == 0))) {
                var to = ranges[0];
                var startCell = to.fromCell;
                var startRow = to.fromRow;
                // to.toRow – to.fromRow
                // 通過數據反向操作
                for (var y = 0; y < clippeds.length; y++) {
                    var desty = startRow + y;
                    if (desty <= to.toRow) {
                        var dt = _grid.getDataItem(desty);
                        if (dt) {
                            for (var x = 0; x < clippeds[y].length; x++) {
                                var destx = startCell + x;
                                if (destx < grid.getColumns().length && destx <= to.toCell) {
                                    if (!_grid.onBeforeEditCellReadonly(desty, destx, dt, columns[destx])) {
                                        setDataItemValueForColumn(dt, columns[destx], clippeds[y][x]);
                                        // dt[columns[destx].field] = clippeds[y][x];
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                // if startPoint 
                // else if range 
                var selectedCell = _grid.getActiveCell();
                if (selectedCell) {
                    var startCell = selectedCell.cell;
                    var startRow = selectedCell.row;
                    // 通過數據反向操作
                    for (var y = 0; y < clippeds.length; y++) {
                        var desty = startRow + y;
                        var dt = _grid.getDataItem(desty);
                        if (dt) {
                            for (var x = 0; x < clippeds[y].length; x++) {
                                var destx = startCell + x;
                                if (destx < grid.getColumns().length) {
 
                                    if (!_grid.onBeforeEditCellReadonly(desty, destx, dt, columns[destx])) {
                                        setDataItemValueForColumn(dt, columns[destx], clippeds[y][x]);
                                        //dt[columns[destx].field] = clippeds[y][x];
                                    }
                                }
                            }
                        }
                    }
                }
            }
 
            _grid.invalidate();
 
            _grid.render();
            clearCopySelection();
 
            return;
}
  • 擴展能夠動態導入tree,增加了發布粘貼事件。
 setTimeout(function () {
                        if (_grid.trigger(_self.onPasteCells, toRow(_grid, ta), e) === true) {
                            return;
                        }
 
                        _decodeTabularData(_grid, ta);
                    }, 50);
自定義粘貼示例:
copyExtManager.onPasteCells.subscribe(function (e, args) {
        if ($(e.target).hasClass(“bom-past”)) {
            var selectedCell = grid.getActiveCell();
            if (selectedCell) {
                var startRow = selectedCell.row;
                var rowData = grid.getDataItem(startRow);
                var children = [];
                rowData.___path = “”;
                var treeViewStack = [rowData];
 
                var bomValidator = {
                    parentPath: function (row, rows) {
                        var tempRow = row;
                        var parentPath = [];
                        while (tempRow) {
                            parentPath.push(tempRow.f3000);
                            if (tempRow.parent) {
                                tempRow = findItemById(tempRow.parent);
                            } else {
                                tempRow = null;
                            }
                        }
                        return parentPath;
                    },
                    cycleCheck: function (row, parentPath) {
 
                    }
                }
 
                var parentPath = bomValidator.parentPath(rowData, getSgAllData());
                for (var x = 0; x < args.length; x++) {
                    var nRow = $.extend({}, rowData);
                    nRow.id = sbz.uuid();
 
                    for (var y = 1; y < args[x].length; y++) {
                        if (y + 1 < grid.getColumns().length) {
                            nRow[grid.getColumns()[y + 1].field] = args[x][y];
                        }
                    }
 
                    nRow.f1000 = nRow.f2001 = nRow.f2000;
                    nRow.f3000 = nRow.f3001 = nRow.f2000;
                    nRow.__state = 0;
                    nRow.___path = args[x][0];
 
                    if (treeViewStack.length > 0) {
                        if (treeViewStack[treeViewStack.length – 1].___path.length < nRow.___path.length) {
 
                            var parent = treeViewStack[treeViewStack.length – 1];
                            // 找到父
                            var nParentPath = treeViewStack.filter((v) => {
                                return v.f2000 == nRow.f2000;
                            });
 
                            if (nParentPath.length > 0 || parentPath.indexOf(nRow.f2000) != -1) {
                                alert(“死循環:” + parentPath);
                                return;
                            }
 
                            nRow.parentNumber = parent.f2000;
                            treeViewStack.push(nRow);
 
                            // 確定層級
                            treeViewPath(parent, nRow, x);
                        } else {
                            // 找到最近的兄弟或直接的父
                            var tempPaths = [];
                            tempPaths.push(parentPath);
                            for (var i = treeViewStack.length – 1; i >= 0; i–) {
                                if (treeViewStack[i].___path.length >= nRow.___path.length) {
                                    treeViewStack.pop();
                                } else {
                                    tempPaths.push(treeViewStack[i].f2000);
                                }
                            }
 
                            if (tempPaths.indexOf(nRow.f2000) != -1) {
                                alert(“死循環”);
                                return;
                            }
 
                            var parent = treeViewStack[treeViewStack.length – 1];
                            nRow.parentNumber = parent.f2000;
                            treeViewStack.push(nRow);
                            // 確定層級
                            treeViewPath(parent, nRow, x);
                        }
                    }
 
 
                    // 提示是否增加 行 ,假設增加 
                    // 直接更新和刷新狀態…
 
                    children[x] = nRow;
                }
 
 
                if (children && children.length > 0) {
                    var parents = treeViewSameNodes(rowData);
 
                    for (var i = 0; i < parents.length; i++) {
                        treeViewCopyData(children, parents[i]);
                    }
 
                    treeViewInsert(sgBomData, rowData, children);
                    refresh();
                }
            }
            return true;
        }
 
        return false;
    });