slickgrid 2.3.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +20 -0
  4. data/README.md +30 -0
  5. data/lib/slickgrid.rb +6 -0
  6. data/lib/slickgrid/version.rb +3 -0
  7. data/slickgrid.gemspec +20 -0
  8. data/vendor/assets/images/slickgrid/CheckboxN.png +0 -0
  9. data/vendor/assets/images/slickgrid/CheckboxY.png +0 -0
  10. data/vendor/assets/images/slickgrid/GrpCheckboxN.png +0 -0
  11. data/vendor/assets/images/slickgrid/GrpCheckboxY.png +0 -0
  12. data/vendor/assets/images/slickgrid/actions.gif +0 -0
  13. data/vendor/assets/images/slickgrid/ajax-loader-small.gif +0 -0
  14. data/vendor/assets/images/slickgrid/arrow-right.gif +0 -0
  15. data/vendor/assets/images/slickgrid/arrow_redo.png +0 -0
  16. data/vendor/assets/images/slickgrid/arrow_right_peppermint.png +0 -0
  17. data/vendor/assets/images/slickgrid/arrow_right_spearmint.png +0 -0
  18. data/vendor/assets/images/slickgrid/arrow_undo.png +0 -0
  19. data/vendor/assets/images/slickgrid/bullet_blue.png +0 -0
  20. data/vendor/assets/images/slickgrid/bullet_star.png +0 -0
  21. data/vendor/assets/images/slickgrid/bullet_toggle_minus.png +0 -0
  22. data/vendor/assets/images/slickgrid/bullet_toggle_plus.png +0 -0
  23. data/vendor/assets/images/slickgrid/calendar.gif +0 -0
  24. data/vendor/assets/images/slickgrid/collapse.gif +0 -0
  25. data/vendor/assets/images/slickgrid/comment_yellow.gif +0 -0
  26. data/vendor/assets/images/slickgrid/delete.png +0 -0
  27. data/vendor/assets/images/slickgrid/down.gif +0 -0
  28. data/vendor/assets/images/slickgrid/drag-handle.png +0 -0
  29. data/vendor/assets/images/slickgrid/editor-helper-bg.gif +0 -0
  30. data/vendor/assets/images/slickgrid/expand.gif +0 -0
  31. data/vendor/assets/images/slickgrid/header-bg.gif +0 -0
  32. data/vendor/assets/images/slickgrid/header-columns-bg.gif +0 -0
  33. data/vendor/assets/images/slickgrid/header-columns-over-bg.gif +0 -0
  34. data/vendor/assets/images/slickgrid/help.png +0 -0
  35. data/vendor/assets/images/slickgrid/info.gif +0 -0
  36. data/vendor/assets/images/slickgrid/listview.gif +0 -0
  37. data/vendor/assets/images/slickgrid/pencil.gif +0 -0
  38. data/vendor/assets/images/slickgrid/row-over-bg.gif +0 -0
  39. data/vendor/assets/images/slickgrid/sort-asc.gif +0 -0
  40. data/vendor/assets/images/slickgrid/sort-asc.png +0 -0
  41. data/vendor/assets/images/slickgrid/sort-desc.gif +0 -0
  42. data/vendor/assets/images/slickgrid/sort-desc.png +0 -0
  43. data/vendor/assets/images/slickgrid/stripes.png +0 -0
  44. data/vendor/assets/images/slickgrid/tag_red.png +0 -0
  45. data/vendor/assets/images/slickgrid/tick.png +0 -0
  46. data/vendor/assets/images/slickgrid/user_identity.gif +0 -0
  47. data/vendor/assets/images/slickgrid/user_identity_plus.gif +0 -0
  48. data/vendor/assets/javascripts/slickgrid.js +5 -0
  49. data/vendor/assets/javascripts/slickgrid/controls/columnpicker.js +221 -0
  50. data/vendor/assets/javascripts/slickgrid/controls/gridmenu.js +429 -0
  51. data/vendor/assets/javascripts/slickgrid/controls/pager.js +154 -0
  52. data/vendor/assets/javascripts/slickgrid/core.js +493 -0
  53. data/vendor/assets/javascripts/slickgrid/dataview.js +1220 -0
  54. data/vendor/assets/javascripts/slickgrid/editors.js +640 -0
  55. data/vendor/assets/javascripts/slickgrid/formatters.js +65 -0
  56. data/vendor/assets/javascripts/slickgrid/grid.js +3990 -0
  57. data/vendor/assets/javascripts/slickgrid/groupitemmetadataprovider.js +172 -0
  58. data/vendor/assets/javascripts/slickgrid/plugins/autotooltips.js +83 -0
  59. data/vendor/assets/javascripts/slickgrid/plugins/cellcopymanager.js +88 -0
  60. data/vendor/assets/javascripts/slickgrid/plugins/cellexternalcopymanager.js +452 -0
  61. data/vendor/assets/javascripts/slickgrid/plugins/cellrangedecorator.js +72 -0
  62. data/vendor/assets/javascripts/slickgrid/plugins/cellrangeselector.js +123 -0
  63. data/vendor/assets/javascripts/slickgrid/plugins/cellselectionmodel.js +168 -0
  64. data/vendor/assets/javascripts/slickgrid/plugins/checkboxselectcolumn.js +202 -0
  65. data/vendor/assets/javascripts/slickgrid/plugins/draggablegrouping.js +207 -0
  66. data/vendor/assets/javascripts/slickgrid/plugins/headerbuttons.js +177 -0
  67. data/vendor/assets/javascripts/slickgrid/plugins/headermenu.js +296 -0
  68. data/vendor/assets/javascripts/slickgrid/plugins/rowdetailview.js +455 -0
  69. data/vendor/assets/javascripts/slickgrid/plugins/rowmovemanager.js +138 -0
  70. data/vendor/assets/javascripts/slickgrid/plugins/rowselectionmodel.js +191 -0
  71. data/vendor/assets/javascripts/slickgrid/remotemodel.js +169 -0
  72. data/vendor/assets/stylesheets/slickgrid.scss +1 -0
  73. data/vendor/assets/stylesheets/slickgrid/controls/columnpicker.css +46 -0
  74. data/vendor/assets/stylesheets/slickgrid/controls/gridmenu.css +113 -0
  75. data/vendor/assets/stylesheets/slickgrid/controls/pager.css +41 -0
  76. data/vendor/assets/stylesheets/slickgrid/default-theme.css +132 -0
  77. data/vendor/assets/stylesheets/slickgrid/grid.css +189 -0
  78. data/vendor/assets/stylesheets/slickgrid/plugins/headerbuttons.css +39 -0
  79. data/vendor/assets/stylesheets/slickgrid/plugins/headermenu.css +59 -0
  80. data/vendor/assets/stylesheets/slickgrid/plugins/rowdetailview.css +39 -0
  81. metadata +165 -0
@@ -0,0 +1,172 @@
1
+ (function ($) {
2
+ $.extend(true, window, {
3
+ Slick: {
4
+ Data: {
5
+ GroupItemMetadataProvider: GroupItemMetadataProvider
6
+ }
7
+ }
8
+ });
9
+
10
+
11
+ /***
12
+ * Provides item metadata for group (Slick.Group) and totals (Slick.Totals) rows produced by the DataView.
13
+ * This metadata overrides the default behavior and formatting of those rows so that they appear and function
14
+ * correctly when processed by the grid.
15
+ *
16
+ * This class also acts as a grid plugin providing event handlers to expand & collapse groups.
17
+ * If "grid.registerPlugin(...)" is not called, expand & collapse will not work.
18
+ *
19
+ * @class GroupItemMetadataProvider
20
+ * @module Data
21
+ * @namespace Slick.Data
22
+ * @constructor
23
+ * @param options
24
+ */
25
+ function GroupItemMetadataProvider(options) {
26
+ var _grid;
27
+ var _defaults = {
28
+ checkboxSelect: false,
29
+ checkboxSelectCssClass: "slick-group-select-checkbox",
30
+ checkboxSelectPlugin: null,
31
+ groupCssClass: "slick-group",
32
+ groupTitleCssClass: "slick-group-title",
33
+ totalsCssClass: "slick-group-totals",
34
+ groupFocusable: true,
35
+ totalsFocusable: false,
36
+ toggleCssClass: "slick-group-toggle",
37
+ toggleExpandedCssClass: "expanded",
38
+ toggleCollapsedCssClass: "collapsed",
39
+ enableExpandCollapse: true,
40
+ groupFormatter: defaultGroupCellFormatter,
41
+ totalsFormatter: defaultTotalsCellFormatter
42
+ };
43
+
44
+ options = $.extend(true, {}, _defaults, options);
45
+
46
+
47
+ function defaultGroupCellFormatter(row, cell, value, columnDef, item) {
48
+ if (!options.enableExpandCollapse) {
49
+ return item.title;
50
+ }
51
+
52
+ var indentation = item.level * 15 + "px";
53
+
54
+ return (options.checkboxSelect ? '<span class="' + options.checkboxSelectCssClass +
55
+ ' ' + (item.selectChecked ? 'checked' : 'unchecked') + '"></span>' : '') +
56
+ "<span class='" + options.toggleCssClass + " " +
57
+ (item.collapsed ? options.toggleCollapsedCssClass : options.toggleExpandedCssClass) +
58
+ "' style='margin-left:" + indentation +"'>" +
59
+ "</span>" +
60
+ "<span class='" + options.groupTitleCssClass + "' level='" + item.level + "'>" +
61
+ item.title +
62
+ "</span>";
63
+ }
64
+
65
+ function defaultTotalsCellFormatter(row, cell, value, columnDef, item) {
66
+ return (columnDef.groupTotalsFormatter && columnDef.groupTotalsFormatter(item, columnDef)) || "";
67
+ }
68
+
69
+
70
+ function init(grid) {
71
+ _grid = grid;
72
+ _grid.onClick.subscribe(handleGridClick);
73
+ _grid.onKeyDown.subscribe(handleGridKeyDown);
74
+
75
+ }
76
+
77
+ function destroy() {
78
+ if (_grid) {
79
+ _grid.onClick.unsubscribe(handleGridClick);
80
+ _grid.onKeyDown.unsubscribe(handleGridKeyDown);
81
+ }
82
+ }
83
+
84
+ function handleGridClick(e, args) {
85
+ var $target = $(e.target);
86
+ var item = this.getDataItem(args.row);
87
+ if (item && item instanceof Slick.Group && $target.hasClass(options.toggleCssClass)) {
88
+ var range = _grid.getRenderedRange();
89
+ this.getData().setRefreshHints({
90
+ ignoreDiffsBefore: range.top,
91
+ ignoreDiffsAfter: range.bottom + 1
92
+ });
93
+
94
+ if (item.collapsed) {
95
+ this.getData().expandGroup(item.groupingKey);
96
+ } else {
97
+ this.getData().collapseGroup(item.groupingKey);
98
+ }
99
+
100
+ e.stopImmediatePropagation();
101
+ e.preventDefault();
102
+ }
103
+ if (item && item instanceof Slick.Group && $target.hasClass(options.checkboxSelectCssClass)) {
104
+ item.selectChecked = !item.selectChecked;
105
+ $target.removeClass((item.selectChecked ? "unchecked" : "checked"));
106
+ $target.addClass((item.selectChecked ? "checked" : "unchecked"));
107
+ // get rowIndexes array
108
+ var rowIndexes = _grid.getData().mapItemsToRows(item.rows);
109
+ (item.selectChecked ? options.checkboxSelectPlugin.selectRows : options.checkboxSelectPlugin.deSelectRows)(rowIndexes);
110
+ }
111
+ }
112
+
113
+ // TODO: add -/+ handling
114
+ function handleGridKeyDown(e, args) {
115
+ if (options.enableExpandCollapse && (e.which == $.ui.keyCode.SPACE)) {
116
+ var activeCell = this.getActiveCell();
117
+ if (activeCell) {
118
+ var item = this.getDataItem(activeCell.row);
119
+ if (item && item instanceof Slick.Group) {
120
+ var range = _grid.getRenderedRange();
121
+ this.getData().setRefreshHints({
122
+ ignoreDiffsBefore: range.top,
123
+ ignoreDiffsAfter: range.bottom + 1
124
+ });
125
+
126
+ if (item.collapsed) {
127
+ this.getData().expandGroup(item.groupingKey);
128
+ } else {
129
+ this.getData().collapseGroup(item.groupingKey);
130
+ }
131
+
132
+ e.stopImmediatePropagation();
133
+ e.preventDefault();
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ function getGroupRowMetadata(item) {
140
+ return {
141
+ selectable: false,
142
+ focusable: options.groupFocusable,
143
+ cssClasses: options.groupCssClass,
144
+ columns: {
145
+ 0: {
146
+ colspan: "*",
147
+ formatter: options.groupFormatter,
148
+ editor: null
149
+ }
150
+ }
151
+ };
152
+ }
153
+
154
+ function getTotalsRowMetadata(item) {
155
+ return {
156
+ selectable: false,
157
+ focusable: options.totalsFocusable,
158
+ cssClasses: options.totalsCssClass,
159
+ formatter: options.totalsFormatter,
160
+ editor: null
161
+ };
162
+ }
163
+
164
+
165
+ return {
166
+ "init": init,
167
+ "destroy": destroy,
168
+ "getGroupRowMetadata": getGroupRowMetadata,
169
+ "getTotalsRowMetadata": getTotalsRowMetadata
170
+ };
171
+ }
172
+ })(jQuery);
@@ -0,0 +1,83 @@
1
+ (function ($) {
2
+ // Register namespace
3
+ $.extend(true, window, {
4
+ "Slick": {
5
+ "AutoTooltips": AutoTooltips
6
+ }
7
+ });
8
+
9
+ /**
10
+ * AutoTooltips plugin to show/hide tooltips when columns are too narrow to fit content.
11
+ * @constructor
12
+ * @param {boolean} [options.enableForCells=true] - Enable tooltip for grid cells
13
+ * @param {boolean} [options.enableForHeaderCells=false] - Enable tooltip for header cells
14
+ * @param {number} [options.maxToolTipLength=null] - The maximum length for a tooltip
15
+ */
16
+ function AutoTooltips(options) {
17
+ var _grid;
18
+ var _self = this;
19
+ var _defaults = {
20
+ enableForCells: true,
21
+ enableForHeaderCells: false,
22
+ maxToolTipLength: null
23
+ };
24
+
25
+ /**
26
+ * Initialize plugin.
27
+ */
28
+ function init(grid) {
29
+ options = $.extend(true, {}, _defaults, options);
30
+ _grid = grid;
31
+ if (options.enableForCells) _grid.onMouseEnter.subscribe(handleMouseEnter);
32
+ if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.subscribe(handleHeaderMouseEnter);
33
+ }
34
+
35
+ /**
36
+ * Destroy plugin.
37
+ */
38
+ function destroy() {
39
+ if (options.enableForCells) _grid.onMouseEnter.unsubscribe(handleMouseEnter);
40
+ if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.unsubscribe(handleHeaderMouseEnter);
41
+ }
42
+
43
+ /**
44
+ * Handle mouse entering grid cell to add/remove tooltip.
45
+ * @param {jQuery.Event} e - The event
46
+ */
47
+ function handleMouseEnter(e) {
48
+ var cell = _grid.getCellFromEvent(e);
49
+ if (cell) {
50
+ var $node = $(_grid.getCellNode(cell.row, cell.cell));
51
+ var text;
52
+ if ($node.innerWidth() < $node[0].scrollWidth) {
53
+ text = $.trim($node.text());
54
+ if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
55
+ text = text.substr(0, options.maxToolTipLength - 3) + "...";
56
+ }
57
+ } else {
58
+ text = "";
59
+ }
60
+ $node.attr("title", text);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Handle mouse entering header cell to add/remove tooltip.
66
+ * @param {jQuery.Event} e - The event
67
+ * @param {object} args.column - The column definition
68
+ */
69
+ function handleHeaderMouseEnter(e, args) {
70
+ var column = args.column,
71
+ $node = $(e.target).closest(".slick-header-column");
72
+ if (column && !column.toolTip) {
73
+ $node.attr("title", ($node.innerWidth() < $node[0].scrollWidth) ? column.name : "");
74
+ }
75
+ }
76
+
77
+ // Public API
78
+ $.extend(this, {
79
+ "init": init,
80
+ "destroy": destroy
81
+ });
82
+ }
83
+ })(jQuery);
@@ -0,0 +1,88 @@
1
+ (function ($) {
2
+ // register namespace
3
+ $.extend(true, window, {
4
+ "Slick": {
5
+ "CellCopyManager": CellCopyManager
6
+ }
7
+ });
8
+
9
+
10
+ function CellCopyManager() {
11
+ var _grid;
12
+ var _self = this;
13
+ var _copiedRanges;
14
+
15
+ function init(grid) {
16
+ _grid = grid;
17
+ _grid.onKeyDown.subscribe(handleKeyDown);
18
+ }
19
+
20
+ function destroy() {
21
+ _grid.onKeyDown.unsubscribe(handleKeyDown);
22
+ }
23
+
24
+ function handleKeyDown(e, args) {
25
+ var ranges;
26
+ if (!_grid.getEditorLock().isActive()) {
27
+ if (e.which == $.ui.keyCode.ESCAPE) {
28
+ if (_copiedRanges) {
29
+ e.preventDefault();
30
+ clearCopySelection();
31
+ _self.onCopyCancelled.notify({ranges: _copiedRanges});
32
+ _copiedRanges = null;
33
+ }
34
+ }
35
+
36
+ if (e.which == 67 && (e.ctrlKey || e.metaKey)) {
37
+ ranges = _grid.getSelectionModel().getSelectedRanges();
38
+ if (ranges.length != 0) {
39
+ e.preventDefault();
40
+ _copiedRanges = ranges;
41
+ markCopySelection(ranges);
42
+ _self.onCopyCells.notify({ranges: ranges});
43
+ }
44
+ }
45
+
46
+ if (e.which == 86 && (e.ctrlKey || e.metaKey)) {
47
+ if (_copiedRanges) {
48
+ e.preventDefault();
49
+ ranges = _grid.getSelectionModel().getSelectedRanges();
50
+ _self.onPasteCells.notify({from: _copiedRanges, to: ranges});
51
+ if (!_grid.getOptions().preserveCopiedSelectionOnPaste) {
52
+ clearCopySelection();
53
+ _copiedRanges = null;
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ function markCopySelection(ranges) {
61
+ var columns = _grid.getColumns();
62
+ var hash = {};
63
+ for (var i = 0; i < ranges.length; i++) {
64
+ for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
65
+ hash[j] = {};
66
+ for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
67
+ hash[j][columns[k].id] = "copied";
68
+ }
69
+ }
70
+ }
71
+ _grid.setCellCssStyles("copy-manager", hash);
72
+ }
73
+
74
+ function clearCopySelection() {
75
+ _grid.removeCellCssStyles("copy-manager");
76
+ }
77
+
78
+ $.extend(this, {
79
+ "init": init,
80
+ "destroy": destroy,
81
+ "clearCopySelection": clearCopySelection,
82
+
83
+ "onCopyCells": new Slick.Event(),
84
+ "onCopyCancelled": new Slick.Event(),
85
+ "onPasteCells": new Slick.Event()
86
+ });
87
+ }
88
+ })(jQuery);
@@ -0,0 +1,452 @@
1
+ (function ($) {
2
+ // register namespace
3
+ $.extend(true, window, {
4
+ "Slick": {
5
+ "CellExternalCopyManager": CellExternalCopyManager
6
+ }
7
+ });
8
+
9
+
10
+ function CellExternalCopyManager(options) {
11
+ /*
12
+ This manager enables users to copy/paste data from/to an external Spreadsheet application
13
+ such as MS-Excel® or OpenOffice-Spreadsheet.
14
+
15
+ Since it is not possible to access directly the clipboard in javascript, the plugin uses
16
+ a trick to do it's job. After detecting the keystroke, we dynamically create a textarea
17
+ where the browser copies/pastes the serialized data.
18
+
19
+ options:
20
+ copiedCellStyle : sets the css className used for copied cells. default : "copied"
21
+ copiedCellStyleLayerKey : sets the layer key for setting css values of copied cells. default : "copy-manager"
22
+ dataItemColumnValueExtractor : option to specify a custom column value extractor function
23
+ dataItemColumnValueSetter : option to specify a custom column value setter function
24
+ clipboardCommandHandler : option to specify a custom handler for paste actions
25
+ includeHeaderWhenCopying : set to true and the plugin will take the name property from each column (which is usually what appears in your header) and put that as the first row of the text that's copied to the clipboard
26
+ bodyElement: option to specify a custom DOM element which to will be added the hidden textbox. It's useful if the grid is inside a modal dialog.
27
+ onCopyInit: optional handler to run when copy action initializes
28
+ onCopySuccess: optional handler to run when copy action is complete
29
+ newRowCreator: function to add rows to table if paste overflows bottom of table, if this function is not provided new rows will be ignored.
30
+ readOnlyMode: suppresses paste
31
+ */
32
+ var _grid;
33
+ var _self = this;
34
+ var _copiedRanges;
35
+ var _options = options || {};
36
+ var _copiedCellStyleLayerKey = _options.copiedCellStyleLayerKey || "copy-manager";
37
+ var _copiedCellStyle = _options.copiedCellStyle || "copied";
38
+ var _clearCopyTI = 0;
39
+ var _bodyElement = _options.bodyElement || document.body;
40
+ var _onCopyInit = _options.onCopyInit || null;
41
+ var _onCopySuccess = _options.onCopySuccess || null;
42
+
43
+ var keyCodes = {
44
+ 'C': 67,
45
+ 'V': 86,
46
+ 'ESC': 27,
47
+ 'INSERT': 45
48
+ };
49
+
50
+ function init(grid) {
51
+ _grid = grid;
52
+ _grid.onKeyDown.subscribe(handleKeyDown);
53
+
54
+ // we need a cell selection model
55
+ var cellSelectionModel = grid.getSelectionModel();
56
+ if (!cellSelectionModel){
57
+ 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())");
58
+ }
59
+ // we give focus on the grid when a selection is done on it.
60
+ // 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
61
+ cellSelectionModel.onSelectedRangesChanged.subscribe(function(e, args){
62
+ _grid.focus();
63
+ });
64
+ }
65
+
66
+ function destroy() {
67
+ _grid.onKeyDown.unsubscribe(handleKeyDown);
68
+ }
69
+
70
+ function getDataItemValueForColumn(item, columnDef) {
71
+ if (_options.dataItemColumnValueExtractor) {
72
+ var dataItemColumnValueExtractorValue = _options.dataItemColumnValueExtractor(item, columnDef);
73
+
74
+ if (dataItemColumnValueExtractorValue)
75
+ return dataItemColumnValueExtractorValue;
76
+ }
77
+
78
+ var retVal = '';
79
+
80
+ // if a custom getter is not defined, we call serializeValue of the editor to serialize
81
+ if (columnDef.editor){
82
+ var editorArgs = {
83
+ 'container':$("<p>"), // a dummy container
84
+ 'column':columnDef,
85
+ 'position':{'top':0, 'left':0}, // a dummy position required by some editors
86
+ 'grid':_grid
87
+ };
88
+ var editor = new columnDef.editor(editorArgs);
89
+ editor.loadValue(item);
90
+ retVal = editor.serializeValue();
91
+ editor.destroy();
92
+ } else {
93
+ retVal = item[columnDef.field];
94
+ }
95
+
96
+ return retVal;
97
+ }
98
+
99
+ function setDataItemValueForColumn(item, columnDef, value) {
100
+ if (_options.dataItemColumnValueSetter) {
101
+ return _options.dataItemColumnValueSetter(item, columnDef, value);
102
+ }
103
+
104
+ // if a custom setter is not defined, we call applyValue of the editor to unserialize
105
+ if (columnDef.editor){
106
+ var editorArgs = {
107
+ 'container':$("body"), // a dummy container
108
+ 'column':columnDef,
109
+ 'position':{'top':0, 'left':0}, // a dummy position required by some editors
110
+ 'grid':_grid
111
+ };
112
+ var editor = new columnDef.editor(editorArgs);
113
+ editor.loadValue(item);
114
+ editor.applyValue(item, value);
115
+ editor.destroy();
116
+ } else {
117
+ item[columnDef.field] = value;
118
+ }
119
+ }
120
+
121
+
122
+ function _createTextBox(innerText){
123
+ var ta = document.createElement('textarea');
124
+ ta.style.position = 'absolute';
125
+ ta.style.left = '-1000px';
126
+ ta.style.top = document.body.scrollTop + 'px';
127
+ ta.value = innerText;
128
+ _bodyElement.appendChild(ta);
129
+ ta.select();
130
+
131
+ return ta;
132
+ }
133
+
134
+ function _decodeTabularData(_grid, ta){
135
+ var columns = _grid.getColumns();
136
+ var clipText = ta.value;
137
+ var clipRows = clipText.split(/[\n\f\r]/);
138
+ // trim trailing CR if present
139
+ if (clipRows[clipRows.length - 1]=="") { clipRows.pop(); }
140
+
141
+ var clippedRange = [];
142
+ var j = 0;
143
+
144
+ _bodyElement.removeChild(ta);
145
+ for (var i=0; i<clipRows.length; i++) {
146
+ if (clipRows[i]!="")
147
+ clippedRange[j++] = clipRows[i].split("\t");
148
+ else
149
+ clippedRange[i] = [""];
150
+ }
151
+ var selectedCell = _grid.getActiveCell();
152
+ var ranges = _grid.getSelectionModel().getSelectedRanges();
153
+ var selectedRange = ranges && ranges.length ? ranges[0] : null; // pick only one selection
154
+ var activeRow = null;
155
+ var activeCell = null;
156
+
157
+ if (selectedRange){
158
+ activeRow = selectedRange.fromRow;
159
+ activeCell = selectedRange.fromCell;
160
+ } else if (selectedCell){
161
+ activeRow = selectedCell.row;
162
+ activeCell = selectedCell.cell;
163
+ } else {
164
+ // we don't know where to paste
165
+ return;
166
+ }
167
+
168
+ var oneCellToMultiple = false;
169
+ var destH = clippedRange.length;
170
+ var destW = clippedRange.length ? clippedRange[0].length : 0;
171
+ if (clippedRange.length == 1 && clippedRange[0].length == 1 && selectedRange){
172
+ oneCellToMultiple = true;
173
+ destH = selectedRange.toRow - selectedRange.fromRow +1;
174
+ destW = selectedRange.toCell - selectedRange.fromCell +1;
175
+ }
176
+ var availableRows = _grid.getData().length - activeRow;
177
+ var addRows = 0;
178
+
179
+ // ignore new rows if we don't have a "newRowCreator"
180
+ if(availableRows < destH && _options.newRowCreator)
181
+ {
182
+ var d = _grid.getData();
183
+ for(addRows = 1; addRows <= destH - availableRows; addRows++)
184
+ d.push({});
185
+ _grid.setData(d);
186
+ _grid.render();
187
+ }
188
+
189
+ var overflowsBottomOfGrid = activeRow + destH > _grid.getDataLength();
190
+
191
+ if (_options.newRowCreator && overflowsBottomOfGrid) {
192
+
193
+ var newRowsNeeded = activeRow + destH - _grid.getDataLength();
194
+
195
+ _options.newRowCreator(newRowsNeeded);
196
+
197
+ }
198
+
199
+ var clipCommand = {
200
+
201
+ isClipboardCommand: true,
202
+ clippedRange: clippedRange,
203
+ oldValues: [],
204
+ cellExternalCopyManager: _self,
205
+ _options: _options,
206
+ setDataItemValueForColumn: setDataItemValueForColumn,
207
+ markCopySelection: markCopySelection,
208
+ oneCellToMultiple: oneCellToMultiple,
209
+ activeRow: activeRow,
210
+ activeCell: activeCell,
211
+ destH: destH,
212
+ destW: destW,
213
+ maxDestY: _grid.getDataLength(),
214
+ maxDestX: _grid.getColumns().length,
215
+ h: 0,
216
+ w: 0,
217
+
218
+ execute: function() {
219
+ this.h=0;
220
+ for (var y = 0; y < this.destH; y++){
221
+ this.oldValues[y] = [];
222
+ this.w=0;
223
+ this.h++;
224
+ for (var x = 0; x < this.destW; x++){
225
+ this.w++;
226
+ var desty = activeRow + y;
227
+ var destx = activeCell + x;
228
+
229
+ if (desty < this.maxDestY && destx < this.maxDestX ) {
230
+ var nd = _grid.getCellNode(desty, destx);
231
+ var dt = _grid.getDataItem(desty);
232
+ this.oldValues[y][x] = dt[columns[destx]['field']];
233
+ if (oneCellToMultiple)
234
+ this.setDataItemValueForColumn(dt, columns[destx], clippedRange[0][0]);
235
+ else
236
+ this.setDataItemValueForColumn(dt, columns[destx], clippedRange[y] ? clippedRange[y][x] : '');
237
+ _grid.updateCell(desty, destx);
238
+ _grid.onCellChange.notify({
239
+ row: desty,
240
+ cell: destx,
241
+ item: dt,
242
+ grid: _grid
243
+ });
244
+
245
+ }
246
+ }
247
+ }
248
+
249
+ var bRange = {
250
+ 'fromCell': activeCell,
251
+ 'fromRow': activeRow,
252
+ 'toCell': activeCell+this.w-1,
253
+ 'toRow': activeRow+this.h-1
254
+ }
255
+
256
+ this.markCopySelection([bRange]);
257
+ _grid.getSelectionModel().setSelectedRanges([bRange]);
258
+ this.cellExternalCopyManager.onPasteCells.notify({ranges: [bRange]});
259
+ },
260
+
261
+ undo: function() {
262
+ for (var y = 0; y < this.destH; y++){
263
+ for (var x = 0; x < this.destW; x++){
264
+ var desty = activeRow + y;
265
+ var destx = activeCell + x;
266
+
267
+ if (desty < this.maxDestY && destx < this.maxDestX ) {
268
+ var nd = _grid.getCellNode(desty, destx);
269
+ var dt = _grid.getDataItem(desty);
270
+ if (oneCellToMultiple)
271
+ this.setDataItemValueForColumn(dt, columns[destx], this.oldValues[0][0]);
272
+ else
273
+ this.setDataItemValueForColumn(dt, columns[destx], this.oldValues[y][x]);
274
+ _grid.updateCell(desty, destx);
275
+ _grid.onCellChange.notify({
276
+ row: desty,
277
+ cell: destx,
278
+ item: dt,
279
+ grid: _grid
280
+ });
281
+ }
282
+ }
283
+ }
284
+
285
+ var bRange = {
286
+ 'fromCell': activeCell,
287
+ 'fromRow': activeRow,
288
+ 'toCell': activeCell+this.w-1,
289
+ 'toRow': activeRow+this.h-1
290
+ }
291
+
292
+ this.markCopySelection([bRange]);
293
+ _grid.getSelectionModel().setSelectedRanges([bRange]);
294
+ this.cellExternalCopyManager.onPasteCells.notify({ranges: [bRange]});
295
+
296
+ if(addRows > 1){
297
+ var d = _grid.getData();
298
+ for(; addRows > 1; addRows--)
299
+ d.splice(d.length - 1, 1);
300
+ _grid.setData(d);
301
+ _grid.render();
302
+ }
303
+ }
304
+ };
305
+
306
+ if(_options.clipboardCommandHandler) {
307
+ _options.clipboardCommandHandler(clipCommand);
308
+ }
309
+ else {
310
+ clipCommand.execute();
311
+ }
312
+ }
313
+
314
+
315
+ function handleKeyDown(e, args) {
316
+ var ranges;
317
+ if (!_grid.getEditorLock().isActive() || _grid.getOptions().autoEdit) {
318
+ if (e.which == keyCodes.ESC) {
319
+ if (_copiedRanges) {
320
+ e.preventDefault();
321
+ clearCopySelection();
322
+ _self.onCopyCancelled.notify({ranges: _copiedRanges});
323
+ _copiedRanges = null;
324
+ }
325
+ }
326
+
327
+ if ((e.which === keyCodes.C || e.which === keyCodes.INSERT) && (e.ctrlKey || e.metaKey) && !e.shiftKey) { // CTRL+C or CTRL+INS
328
+ if (_onCopyInit) {
329
+ _onCopyInit.call();
330
+ }
331
+ ranges = _grid.getSelectionModel().getSelectedRanges();
332
+ if (ranges.length != 0) {
333
+ _copiedRanges = ranges;
334
+ markCopySelection(ranges);
335
+ _self.onCopyCells.notify({ranges: ranges});
336
+
337
+ var columns = _grid.getColumns();
338
+ var clipText = "";
339
+
340
+ for (var rg = 0; rg < ranges.length; rg++){
341
+ var range = ranges[rg];
342
+ var clipTextRows = [];
343
+ for (var i=range.fromRow; i< range.toRow+1 ; i++){
344
+ var clipTextCells = [];
345
+ var dt = _grid.getDataItem(i);
346
+
347
+ if (clipTextRows == "" && _options.includeHeaderWhenCopying) {
348
+ var clipTextHeaders = [];
349
+ for (var j = range.fromCell; j < range.toCell + 1 ; j++) {
350
+ if (columns[j].name.length > 0)
351
+ clipTextHeaders.push(columns[j].name);
352
+ }
353
+ clipTextRows.push(clipTextHeaders.join("\t"));
354
+ }
355
+
356
+ for (var j=range.fromCell; j< range.toCell+1 ; j++){
357
+ clipTextCells.push(getDataItemValueForColumn(dt, columns[j]));
358
+ }
359
+ clipTextRows.push(clipTextCells.join("\t"));
360
+ }
361
+ clipText += clipTextRows.join("\r\n") + "\r\n";
362
+ }
363
+
364
+ if(window.clipboardData) {
365
+ window.clipboardData.setData("Text", clipText);
366
+ return true;
367
+ }
368
+ else {
369
+ var focusEl = document.activeElement;
370
+
371
+ var ta = _createTextBox(clipText);
372
+
373
+ ta.focus();
374
+
375
+ setTimeout(function(){
376
+ _bodyElement.removeChild(ta);
377
+ // restore focus
378
+ if (focusEl)
379
+ focusEl.focus();
380
+ else
381
+ console.log("Not element to restore focus to after copy?");
382
+
383
+ }, 100);
384
+
385
+ if (_onCopySuccess) {
386
+ var rowCount = 0;
387
+ // If it's cell selection, use the toRow/fromRow fields
388
+ if (ranges.length === 1) {
389
+ rowCount = (ranges[0].toRow + 1) - ranges[0].fromRow;
390
+ }
391
+ else {
392
+ rowCount = ranges.length;
393
+ }
394
+ _onCopySuccess.call(this, rowCount);
395
+ }
396
+
397
+ return false;
398
+ }
399
+ }
400
+ }
401
+
402
+ if (!_options.readOnlyMode && (
403
+ (e.which === keyCodes.V && (e.ctrlKey || e.metaKey) && !e.shiftKey)
404
+ || (e.which === keyCodes.INSERT && e.shiftKey && !e.ctrlKey)
405
+ )) { // CTRL+V or Shift+INS
406
+ var ta = _createTextBox('');
407
+
408
+ setTimeout(function(){
409
+ _decodeTabularData(_grid, ta);
410
+ }, 100);
411
+
412
+ return false;
413
+ }
414
+ }
415
+ }
416
+
417
+ function markCopySelection(ranges) {
418
+ clearCopySelection();
419
+
420
+ var columns = _grid.getColumns();
421
+ var hash = {};
422
+ for (var i = 0; i < ranges.length; i++) {
423
+ for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
424
+ hash[j] = {};
425
+ for (var k = ranges[i].fromCell; k <= ranges[i].toCell && k<columns.length; k++) {
426
+ hash[j][columns[k].id] = _copiedCellStyle;
427
+ }
428
+ }
429
+ }
430
+ _grid.setCellCssStyles(_copiedCellStyleLayerKey, hash);
431
+ clearTimeout(_clearCopyTI);
432
+ _clearCopyTI = setTimeout(function(){
433
+ _self.clearCopySelection();
434
+ }, 2000);
435
+ }
436
+
437
+ function clearCopySelection() {
438
+ _grid.removeCellCssStyles(_copiedCellStyleLayerKey);
439
+ }
440
+
441
+ $.extend(this, {
442
+ "init": init,
443
+ "destroy": destroy,
444
+ "clearCopySelection": clearCopySelection,
445
+ "handleKeyDown":handleKeyDown,
446
+
447
+ "onCopyCells": new Slick.Event(),
448
+ "onCopyCancelled": new Slick.Event(),
449
+ "onPasteCells": new Slick.Event()
450
+ });
451
+ }
452
+ })(jQuery);