slickgrid-rails 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. data/.gitignore +2 -0
  2. data/README.md +9 -0
  3. data/Rakefile +33 -0
  4. data/slickgrid-rails.gemspec +1 -2
  5. data/vendor/assets/javascripts/slick/controls/columnpicker.css +31 -0
  6. data/vendor/assets/javascripts/slick/controls/columnpicker.js +32 -0
  7. data/vendor/assets/javascripts/slick/controls/pager.css +41 -0
  8. data/vendor/assets/javascripts/slick/controls/pager.js +4 -8
  9. data/vendor/assets/javascripts/slick/core.js +35 -1
  10. data/vendor/assets/javascripts/slick/dataview.js +240 -85
  11. data/vendor/assets/javascripts/slick/editors.js +5 -5
  12. data/vendor/assets/javascripts/slick/formatters.js +5 -1
  13. data/vendor/assets/javascripts/slick/grid.css +157 -0
  14. data/vendor/assets/javascripts/slick/grid.js +770 -269
  15. data/vendor/assets/javascripts/slick/groupitemmetadataprovider.js +15 -10
  16. data/vendor/assets/javascripts/slick/plugins/autotooltips.js +49 -14
  17. data/vendor/assets/javascripts/slick/plugins/cellrangeselector.js +9 -8
  18. data/vendor/assets/javascripts/slick/plugins/cellselectionmodel.js +62 -2
  19. data/vendor/assets/javascripts/slick/plugins/checkboxselectcolumn.js +8 -9
  20. data/vendor/assets/javascripts/slick/plugins/headerbuttons.css +39 -0
  21. data/vendor/assets/javascripts/slick/plugins/headerbuttons.js +177 -0
  22. data/vendor/assets/javascripts/slick/plugins/headermenu.css +59 -0
  23. data/vendor/assets/javascripts/slick/plugins/headermenu.js +275 -0
  24. data/vendor/assets/javascripts/slick/plugins/rowmovemanager.js +17 -11
  25. data/vendor/assets/javascripts/slick/plugins/rowselectionmodel.js +1 -1
  26. data/vendor/assets/javascripts/slick/remotemodel.js +164 -0
  27. data/vendor/assets/stylesheets/slick/controls/columnpicker.css +31 -0
  28. data/vendor/assets/stylesheets/slick/controls/pager.css +41 -0
  29. data/vendor/assets/stylesheets/slick/grid.css +157 -0
  30. data/vendor/assets/stylesheets/slick/plugins/headerbuttons.css +39 -0
  31. data/vendor/assets/stylesheets/slick/plugins/headermenu.css +59 -0
  32. metadata +51 -17
  33. data/.rvmrc +0 -1
  34. data/Gemfile.lock +0 -85
  35. data/fetch.sh +0 -8
  36. data/lib/slickgrid/rails/version.rb +0 -6
@@ -26,6 +26,7 @@
26
26
  var _grid;
27
27
  var _defaults = {
28
28
  groupCssClass: "slick-group",
29
+ groupTitleCssClass: "slick-group-title",
29
30
  totalsCssClass: "slick-group-totals",
30
31
  groupFocusable: true,
31
32
  totalsFocusable: false,
@@ -43,9 +44,15 @@
43
44
  return item.title;
44
45
  }
45
46
 
47
+ var indentation = item.level * 15 + "px";
48
+
46
49
  return "<span class='" + options.toggleCssClass + " " +
47
50
  (item.collapsed ? options.toggleCollapsedCssClass : options.toggleExpandedCssClass) +
48
- "'></span>" + item.title;
51
+ "' style='margin-left:" + indentation +"'>" +
52
+ "</span>" +
53
+ "<span class='" + options.groupTitleCssClass + "' level='" + item.level + "'>" +
54
+ item.title +
55
+ "</span>";
49
56
  }
50
57
 
51
58
  function defaultTotalsCellFormatter(row, cell, value, columnDef, item) {
@@ -71,10 +78,9 @@
71
78
  var item = this.getDataItem(args.row);
72
79
  if (item && item instanceof Slick.Group && $(e.target).hasClass(options.toggleCssClass)) {
73
80
  if (item.collapsed) {
74
- this.getData().expandGroup(item.value);
75
- }
76
- else {
77
- this.getData().collapseGroup(item.value);
81
+ this.getData().expandGroup(item.groupingKey);
82
+ } else {
83
+ this.getData().collapseGroup(item.groupingKey);
78
84
  }
79
85
 
80
86
  e.stopImmediatePropagation();
@@ -90,10 +96,9 @@
90
96
  var item = this.getDataItem(activeCell.row);
91
97
  if (item && item instanceof Slick.Group) {
92
98
  if (item.collapsed) {
93
- this.getData().expandGroup(item.value);
94
- }
95
- else {
96
- this.getData().collapseGroup(item.value);
99
+ this.getData().expandGroup(item.groupingKey);
100
+ } else {
101
+ this.getData().collapseGroup(item.groupingKey);
97
102
  }
98
103
 
99
104
  e.stopImmediatePropagation();
@@ -136,4 +141,4 @@
136
141
  "getTotalsRowMetadata": getTotalsRowMetadata
137
142
  };
138
143
  }
139
- })(jQuery);
144
+ })(jQuery);
@@ -1,45 +1,80 @@
1
1
  (function ($) {
2
- // register namespace
2
+ // Register namespace
3
3
  $.extend(true, window, {
4
4
  "Slick": {
5
5
  "AutoTooltips": AutoTooltips
6
6
  }
7
7
  });
8
8
 
9
-
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
+ */
10
16
  function AutoTooltips(options) {
11
17
  var _grid;
12
18
  var _self = this;
13
19
  var _defaults = {
20
+ enableForCells: true,
21
+ enableForHeaderCells: false,
14
22
  maxToolTipLength: null
15
23
  };
16
-
24
+
25
+ /**
26
+ * Initialize plugin.
27
+ */
17
28
  function init(grid) {
18
29
  options = $.extend(true, {}, _defaults, options);
19
30
  _grid = grid;
20
- _grid.onMouseEnter.subscribe(handleMouseEnter);
31
+ if (options.enableForCells) _grid.onMouseEnter.subscribe(handleMouseEnter);
32
+ if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.subscribe(handleHeaderMouseEnter);
21
33
  }
22
-
34
+
35
+ /**
36
+ * Destroy plugin.
37
+ */
23
38
  function destroy() {
24
- _grid.onMouseEnter.unsubscribe(handleMouseEnter);
39
+ if (options.enableForCells) _grid.onMouseEnter.unsubscribe(handleMouseEnter);
40
+ if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.unsubscribe(handleHeaderMouseEnter);
25
41
  }
26
-
27
- function handleMouseEnter(e, args) {
42
+
43
+ /**
44
+ * Handle mouse entering grid cell to add/remove tooltip.
45
+ * @param {jQuery.Event} e - The event
46
+ */
47
+ function handleMouseEnter(e) {
28
48
  var cell = _grid.getCellFromEvent(e);
29
49
  if (cell) {
30
- var node = _grid.getCellNode(cell.row, cell.cell);
31
- if ($(node).innerWidth() < node.scrollWidth) {
32
- var text = $.trim($(node).text());
50
+ var $node = $(_grid.getCellNode(cell.row, cell.cell));
51
+ var text;
52
+ if ($node.innerWidth() < $node[0].scrollWidth) {
53
+ text = $.trim($node.text());
33
54
  if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
34
55
  text = text.substr(0, options.maxToolTipLength - 3) + "...";
35
56
  }
36
- $(node).attr("title", text);
37
57
  } else {
38
- $(node).attr("title", "");
58
+ text = "";
39
59
  }
60
+ $node.attr("title", text);
40
61
  }
41
62
  }
42
-
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.toolTip) {
73
+ $node.attr("title", ($node.innerWidth() < $node[0].scrollWidth) ? column.name : "");
74
+ }
75
+ }
76
+
77
+ // Public API
43
78
  $.extend(this, {
44
79
  "init": init,
45
80
  "destroy": destroy
@@ -13,6 +13,7 @@
13
13
  var _dragging;
14
14
  var _decorator;
15
15
  var _self = this;
16
+ var _handler = new Slick.EventHandler();
16
17
  var _defaults = {
17
18
  selectionCss: {
18
19
  "border": "2px dashed blue"
@@ -25,17 +26,15 @@
25
26
  _decorator = new Slick.CellRangeDecorator(grid, options);
26
27
  _grid = grid;
27
28
  _canvas = _grid.getCanvasNode();
28
- _grid.onDragInit.subscribe(handleDragInit);
29
- _grid.onDragStart.subscribe(handleDragStart);
30
- _grid.onDrag.subscribe(handleDrag);
31
- _grid.onDragEnd.subscribe(handleDragEnd);
29
+ _handler
30
+ .subscribe(_grid.onDragInit, handleDragInit)
31
+ .subscribe(_grid.onDragStart, handleDragStart)
32
+ .subscribe(_grid.onDrag, handleDrag)
33
+ .subscribe(_grid.onDragEnd, handleDragEnd);
32
34
  }
33
35
 
34
36
  function destroy() {
35
- _grid.onDragInit.unsubscribe(handleDragInit);
36
- _grid.onDragStart.unsubscribe(handleDragStart);
37
- _grid.onDrag.unsubscribe(handleDrag);
38
- _grid.onDragEnd.unsubscribe(handleDragEnd);
37
+ _handler.unsubscribeAll();
39
38
  }
40
39
 
41
40
  function handleDragInit(e, dd) {
@@ -55,6 +54,8 @@
55
54
  return;
56
55
  }
57
56
 
57
+ _grid.focus();
58
+
58
59
  var start = _grid.getCellFromPoint(
59
60
  dd.startX - $(_canvas).offset().left,
60
61
  dd.startY - $(_canvas).offset().top);
@@ -28,6 +28,7 @@
28
28
  _grid = grid;
29
29
  _canvas = _grid.getCanvasNode();
30
30
  _grid.onActiveCellChanged.subscribe(handleActiveCellChange);
31
+ _grid.onKeyDown.subscribe(handleKeyDown);
31
32
  grid.registerPlugin(_selector);
32
33
  _selector.onCellRangeSelected.subscribe(handleCellRangeSelected);
33
34
  _selector.onBeforeCellRangeSelected.subscribe(handleBeforeCellRangeSelected);
@@ -35,6 +36,7 @@
35
36
 
36
37
  function destroy() {
37
38
  _grid.onActiveCellChanged.unsubscribe(handleActiveCellChange);
39
+ _grid.onKeyDown.unsubscribe(handleKeyDown);
38
40
  _selector.onCellRangeSelected.unsubscribe(handleCellRangeSelected);
39
41
  _selector.onBeforeCellRangeSelected.unsubscribe(handleBeforeCellRangeSelected);
40
42
  _grid.unregisterPlugin(_selector);
@@ -74,10 +76,68 @@
74
76
  }
75
77
 
76
78
  function handleActiveCellChange(e, args) {
77
- if (_options.selectActiveCell) {
79
+ if (_options.selectActiveCell && args.row != null && args.cell != null) {
78
80
  setSelectedRanges([new Slick.Range(args.row, args.cell)]);
79
81
  }
80
82
  }
83
+
84
+ function handleKeyDown(e) {
85
+ /***
86
+ * Кey codes
87
+ * 37 left
88
+ * 38 up
89
+ * 39 right
90
+ * 40 down
91
+ */
92
+ var ranges, last;
93
+ var active = _grid.getActiveCell();
94
+
95
+ if ( active && e.shiftKey && !e.ctrlKey && !e.altKey &&
96
+ (e.which == 37 || e.which == 39 || e.which == 38 || e.which == 40) ) {
97
+
98
+ ranges = getSelectedRanges();
99
+ if (!ranges.length)
100
+ ranges.push(new Slick.Range(active.row, active.cell));
101
+
102
+ // keyboard can work with last range only
103
+ last = ranges.pop();
104
+
105
+ // can't handle selection out of active cell
106
+ if (!last.contains(active.row, active.cell))
107
+ last = new Slick.Range(active.row, active.cell);
108
+
109
+ var dRow = last.toRow - last.fromRow,
110
+ dCell = last.toCell - last.fromCell,
111
+ // walking direction
112
+ dirRow = active.row == last.fromRow ? 1 : -1,
113
+ dirCell = active.cell == last.fromCell ? 1 : -1;
114
+
115
+ if (e.which == 37) {
116
+ dCell -= dirCell;
117
+ } else if (e.which == 39) {
118
+ dCell += dirCell ;
119
+ } else if (e.which == 38) {
120
+ dRow -= dirRow;
121
+ } else if (e.which == 40) {
122
+ dRow += dirRow;
123
+ }
124
+
125
+ // define new selection range
126
+ var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow*dRow, active.cell + dirCell*dCell);
127
+ if (removeInvalidRanges([new_last]).length) {
128
+ ranges.push(new_last);
129
+ _grid.scrollRowIntoView(dirRow > 0 ? new_last.toRow : new_last.fromRow);
130
+ _grid.scrollCellIntoView(new_last.fromRow, dirCell > 0 ? new_last.toCell : new_last.fromCell);
131
+ }
132
+ else
133
+ ranges.push(last);
134
+
135
+ setSelectedRanges(ranges);
136
+
137
+ e.preventDefault();
138
+ e.stopPropagation();
139
+ }
140
+ }
81
141
 
82
142
  $.extend(this, {
83
143
  "getSelectedRanges": getSelectedRanges,
@@ -89,4 +149,4 @@
89
149
  "onSelectedRangesChanged": new Slick.Event()
90
150
  });
91
151
  }
92
- })(jQuery);
152
+ })(jQuery);
@@ -10,6 +10,7 @@
10
10
  function CheckboxSelectColumn(options) {
11
11
  var _grid;
12
12
  var _self = this;
13
+ var _handler = new Slick.EventHandler();
13
14
  var _selectedRowsLookup = {};
14
15
  var _defaults = {
15
16
  columnId: "_checkbox_selector",
@@ -22,17 +23,15 @@
22
23
 
23
24
  function init(grid) {
24
25
  _grid = grid;
25
- _grid.onSelectedRowsChanged.subscribe(handleSelectedRowsChanged);
26
- _grid.onClick.subscribe(handleClick);
27
- _grid.onHeaderClick.subscribe(handleHeaderClick);
28
- _grid.onKeyDown.subscribe(handleKeyDown);
26
+ _handler
27
+ .subscribe(_grid.onSelectedRowsChanged, handleSelectedRowsChanged)
28
+ .subscribe(_grid.onClick, handleClick)
29
+ .subscribe(_grid.onHeaderClick, handleHeaderClick)
30
+ .subscribe(_grid.onKeyDown, handleKeyDown);
29
31
  }
30
32
 
31
33
  function destroy() {
32
- _grid.onSelectedRowsChanged.unsubscribe(handleSelectedRowsChanged);
33
- _grid.onClick.unsubscribe(handleClick);
34
- _grid.onHeaderClick.unsubscribe(handleHeaderClick);
35
- _grid.onKeyDown.unsubscribe(handleKeyDown);
34
+ _handler.unsubscribeAll();
36
35
  }
37
36
 
38
37
  function handleSelectedRowsChanged(e, args) {
@@ -52,7 +51,7 @@
52
51
  _selectedRowsLookup = lookup;
53
52
  _grid.render();
54
53
 
55
- if (selectedRows.length == _grid.getDataLength()) {
54
+ if (selectedRows.length && selectedRows.length == _grid.getDataLength()) {
56
55
  _grid.updateColumnHeader(_options.columnId, "<input type='checkbox' checked='checked'>", _options.toolTip);
57
56
  } else {
58
57
  _grid.updateColumnHeader(_options.columnId, "<input type='checkbox'>", _options.toolTip);
@@ -0,0 +1,39 @@
1
+ .slick-column-name,
2
+ .slick-sort-indicator {
3
+ /**
4
+ * This makes all "float:right" elements after it that spill over to the next line
5
+ * display way below the lower boundary of the column thus hiding them.
6
+ */
7
+ display: inline-block;
8
+ float: left;
9
+ margin-bottom: 100px;
10
+ }
11
+
12
+ .slick-header-button {
13
+ display: inline-block;
14
+ float: right;
15
+ vertical-align: top;
16
+ margin: 1px;
17
+ /**
18
+ * This makes all "float:right" elements after it that spill over to the next line
19
+ * display way below the lower boundary of the column thus hiding them.
20
+ */
21
+ margin-bottom: 100px;
22
+ height: 15px;
23
+ width: 15px;
24
+ background-repeat: no-repeat;
25
+ background-position: center center;
26
+ cursor: pointer;
27
+ }
28
+
29
+ .slick-header-button-hidden {
30
+ width: 0;
31
+
32
+ -webkit-transition: 0.2s width;
33
+ -ms-transition: 0.2s width;
34
+ transition: 0.2s width;
35
+ }
36
+
37
+ .slick-header-column:hover > .slick-header-button {
38
+ width: 15px;
39
+ }
@@ -0,0 +1,177 @@
1
+ (function ($) {
2
+ // register namespace
3
+ $.extend(true, window, {
4
+ "Slick": {
5
+ "Plugins": {
6
+ "HeaderButtons": HeaderButtons
7
+ }
8
+ }
9
+ });
10
+
11
+
12
+ /***
13
+ * A plugin to add custom buttons to column headers.
14
+ *
15
+ * USAGE:
16
+ *
17
+ * Add the plugin .js & .css files and register it with the grid.
18
+ *
19
+ * To specify a custom button in a column header, extend the column definition like so:
20
+ *
21
+ * var columns = [
22
+ * {
23
+ * id: 'myColumn',
24
+ * name: 'My column',
25
+ *
26
+ * // This is the relevant part
27
+ * header: {
28
+ * buttons: [
29
+ * {
30
+ * // button options
31
+ * },
32
+ * {
33
+ * // button options
34
+ * }
35
+ * ]
36
+ * }
37
+ * }
38
+ * ];
39
+ *
40
+ * Available button options:
41
+ * cssClass: CSS class to add to the button.
42
+ * image: Relative button image path.
43
+ * tooltip: Button tooltip.
44
+ * showOnHover: Only show the button on hover.
45
+ * handler: Button click handler.
46
+ * command: A command identifier to be passed to the onCommand event handlers.
47
+ *
48
+ * The plugin exposes the following events:
49
+ * onCommand: Fired on button click for buttons with 'command' specified.
50
+ * Event args:
51
+ * grid: Reference to the grid.
52
+ * column: Column definition.
53
+ * command: Button command identified.
54
+ * button: Button options. Note that you can change the button options in your
55
+ * event handler, and the column header will be automatically updated to
56
+ * reflect them. This is useful if you want to implement something like a
57
+ * toggle button.
58
+ *
59
+ *
60
+ * @param options {Object} Options:
61
+ * buttonCssClass: a CSS class to use for buttons (default 'slick-header-button')
62
+ * @class Slick.Plugins.HeaderButtons
63
+ * @constructor
64
+ */
65
+ function HeaderButtons(options) {
66
+ var _grid;
67
+ var _self = this;
68
+ var _handler = new Slick.EventHandler();
69
+ var _defaults = {
70
+ buttonCssClass: "slick-header-button"
71
+ };
72
+
73
+
74
+ function init(grid) {
75
+ options = $.extend(true, {}, _defaults, options);
76
+ _grid = grid;
77
+ _handler
78
+ .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
79
+ .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
80
+
81
+ // Force the grid to re-render the header now that the events are hooked up.
82
+ _grid.setColumns(_grid.getColumns());
83
+ }
84
+
85
+
86
+ function destroy() {
87
+ _handler.unsubscribeAll();
88
+ }
89
+
90
+
91
+ function handleHeaderCellRendered(e, args) {
92
+ var column = args.column;
93
+
94
+ if (column.header && column.header.buttons) {
95
+ // Append buttons in reverse order since they are floated to the right.
96
+ var i = column.header.buttons.length;
97
+ while (i--) {
98
+ var button = column.header.buttons[i];
99
+ var btn = $("<div></div>")
100
+ .addClass(options.buttonCssClass)
101
+ .data("column", column)
102
+ .data("button", button);
103
+
104
+ if (button.showOnHover) {
105
+ btn.addClass("slick-header-button-hidden");
106
+ }
107
+
108
+ if (button.image) {
109
+ btn.css("backgroundImage", "url(" + button.image + ")");
110
+ }
111
+
112
+ if (button.cssClass) {
113
+ btn.addClass(button.cssClass);
114
+ }
115
+
116
+ if (button.tooltip) {
117
+ btn.attr("title", button.tooltip);
118
+ }
119
+
120
+ if (button.command) {
121
+ btn.data("command", button.command);
122
+ }
123
+
124
+ if (button.handler) {
125
+ btn.bind("click", button.handler);
126
+ }
127
+
128
+ btn
129
+ .bind("click", handleButtonClick)
130
+ .appendTo(args.node);
131
+ }
132
+ }
133
+ }
134
+
135
+
136
+ function handleBeforeHeaderCellDestroy(e, args) {
137
+ var column = args.column;
138
+
139
+ if (column.header && column.header.buttons) {
140
+ // Removing buttons via jQuery will also clean up any event handlers and data.
141
+ // NOTE: If you attach event handlers directly or using a different framework,
142
+ // you must also clean them up here to avoid memory leaks.
143
+ $(args.node).find("." + options.buttonCssClass).remove();
144
+ }
145
+ }
146
+
147
+
148
+ function handleButtonClick(e) {
149
+ var command = $(this).data("command");
150
+ var columnDef = $(this).data("column");
151
+ var button = $(this).data("button");
152
+
153
+ if (command != null) {
154
+ _self.onCommand.notify({
155
+ "grid": _grid,
156
+ "column": columnDef,
157
+ "command": command,
158
+ "button": button
159
+ }, e, _self);
160
+
161
+ // Update the header in case the user updated the button definition in the handler.
162
+ _grid.updateColumnHeader(columnDef.id);
163
+ }
164
+
165
+ // Stop propagation so that it doesn't register as a header click event.
166
+ e.preventDefault();
167
+ e.stopPropagation();
168
+ }
169
+
170
+ $.extend(this, {
171
+ "init": init,
172
+ "destroy": destroy,
173
+
174
+ "onCommand": new Slick.Event()
175
+ });
176
+ }
177
+ })(jQuery);