w2ui gridのセル内に、行の値に応じたHighchartsのグラフを表示させる

ここに二つの素敵なライブラリがあります。

[w2ui](http://w2ui.com/web/)
・いい感じのgrid(それ以外のコンポーネントもある)をjavascriptから生成できる

[Highcharts](https://www.highcharts.com/)
・いい感じの各種チャートをjavascriptから生成できる

こいつら(w2uiのgrid＋Highcharts)を組み合わせて、ウェブページにグリッドを表示させ、
さらにそのセル内にグラフを表示させようとしたときに詰まったのでメモを残しておく次第。

---

# 完成イメージ
見た目は調整していないのでアレですが、こんな感じでウェブページに表示させるためのメモです。
~~画像だけだと分からないですが、ちゃんとセル内の値に応じてリアルタイムにグラフも変化します。~~
(せっかくなのでgifにしました、[ScreenToGif](https://github.com/NickeManarin/ScreenToGif/releases)が便利！)
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/193827/2cd3aca0-a1c8-a10e-930e-c056e0db53b1.gif)

※ちなみに、アニメーションを切った上でY軸をある程度しっかり指定してあげると、もっと大人しい動きになるはずです。

# セル内にグラフを表示させる方法
w2uiのgridは、recordを適当にセットした後にrefreshメソッドを呼び出して、表示内容を更新します。

```javascript:highcharts_in_w2ui_grid.js
	// w2uiグリッドの生成
	$('#grid').w2grid({ 
        name: 'grid', 
        columns: [                
            { field: 'a', caption: 'a', size: '50px' },
            { field: 'b', caption: 'b', size: '50px' },
            { field: 'c', caption: 'c', size: '50px' },
            { field: 'chart', caption: 'Highcharts', size: '100%' }
        ],
    });
    // 適当にダミーのデータをセット
    w2ui['grid'].records = [
		{a:11, b:22, c:15},
		{a:934, b:503, c:571},
	];
    // グリッドの更新
	w2ui['grid'].refresh();
```

が、この更新時にグリッド内のセルは一度クリアされてしまうので、refresh後にうまいことセルの中に
HighchartsによるHTML要素を作ってやる必要があります。
今回詰まったのは、この「refresh後」に処理する方法。

結論としては、こんな感じでonRefreshに割り当てた関数の第一引数の、
onCompleteに任意の処理を割り当てることで解決できます。

```javascript:highcharts_in_w2ui_grid.js
	// w2uiグリッドの生成
	$('#grid').w2grid({ 
        name: 'grid', 
        columns: [                
            { field: 'a', caption: 'a', size: '50px' },
            { field: 'b', caption: 'b', size: '50px' },
            { field: 'c', caption: 'c', size: '50px' },
            { field: 'chart', caption: 'Highcharts', size: '100%' }
        ],
        onRefresh: function(event){
        	// event.onCompleteにセットした関数がrefresh後に呼び出される
        	event.onComplete = function(){
        		// Highcharts生成のターゲットとするdivを作成
        		highcharts_in_w2ui_grid.makeChartDiv();
				
				// Highchartsのチャート生成処理呼び出し
				highcharts_in_w2ui_grid.makeChart();
        	};
        }
    });
```

この「refresh後」のタイミングさえ取れれば、あとは好みに応じて大体何でもできます。
今回はこんな感じで、グリッド内のグラフを表示させたいセルを見つけ出して、divを追加することにしました。

```javascript:highcharts_in_w2ui_grid.js
highcharts_in_w2ui_grid.makeChartDiv = function(){
	// w2uiグリッド内のチャート生成先にしたいセルに、Highcharts生成のターゲットとするdivを作成
	var cells = $('tr[index] td.w2ui-grid-data[col=3]');
	cells.append('<div class="chart-cell"></div>');
};
```

この後は、該当のdivに対してHighchartsのグラフ生成処理を呼び出すだけです。

```javascript:highcharts_in_w2ui_grid.js
highcharts_in_w2ui_grid.makeChart = function(){
	// 目印のクラスが付加されたdivを対象にチャートを生成
	var $targets = $('.chart-cell');
	for(var i=0; i<$targets.length; i++){
		var $target = $targets[i];
		// データはグリッドのレコードを使用
		// (データの成形タイミング自体は自由なので、divにカスタム属性として持たせておくとかでもOK)
		var record = w2ui['grid'].records[i];
		chartData = [record.a, record.b, record.c];
		// チャート生成
		Highcharts.chart($target, {
	        series: [{
		        data: chartData
		    }],
		    // (以下省略)
```

# 問題点

一般的なHighchartsの更新方法と異なり、w2ui gridに消されたチャートを毎回生成しなおすという動きをさせています。
それに伴って表示更新のアニメーションや、パフォーマンスに影響が出る可能性があります。
(もしかしたらHighchartsが生成したHTML要素を、refresh前に別の個所に移動させて、refresh後に元に戻すとかもできるかも？ 今のところ試す気力は無いですが)


# ソースコード

突貫で書いたざっくりコードですが、一応すぐに動かせそうなやつを公開しておきます。
2秒間隔でグリッド内の値を更新して、その値に応じてグラフの描画も変化します。

[highcharts_in_w2ui_grid (GitHub)](https://github.com/tokisuzume/highcharts_in_w2ui_grid)


# 参考にしたページ
[w2ui Docs _ common.onRefresh](http://w2ui.com/web/docs/1.5/common.onRefresh)