{"size": 5505, "ext": "js", "max_stars_repo_path": "plugins/slick.cellcopymanager.js", "max_stars_repo_name": "beardedlinuxgeek/SlickGrid", "max_stars_repo_stars_event_min_datetime": "2015-01-22T07:45:52.000Z", "max_stars_repo_stars_event_max_datetime": "2021-06-09T19:12:53.000Z", "max_issues_repo_path": "plugins/slick.cellcopymanager.js", "max_issues_repo_name": "beardedlinuxgeek/SlickGrid", "max_issues_repo_issues_event_min_datetime": "2015-09-27T22:22:54.000Z", "max_issues_repo_issues_event_max_datetime": "2015-12-11T04:46:22.000Z", "max_forks_repo_path": "plugins/slick.cellcopymanager.js", "max_forks_repo_name": "beardedlinuxgeek/SlickGrid", "max_forks_repo_forks_event_min_datetime": "2015-07-21T05:10:28.000Z", "max_forks_repo_forks_event_max_datetime": "2018-09-28T14:51:06.000Z"}
{"max_stars_count": 21, "max_issues_count": 9, "max_forks_count": 4, "avg_line_length": 35.0636942675, "max_line_length": 199, "alphanum_fraction": 0.5705722071}
(function ($) {
  // register namespace
  $.extend(true, window, {
    Slick: {
      CellCopyManager: CellCopyManager
    }
  });


  function CellCopyManager(options) {
    var _grid;
    var _self = this;
    var _copiedRanges;    // keeps track of the last marked (Ctrl-C copied) range
    var _options = options || {};
    var _copiedCellStyleLayerKey = _options.copiedCellStyleLayerKey || "copy-manager";
    var _copiedCellStyle = _options.copiedCellStyle || "copied";

    var keyCodes = {
      'C': 67,
      'V': 86,
      'X': 88,
      'ESC': 27
    };

    function init(grid) {
      _grid = grid;
      _grid.onKeyDown.subscribe(handleKeyDown);

      // we need a cell selection model
      var cellSelectionModel = grid.getSelectionModel();
      if (!cellSelectionModel) {
        throw new Error("Selection model is mandatory for this plugin. Please set a selection model on the grid before adding this plugin: grid.setSelectionModel(new Slick.CellSelectionModel())");
      }
      // we give focus on the grid when a selection is done on it.
      // without this, if the user selects a range of cell without giving focus on a particular cell,
      // the grid doesn't get the focus and key stroke handles (ctrl+C) don't work.
      cellSelectionModel.onSelectedRangesChanged.subscribe(function(e, args) {
        _grid.focus();
      });
    }

    function destroy() {
      _grid.onKeyDown.unsubscribe(handleKeyDown);
    }

    function handleKeyDown(e, args) {
      var ranges;
      if (!_grid.getEditorLock().isActive()) {
        if (e.which === keyCodes.ESC) {
          if (_copiedRanges) {
            e.preventDefault();
            clearCopySelection();
            _self.onCopyCancelled.notify({
              ranges: _copiedRanges,
              rangeIsCopied: _copiedRanges.copy
            });
            _copiedRanges = null;
          }
        }

        // Control+C / Control+X  -- these have the same effect on initial range
        if ((e.which === keyCodes.C || e.which === keyCodes.X) && (e.ctrlKey || e.metaKey)) {
          // make sure to clone (shallow) the range set as any subsequent selection action will echo into _copiedRanges!
          ranges = _grid.getSelectionModel().getSelectedRanges().slice(0);

          // also remember whether this was Ctrl-C (copy) or Ctrl-X (cut):
          ranges.copy = (e.which === keyCodes.C);

          if (ranges.length !== 0) {
            e.preventDefault();
            _copiedRanges = ranges;
            markCopySelection(ranges);
            _self.onCopyCells.notify({
              ranges: ranges, 
              rangeIsCopied: ranges.copy 
            });

            return false;
          }
        }

        // Control+V
        if (e.which === keyCodes.V && (e.ctrlKey || e.metaKey)) {
          if (_copiedRanges) {
            e.preventDefault();
            ranges = _grid.getSelectionModel().getSelectedRanges();
            var selectedCell = _grid.getActiveCell();
            if (!ranges || ranges.length === 0 || _copiedRanges[0].matches(ranges[0])) {
              if (selectedCell) {
                // only having the active cell implies we want the entire range pasted from this top/left corner...
                var srcRange = _copiedRanges[0];
                ranges = [new Slick.Range(selectedCell.row, selectedCell.cell, selectedCell.row + srcRange.toRow - srcRange.fromRow + 1, selectedCell.cell + srcRange.toCell - srcRange.fromCell + 1)];
              } else {
                // we don't know where to paste
                _self.onCopyCancelled.notify({
                  ranges: _copiedRanges,
                  rangeIsCopied: _copiedRanges.copy,
                  rangeDataFromExternalSource: false,
                  status: "No destination cell or range has been provided"
                });
                return false;
              }
            }

            _self.onPasteCells.notify({
              from: _copiedRanges,
              to: ranges,
              rangeIsCopied: _copiedRanges.copy,
              rangeDataFromExternalSource: false
            });
            // allow for Ctrl-C, Ctrl-V, Ctrl-V, ... repeated paste sequences to be all 'internal' based on that single Ctrl-C copied range!
            //
            // the ctrl-X effect is to delete original range at the first ctrl-V, so no repeat performance for that one though!
            if (!_copiedRanges.copy) {
              clearCopySelection();
              _copiedRanges = null;
            }
          }

          return false;
        }
      }
    }

    function markCopySelection(ranges) {
      clearCopySelection();

      var columns = _grid.getColumns();
      var hash = {};
      for (var i = 0; i < ranges.length; i++) {
        for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
          hash[j] = {};
          for (var k = ranges[i].fromCell; k <= ranges[i].toCell && k < columns.length; k++) {
            hash[j][columns[k].id] = _copiedCellStyle;
          }
        }
      }
      _grid.setCellCssStyles(_copiedCellStyleLayerKey, hash);
    }

    function clearCopySelection() {
      _grid.removeCellCssStyles(_copiedCellStyleLayerKey);
    }

    $.extend(this, {
      "init": init,
      "destroy": destroy,
      "clearCopySelection": clearCopySelection,
      "handleKeyDown": handleKeyDown,

      "onCopyCells": new Slick.Event(),
      "onCopyCancelled": new Slick.Event(),
      "onPasteCells": new Slick.Event()
    });
  }
})(jQuery);
