placeholder の色を変更

input タグの placeholder の文字色が濃く、うすい色にするのは、
CSS でどのように指定するんだっけ?とよく忘れてしまうので、
書き留めておきます。
placeholder 疑似クラスを使うのです。

input::-webkit-input-placeholder{
   color: #cccccc;
}
input:-ms-input-placeholder{
   color: #cccccc;
}
input::placeholder{
   color: #cccccc;
}

でも、BootStrap を使うとこれでは効きません!
解決策は、以下のように placeholder 疑似クラスを指定します。

.form-control::placeholder{
    color: #cccccc;
}

Handsontable Renderer で readOnly を指定する方法、

特定の列全てを readOnly にする場合は、columns 定義で、readOnly = true を指定、
動的に任意のセルに対して readOnly = true を指定したければ、
先日のように、セルのメタ情報のreadOnly を true にして、render() 実行すれば良いが、
Handsontable readOnly セルの設定とコンテキストメニュー - Oboe吹きプログラマの黙示録

Renderer で、データの値によって readOnly を指定する場合は、以下のようにする。

var hot = new Handsontable(document.getElementById("table"), {
    data: Handsontable.helper.createSpreadsheetData(10, 3),
    rowHeaders: true,
    colHeaders: true,
    maxCols: 3,
    columns: [
        { type:'text' },
        { type:'text' },
        { type:'text',
            renderer: function(hotInstance, td, row, column, prop, value, cellProperties) {
                var v = hotInstance.getDataAtCell(row, 0);
                // 1列目の値が、"A2" or "A4" ならば、readOnly
                if (v=='A2' || v=='A4'){
                    cellProperties.readOnly = true;
                }
                Handsontable.renderers.TextRenderer.apply(this, arguments);
            },
        },

    ],
    licenseKey: 'non-commercial-and-evaluation'
});

上記の指定で興味深いのは、、
readOnly = true にする条件にあてはまらない行の1列目を、
条件に一致するように編集して変更した時、(6行目、1列目 'A6' → 'A2' に変更)
即座に上記 renderer が動いて readOnly になることである。

なお、renderer は、以下の表のとおり、type と renderer が対応していることに留意したい。

type renderer
autocomplete Handsontable.renderers.AutocompleteRenderer
base Handsontable.renderers.BaseRenderer
checkbox Handsontable.renderers.CheckboxRenderer
date Handsontable.renderers.DateRenderer
dropdown Handsontable.renderers.DropdownRenderer
html Handsontable.renderers.HtmlRenderer
numeric Handsontable.renderers.NumericRenderer
password Handsontable.renderers.PasswordRenderer
text Handsontable.renderers.TextRenderer
time Handsontable.renderers.TimeRenderer

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

Handsontable contextmenu disabled

Handsontable の右クリックコンテキストメニューcallback は、選択領域をメソッドの
引数で認識できますが、
 disabled - メニュー表示するが非活性にするなら true
この時、メソッド引数で選択領域を知ることができません。
代用になりますが、最後に選択した領域の取得、
インスタンスメソッドの getSelectedRangeLast() から、
行番号、列番号が取得できます。

偶数行だけ実行可能なコンテキストメニューの例

contextMenu: { 
    items: {
         "run" : {
                 name : '実行',
                 disabled: function(){
                       return !(hot.getSelectedRangeLast().from.row % 2);
                 },
                 callback: function(key, selection, clickEvent){
                           // TODO
                 },
          },
    }
},

Bootstrap Modal のデータ受け渡し

show 実行の引数、JSON で渡す。

例)

<div class="modal fade" id="exampleModal" tabindex="-1"
    role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
   <div class="modal-dialog modal-dialog-centered" role="document">
      <div class="modal-content">
   :
省略
$('#exampleModal').modal('show', { 'dvalue': 'i001' });

shown.bs.modal イベントを捕捉して受け取る。
イベントの relatedTarget が受け取るJSONルートである。

$('#exampleModal').on('shown.bs.modal', function(ev){
    var dvalue = ev.relatedTarget.dvalue;
    
});

bootstrap モーダル表示を中央にする時は、、modal-dialog-centered

Handsontable グリッドに表示させないデータを使う

Handsontable インスタンスの getDataAtRow( row ) は、表示しているグリッドデータの表示範囲しか取得しない。
つまり、4列存在するデータでも、maxCols : 3 と定義していれば、
表示している3列までしか getDataAtRow はデータ取得をしない。

グリッド表示させないデータを持ち何らかの操作で使用したい場合にどうするか?

var data = [
      {   A:'A1', B:'B1', C:'C1', D:'D1'   },
      {   A:'A2', B:'B2', C:'C2', D:'D2'   },
      {   A:'A3', B:'B3', C:'C3', D:'D3'   },
];

このJSONを3列まで表示して、4列目のキー'D' をコンテキストメニューで選択した時に
使用する場合、、特別なコーディングではないが、以下になる。

var hot = new Handsontable(document.getElementById("table"), {
    data: data,
    rowHeaders: true,
    colHeaders: true,
    maxCols: 3,
    columns: [
        {  data:'A',   type:'text',   },
        {  data:'B',   type:'text',   },
        {  data:'C',   type:'text',   },
    ],
    contextMenu: { items:{
            "goPage": {
                name: 'ページ遷移',
                callback: function(key, selection, clickEvent){
                    // 非表示データ key='D' の値を使用
                    var value = data[selection[0].start.row]['D'];
                    location.href = './etcPage?param1='+value;
                },
            },
        },
    },
    licenseKey: 'non-commercial-and-evaluation'
});