Contextmenu

There are two possible ways to customize the context menu. Defining a custom handler using the initial menu property or via a custom plugin. The handler will intercept, change the default items or cancel the user action. This method receives the default items, the section, and some other extra information about the click, such as coordinates.

If you are interested in know more about plugins, click here.

Documentation

The event handler

EventDescription
contextmenu contextmenu(worksheet: Object, col: Number, row: Number, event: Object, items: Array, section: Array, a1: Mixed, a2: Mixed) => Array
@param {object} worksheet - Instance of the active worksheet
@param {number=} col - column number
@param {number=} row - row number
@param {object} event - mouse event handler
@param {array} items - default contextmenu items
@param {string} section - section clicked. Sections: nested | header | row | cell | selectall | tabs | cloning | toolbar | footer
@param {mixed} a1 - this is a first mixed argument that depends on the section
@param {mixed} a2 - this is a second mixed argument that depends on the section


Item properties

As previously stated, the contextmenu custom handler should return an array of items. Each item is an Object and the following properties can be used
Property Description
type: string Context menu item type: line | divisor | default
icon: string Context menu icon key. (Material icon key icon identification)
id: string HTML id property of the item DOM element
disabled: boolean The item is disabled
onclick: function Specific onclick event for the element.
shortcut: string A short description or instruction for the item. Normally a shortcut.
tooltip: string Show this text when the user mouse over the element
submenu: Array of items Submenu items

Jspreadsheet uses jSuites contextmenu plugin. For more details and example, please visit: https://jsuites.net/v4/contextmenu.



Examples

Customize the contextmenu with a few basic options depending on the section clicked.



Source code

<html>
<script src="https://jspreadsheet.com/v8/jspreadsheet.js"></script>
<script src="https://jsuites.net/v4/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v8/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v4/jsuites.css" type="text/css" />

<div id="spreadsheet"></div>

<script>
var data = [
    ['US', 'Cheese', '2019-02-12'],
    ['CA', 'Apples', '2019-03-01'],
    ['CA', 'Carrots', '2018-11-10'],
    ['BR', 'Oranges', '2019-01-12'],
];

jspreadsheet(document.getElementById('spreadsheet'), {
    data: data,
    columns: [
        { type: 'dropdown', url:'/jspreadsheet/countries', width:200, },
        { type: 'text', width:200, },
        { type: 'calendar', width:100, }
     ],
     allowComments: true,
     contextMenu: function(o, x, y, e, items, section) {
         // Reset all items
         var items = [];

         // If the click was in the headers
         if (section == 'header') {
            // Items to the header only
            items.push({
                title: jSuites.translate('Execute one action'),
                onclick: function() {
                    alert('test')
                }
            });

            // Add a line
            items.push({ type: 'line' });
         }

         // Save
         items.push({
             title: jSuites.translate('Save as'),
             shortcut: 'Ctrl + S',
             icon: 'save',
             onclick: function () {
                 o.download();
             }
         });

         // About
         items.push({
             title: jSuites.translate('About'),
             onclick: function() {
                 alert('https://jspreadsheet.com');
             }
         });

         return items;
     }
});
</script>
</html>


Default contextmenu method

If you wish to customize the original method, you can use this code as reference.
/**
 * Translation helper
 */
function T(t) {
    return jSuites.translate(t);
}

/**
 * Default context menu items
 * @param {object} obj - worksheet
 * @param {number} x
 * @param {number} y
 * @param {object} event
 * @param {string} section
 * @param {object|number} argument1
 * @param {number} argument2
 * @return {array} Return the items to create the contextmenu
 */
function(obj, x, y, e, section, a1, a2) {
    var items = [];
    var o = obj.parent.config;

    // Click in the tabs
    if (section == 'tabs') {
        if (o.allowRenameWorksheet == true) {
            items.push({
                title: T('Rename this worksheet'),
                onclick: function() {
                    var newName = prompt(T('Rename this worksheet'), e.target.innerText);
                    if (newName) {
                        obj.parent.renameWorksheet(a1, newName);
                    }
                }
            });
        }

        if (o.allowDeleteWorksheet == true) {
            items.push({
                title: T('Delete this worksheet'),
                onclick: function() {
                    if (confirm(T('Are you sure?'), e.target.innerText)) {
                        obj.parent.deleteWorksheet(a1);
                    }
                }
            });
        }

        items.push({ type:'line' });
    }

    // Nested header only
    if (section == 'nested') {
        // Rename nested headers
        items.push({
            title: T('Rename this cell'),
            onclick: function() {
                // Get the new title
                var text = prompt(T('Rename this cell'), e.target.innerText);
                // Update the nested cell title
                obj.setNestedCell(a1, a2, { title: text });
            }
        });

        items.push({ type:'line' });
    }

    // Sections that affect the selection
    if (section == 'header' || section == 'row' || section == 'cell' || section == 'nested') {
        // Cut
        items.push({
            title: T('Cut'),
            icon: 'content_cut',
            shortcut: 'Ctrl + X',
            onclick: function() {
                obj.cut();
            }
        });

        // Copy
        items.push({
            title: T('Copy'),
            icon: 'content_copy',
            shortcut: 'Ctrl + C',
            onclick: function() {
                obj.copy();
            }
        });

        // Paste
        if (navigator && navigator.clipboard && navigator.clipboard.readText) {
            items.push({
                title: T('Paste'),
                icon: 'content_paste',
                shortcut: 'Ctrl + V',
                onclick: function() {
                    if (obj.selectedCell) {
                        navigator.clipboard.readText().then(function(text) {
                            if (text) {
                                obj.paste(obj.selectedCell[0], obj.selectedCell[1], text);
                            }
                        });
                    }
                }
            });
        }

        items.push({ type:'line' });
    }

    // Clicking in the headers
    if (section == 'header') {
        // Insert a new column
        if (obj.options.allowInsertColumn == true) {
            items.push({
                title: T('Insert a new column before'),
                onclick: function() {
                    obj.insertColumn(1, parseInt(x), 1);
                }
            });
        }

        if (obj.options.allowInsertColumn == true) {
            items.push({
                title: T('Insert a new column after'),
                onclick: function() {
                    obj.insertColumn(1, parseInt(x), 0);
                }
            });
        }

        // Delete a column
        if (obj.options.allowDeleteColumn == true) {
            items.push({
                title: T('Delete selected columns'),
                onclick: function() {
                    obj.deleteColumn(obj.getSelectedColumns().length ? undefined : parseInt(x));
                }
            });
        }

        // Rename column
        if (obj.options.allowRenameColumn == true) {
            items.push({
                title: T('Rename this column'),
                onclick: function() {
                    obj.setHeader(x);
                }
            });
        }

        // Sorting
        if (obj.options.columnSorting == true) {
            // Line
            items.push({ type:'line' });

            items.push({
                title: T('Order ascending'),
                onclick: function() {
                    obj.orderBy(x, 0);
                }
            });
            items.push({
                title: T('Order descending'),
                onclick: function() {
                    obj.orderBy(x, 1);
                }
            });

            items.push({ type:'line' });
        }
    }

    // Row only
    if (section == 'cell' || section == 'row') {
        // Insert new row
        if (obj.options.allowInsertRow == true) {
            items.push({
                title: T('Insert a new row before'),
                onclick: function() {
                    obj.insertRow(1, parseInt(y), 1);
                }
            });

            items.push({
                title: T('Insert a new row after'),
                onclick: function() {
                    obj.insertRow(1, parseInt(y));
                }
            });
        }

        if (obj.options.allowDeleteRow == true) {
            items.push({
                title: T('Delete selected rows'),
                onclick: function() {
                    obj.deleteRow(obj.getSelectedRows().length ? undefined : parseInt(y));
                }
            });
        }

        items.push({ type:'line' });
    }

    // Click in the cell
    if (section == 'cell') {
        if (obj.options.allowComments == true) {
            var title = obj.records[a2][a1].element.getAttribute('title') || '';

            items.push({
                title: title ? T('Edit comments') : T('Add comments'),
                icon: 'notes',
                onclick: function() {
                    var cell = Helpers.getColumnNameFromCoords(a1, a2);
                    var comment = prompt(T('Comments'), title);
                    if (comment) {
                        obj.setComments(cell, comment);
                    }
                }
            });

            if (title) {
                items.push({
                    title: T('Clear comments'),
                    onclick: function() {
                        var cell = Helpers.getColumnNameFromCoords(a1, a2);
                        obj.setComments(cell, '');
                    }
                });
            }
        }

        // Line
        items.push({ type:'line' });
    }

    // Save
    if (o.allowExport) {
        items.push({
            title: T('Save as'),
            icon: 'save',
            shortcut: 'Ctrl + S',
            onclick: function () {
                obj.download();
            }
        });
    }

    // About
    if (o.about) {
        items.push({
            title: T('About'),
            icon: 'info',
            onclick: function() {
                if (o.about === true) {
                    alert(Version().print());
                } else {
                    alert(o.about);
                }
            }
        });
    }

    return items;
}