slickgrid
Version:
A lightning fast JavaScript grid/spreadsheet
253 lines (251 loc) • 17.9 kB
JavaScript
"use strict";
(() => {
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
// src/plugins/slick.draggablegrouping.ts
var BindingEventService = Slick.BindingEventService, SlickEvent = Slick.Event, SlickEventHandler = Slick.EventHandler, Utils = Slick.Utils, SlickDraggableGrouping = class {
/**
* @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
*/
constructor(options) {
// --
// public API
__publicField(this, "pluginName", "DraggableGrouping");
__publicField(this, "onGroupChanged", new SlickEvent("onGroupChanged"));
// --
// protected props
__publicField(this, "_grid");
__publicField(this, "_gridUid", "");
__publicField(this, "_gridColumns", []);
__publicField(this, "_dataView");
__publicField(this, "_dropzoneElm");
__publicField(this, "_droppableInstance");
__publicField(this, "_dropzonePlaceholder");
__publicField(this, "_groupToggler");
__publicField(this, "_isInitialized", !1);
__publicField(this, "_options");
__publicField(this, "_defaults", {
dropPlaceHolderText: "Drop a column header here to group by the column",
hideGroupSortIcons: !1,
hideToggleAllButton: !1,
toggleAllButtonText: "",
toggleAllPlaceholderText: "Toggle all Groups"
});
__publicField(this, "_bindingEventService", new BindingEventService());
__publicField(this, "_handler", new SlickEventHandler());
__publicField(this, "_sortableLeftInstance");
__publicField(this, "_sortableRightInstance");
__publicField(this, "_columnsGroupBy", []);
this._options = Utils.extend(!0, {}, this._defaults, options);
}
/**
* Initialize plugin.
*/
init(grid) {
if (this._grid = grid, Utils.addSlickEventPubSubWhenDefined(grid.getPubSubService(), this), this._gridUid = this._grid.getUID(), this._gridColumns = this._grid.getColumns(), this._dataView = this._grid.getData(), this._dropzoneElm = this._grid.getTopHeaderPanel() || this._grid.getPreHeaderPanel(), !this._dropzoneElm)
throw new Error(
"[Slickgrid] Draggable Grouping requires the pre-header to be created and shown for the plugin to work correctly (use `createPreHeaderPanel` and `showPreHeaderPanel`)."
);
this._dropzoneElm.classList.add("slick-dropzone");
let dropPlaceHolderText = this._options.dropPlaceHolderText || "Drop a column header here to group by the column";
this._dropzonePlaceholder = document.createElement("div"), this._dropzonePlaceholder.className = "slick-placeholder", this._dropzonePlaceholder.textContent = dropPlaceHolderText, this._groupToggler = document.createElement("div"), this._groupToggler.className = "slick-group-toggle-all expanded", this._groupToggler.style.display = "none", this._dropzoneElm.appendChild(this._dropzonePlaceholder), this._dropzoneElm.appendChild(this._groupToggler), this.setupColumnDropbox(), this._handler.subscribe(this._grid.onHeaderCellRendered, (_e, args) => {
let column = args.column, node = args.node;
if (!Utils.isEmptyObject(column.grouping) && node && (node.style.cursor = "pointer", this._options.groupIconCssClass || this._options.groupIconImage)) {
let groupableIconElm = document.createElement("span");
groupableIconElm.className = "slick-column-groupable", this._options.groupIconCssClass && groupableIconElm.classList.add(...Utils.classNameToList(this._options.groupIconCssClass)), this._options.groupIconImage && (groupableIconElm.style.background = `url(${this._options.groupIconImage}) no-repeat center center`), node.appendChild(groupableIconElm);
}
});
for (let i = 0; i < this._gridColumns.length; i++) {
let columnId = this._gridColumns[i].field;
this._grid.updateColumnHeader(columnId);
}
}
/**
* Setup the column reordering
* NOTE: this function is a standalone function and is called externally and does not have access to `this` instance
* @param grid - slick grid object
* @param headers - slick grid column header elements
* @param _headerColumnWidthDiff - header column width difference
* @param setColumns - callback to reassign columns
* @param setupColumnResize - callback to setup the column resize
* @param columns - columns array
* @param getColumnIndex - callback to find index of a column
* @param uid - grid UID
* @param trigger - callback to execute when triggering a column grouping
*/
getSetupColumnReorder(grid, headers, _headerColumnWidthDiff, setColumns, setupColumnResize, _columns, getColumnIndex, _uid, trigger) {
this.destroySortableInstances();
let dropzoneElm = grid.getTopHeaderPanel() || grid.getPreHeaderPanel(), groupTogglerElm = dropzoneElm.querySelector(".slick-group-toggle-all"), sortableOptions = {
animation: 50,
// chosenClass: 'slick-header-column-active',
ghostClass: "slick-sortable-placeholder",
draggable: ".slick-header-column",
dataIdAttr: "data-id",
group: {
name: "shared",
pull: "clone",
put: !1
},
revertClone: !0,
// filter: function (_e, target) {
// // block column from being able to be dragged if it's already a grouped column
// // NOTE: need to disable for now since it also blocks the column reordering
// return this.columnsGroupBy.some(c => c.id === target.getAttribute('data-id'));
// },
onStart: (e) => {
e.item.classList.add("slick-header-column-active"), dropzoneElm.classList.add("slick-dropzone-hover"), dropzoneElm.classList.add("slick-dropzone-placeholder-hover");
let draggablePlaceholderElm = dropzoneElm.querySelector(".slick-placeholder");
draggablePlaceholderElm && (draggablePlaceholderElm.style.display = "inline-block"), dropzoneElm.querySelectorAll(".slick-dropped-grouping").forEach((droppedGroupingElm) => droppedGroupingElm.style.display = "none"), groupTogglerElm && (groupTogglerElm.style.display = "none");
},
onEnd: (e) => {
var _a, _b, _c, _d, _e;
e.item.classList.remove("slick-header-column-active");
let draggablePlaceholderElm = dropzoneElm.querySelector(".slick-placeholder");
dropzoneElm.classList.remove("slick-dropzone-hover"), draggablePlaceholderElm == null || draggablePlaceholderElm.classList.remove("slick-dropzone-placeholder-hover"), this._dropzonePlaceholder && (this._dropzonePlaceholder.style.display = "none"), draggablePlaceholderElm && ((_a = draggablePlaceholderElm.parentElement) == null || _a.classList.remove("slick-dropzone-placeholder-hover"));
let droppedGroupingElms = dropzoneElm.querySelectorAll(".slick-dropped-grouping");
if (droppedGroupingElms.length && (droppedGroupingElms.forEach((droppedGroupingElm) => droppedGroupingElm.style.display = "inline-flex"), draggablePlaceholderElm && (draggablePlaceholderElm.style.display = "none"), groupTogglerElm && (groupTogglerElm.style.display = "inline-block")), !grid.getEditorLock().commitCurrentEdit())
return;
let reorderedIds = (_c = (_b = this._sortableLeftInstance) == null ? void 0 : _b.toArray()) != null ? _c : [];
if (headers.length > 1) {
let ids = (_e = (_d = this._sortableRightInstance) == null ? void 0 : _d.toArray()) != null ? _e : [];
for (let id of ids)
reorderedIds.push(id);
}
let finalReorderedColumns = [], reorderedColumns = grid.getColumns();
for (let reorderedId of reorderedIds)
finalReorderedColumns.push(reorderedColumns[getColumnIndex.call(grid, reorderedId)]);
setColumns.call(grid, finalReorderedColumns), trigger.call(grid, grid.onColumnsReordered, { grid, impactedColumns: finalReorderedColumns }), e.stopPropagation(), setupColumnResize.call(grid);
}
};
return this._sortableLeftInstance = Sortable.create(document.querySelector(`.${grid.getUID()} .slick-header-columns.slick-header-columns-left`), sortableOptions), this._sortableRightInstance = Sortable.create(document.querySelector(`.${grid.getUID()} .slick-header-columns.slick-header-columns-right`), sortableOptions), this._options.initialGroupBy && !this._isInitialized && setTimeout(() => this.setDroppedGroups(this._options.initialGroupBy)), this._isInitialized = !0, {
sortableLeftInstance: this._sortableLeftInstance,
sortableRightInstance: this._sortableRightInstance
};
}
/**
* Destroy plugin.
*/
destroy() {
var _a, _b;
this.destroySortableInstances(), (_a = this._droppableInstance) != null && _a.el && ((_b = this._droppableInstance) == null || _b.destroy()), this.onGroupChanged.unsubscribe(), this._handler.unsubscribeAll(), this._bindingEventService.unbindAll(), Utils.emptyElement(document.querySelector(`.${this._gridUid} .slick-preheader-panel,.${this._gridUid} .slick-topheader-panel`));
}
destroySortableInstances() {
var _a, _b, _c, _d;
(_a = this._sortableLeftInstance) != null && _a.el && ((_b = this._sortableLeftInstance) == null || _b.destroy()), (_c = this._sortableRightInstance) != null && _c.el && ((_d = this._sortableRightInstance) == null || _d.destroy());
}
addDragOverDropzoneListeners() {
let draggablePlaceholderElm = this._dropzoneElm.querySelector(".slick-placeholder");
draggablePlaceholderElm && this._dropzoneElm && (this._bindingEventService.bind(draggablePlaceholderElm, "dragover", (e) => e.preventDefault()), this._bindingEventService.bind(draggablePlaceholderElm, "dragenter", () => this._dropzoneElm.classList.add("slick-dropzone-hover")), this._bindingEventService.bind(draggablePlaceholderElm, "dragleave", () => this._dropzoneElm.classList.remove("slick-dropzone-hover")));
}
setupColumnDropbox() {
let dropzoneElm = this._dropzoneElm;
this._droppableInstance = Sortable.create(dropzoneElm, {
group: "shared",
// chosenClass: 'slick-header-column-active',
ghostClass: "slick-droppable-sortitem-hover",
draggable: ".slick-dropped-grouping",
dragoverBubble: !0,
onAdd: (evt) => {
var _a;
let el = evt.item, elId = el.getAttribute("id");
elId != null && elId.replace(this._gridUid, "") && this.handleGroupByDrop(dropzoneElm, Sortable.utils.clone(evt.item)), evt.clone.style.opacity = ".5", (_a = el.parentNode) == null || _a.removeChild(el);
},
onUpdate: () => {
var _a, _b;
let sortArray = (_b = (_a = this._droppableInstance) == null ? void 0 : _a.toArray()) != null ? _b : [], newGroupingOrder = [];
for (let i = 0, l = sortArray.length; i < l; i++)
for (let a = 0, b = this._columnsGroupBy.length; a < b; a++)
if (this._columnsGroupBy[a].id === sortArray[i]) {
newGroupingOrder.push(this._columnsGroupBy[a]);
break;
}
this._columnsGroupBy = newGroupingOrder, this.updateGroupBy("sort-group");
}
}), this.addDragOverDropzoneListeners(), this._groupToggler && this._bindingEventService.bind(this._groupToggler, "click", (event) => {
let target = event.target;
this.toggleGroupToggler(target, target == null ? void 0 : target.classList.contains("expanded"));
});
}
handleGroupByDrop(containerElm, headerColumnElm) {
var _a, _b;
let headerColDataId = headerColumnElm.getAttribute("data-id"), columnId = headerColDataId == null ? void 0 : headerColDataId.replace(this._gridUid, ""), columnAllowed = !0;
for (let colGroupBy of this._columnsGroupBy)
colGroupBy.id === columnId && (columnAllowed = !1);
if (columnAllowed) {
for (let col of this._gridColumns)
if (col.id === columnId && col.grouping && !Utils.isEmptyObject(col.grouping)) {
let columnNameElm = headerColumnElm.querySelector(".slick-column-name"), entryElm = document.createElement("div");
entryElm.id = `${this._gridUid}_${col.id}_entry`, entryElm.className = "slick-dropped-grouping", entryElm.dataset.id = `${col.id}`;
let groupTextElm = document.createElement("div");
groupTextElm.className = "slick-dropped-grouping-title", groupTextElm.style.display = "inline-flex", groupTextElm.textContent = columnNameElm ? columnNameElm.textContent : headerColumnElm.textContent, entryElm.appendChild(groupTextElm);
let groupRemoveIconElm = document.createElement("div");
groupRemoveIconElm.className = "slick-groupby-remove", this._options.deleteIconCssClass && groupRemoveIconElm.classList.add(...Utils.classNameToList(this._options.deleteIconCssClass)), this._options.deleteIconImage && groupRemoveIconElm.classList.add(...Utils.classNameToList(this._options.deleteIconImage)), this._options.deleteIconCssClass || groupRemoveIconElm.classList.add("slick-groupby-remove-icon"), !this._options.deleteIconCssClass && !this._options.deleteIconImage && groupRemoveIconElm.classList.add("slick-groupby-remove-image"), ((_a = this._options) == null ? void 0 : _a.hideGroupSortIcons) !== !0 && col.sortable && ((_b = col.grouping) == null ? void 0 : _b.sortAsc) === void 0 && (col.grouping.sortAsc = !0), entryElm.appendChild(groupRemoveIconElm), entryElm.appendChild(document.createElement("div")), containerElm.appendChild(entryElm), this.addColumnGroupBy(col), this.addGroupByRemoveClickHandler(col.id, groupRemoveIconElm, headerColumnElm, entryElm);
}
this._groupToggler && this._columnsGroupBy.length > 0 && (this._groupToggler.style.display = "inline-block");
}
}
addColumnGroupBy(column) {
this._columnsGroupBy.push(column), this.updateGroupBy("add-group");
}
addGroupByRemoveClickHandler(id, groupRemoveIconElm, headerColumnElm, entry) {
this._bindingEventService.bind(groupRemoveIconElm, "click", () => {
let boundedElms = this._bindingEventService.getBoundedEvents().filter((boundedEvent) => boundedEvent.element === groupRemoveIconElm);
for (let boundedEvent of boundedElms)
this._bindingEventService.unbind(boundedEvent.element, "click", boundedEvent.listener);
this.removeGroupBy(id, headerColumnElm, entry);
});
}
setDroppedGroups(groupingInfo) {
let groupingInfos = Array.isArray(groupingInfo) ? groupingInfo : [groupingInfo];
this._dropzonePlaceholder.style.display = "none";
for (let groupInfo of groupingInfos) {
let columnElm = this._grid.getHeaderColumn(groupInfo);
this.handleGroupByDrop(this._dropzoneElm, columnElm);
}
}
clearDroppedGroups() {
this._columnsGroupBy = [], this.updateGroupBy("clear-all");
let allDroppedGroupingElms = this._dropzoneElm.querySelectorAll(".slick-dropped-grouping");
for (let groupElm of Array.from(allDroppedGroupingElms)) {
let groupRemoveBtnElm = this._dropzoneElm.querySelector(".slick-groupby-remove");
groupRemoveBtnElm == null || groupRemoveBtnElm.remove(), groupElm == null || groupElm.remove();
}
this._dropzonePlaceholder.style.display = "inline-block", this._groupToggler && (this._groupToggler.style.display = "none");
}
removeFromArray(arrayToModify, itemToRemove) {
if (Array.isArray(arrayToModify)) {
let itemIdx = arrayToModify.findIndex((a) => a.id === itemToRemove.id);
itemIdx >= 0 && arrayToModify.splice(itemIdx, 1);
}
return arrayToModify;
}
removeGroupBy(id, _hdrColumnElm, entry) {
entry.remove();
let groupby = [];
this._gridColumns.forEach((col) => groupby[col.id] = col), this.removeFromArray(this._columnsGroupBy, groupby[id]), this._columnsGroupBy.length === 0 && (this._dropzonePlaceholder.style.display = "block", this._groupToggler && (this._groupToggler.style.display = "none")), this.updateGroupBy("remove-group");
}
toggleGroupToggler(targetElm, collapsing = !0, shouldExecuteDataViewCommand = !0) {
targetElm && (collapsing === !0 ? (targetElm.classList.add("collapsed"), targetElm.classList.remove("expanded"), shouldExecuteDataViewCommand && this._dataView.collapseAllGroups()) : (targetElm.classList.remove("collapsed"), targetElm.classList.add("expanded"), shouldExecuteDataViewCommand && this._dataView.expandAllGroups()));
}
updateGroupBy(originator) {
if (this._columnsGroupBy.length === 0) {
this._dataView.setGrouping([]), this.onGroupChanged.notify({ caller: originator, groupColumns: [] });
return;
}
let groupingArray = [];
this._columnsGroupBy.forEach((element) => groupingArray.push(element.grouping)), this._dataView.setGrouping(groupingArray), this.onGroupChanged.notify({ caller: originator, groupColumns: groupingArray });
}
};
window.Slick && Utils.extend(!0, window, {
Slick: {
DraggableGrouping: SlickDraggableGrouping
}
});
})();
//# sourceMappingURL=slick.draggablegrouping.js.map