You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
11 KiB
332 lines
11 KiB
/**
|
|
*
|
|
* Draggable Grouping contributed by: Muthukumar Selvarasu
|
|
* muthukumar{dot}se{at}gmail{dot}com
|
|
* github.com/muthukumarse/Slickgrid
|
|
*
|
|
* NOTES:
|
|
* This plugin provides the Draggable Grouping feature
|
|
*/
|
|
|
|
(function ($) {
|
|
// Register namespace
|
|
$.extend(true, window, {
|
|
"Slick": {
|
|
"DraggableGrouping": DraggableGrouping
|
|
}
|
|
});
|
|
|
|
/***
|
|
* A plugin to add Draggable Grouping feature.
|
|
*
|
|
* USAGE:
|
|
*
|
|
* Add the plugin .js & .css files and register it with the grid.
|
|
*
|
|
*
|
|
* The plugin expose the following methods:
|
|
* destroy: used to destroy the plugin
|
|
* setDroppedGroups: provide option to set default grouping on loading
|
|
* clearDroppedGroups: provide option to clear grouping
|
|
* getSetupColumnReorder: its function to setup draggable feature agains Header Column, should be passed on grid option. Also possible to pass custom function
|
|
*
|
|
*
|
|
* The plugin expose the following event(s):
|
|
* onGroupChanged: pass the grouped columns to who subscribed.
|
|
*
|
|
* @param options {Object} Options:
|
|
* deleteIconCssClass: an extra CSS class to add to the delete button (default undefined), if deleteIconCssClass && deleteIconImage undefined then slick-groupby-remove-image class will be added
|
|
* deleteIconImage: a url to the delete button image (default undefined)
|
|
* groupIconCssClass: an extra CSS class to add to the grouping field hint (default undefined)
|
|
* groupIconImage: a url to the grouping field hint image (default undefined)
|
|
* dropPlaceHolderText: option to specify set own placeholder note text
|
|
*
|
|
|
|
*/
|
|
|
|
function DraggableGrouping(options) {
|
|
var _grid;
|
|
var _gridUid;
|
|
var _gridColumns;
|
|
var _dataView;
|
|
var dropbox;
|
|
var dropboxPlaceholder;
|
|
var groupToggler;
|
|
var _self = this;
|
|
var _defaults = {
|
|
};
|
|
var onGroupChanged = new Slick.Event();
|
|
|
|
/**
|
|
* Initialize plugin.
|
|
*/
|
|
function init(grid) {
|
|
options = $.extend(true, {}, _defaults, options);
|
|
_grid = grid;
|
|
_gridUid = _grid.getUID();
|
|
_gridColumns = _grid.getColumns();
|
|
_dataView = _grid.getData();
|
|
|
|
dropbox = $(_grid.getPreHeaderPanel());
|
|
var dropPlaceHolderText = options.dropPlaceHolderText || 'Drop a column header here to group by the column';
|
|
dropbox.html("<div class='slick-placeholder'>" + dropPlaceHolderText + "</div><div class='slick-group-toggle-all expanded' style='display:none'></div>");
|
|
|
|
dropboxPlaceholder = dropbox.find(".slick-placeholder");
|
|
groupToggler = dropbox.find(".slick-group-toggle-all");
|
|
setupColumnDropbox();
|
|
|
|
|
|
_grid.onHeaderCellRendered.subscribe(function (e, args) {
|
|
var column = args.column;
|
|
var node = args.node;
|
|
if (!$.isEmptyObject(column.grouping)) {
|
|
var groupableIcon = $("<span class='slick-column-groupable' />");
|
|
if(options.groupIconCssClass) groupableIcon.addClass(options.groupIconCssClass)
|
|
if(options.groupIconImage) groupableIcon.css("background", "url(" + options.groupIconImage + ") no-repeat center center");
|
|
$(node).css('cursor', 'pointer').append(groupableIcon);
|
|
}
|
|
})
|
|
|
|
for (var i = 0; i < _gridColumns.length; i++) {
|
|
var columnId = _gridColumns[i].field;
|
|
_grid.updateColumnHeader(columnId);
|
|
}
|
|
|
|
}
|
|
|
|
function setupColumnReorder(grid, $headers, headerColumnWidthDiff, setColumns, setupColumnResize, columns, getColumnIndex, uid, trigger) {
|
|
$headers.filter(":ui-sortable").sortable("destroy");
|
|
var $headerDraggableGroupBy = $(grid.getPreHeaderPanel());
|
|
$headers.sortable({
|
|
distance: 3,
|
|
cursor: "default",
|
|
tolerance: "intersection",
|
|
helper: "clone",
|
|
placeholder: "slick-sortable-placeholder ui-state-default slick-header-column",
|
|
forcePlaceholderSize: true,
|
|
appendTo: "body",
|
|
start: function(e, ui) {
|
|
$(ui.helper).addClass("slick-header-column-active");
|
|
$headerDraggableGroupBy.find(".slick-placeholder").show();
|
|
$headerDraggableGroupBy.find(".slick-dropped-grouping").hide();
|
|
},
|
|
beforeStop: function(e, ui) {
|
|
$(ui.helper).removeClass("slick-header-column-active");
|
|
var hasDroppedColumn = $headerDraggableGroupBy.find(".slick-dropped-grouping").length;
|
|
if(hasDroppedColumn > 0){
|
|
$headerDraggableGroupBy.find(".slick-placeholder").hide();
|
|
$headerDraggableGroupBy.find(".slick-dropped-grouping").show();
|
|
}
|
|
},
|
|
stop: function(e) {
|
|
if (!grid.getEditorLock().commitCurrentEdit()) {
|
|
$(this).sortable("cancel");
|
|
return;
|
|
}
|
|
var reorderedIds = $headers.sortable("toArray");
|
|
var reorderedColumns = [];
|
|
for (var i = 0; i < reorderedIds.length; i++) {
|
|
reorderedColumns.push(columns[getColumnIndex(reorderedIds[i].replace(uid, ""))]);
|
|
}
|
|
setColumns(reorderedColumns);
|
|
trigger(grid.onColumnsReordered, {
|
|
grid: grid
|
|
});
|
|
e.stopPropagation();
|
|
setupColumnResize();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Destroy plugin.
|
|
*/
|
|
function destroy() {
|
|
onGroupChanged.unsubscribe();
|
|
}
|
|
|
|
|
|
function setColumns(col) {
|
|
_gridColumns = col;
|
|
}
|
|
|
|
var emptyDropbox;
|
|
|
|
function setupColumnDropbox() {
|
|
dropbox.droppable({
|
|
activeClass: "ui-state-default",
|
|
hoverClass: "ui-state-hover",
|
|
accept: ":not(.ui-sortable-helper)",
|
|
deactivate: function(event, ui) {
|
|
dropbox.removeClass("slick-header-column-denied");
|
|
},
|
|
drop: function(event, ui) {
|
|
handleGroupByDrop(this, ui.draggable);
|
|
},
|
|
over: function(event, ui) {
|
|
var id = (ui.draggable).attr('id').replace(_gridUid, "");
|
|
_gridColumns.forEach(function(e, i, a) {
|
|
if (e.id == id) {
|
|
if (e.grouping == null) {
|
|
dropbox.addClass("slick-header-column-denied");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
dropbox.sortable({
|
|
items: "div.slick-dropped-grouping",
|
|
cursor: "default",
|
|
tolerance: "pointer",
|
|
helper: "clone",
|
|
update: function(event, ui) {
|
|
var sortArray = $(this).sortable('toArray', {
|
|
attribute: 'data-id'
|
|
}),
|
|
newGroupingOrder = [];
|
|
for (var i = 0, l = sortArray.length; i < l; i++) {
|
|
for (var a = 0, b = columnsGroupBy.length; a < b; a++) {
|
|
if (columnsGroupBy[a].id == sortArray[i]) {
|
|
newGroupingOrder.push(columnsGroupBy[a]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
columnsGroupBy = newGroupingOrder;
|
|
updateGroupBy("sort-group");
|
|
}
|
|
});
|
|
emptyDropbox = dropbox.html();
|
|
|
|
groupToggler.on('click', function(e) {
|
|
if (this.classList.contains('collapsed')) {
|
|
this.classList.remove('collapsed');
|
|
this.classList.add('expanded');
|
|
_dataView.expandAllGroups();
|
|
} else {
|
|
this.classList.add('collapsed');
|
|
this.classList.remove('expanded');
|
|
_dataView.collapseAllGroups();
|
|
}
|
|
});
|
|
}
|
|
|
|
var columnsGroupBy = [];
|
|
var groupBySorters = [];
|
|
|
|
function handleGroupByDrop(container, column) {
|
|
var columnid = column.attr('id').replace(_gridUid, "");
|
|
var columnAllowed = true;
|
|
columnsGroupBy.forEach(function(e, i, a) {
|
|
if (e.id == columnid) {
|
|
columnAllowed = false;
|
|
}
|
|
});
|
|
if (columnAllowed) {
|
|
_gridColumns.forEach(function(e, i, a) {
|
|
if (e.id == columnid) {
|
|
if (e.grouping != null && !$.isEmptyObject(e.grouping)) {
|
|
var entry = $("<div id='" + _gridUid + e.id + "_entry' data-id='" + e.id + "' class='slick-dropped-grouping'>");
|
|
var groupText = $("<div style='display: inline-flex'>" + column.text() + "</div>")
|
|
groupText.appendTo(entry);
|
|
var groupRemoveIcon = $("<div class='slick-groupby-remove'> </div>")
|
|
if(options.deleteIconCssClass) groupRemoveIcon.addClass(options.deleteIconCssClass);
|
|
if(options.deleteIconImage) groupRemoveIcon.css("background", "url(" + options.deleteIconImage + ") no-repeat center right");
|
|
if(!options.deleteIconCssClass && !options.deleteIconImage) groupRemoveIcon.addClass('slick-groupby-remove-image');
|
|
groupRemoveIcon.appendTo(entry);
|
|
|
|
$("</div>").appendTo(entry);
|
|
entry.appendTo(container);
|
|
addColumnGroupBy(e, column, container, entry);
|
|
addGroupByRemoveClickHandler(e.id, container, column, entry);
|
|
}
|
|
}
|
|
});
|
|
groupToggler.css('display', 'block');
|
|
}
|
|
}
|
|
|
|
function addColumnGroupBy(column) {
|
|
columnsGroupBy.push(column);
|
|
updateGroupBy("add-group");
|
|
}
|
|
|
|
function addGroupByRemoveClickHandler(id, container, column, entry) {
|
|
var text = entry;
|
|
$("#" + _gridUid + id + "_entry >.slick-groupby-remove").on('click', function() {
|
|
$(this).off('click');
|
|
removeGroupBy(id, column, text);
|
|
});
|
|
}
|
|
|
|
function setDroppedGroups(groupingInfo) {
|
|
groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
|
|
dropboxPlaceholder.hide()
|
|
for (var i = 0; i < groupingInfos.length; i++) {
|
|
var column = $(_grid.getHeaderColumn(groupingInfos[i]));
|
|
handleGroupByDrop(dropbox, column);
|
|
}
|
|
}
|
|
function clearDroppedGroups() {
|
|
columnsGroupBy = [];
|
|
updateGroupBy("clear-all");
|
|
dropbox.find(".slick-dropped-grouping").remove();
|
|
groupToggler.css("display", "none");
|
|
dropboxPlaceholder.show()
|
|
}
|
|
|
|
function removeFromArray(arr) {
|
|
var what, a = arguments,
|
|
L = a.length,
|
|
ax;
|
|
while (L > 1 && arr.length) {
|
|
what = a[--L];
|
|
while ((ax = arr.indexOf(what)) != -1) {
|
|
arr.splice(ax, 1);
|
|
}
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
function removeGroupBy(id, column, entry) {
|
|
entry.remove();
|
|
var groupby = [];
|
|
_gridColumns.forEach(function(e, i, a) {
|
|
groupby[e.id] = e;
|
|
});
|
|
removeFromArray(columnsGroupBy, groupby[id]);
|
|
if(columnsGroupBy.length == 0){
|
|
dropboxPlaceholder.show();
|
|
}
|
|
updateGroupBy("remove-group");
|
|
}
|
|
|
|
function updateGroupBy(originator) {
|
|
if (columnsGroupBy.length == 0) {
|
|
_dataView.setGrouping([]);
|
|
onGroupChanged.notify({ caller: originator, groupColumns: [] });
|
|
return;
|
|
}
|
|
var groupingArray = [];
|
|
columnsGroupBy.forEach(function(element, index, array) {
|
|
groupingArray.push(element.grouping);
|
|
});
|
|
_dataView.setGrouping(groupingArray);
|
|
/*
|
|
collapseAllGroups();
|
|
*/
|
|
onGroupChanged.notify({ caller: originator, groupColumns: groupingArray})
|
|
}
|
|
|
|
// Public API
|
|
$.extend(this, {
|
|
"init": init,
|
|
"destroy": destroy,
|
|
"onGroupChanged": onGroupChanged,
|
|
"setDroppedGroups": setDroppedGroups,
|
|
"clearDroppedGroups": clearDroppedGroups,
|
|
"getSetupColumnReorder": setupColumnReorder,
|
|
});
|
|
}
|
|
})(jQuery);
|