如何在 handsontable 的上下文菜单中添加具有默认项目的自定义项目

How to add custom items with default items in Context Menu of handsontable

我尝试使用 handsontable 并想将自定义项目添加到上下文菜单。

有很多实现自定义菜单的教程,但是忽略了默认项。

所以我添加了所有项目的密钥,但其中一些不起作用。

我的设置如下。

var basicSettings = {
    minRows: 1,
    minCols: 1,
    rowHeaders: false,
    colHeaders: false,
    hiddenColumns: true,
    contextMenu: {
        items: {
            row_above: {},
            row_below: {},
            "hsep1": "---------",
            col_left: {},
            col_right: {},
            "hsep2": "---------",
            remove_row: {},
            remove_col: {},
            "hsep3": "---------",
            undo: {},
            redo: {},
            "hsep4": "---------",
            make_read_only: {},
            "hsep5": "---------",
            alignment: {},
            "hsep6": "---------",
            copy: {},
            cut: {},
            "paste": {
                name: 'Paste',
                callback: function (key, option) {
                    this.copyPaste.triggerPaste();
                }
            },
            "hsep7": "---------",
            mergeCells: {
                name: "Merge"
            },
            "hsep8": "---------",
            // Custom menu item to set color of cells
            set_color: {
                key: "color",
                name: "Color",
                "submenu": {
                    "items": [
                        {
                            key: "color:1",
                            "name": "Black",
                            callback: function(key, options) {
                                for (var i = options[0].start.row; i <= options[0].end.row; i ++){
                                    for (var j = options[0].start.col; j <= options[0].end.col; j ++){
                                        this.getCell(i, j).className = "color-black";
                                    }
                                }
                            }
                        }, {
                            key: "color:2",
                            "name": "White",
                            callback: function(key, options) {
                                for (var i = options[0].start.row; i <= options[0].end.row; i ++){
                                    for (var j = options[0].start.col; j <= options[0].end.col; j ++){
                                        $(this.getCell(i, j)).removeClass("color-*").addClass("color-white");
                                    }
                                }
                                this.render();
                            }
                        }, {
                            key: "color:3",
                            "name": "Red",
                            callback: function(key, options) {
                                for (var i = options[0].start.row; i <= options[0].end.row; i ++){
                                    for (var j = options[0].start.col; j <= options[0].end.col; j ++){
                                        this.getCell(i, j).style.backgroundColor = "red";
                                    }
                                }
                                this.render();
                            }
                        }
                    ]
                }
            }
        }
    },
    manualRowResize: true,
    manualColumnResize: true,
    contextMenuCopyPaste: {
        swfPath: '/bower_components/zeroclipboard/dist/ZeroClipboard.swf'
    },
    copyPaste: true,
    mergeCells: true,
    search: true,
    stretchH: 'all',
    autoColumnSize: {useHeaders: true},
    autoRowSize: {syncLimit: 300},
    width: 1000,
    height: window.innerHeight - 100,
    licenseKey: "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
};

菜单看起来像这样。

问题 1:

有什么方法可以在所有默认菜单项中添加自定义项吗?如果是这样,我不需要问题 3 和问题 4 的答案。

问题 2:

让我问这个问题的最重要的部分是自定义菜单,即"set_color"。 点击"Black"或"Red"后变成那个颜色,但我改变一个单元格的值后,它又变回来了。 如何防止单元格变回背景颜色?

问题 3:

除了启用所有功能外,我还想要额外的自定义项目。但是我找不到 "Merge" 项目的正确密钥。当前的 "Merge" 函数工作起来很奇怪。 如何让功能正常运行?

问题 4:

我尝试 https://github.com/handsontable/handsontable/issues/2853 实现粘贴功能,但我看到了这个错误。

Uncaught TypeError: Cannot read property 'triggerPaste' of undefined

请帮助我了解那些可上手的用法。提前致谢。

对于问题 1:

Is there any way to add custom item with all the default menu items? If so, I don't need answers to Question 3 and Question 4.

  • 初始化 Handsontable 并将 contextMenu 设置为 true。示例:

      let
        example3 = document.getElementById('example3'),
        settings3,
        hot3;
    
      settings3 = {
        data: [...],
        rowHeaders: true,
        colHeaders: true,
        contextMenu: true // set to `true`..
      };
      hot3 = new Handsontable(example3, settings3);
    

  • 然后像这样更新 contextMenu 设置:

      let cm = hot3.getPlugin('ContextMenu');
      hot3.updateSettings({
        contextMenu: {
            // Clone the pre-defined items and add your custom items.
          items: Object.assign({}, cm.itemsFactory.predefinedItems, {
            'hsep1': '---------',
            'set_color': {
                key: 'color',
                name: 'Color',
              submenu: {
                items: [{
                  key: 'color:red',
                  name: 'Red',
                  callback: setCellColor
                }, {
                  key: 'color:blue',
                  name: 'Blue',
                  callback: setCellColor
                }]
              }
            }
          })
        }
      });
    

  • 对于问题 2:

    The most important part that let me ask this question is custom menu, that is "set_color". After clicking "Black" or "Red", it turns into that color, but after I change value of a cell, it turns back. How can I prevent the cells from turning their background color back?

    我不确定如何防止;然而,这里有一种方法可以恢复适当单元格的颜色(或任何其他custom/meta数据..)。

      // This is my callback for the 'set_color' context menu items.
      // Sample `key`: 'color:red'
      function setCellColor(key, opt) {
        let color = key.substring(6);
        for (let i = opt[0].start.row; i <= opt[0].end.row; i++) {
          for (let j = opt[0].start.col; j <= opt[0].end.col; j++) {
            this.getCell(i, j).style.color = color;
            this.setCellMeta(i, j, 'color', color); // Save the color
          }
        }
      }
    
      // Listen to the `beforeRenderer` event, and restore the cell's color
      // before the "renderer" starting rendering the cell
      Handsontable.hooks.add('beforeRenderer', function(td, r, c, p, pv, cp){
        if (cp.color) {
            td.style.color = cp.color;
        }
      }, hot3);
    

    演示

    在此处尝试完整示例:http://jsfiddle.net/y9j3m29c/1/, which is based on https://docs.handsontable.com/3.0.0/demo-context-menu.html#page-custom

    对于粘贴功能:

  • 加载SheetClip():

    <script src="https://unpkg.com/sheetclip"></script>
    

  • 添加必要的变量:

    let clipboardCache = '';
    const sheetclip = new SheetClip();
    

  • 添加必要的回调:

      settings3 = {
        ...
        afterCopy: function(changes){
            clipboardCache = sheetclip.stringify(changes);
        },
        afterCut: function(changes){
            clipboardCache = sheetclip.stringify(changes);
        },
        afterPaste: function(changes){
            clipboardCache = sheetclip.stringify(changes);
        }
      };
    

  • 添加上下文菜单项:

      let cm = hot3.getPlugin('ContextMenu');
      hot3.updateSettings({
        contextMenu: {
            // Clone the pre-defined items and add your custom items.
          items: Object.assign({}, cm.itemsFactory.predefinedItems, {
            ...
            'paste': {
                name: 'Paste',
              disabled: function(){
                return clipboardCache.length === 0;
              },
              callback: function(){
                var plugin = this.getPlugin('copyPaste');
    
                this.listen();
                plugin.paste(clipboardCache);
              }
            }
          })
        }
      });
    

  • 有关具有 "Clear clipboard" 功能的 https://docs.handsontable.com/3.0.0/demo-copy-paste.html#paste-in-context-menu and demo on http://jsfiddle.net/y9j3m29c/2/ — or http://jsfiddle.net/y9j3m29c/4/ 的更多详细信息。