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,207 @@
1
+ /**
2
+ *
3
+ * Draggable Grouping contributed by: Muthukumar Selvarasu
4
+ * muthukumar{dot}se{at}gmail{dot}com
5
+ * github.com/muthukumarse/Slickgrid
6
+ *
7
+ * NOTES:
8
+ * This plugin provides the Draggable Grouping feature
9
+ */
10
+
11
+ (function ($) {
12
+ // Register namespace
13
+ $.extend(true, window, {
14
+ "Slick": {
15
+ "DraggableGrouping": DraggableGrouping
16
+ }
17
+ });
18
+
19
+ /**
20
+ * DraggableGrouping plugin to show/hide tooltips when columns are too narrow to fit content.
21
+ * @constructor
22
+ * @param {boolean} [options.enableForCells=true] - Enable tooltip for grid cells
23
+ * @param {boolean} [options.enableForHeaderCells=false] - Enable tooltip for header cells
24
+ * @param {number} [options.maxToolTipLength=null] - The maximum length for a tooltip
25
+ */
26
+ function DraggableGrouping(options) {
27
+ var _grid;
28
+ var _gridUid;
29
+ var _gridColumns;
30
+ var _dataView;
31
+ var dropbox;
32
+ var dropboxPlaceholder;
33
+ var _self = this;
34
+ var _defaults = {
35
+ };
36
+
37
+ /**
38
+ * Initialize plugin.
39
+ */
40
+ function init(grid) {
41
+ options = $.extend(true, {}, _defaults, options);
42
+ _grid = grid;
43
+ _gridUid = _grid.getUID();
44
+ _gridColumns = _grid.getColumns();
45
+ _dataView = _grid.getData();
46
+
47
+ dropbox = $(_grid.getPreHeaderPanel());
48
+ dropbox.html("<div class='slick-placeholder'>Drop a column header here to group by the column</div>");
49
+
50
+ dropboxPlaceholder = dropbox.find(".slick-placeholder");
51
+ setupColumnDropbox();
52
+ }
53
+
54
+ /**
55
+ * Destroy plugin.
56
+ */
57
+ function destroy() {
58
+ }
59
+
60
+
61
+ function setColumns(col) {
62
+ _gridColumns = col;
63
+ }
64
+
65
+ var emptyDropbox;
66
+
67
+ function setupColumnDropbox() {
68
+ dropbox.droppable({
69
+ activeClass: "ui-state-default",
70
+ hoverClass: "ui-state-hover",
71
+ accept: ":not(.ui-sortable-helper)",
72
+ deactivate: function(event, ui) {
73
+ dropbox.removeClass("slick-header-column-denied");
74
+ },
75
+ drop: function(event, ui) {
76
+ handleGroupByDrop(this, ui.draggable);
77
+ },
78
+ over: function(event, ui) {
79
+ var id = (ui.draggable).attr('id').replace(_gridUid, "");
80
+ _gridColumns.forEach(function(e, i, a) {
81
+ if (e.id == id) {
82
+ if (e.grouping == null) {
83
+ dropbox.addClass("slick-header-column-denied");
84
+ }
85
+ }
86
+ });
87
+ }
88
+ });
89
+ dropbox.sortable({
90
+ items: "div.slick-dropped-grouping",
91
+ cursor: "default",
92
+ tolerance: "pointer",
93
+ helper: "clone",
94
+ update: function(event, ui) {
95
+ var sortArray = $(this).sortable('toArray', {
96
+ attribute: 'data-id'
97
+ }),
98
+ newGroupingOrder = [];
99
+ for (var i = 0, l = sortArray.length; i < l; i++) {
100
+ for (var a = 0, b = columnsGroupBy.length; a < b; a++) {
101
+ if (columnsGroupBy[a].id == sortArray[i]) {
102
+ newGroupingOrder.push(columnsGroupBy[a]);
103
+ break;
104
+ }
105
+ }
106
+ }
107
+ columnsGroupBy = newGroupingOrder;
108
+ updateGroupBy();
109
+ }
110
+ });
111
+ emptyDropbox = dropbox.html();
112
+ }
113
+
114
+ var columnsGroupBy = [];
115
+ var groupBySorters = [];
116
+
117
+ function handleGroupByDrop(container, column) {
118
+ var columnid = column.attr('id').replace(_gridUid, "");
119
+ var columnAllowed = true;
120
+ columnsGroupBy.forEach(function(e, i, a) {
121
+ if (e.id == columnid) {
122
+ columnAllowed = false;
123
+ }
124
+ });
125
+ if (columnAllowed) {
126
+ _gridColumns.forEach(function(e, i, a) {
127
+ if (e.id == columnid) {
128
+ if (e.grouping != null) {
129
+ var entry = $("<div id='" + _gridUid + e.id + "_entry' data-id='" + e.id + "' class='slick-dropped-grouping'>");
130
+ var span = $("<span class='slick-groupby-remove'></span>").text(column.text() + " ")
131
+ span.appendTo(entry);
132
+ $("</div>").appendTo(entry);
133
+ entry.appendTo(container);
134
+ addColumnGroupBy(e, column, container, entry);
135
+ addGroupByRemoveClickHandler(e.id, container, column, entry);
136
+ }
137
+ }
138
+ });
139
+ }
140
+ }
141
+
142
+ function addColumnGroupBy(column) {
143
+ columnsGroupBy.push(column);
144
+ updateGroupBy();
145
+ }
146
+
147
+ function addGroupByRemoveClickHandler(id, container, column, entry) {
148
+ var text = entry;
149
+ $("#" + _gridUid + id + "_entry").on('click', function() {
150
+ $(this).off('click');
151
+ removeGroupBy(id, column, text);
152
+ });
153
+ }
154
+
155
+ function clearDroppedGroups() {
156
+ columnsGroupBy = [];
157
+ }
158
+
159
+ function removeFromArray(arr) {
160
+ var what, a = arguments,
161
+ L = a.length,
162
+ ax;
163
+ while (L > 1 && arr.length) {
164
+ what = a[--L];
165
+ while ((ax = arr.indexOf(what)) != -1) {
166
+ arr.splice(ax, 1);
167
+ }
168
+ }
169
+ return arr;
170
+ }
171
+
172
+ function removeGroupBy(id, column, entry) {
173
+ entry.remove();
174
+ var groupby = [];
175
+ _gridColumns.forEach(function(e, i, a) {
176
+ groupby[e.id] = e;
177
+ });
178
+ removeFromArray(columnsGroupBy, groupby[id]);
179
+ if(columnsGroupBy.length == 0){
180
+ dropboxPlaceholder.show();
181
+ }
182
+ updateGroupBy();
183
+ }
184
+
185
+ function updateGroupBy() {
186
+ if (columnsGroupBy.length == 0) {
187
+ _dataView.setGrouping([]);
188
+ return;
189
+ }
190
+ var groupingArray = [];
191
+ columnsGroupBy.forEach(function(element, index, array) {
192
+ groupingArray.push(element.grouping);
193
+ });
194
+ _dataView.setGrouping(groupingArray);
195
+ /*
196
+ collapseAllGroups();
197
+ */
198
+ }
199
+
200
+ // Public API
201
+ $.extend(this, {
202
+ "init": init,
203
+ "destroy": destroy,
204
+ "clearDroppedGroups": clearDroppedGroups
205
+ });
206
+ }
207
+ })(jQuery);
@@ -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.on("click", button.handler);
126
+ }
127
+
128
+ btn
129
+ .on("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);
@@ -0,0 +1,296 @@
1
+ (function ($) {
2
+ // register namespace
3
+ $.extend(true, window, {
4
+ "Slick": {
5
+ "Plugins": {
6
+ "HeaderMenu": HeaderMenu
7
+ }
8
+ }
9
+ });
10
+
11
+
12
+ /***
13
+ * A plugin to add drop-down menus 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 menu 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
+ * menu: {
29
+ * items: [
30
+ * {
31
+ * // menu item options
32
+ * },
33
+ * {
34
+ * // menu item options
35
+ * }
36
+ * ]
37
+ * }
38
+ * }
39
+ * }
40
+ * ];
41
+ *
42
+ *
43
+ * Available menu options:
44
+ * tooltip: Menu button tooltip.
45
+ *
46
+ *
47
+ * Available menu item options:
48
+ * title: Menu item text.
49
+ * disabled: Whether the item is disabled.
50
+ * tooltip: Item tooltip.
51
+ * command: A command identifier to be passed to the onCommand event handlers.
52
+ * iconCssClass: A CSS class to be added to the menu item icon.
53
+ * iconImage: A url to the icon image.
54
+ * minWidth: Minimum width that the drop menu will have
55
+ * autoAlign: Auto-align drop menu to the left when not enough viewport space to show on the right
56
+ * autoAlignOffset: When drop menu is aligned to the left, it might not be perfectly aligned with the header menu icon, if that is the case you can add an offset (positive/negative number to move right/left)
57
+ *
58
+ *
59
+ * The plugin exposes the following events:
60
+ * onBeforeMenuShow: Fired before the menu is shown. You can customize the menu or dismiss it by returning false.
61
+ * Event args:
62
+ * grid: Reference to the grid.
63
+ * column: Column definition.
64
+ * menu: Menu options. Note that you can change the menu items here.
65
+ *
66
+ * onCommand: Fired on menu item click for buttons with 'command' specified.
67
+ * Event args:
68
+ * grid: Reference to the grid.
69
+ * column: Column definition.
70
+ * command: Button command identified.
71
+ * button: Button options. Note that you can change the button options in your
72
+ * event handler, and the column header will be automatically updated to
73
+ * reflect them. This is useful if you want to implement something like a
74
+ * toggle button.
75
+ *
76
+ *
77
+ * @param options {Object} Options:
78
+ * buttonCssClass: an extra CSS class to add to the menu button
79
+ * buttonImage: a url to the menu button image (default '../slickgrid/down.gif')
80
+ * @class Slick.Plugins.HeaderButtons
81
+ * @constructor
82
+ */
83
+ function HeaderMenu(options) {
84
+ var _grid;
85
+ var _self = this;
86
+ var _handler = new Slick.EventHandler();
87
+ var _defaults = {
88
+ buttonCssClass: null,
89
+ buttonImage: null,
90
+ minWidth: 100,
91
+ autoAlign: true,
92
+ autoAlignOffset: 0
93
+ };
94
+ var $menu;
95
+ var $activeHeaderColumn;
96
+
97
+
98
+ function init(grid) {
99
+ options = $.extend(true, {}, _defaults, options);
100
+ _grid = grid;
101
+ _handler
102
+ .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
103
+ .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
104
+
105
+ // Force the grid to re-render the header now that the events are hooked up.
106
+ _grid.setColumns(_grid.getColumns());
107
+
108
+ // Hide the menu on outside click.
109
+ $(document.body).on("mousedown", handleBodyMouseDown);
110
+ }
111
+
112
+ function setOptions(newOptions) {
113
+ options = $.extend(true, {}, options, newOptions);
114
+ }
115
+
116
+
117
+ function destroy() {
118
+ _handler.unsubscribeAll();
119
+ $(document.body).off("mousedown", handleBodyMouseDown);
120
+ }
121
+
122
+
123
+ function handleBodyMouseDown(e) {
124
+ if ($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) {
125
+ hideMenu();
126
+ }
127
+ }
128
+
129
+
130
+ function hideMenu() {
131
+ if ($menu) {
132
+ $menu.remove();
133
+ $menu = null;
134
+ $activeHeaderColumn
135
+ .removeClass("slick-header-column-active");
136
+ }
137
+ }
138
+
139
+ function handleHeaderCellRendered(e, args) {
140
+ var column = args.column;
141
+ var menu = column.header && column.header.menu;
142
+
143
+ if (menu) {
144
+ var $el = $("<div></div>")
145
+ .addClass("slick-header-menubutton")
146
+ .data("column", column)
147
+ .data("menu", menu);
148
+
149
+ if (options.buttonCssClass) {
150
+ $el.addClass(options.buttonCssClass);
151
+ }
152
+
153
+ if (options.buttonImage) {
154
+ $el.css("background-image", "url(" + options.buttonImage + ")");
155
+ }
156
+
157
+ if (menu.tooltip) {
158
+ $el.attr("title", menu.tooltip);
159
+ }
160
+
161
+ $el
162
+ .on("click", showMenu)
163
+ .appendTo(args.node);
164
+ }
165
+ }
166
+
167
+
168
+ function handleBeforeHeaderCellDestroy(e, args) {
169
+ var column = args.column;
170
+
171
+ if (column.header && column.header.menu) {
172
+ $(args.node).find(".slick-header-menubutton").remove();
173
+ }
174
+ }
175
+
176
+
177
+ function showMenu(e) {
178
+ var $menuButton = $(this);
179
+ var menu = $menuButton.data("menu");
180
+ var columnDef = $menuButton.data("column");
181
+
182
+ // Let the user modify the menu or cancel altogether,
183
+ // or provide alternative menu implementation.
184
+ if (_self.onBeforeMenuShow.notify({
185
+ "grid": _grid,
186
+ "column": columnDef,
187
+ "menu": menu
188
+ }, e, _self) == false) {
189
+ return;
190
+ }
191
+
192
+
193
+ if (!$menu) {
194
+ $menu = $("<div class='slick-header-menu' style='min-width: " + options.minWidth + "px'></div>")
195
+ .appendTo(_grid.getContainerNode());
196
+ }
197
+ $menu.empty();
198
+
199
+
200
+ // Construct the menu items.
201
+ for (var i = 0; i < menu.items.length; i++) {
202
+ var item = menu.items[i];
203
+
204
+ var $li = $("<div class='slick-header-menuitem'></div>")
205
+ .data("command", item.command || '')
206
+ .data("column", columnDef)
207
+ .data("item", item)
208
+ .on("click", handleMenuItemClick)
209
+ .appendTo($menu);
210
+
211
+ if (item.disabled) {
212
+ $li.addClass("slick-header-menuitem-disabled");
213
+ }
214
+
215
+ if (item.tooltip) {
216
+ $li.attr("title", item.tooltip);
217
+ }
218
+
219
+ var $icon = $("<div class='slick-header-menuicon'></div>")
220
+ .appendTo($li);
221
+
222
+ if (item.iconCssClass) {
223
+ $icon.addClass(item.iconCssClass);
224
+ }
225
+
226
+ if (item.iconImage) {
227
+ $icon.css("background-image", "url(" + item.iconImage + ")");
228
+ }
229
+
230
+ $("<span class='slick-header-menucontent'></span>")
231
+ .text(item.title)
232
+ .appendTo($li);
233
+ }
234
+
235
+ var leftPos = $(this).offset().left;
236
+
237
+ // when auto-align is set, it will calculate whether it has enough space in the viewport to show the drop menu on the right (default)
238
+ // if there isn't enough space on the right, it will automatically align the drop menu to the left
239
+ // to simulate an align left, we actually need to know the width of the drop menu
240
+ if (options.autoAlign) {
241
+ var gridPos = _grid.getGridPosition();
242
+ if ((leftPos + options.minWidth) >= gridPos.width) {
243
+ leftPos = leftPos - options.minWidth + options.autoAlignOffset;
244
+ }
245
+ }
246
+
247
+ $menu
248
+ .offset({ top: $(this).offset().top + $(this).height(), left: leftPos });
249
+
250
+
251
+ // Mark the header as active to keep the highlighting.
252
+ $activeHeaderColumn = $menuButton.closest(".slick-header-column");
253
+ $activeHeaderColumn
254
+ .addClass("slick-header-column-active");
255
+
256
+ // Stop propagation so that it doesn't register as a header click event.
257
+ e.preventDefault();
258
+ e.stopPropagation();
259
+ }
260
+
261
+
262
+ function handleMenuItemClick(e) {
263
+ var command = $(this).data("command");
264
+ var columnDef = $(this).data("column");
265
+ var item = $(this).data("item");
266
+
267
+ if (item.disabled) {
268
+ return;
269
+ }
270
+
271
+ hideMenu();
272
+
273
+ if (command != null && command != '') {
274
+ _self.onCommand.notify({
275
+ "grid": _grid,
276
+ "column": columnDef,
277
+ "command": command,
278
+ "item": item
279
+ }, e, _self);
280
+ }
281
+
282
+ // Stop propagation so that it doesn't register as a header click event.
283
+ e.preventDefault();
284
+ e.stopPropagation();
285
+ }
286
+
287
+ $.extend(this, {
288
+ "init": init,
289
+ "destroy": destroy,
290
+ "setOptions": setOptions,
291
+
292
+ "onBeforeMenuShow": new Slick.Event(),
293
+ "onCommand": new Slick.Event()
294
+ });
295
+ }
296
+ })(jQuery);