Handsontable 使い方メモ２（グリッドのオプション）

[基本](http://qiita.com/opengl-8080/items/ac19deec388c357cd498)
[セル・カラムのオプション](http://qiita.com/opengl-8080/items/ccf5cbccd0ceb0a6bb47)
[メソッド](http://qiita.com/opengl-8080/items/e756af444147771fab18)

※全てのオプションは網羅していません。

全てのオプションを確認したい場合は、 [公式ドキュメント](http://docs.handsontable.com/0.24.1/tutorial-introduction.html) を参照。

# オプション
## `autoColumnSize`：初期表示時のカラム幅を自動調整する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこさしすせそ'],
        ['やゆよ', 'たちつてと']
    ],
    autoColumnSize: true
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/b0bf3061-42c8-529b-f11d-7bfe37706cfb.jpeg)

- 内容が１行に表示できるように幅が自動調整される。
- デフォルトは `false` で、以下のようになる。

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/69e3986a-39c6-9579-440a-dd0c5559cced.jpeg)

## `colHeaders `：ヘッダーを表示する
### boolean で指定
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colHeaders: true
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/5b796131-7445-2745-634b-9aceda8a7d05.jpeg)

- `A`, `B` と簡易なヘッダーが表示される。

### 列名を配列で指定
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colHeaders: ['列１', '列２']
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/6006d271-d20a-c180-b5ce-53b7368b04a4.jpeg)

- 配列で列名を指定できる。

### 列名を関数で処理して決定
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colHeaders: function(index) {
        return ['列A', '列B'][index];
    }
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/2fc1787e-0808-69c3-8ad5-dbf20f52c9b3.jpeg)

- 関数を指定すると、列ごとにその関数がコールバックされる。
- 関数の引数に列のインデックスが渡されるので、それを元にその列の名前を `return` するように実装する。

### `title` でカラムごとに設定する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    columns: [
        {title: 'foo'},
        {}
    ]
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/42c1c3e0-7d6f-d161-9242-346c008e3750.jpeg)

- カラムごとに `title` で、ヘッダーを指定できる。
- `title` を設定していないカラムがあると、 `null` と出てしまう。

## `rowHeaders`：行ヘッダーを表示する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

new Handsontable(grid, {
    data: data,
    rowHeaders: true
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/1e02806f-6168-341b-bcdc-d71a6064252f.jpeg)

- `rowHeaders` に `true` を設定すると、行ヘッダーが表示される。
- デフォルトは、１始まりの連番が表示される。
- こちらも、配列や関数を渡すことでカスタマイズが可能。

## `colWidths`：列幅を指定する
### 全ての列をまとめて設定する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colWidths: 200
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/c7f27b94-65f4-72af-a6b8-1fc93ac81144.jpeg)

### 列ごとに指定する（配列指定）
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colWidths: [200, 50]
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/848696c9-9d13-5e12-c8b8-17ff2e32c493.jpeg)

- 配列を渡せば、列ごとの幅を指定できる。

### 列ごとに指定する（関数指定）
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['あいうえお', 'かきくけこ'],
        ['さしすせそ', 'たちつてと']
    ],
    colWidths: function(index) {
        return [100, 200][index];
    }
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/38ccdd87-e253-9138-b7a3-2a744b2437fd.jpeg)


## `columnSorting`：ソート
### カラム名のクリックでソートできるようにする
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['a', 'd'],
        ['b', 'c']
    ],
    colHeaders: true,
    columnSorting: true
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/ba182e6b-69fe-8f3e-a770-4fc8bb28d722.gif)

- `columnSorting` に `true` を指定すれば、カラム名をクリックすることでソートできるようになる。

### ソートさせてから表示する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['a', 'd'],
        ['b', 'c']
    ],
    colHeaders: true,
    columnSorting: {
        column: 0,
        sortColumn: false
    }
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/d888a62e-a40e-dd9a-788f-5d8dfde78299.jpeg)

- `columnSorting` の値をオブジェクトにする。
    - `column` に、ソートする項目のインデックス、
    - `sortColumn` に昇順にするか降順にするかを `boolean` で指定する（`true` が昇順でデフォルト）。

### 現在のソートの向きを表示する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    colHeaders: true,
    columnSorting: true,
    sortIndicator: true
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/c3e74fbf-0531-9fdd-7701-998d2254f5d2.jpeg)

- `sortIndicator` を `true` にすると、カラム名の横に三角印で現在のソートの向きが表示されるようになる。
- 上向きが昇順、下向きが降順、何も表示されていないときがデフォルト。


## `contextMenu`：コンテキストメニュー
### メニューを有効にする
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    contextMenu: true
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/e90bbb75-4e25-d171-93b4-670428970744.jpeg)

- `contextMenu` に `true` を設定すると、右クリックでメニューが開くようになる。
- デフォルトで、いくつかのメニューが表示されるようになっている。

### 表示するメニューをカスタマイズする
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    contextMenu: ['row_above']
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/eb204c91-a520-66fb-5a51-d859f848f8e5.jpeg)

- 表示させたい項目だけを配列で指定できる。
- 以下が、指定できる文字列。

|        値         |                                    説明                                    |
|-------------------|----------------------------------------------------------------------------|
| `row_above`       | 選択している行の上に空行を挿入。                                             |
| `row_below`       | 選択している行の下に空行を挿入。                                             |
| `---------`       | メニューにセパレータを挿入。                                               |
| `col_left`        | 選択している列の左に空列を挿入。                                           |
| `col_right`       | 選択している列の右に空列を挿入。                                           |
| `remove_row`      | 選択している行を削除。                                                     |
| `remove_col`      | 選択している列を削除。                                                     |
| `undo`            | 元に戻す。                                                                 |
| `redo`            | やり直し。                                                                 |
| `make_read_only`  | 選択しているセルを読み取り専用にする。                                     |
| `alignment`       | セルのアライメントを指定する。（左寄せ、右寄せ、中央寄せ、上寄せ、下寄せ） |
| `borders`         | セルの枠線を設定する（`customBorders` が有効な場合のみ）。                 |
| `commentsAddEdit` | セルにコメントを挿入する（`comments` が有効な場合のみ）。                  |
| `commentsRemove`  | セルのコメントを削除する（`comments` が有効な場合のみ）。                  |

### デフォルトで使用できるメニューのラベルを変更する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    contextMenu: {
        items: {
            row_above: {
                name: '上に行を挿入'
            },
            row_below: {
                name: '下に行を挿入'
            }
        }
    }
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/ce795184-aa48-2997-c4a8-b4651348a06b.jpeg)

- `contexMenu` にオブジェクトを渡すようにする。
- `items` というプロパティに上書きする設定内容を持った **オブジェクト** を渡す。
    - キーに対象のメニューの名前（`row_above`, `row_below` 等）、値にそのメニュー項目の設定値をオブジェクトで渡す。
    - `name` が、表示で使用される文字列。
    - オブジェクトのキーだと順序が保証されないのでは？　と思うけど、なんか一応宣言した順序でメニューも並ぶようになっている。
        - [公式の記述がこうなっている](http://docs.handsontable.com/0.24.1/demo-context-menu.html#page-custom) から仕方ない。
- このメソッドは、 [jQuery contextMenu](http://swisnl.github.io/jQuery-contextMenu/docs/items.html) で設定できるのと似たような設定ができる。
    - 完全に同じではないようで、設定できないものが多い。

### メニュー項目を自作する
#### 基本
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    contextMenu: {
        items: [
            {
                key: 'myItem',
                name: 'メニュ～',
                callback: function() {
                    alert('クリックした！');
                }
            }
        ]
    }
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/fa579699-a29e-9d5c-ac8d-9412e389f89e.gif)

- `items` に、メニューを定義したオブジェクトを **配列** でセットする。
- `key` で、メニューを識別するための名前を設定する。
- `name` で、メニューの表示内容を設定できる。
- `callback` に、メニューが選択されたときのコールバック関数を指定できる。

#### コールバックに渡される引数
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    contextMenu: {
        items: [
            {
                key: 'myItem',
                name: 'メニュ～',
                callback: function() {
                    console.log(arguments);
                }
            }
        ]
    }
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/fcecfbf7-db8a-f4ef-fb56-fef5cea97e54.jpeg)

- 第一引数には、その項目を識別する名前（`myItem`）が渡される。
- 第二引数には、選択されているセルの情報が渡される。
    - `start` と `end` というプロパティを持ち、両方ともセルの位置を特定する `col` と `row` を持つ。
    - 範囲選択している場合は、 `start` に開始位置が、 `end` には終了位置が設定されている。
- 第三引数には、マウスイベントオブジェクトが渡される。

#### ラジオボタン(ぽいもの)を実装する
幾つかの項目のうち１つだけが選択できる、みたいなメニューを作る。

```js
var grid = document.getElementById('grid');

var selected = 1;

var table = new Handsontable(grid, {
    contextMenu: {
        items: [
            {
                key: 'item1',
                name: function() {
                    return selected === 1 ? '●item1' : 'item1';
                },
                callback: function() {
                    selected *= -1;
                }
            },
            {
                key: 'item2',
                name: function() {
                    return selected === -1 ? '●item2' : 'item2';
                },
                callback: function() {
                    selected *= -1;
                }
            }
        ]
    }
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/e03b5fb4-1340-81f6-8586-4c5a080d8b22.gif)

- `name` を関数にすると、メニューが開かれる度にコールバックされ、その戻り値がメニューのテキストとして表示される。
- これを利用して、選択状態に合わせて表示する文字を切り替えることで、ラジオボタンを実現する。
- [jQuery contextMenu](http://swisnl.github.io/jQuery-contextMenu/docs/items.html#type) には `type` というオプションがあったのでそれが利用できるのかと思ったけど、動かなかった。
- デフォルトで用意されているアライメントのメニューとかはどうなってるのか実装を見に行ったら、上のようなことをゴリゴリ実装していた。
- チェックボックスとかも、基本同じようにゴリる必要があるっぽい。

#### サブメニュー
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    contextMenu: {
        items: [
            {
                key: 'myMenu',
                name: 'my menu',
                submenu: {
                    items: [
                        {
                            key: 'subMenu1',
                            name: 'sub menu 1'
                        },
                        {
                            key: 'subMenu2',
                            name: 'sub menu 2'
                        }
                    ]
                }
            }
        ]
    }
});
```
 
![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/d23e1b9d-1dd6-fa8b-d5dc-27cb61f3816a.jpeg)

- `submenu` で次の階層のメニューを追加できる。

### 有効無効の切り替え
```js
var grid = document.getElementById('grid');

var flag = true;

var table = new Handsontable(grid, {
    contextMenu: {
        items: [
            {
                name: 'item1',
                disabled: true
            },
            {
                name: 'item2',
                disabled: function() {
                    flag = !flag;
                    return flag;
                }
            }
        ]
    }
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/9c1d6dd4-9362-c30f-ac69-3456f15041ef.gif)

- `disabled` に `boolean` を設定することで、項目の有効・無効を指定できる。
- 関数を渡せば表示のたびにコールバックされるので、同じく `boolean` を返すようにすれば動的に有効・無効を切り替えられる。

### `comments`：コメント
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    comments: true,
    contextMenu: ['commentsAddEdit', 'commentsRemove']
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/ccbb6d95-d3d6-b3b4-6ce5-bdd7439abe6b.gif)

- `comments` を `true` にすると、メニューでコメントを編集するためのオプションを指定できるようになる。

#### 任意のセルにコメントを設定する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    comments: true,
    cell: [
        {col: 1, row: 1, comment: 'Hello Comment'}
    ]
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/801620aa-a4ef-99dd-289d-2cac6c97c10e.jpeg)

- `cell` オプションの `comment` で、任意のセルにコメントを記述できる。



## `copyPaste`：コピペの有効・無効
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        ['a', 'd'],
        ['b', 'c']
    ],
    copyPaste: false
});
```

- `copyPaste` に `false` を設定すると、 `Ctrl` + `c` → `Ctrl` + `v` によるコピペを無効にできる。
- デフォルトは `true` で有効になっている。

## `copyColsLimit`：コピーできる列数を制限する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3, 4, 5],
        [1, 2, 3, 4, 5],
        [1, 2, 3, 4, 5],
        [1, 2, 3, 4, 5]
    ],
    copyColsLimit: 1
});
```

- `copyColsLimit` でコピーできる列数の上限を指定できる。
- デフォルトは `1000`。
- ここで指定した列数以上をコピーしようとすると、ペーストしたときに指定した列数までしかペーストされない（エラーとかにはならない）。
- `0` 以下を指定すると、ペーストしたときに選択している列が全て空白で上書きされる。
- 行数を制限したい場合は `copyRowsLimit` を指定する。

## `customBorders`：罫線の設定
### 基本
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    customBorders: true,
    contextMenu: ['borders']
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/8c189906-845f-455f-2866-a955de1b5957.gif)

- `customBorders` に `true` を指定すると、 `contextMenu` で `borders` が使用できるようになる。
- メニューで `borders` を使用すると、選択しているセルの上下左右に罫線を引けるようになる。

### 任意の場所に罫線を引く
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    customBorders: [
        {
            row: 1,
            col: 1,
            top: {
                width: 3,
                color: 'red'
            },
            right: {
                width: 2,
                color: '#1199ff'
            }
        }
    ]
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/3a6e957c-a98c-afc2-0fb9-0c47c5be1af3.jpeg)

- `true` の代わりに配列を渡し、罫線を引く場所を定義したオブジェクトを渡すことで、任意の場所に罫線を引くことができる。

### 範囲を指定して罫線を引く
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    customBorders: [
        {
            range: {
                from: {col: 0, row: 0},
                to: {col: 1, row: 2}
            },
            top: {
                width: 3,
                color: 'red'
            },
            right: {
                width: 2,
                color: '#1199ff'
            }
        }
    ]
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/16eb1e63-b91b-9147-7aa9-da7834b93365.jpeg)

- `range` を指定すれば、範囲を指定して罫線を引ける。

## `dataSchema`：新しい行を追加するときの定義を指定する
**dataSchema** を指定しない場合

```js
var grid = document.getElementById('grid');

var data = [];

var table = new Handsontable(grid, {
    data: data
});

data.push({
    name: 'foo',
    age: 15
});

table.render();
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/4d3f4a6e-3fa8-156b-22c9-2701d68cfd22.jpeg)

- `dataSchema` を設定していないと、データソースを更新して `render()` メソッドを呼んでもグリッドが表示されない。

**dataSchema を指定した場合**

```js
var grid = document.getElementById('grid');

var data = [];

var table = new Handsontable(grid, {
    data: data,
    dataSchema: {
        name: null,
        age: null
    }
});

data.push({
    name: 'foo',
    age: 15
});

table.render();
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/7084d2b7-de9e-e1e1-b8a3-795181318d3c.jpeg)

- `dataSchema` を設定していれば、再描画で追加したデータが表示される。
- `dataSchema` は、データが全く無い状態から新規にレコードを追加したときなどに必要になる。
- １行目にすでにデータが設定されている場合は、そのデータの構造が `dataSchema` として利用される。

**１行目にデータが設定されている場合**

```js
var grid = document.getElementById('grid');

var data = [
    {name: 'foo', age: 17}
];

var table = new Handsontable(grid, {
    data: data
});

data.push({
    name: 'bar',
    age: 15
});

table.render();
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/0e19af97-e0c9-dba8-7ed1-42ef9659c90e.jpeg)

- `render()` で行が追加された状態になる。

## `disableVisualSelection`：セルの選択可否を設定する
### 全く選択できないようにする
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    disableVisualSelection: true
});
```

- セルを全く選択できなくなる。
- デフォルトは `false` なので、選択できる。

### 範囲選択をできなくする
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    disableVisualSelection: 'area'
});
```

- `'area'` を設定すると、ドラッグによる範囲選択ができなくなる。
- 個々のセルを選択することは可能。



## `enterBeginsEditing`：Enter で次の行に移動する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    enterBeginsEditing: false
});
```

- デフォルトでは、 `Enter` を入力するとセルの編集が始まる。
- `Enter` を入力したときに次の行に移動するようにしたい場合は、 `enterBeginsEditing` を `false` にする。

## `enterMoves`：Enter でセルを抜けたときの移動先を指定する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    enterMoves: {
        row: 1,
        col: 1,
    }
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/d2bbf06d-8494-1f5f-5534-0f8d903eb6d8.gif)

- `Enter` でセルを抜ける時、デフォルトだと下のセルに移動する。
    - `Shift` + `Enter` で上（逆）に移動する。
- `enterMoves` オプションを指定すると、移動先を任意に指定できる。
- オブジェクトを渡して、 `row` と `col` で遷移先の相対位置を指定する。
- 関数を指定することもできる。
    - その場合は戻り値が相対位置を指定するオブジェクトになるようにする。
    - 関数の引数には、 `Enter` を入力したときのイベントオブジェクトが渡される。

## `fillHandle`：フィルハンドル

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/0fbe8355-80e6-108b-1f52-47d6c5d4e80f.jpeg)

- デフォルトでは、選択したセルの右下にカーソルをドラッグすることで、セルの内容を上下 or 左右にコピーできる。
- これを **フィルハンドル** と呼ぶ。

```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    fillHandle: false
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/68751689-f41e-c2af-e984-60601e3b9dea.jpeg)

- `fillHandle` に `false` を設定することで、これを消すことができる。
- また、 `vertical` または `horizontal` を指定することで、コピーの向きを限定することもできる。

## `fixedColumnsLeft`, `fixedRowsTop`：列・行を固定する
```js
var grid = document.getElementById('grid');

var data = [];
for (var i=0; i<50; i++) {
    var row = [];
    for (var j=0; j<50; j++) {
        row.push(i + j);
    }
    data.push(row);
}

new Handsontable(grid, {
    data: data,
    fixedColumnsLeft: 2,
    fixedRowsTop: 2
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/9448ac26-24e0-56e1-4e96-9d8c51ef66b7.gif)

- `fixedColumnsLeft` で列を固定できる。
- `fixedRowsTop` で行を固定できる。

## `manualColumnMove`, manualRowMove：行・列をドラック＆ドロップで移動できるようにする
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [1, 2, 3],
    [1, 2, 3]
];

new Handsontable(grid, {
    data: data,
    colHeaders: true,
    manualColumnMove: true
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/59a2668b-04b1-ca9c-be06-b80f0ebf66d0.gif)

- 列ヘッダーを表示させた状態で `manualColumnMove` を `true` にすると、ドラッグ＆ドロップで列を移動させられるようになる。
- `manualRowMove` を使えば、行の移動もできるようになる。

## `manualColumnResize`, `manualRowResize`：行・列の幅をドラッグで変更できるようにする
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [1, 2, 3],
    [1, 2, 3]
];

new Handsontable(grid, {
    data: data,
    colHeaders: true,
    manualColumnResize: true
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/99baf2e6-a469-202d-c746-dbf3fc79da1f.gif)

- 列ヘッダーを表示させた状態で `manualColumnResize` を `true` にすると、ドラッグで列の幅を変更できるようになる。
- ダブルクリックすれば、セルの内容に合わせて幅を最小サイズにできる。
- `manualRowResize` を使えば行のサイズ変更もできるようになる。

## `maxCols`, `maxRows`：行・列の最大数を設定する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

new Handsontable(grid, {
    data: data,
    maxCols: 4,
    maxRows: 7
});
```

- 範囲選択してコピペしたり、フィルハンドルをドラッグすると、セルが存在しない領域に新しく行や列が追加される。
- `maxCols`, `maxRows` を設定すれば、追加される行や列の最大数を指定できる。

## `mergeCells`：セルを結合する
### 基本
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

new Handsontable(grid, {
    data: data,
    mergeCells: true,
    contextMenu: ['mergeCells']
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/e35f9426-9035-6f77-ae1d-175c45192e04.gif)

- `mergeCells` に `true` を設定すると、 `contextMenu` で `mergeCells` を使えるようになる。
- 選択した複数のセルを結合したり、解除したりできる。

### 任意のセルを結合する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

new Handsontable(grid, {
    data: data,
    mergeCells: [
        {row: 0, col: 0, rowspan: 2, colspan: 1},
        {row: 1, col: 1, rowspan: 1, colspan: 2}
    ]
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/66e24594-bac7-8234-d949-bb333f8e0acb.jpeg)

- 配列を渡して、結合の条件を指定したオブジェクトを渡すことで、任意のセルを結合させられる。
- `row`, `col` で結合の起点となるセルの座標を指定する（`0` 始まり）。
- `rowspan`, `colspan` で、結合する範囲を指定する（`1` 以上の値を指定）。

### コンテキストメニューの表示を日本語にする
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    mergeCells: true
});

table.updateSettings({
    contextMenu: {
        items: {
            mergeCells: {
                name: function() {
                    var sel = this.getSelected();
                    var info = this.mergeCells.mergedCellInfoCollection.getInfo(sel[0], sel[1]);
                    if (info) {
                        return '結合を解除';
                    } else {
                        return 'セルを結合';
                    }
                }
            }
        }
    }
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/ff31a340-4f5b-308c-e1cb-6e924ac314e4.gif)

- `mergeCells` の表示部分のテキストはガッツリハードコーディングされているので、たぶんこうしないとイケない。
- `name` の実装は [MergeCells プラグインの実装](https://github.com/handsontable/handsontable/blob/master/src/plugins/mergeCells/mergeCells.js#L378) をそのまま持ってきて表示の部分だけ日本語にしている。

## `minCols`, `minRows`：行・列の最小数を指定する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    minCols: 2,
    minRows: 3
});
```

- コンテキストメニューで行や列を削除していっても、ここで指定した数の行（列）は残るようになる。

## `minSpareCols`, `minSpareRows`：余白となる行・列の最小値を設定する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    minSpareCols: 2,
    minSpareRows: 3
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/749bfa05-7d57-2cb7-2862-e37bc458aea0.gif)

- 指定した数だけの空の行・列が余白として常に表示されるようになる。

## `multiSelect`：複数セル選択の可否
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    multiSelect: false
});
```

- `multiSelect` に `false` を設定すると、ドラッグなどによる複数セル選択ができなくなる。
- デフォルトは `true` で有効になっている。

## `outsideClickDeselects`：表外をクリックしても選択状態を解除させない
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    outsideClickDeselects: false
});
```

- `outsideClickDeselects` に `false` を設定すると、表外をクリックしても直前に選択していたセルの選択状態を解除させないようにできる。
- デフォルトは `true` で、表外をクリックすると選択状態が解除される。

## `pasteMode`：貼付け時の動作を指定する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    pasteMode: 'shift_right'
});
```

- `Ctrl` + `V` で貼り付けた時の動作を指定できる。
- デフォルトは `override` で、コピー中の内容でセルを上書きする。
- `shift_down` だと、ペーストした分だけ既存のセルが下にずれる。
- `shift_right` だと、右にずれる。

## `placeholder`：空セルの表示内容を指定する
```js
var grid = document.getElementById('grid');

var data = [
    [1, 2, 3],
    [2, 3, 4],
    [3, 4, 5]
];

var table = new Handsontable(grid, {
    data: data,
    placeholder: '( ^ω^)'
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/cf8f6af4-c9a1-c8f6-a894-df4aa9829da4.gif)

- セルが空になったときの文字を指定できる。

## `startCols`, `startRows`：初期データが与えられなかった場合の行と列の数を指定する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    startCols: 2,
    startRows: 3
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/e74f4ddb-c777-012b-4620-21258e255aa1.jpeg)

## `stretchH`：セルの幅を自動伸縮させる
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    stretchH: 'last'
});
```

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/8a6f2477-13d8-5a29-681b-ff840cc535bf.gif)

- `stretchH` に `last` を指定すると、最後の列の幅が最大限まで伸ばされる。
- ドラッグすると幅が自動伸縮する。
- `all` を指定すると、全てのセルが均等に伸縮されるようになる。

![handsontable.gif](https://qiita-image-store.s3.amazonaws.com/0/28302/d82b0759-caa1-8e22-569d-7e4f03cb3d45.gif)

## `tabMoves`：タブを入力したときの移動先を指定する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]
    ],
    tabMoves: {
        col: 0,
        row: 1
    }
});
```

- デフォルトは右のタブに移動する。
- オブジェクトを渡して、 `col` に横方向の移動量、 `row` に縦方向の移動量を指定する。
- 移動先を指定したオブジェクトを返す関数を渡すこともできる。
    - 関数には、キーイベントオブジェクトが渡される。

## `width`, `height`：固定サイズのグリッドを表示する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
        [2, 3, 4],
        [3, 4, 5],
        [4, 5, 6],
        [5, 6, 7],
        [6, 7, 8],
        [7, 8, 9],
        [8, 9, 0],
        [9, 0, 1],
        [0, 1, 2]
    ],
    width: 200,
    height: 100
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/af8b9f79-5eb4-3dd6-74b8-03a191131572.jpeg)

- `width` と `height` を同時に設定すると、固定サイズのグリッドを表示させられる。
- `width` だけの指定だと何も変化しない。
- `height` だけの指定は有効みたい。

## `wordWrap`：セル内で折り返す
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['あいうえお', '', ''],
        ['', '', ''],
        ['', '', '']
    ],
    colWidths: 50,
    wordWrap: false
});
```

![handsontable.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/2d0e7a48-e0bf-00f0-5a3f-8ffa10e884c6.jpeg)

- セルの幅が指定されている状態で、内容がセル幅に収まりきらない場合、デフォルトでは折り返されて表示される。
- `wordWrap` を `false` にすると、折り返しがされなくなり収まりきらない分が隠れるようになる。

## `search`：グリッド内を検索する
### 基本
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

var result = table.search.query('T');
console.dir(result);
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/c278ad02-5d65-0056-0e46-00c3f1be6c48.jpeg)

- `search` オプションに `true` を指定すると、 Search プラグインが有効になる。
- `search.query()` メソッドを実行することで、指定した値を持つセルを検索することができる。
    - デフォルトでは、大文字・小文字は区別されない。

### 検索で該当したセルを着色する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

table.search.query('T');
table.render();
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/45898d01-6660-a485-ea00-127f9b112518.jpeg)

- `search.query()` を実行したあとで `render()` メソッドを呼ぶと、検索で該当したセルが着色される。
- クリアしたい場合は、引数無しで `query()` を呼んだあとで `render()` を呼べば、色が戻る。

### 検索後に処理を挟む
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

table.search.query('T', function(instance, row, col, data, testResult) {
    console.log(arguments);
    instance.getCellMeta(row, col).isSearchResult = testResult;
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/d64f64b4-e971-86ef-827a-91925f101b1b.jpeg)

- `query()` メソッドの第二引数に関数を渡すと、各セルごとに関数がコールバックされる。
- 引数には、以下の値が渡される。
    1. テーブルのインスタンス
    2. 行番号
    3. 列番号
    4. 検索結果（該当する場合は `true`）

### 検索後の処理のデフォルトの動作を変更する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

Handsontable.Search.global.setDefaultCallback(function(instance, row, col, data, testResult) {
    console.log(arguments);
    instance.getCellMeta(row, col).isSearchResult = testResult;
});

table.search.query('T');
```

- `Handsontable.Search.global.setDefaultCallback()` メソッドで、デフォルトのコールバックを変更できる。

### 検証処理を変更する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

table.search.query('T', null, function (query, value) {
    console.dir(arguments);
  
    if (typeof query == 'undefined' || query == null || !query.toLowerCase || query.length === 0) {
        return false;
    }
    
    return value.toString().toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
```

![handsontable.jpg](https://qiita-image-store.s3.amazonaws.com/0/28302/d1160e94-f921-4d0c-3012-7b59de79ac3a.jpeg)

- `query()` メソッドの第三引数に関数を渡すと、検索の検証処理を変更できる。
- 関数は各セルごとにコールバックされ、引数に検索条件の文字列とセルの値が渡される。
- 検証の結果は `boolean` で返す。
- 第二引数は「偽と判定される値」を渡しておけば、デフォルトの処理が実行される。

### 検証処理のデフォルトの動作を変更する
```js
var grid = document.getElementById('grid');

var table = new Handsontable(grid, {
    data: [
        ['one', 'two', 'three'],
        ['four', 'five', 'six'],
        ['seven', 'eight', 'nine']
    ],
    search: true
});

Handsontable.Search.global.setDefaultQueryMethod(function (query, value) {
    console.dir(arguments);
  
    if (typeof query == 'undefined' || query == null || !query.toLowerCase || query.length === 0) {
        return false;
    }
    
    return value.toString().toLowerCase().indexOf(query.toLowerCase()) !== -1;
});

table.search.query('T');
```

- `Handsontable.Search.global.setDefaultQueryMethod()` で検証処理のデフォルト実装を変更できる。

## `trimWhitespace`：前後の空白をトリムするか設定する
```js
var grid = document.getElementById('grid');

new Handsontable(grid, {
    trimWhitespace: false
});
```

- `false` を指定すると、トリムされなくなる。
- デフォルトは `true` なので、トリムされる。


# 参考
- [Tutorial: Introduction | Handsontable - open source spreadsheet solution. Excel-like grid editing with HTML & JavaScript](http://docs.handsontable.com/0.24.0/tutorial-introduction.html)