Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
390 changes: 390 additions & 0 deletions examples/example-plugin-hybridselectionmodel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,390 @@
<!DOCTYPE HTML>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="shortcut icon" type="image/ico" href="favicon.ico" />
<title>SlickGrid example: Cell Menu & Context Menu</title>
<link rel="stylesheet" href="../dist/styles/css/slick.columnpicker.css" type="text/css"/>
<link rel="stylesheet" href="../dist/styles/css/slick.cellmenu.css" type="text/css" />
<link rel="stylesheet" href="../dist/styles/css/slick.contextmenu.css" type="text/css" />
<link rel="stylesheet" href="../dist/styles/css/example-demo.css" type="text/css"/>
<link rel="stylesheet" href="../dist/styles/css/slick-alpine-theme.css" type="text/css"/>
<link rel="stylesheet" href="../dist/styles/css/slick-icons.css" type="text/css"/>
<style>
.bold {
font-weight: bold;
}

.italic {
font-style: italic;
}

.green {
color: #40a840
}

.gray {
color: #c0c0c0;
}

.orange {
color: orange;
}

.pink {
color: pink;
}

.red {
color: red;
}

.pointer {
cursor: pointer;
}

.disabled {
color: #ccc;
}

.cell-menu-dropdown {
border: 1px solid #a3a3a3;
border-radius: 3px;
display: flex;
align-items: center;
height: 90%;
width: max-content;
padding: 0 6px;
cursor: pointer;
}
.cell-menu-dropdown.disabled {
border: 1px solid #c6c6c6;
color: #dddddd;
}
.cell-menu-dropdown:hover:not(.disabled) {
background-color: #9e9e9e;
color: white;
}

/**
* Style the drop-down menu here since the plugin stylesheet mostly contains structural CSS.
*/
.slick-context-menu .title {
font-size: 17px;
}

.slick-context-menu {
border: 1px solid #718BB7;
}
.slick-cell-menu.slick-submenu,
.slick-context-menu.slick-submenu {
background-color: #fbfbfb;
/* border-width: 2px; */
box-shadow: 0 2px 4px 2px rgba(146, 152, 163, 0.4);
min-width: 150px;
}
</style>
</head>

<body>
<h2 class="title">Example - Context Menu Plugin</h2>
<table width="100%">
<tr>
<td valign="top" width="50%" style="padding-left: 0px">
<div id="myGrid" class="slick-container" style="width:650px;height:700px;"></div>
</td>
<td valign="top" style="display: block">
<h2>
Demonstrates:
<span style="margin-left: 15px; font-size: 12px">Slick.Plugins.HybridSelectionModel / Slick.Plugins.CellMenu</span>
</h2>
<ul>
<li><strong>Slick.Plugins.HybridSelectionModel</strong></li>
<li>This selectionmodel is a combination of the row and column selectionmodels.</li>
<li>for a given row, the selectionmodel that applies is selected by the following in priority order:</li>
<li> 1) if options.rowSelectOverride is defined, call rowSelectOverride(rowData, plugin, grid), return value is true to use rowSelectionModel</li>
<li> 2) if the RowMovweManager plugin is used, and rowMoveManager.isHandlerColumn is true, select RowSelectionModel</li>
<li> 3) if the column name is in options.rowSelectColumnIdArr[] then apply rowSelectionModel</li>
<p></p>
<li><strong>Slick.Plugins.ContextMenu - Context Menu (global from any columns right+click)</strong></li>
<li>This plugin subscribes internally to the "onContextMenu" event</li>
<li>Mouse Right-Click the row to open a Context Menu (global any columns)</li>
<li>The context menu showing on left columns will show only commands (from Title to EffortDriven)</li>
<li>
The context menu showing on Priority column will show list of options that will be applied to the Priority
cell
</li>
</ul>
<h2>View Source:</h2>
<ul>
<li><A href="https://github.com/6pac/SlickGrid/blob/master/examples/example-plugin-hybridselectionmodel.html"
target="_sourcewindow"> View the source for this example on Github</a></li>
</ul>
</td>
</tr>
</table>

<script src="https://cdn.jsdelivr.net/npm/sortablejs/Sortable.min.js"></script>
<script src="sortable-cdn-fallback.js"></script>

<script src="../dist/browser/slick.core.js"></script>
<script src="../dist/browser/slick.interactions.js"></script>
<script src="../dist/browser/slick.grid.js"></script>
<script src="../dist/browser/slick.formatters.js"></script>
<script src="../dist/browser/slick.dataview.js"></script>
<script src="../dist/browser/slick.editors.js"></script>
<script src="../dist/browser/controls/slick.columnpicker.js"></script>
<script src="../dist/browser/plugins/slick.cellmenu.js"></script>
<script src="../dist/browser/plugins/slick.contextmenu.js"></script>
<script src="../dist/browser/plugins/slick.cellrangedecorator.js"></script>
<script src="../dist/browser/plugins/slick.cellrangeselector.js"></script>
<script src="../dist/browser/plugins/slick.cellselectionmodel.js"></script>
<script src="../dist/browser/plugins/slick.hybridselectionmodel.js"></script>

<script>
var contextMenuOptions = {
// subItemChevronClass: 'sgi sgi-chevron-right',

// optionally and conditionally define when the the menu is usable,
// this should be used with a custom formatter to show/hide/disable the menu
menuUsabilityOverride: function (args) {
return (args.dataContext.id < 21); // say we want to display the menu only from Task 0 to 20
},
commandTitle: "Commands",
// which column to show the command list? when not defined it will be shown over all columns
commandShownOverColumnIds: ["title", "complete", "start", "finish", "effortDriven" /*, "priority"*/],
commandItems: [
{ command: "copy-text", title: "Copy Cell Value" },
{ command: "delete-row", title: "Delete Row", iconCssClass: "sgi sgi-close red", cssClass: "bold", textCssClass: "red", },
{ divider: true },
{
command: "help", title: "Help", iconCssClass: "sgi sgi-help-circle-outline",
// you can use the "action" callback and/or subscribe to the "onCallback" event, they both have the same arguments
action: function (e, args) {
// action callback.. do something
},
// only show command to "Help" when there's no Effort Driven
itemVisibilityOverride: function (args) {
return (!args.dataContext.effortDriven);
}
}
],

// Options allows you to edit a column from an option chose a list
// for example, changing the Priority value
// you can also optionally define an array of column ids that you wish to display this option list (when not defined it will show over all columns)
optionTitle: "Change Priority",
optionShownOverColumnIds: ["id"], // optional, when defined it will only show over the columns (column id) defined in the array
optionItems: [
{
option: 0, title: "none", textCssClass: "italic",
// only enable this option when there's no Effort Driven
itemUsabilityOverride: function (args) {
return (!args.dataContext.effortDriven);
},
// you can use the "action" callback and/or subscribe to the "onCallback" event, they both have the same arguments
action: function (e, args) {
// action callback.. do something
},
},
{ option: 1, iconCssClass: "sgi sgi-star-outline", title: "Low" },
{ option: 2, iconCssClass: "sgi sgi-star orange", title: "Medium" },
{ option: 3, iconCssClass: "sgi sgi-star red", title: "High" },
// you can pass divider as a string or an object with a boolean
// "divider",
{ divider: true },
{
option: 4, title: "Extreme", disabled: true,
// only shown when there's no Effort Driven
itemVisibilityOverride: function (args) {
return (!args.dataContext.effortDriven);
}
}
]
};

var grid;
var data = [];
var dataView;
var cellMenuPlugin;
var contextMenuPlugin;

function priorityFormatter(row, cell, value, columnDef, dataContext) {
if (!value) {
return "";
}
var count = +(value >= 3 ? 3 : value);
return count === 3 ? "High" : (count === 2 ? "Medium" : "Low");
}

function formattedRandomNum(maxVal) {
var numDigits = ("" + maxVal).length;
return ("0000" + (Math.floor(Math.random() * maxVal) + 1)).slice(-numDigits)
}

// Copy text to clipboard, on IE it's easy to copy a text, we can just call the clipboard
// but on other browsers this is insecure and we need to use the following trick to copy a cell,
// by creating a temp div and change the text value, we can then call the execCommand to copy which only works with dom element
function copyCellValue(textToCopy) {
try {
if (window.clipboardData) {
window.clipboardData.setData("Text", textToCopy);
} else {
var range = document.createRange();
var tmpElem = document.createElement('div');
tmpElem.style.position = 'absolute';
tmpElem.style.left = '-1000px';
tmpElem.style.top = '-1000px';
tmpElem.textContent = textToCopy;
document.body.appendChild(tmpElem);
range.selectNodeContents(tmpElem.get(0));
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
var success = document.execCommand("copy", false, null);
if (success) {
tmpElem.remove();
}
}
} catch (e) { }
}

function loadData(count) {
data = [];
for (var i = 0; i < 500; i++) {
data[i] = {
id: i,
title: "Task " + i,
duration: Math.floor(Math.random() * 25) + " days",
percentComplete: Math.floor(Math.random() * 100),
start: "" + formattedRandomNum(28) + "/03/2009",
finish: "" + formattedRandomNum(28) + "/05/2011",
priority: i % 3 ? 2 : (i % 5 ? 3 : 1),
effortDriven: (i % 4 === 0)
};
}
return data;
}

function executeCommand(e, args) {
var columnDef = args.column;
var command = args.command;
var dataContext = args.dataContext;

switch (command) {
case "command1":
case "command2":
alert(args.item.title);
break;
case "export-csv":
case "export-txt":
case "export-xls":
alert("Exporting as " + args.item.title);
break;
case "copy-text":
copyCellValue(args.value);
break;
case "help":
alert('Please help!');
break;
case "delete-row":
if (confirm("Do you really want to delete row " + (args.row + 1) + " with " + dataContext.title + "?")) {
dataView.deleteItem(dataContext.id);
}
break;
default:
alert("Command: " + args.command);
break;
}
}

var columns = [
{ id: "id", name: "#", field: "id", width: 32 },
{ id: "title", name: "Title", field: "title", width: 90, cssClass: "cell-title", editor: Slick.Editors.Text },
{ id: "complete", name: "% Complete", field: "percentComplete", sortable: true, width: 90 },
{ id: "start", name: "Start", field: "start", sortable: true },
{ id: "finish", name: "Finish", field: "finish", sortable: true },
{ id: "priority", name: "Priority", field: "priority", width: 80, resizable: false, formatter: priorityFormatter },
{ id: "effortDriven", name: "Effort Driven", field: "effortDriven", width: 95, formatter: Slick.Formatters.Checkmark }
];

var gridOptions = {
editable: true,
enableAddRow: false,
enableCellNavigation: true,
enableTextSelectionOnCells: true,
asyncEditorLoading: false,
autoEdit: true,
rowHeight: 30
};

document.addEventListener("DOMContentLoaded", function() {
dataView = new Slick.Data.DataView();
grid = new Slick.Grid("#myGrid", dataView, columns, gridOptions);
grid.setSelectionModel(new Slick.HybridSelectionModel({ selectActiveRow: true, rowSelectColumnIdArr: ['id'] }));
contextMenuPlugin = new Slick.Plugins.ContextMenu(contextMenuOptions);
var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, gridOptions);

grid.registerPlugin(contextMenuPlugin);

dataView.onRowCountChanged.subscribe(function (e, args) {
grid.updateRowCount();
grid.render();
});

dataView.onRowsChanged.subscribe(function (e, args) {
grid.invalidateRows(args.rows);
grid.render();
});

grid.init();
data = loadData(1000);
dataView.beginUpdate();
dataView.setItems(data);
dataView.endUpdate();

//
// -- subscribe to some Context Menu (from any columns) events
// --------------------------------------------------------------

// subscribe to Context Menu
contextMenuPlugin.onBeforeMenuShow.subscribe(function (e, args) {
// for example, you could select the row it was clicked with
// grid.setSelectedRows([args.row]); // select the entire row
grid.setActiveCell(args.row, args.cell, false); // select the cell that the click originated
console.log("Before the global Context Menu is shown", args);
});
contextMenuPlugin.onBeforeMenuClose.subscribe(function (e, args) {
console.log("Global Context Menu is closing", args);
});

contextMenuPlugin.onAfterMenuShow.subscribe(function (e, args) {
// for example, you could select the row it was clicked with
// grid.setSelectedRows([args.row]); // select the entire row
grid.setActiveCell(args.row, args.cell, false); // select the cell that the click originated
console.log("After the Context Menu is shown", args);
});

// subscribe to Context Menu onCommand event (or use the action callback on each command)
contextMenuPlugin.onCommand.subscribe(function (e, args) {
// e.preventDefault(); // you could do if you wish to keep the menu open
executeCommand(e, args);
});

// subscribe to Context Menu onOptionSelected event (or use the action callback on each option)
contextMenuPlugin.onOptionSelected.subscribe(function (e, args) {
// e.preventDefault(); // you could do if you wish to keep the menu open
var dataContext = args && args.dataContext;

// change Priority
if (dataContext && dataContext.hasOwnProperty("priority")) {
dataContext.priority = args.item.option;
grid.updateRow(args.row);
}
});
});
</script>
</body>

</html>
Loading