Handsontable readOnly セルの設定とコンテキストメニュー

column 定義で、readOnly 属性を true にすれば、読込専用になるのだが、
動的に設定する方法で、コンテキストメニューに、make_read_only が用意されている。
Context menu - Guide - Handsontable Documentation
f:id:posturan:20210901091501j:plain
解除する時は、
f:id:posturan:20210901091528j:plain
このコンテキストメニュー表示を日本語にするだけなら、
セルのメタ情報、readOnly の真偽値をチェックするだけで良いのだが、、

var hot = new Handsontable(document.getElementById("table"), {
    data: Handsontable.helper.createSpreadsheetData(5, 5),
    rowHeaders: true,
    colHeaders: true,
    maxCols: 5,
    contextMenu: { items:{
            "make_read_only": {
                name: function(){
                    var range = this.getSelectedRange();
                    var flg = false;
                    for(var row=range[0].from.row;row <= range[0].to.row;row++){
                        for(var col=range[0].from.col;col <= range[0].to.col;col++){
                            flg = flg | hot.getCellMeta(row, col).readOnly;
                        }
                    }
                    return flg ? '読込専用解除' : '読込専用にする';
                },
            },
        },
    },
    licenseKey: 'non-commercial-and-evaluation'
});

読込専用、解除の設定と同時に何らかの処理を差し込みたい場合、
callback を記述するしかない。
callback で実行する setCellMeta() も注意が必要で、
機械的 getCellMeta() で取得するセルのメタ情報、
readOnly の真偽値の逆を実行するだけでは
選択エリアの readOnly 状態が混ざっている場合が、
単純に反転するだけである。

従って以下のようにする。

var readonlyFlg = false;
var hot = new Handsontable(document.getElementById("table"), {
    data: Handsontable.helper.createSpreadsheetData(5, 5),
    rowHeaders: true,
    colHeaders: true,
    maxCols: 5,
    contextMenu: { items:{
            "make_read_only": {
                name: function(){
                    var range = this.getSelectedRange();
                    for(var row=range[0].from.row;row <= range[0].to.row;row++){
                        for(var col=range[0].from.col;col <= range[0].to.col;col++){
                            readonlyFlg = readonlyFlg | hot.getCellMeta(row, col).readOnly;
                        }
                    }
                    return readonlyFlg ? '読込専用解除' : '読込専用にする';
                },
                callback: function(key, selection, clickEvent){
                    for(var row=selection[0].start.row; row <= selection[0].end.row; row++){
                        for(var col=selection[0].start.col; col <= selection[0].end.col; col++){
                            hot.setCellMeta(row, col, 'readOnly', !readonlyFlg);
                            // TODO readonlyFlg による他の処理を行う
                        }
                    }
                    readonlyFlg = !readonlyFlg;
                    hot.render();
                }
            },
        },
    },
    licenseKey: 'non-commercial-and-evaluation'
});

f:id:posturan:20210901094353j:plain
読込専用にした範囲を含んで、混ざっている範囲を選択した時、コンテキストメニューは、、
f:id:posturan:20210901094500j:plain