【パブリッシャー】SharperlightとChart.jsの連携

今回の記事では、Chart.jsに[Sharperlight](https://sharperlight.jp/)からデータを供給するといった使用形態を紹介してみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/655c7f40-02ff-a8f5-4cd5-78a985d1fe24.png)

[Sharperlight](https://sharperlight.jp/)をインストールすると、Chart.jsも梱包されているので即使用可能となります。
Chart.jsの棒グラフを表示するHTMLファイル(script記述込み)を作成し、パブリッシャーで作成するWebレポートにカスタムとして埋め込みます。
この記事の最後に、全コードを添付しています。キーとなる部分をひとつひとつ見ていきましょう。

### < head >部 ###
ここでは、SharperlightとともにインストールされるChart.jsのコードファイルやクラスファイルを参照する記述を行います。それらはSharperlightサービスを利用して参照します。
{*Url.Root}は、Sharperlightの組込みコントロールタグで、実行時には、実際のSharperlightサービスURLに置き換えられます。
```
<link rel="stylesheet" type="text/css" href="{*Url.Root}Resources/Chart.js/Chart.min.css" />
<script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.js"></script>
<script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.min.js"></script>
<script type="text/javascript" src="{*Url.Root}Resources/jquery/jquery.min.js"></script>
```
実行時、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/24439dd1-609d-c9a5-7912-f5c357c6853d.png)
後は、スタイルを設定するくらいです。

### < body >部 ###
ここには、実際のHTMLオブジェクトの定義、棒グラフを描くキャンバスを用意します。
```
<div class="slpt-row">
   <div class="slpt-title"></div>
   <div class="slpt-leftCell">
       <canvas id="chart-area1" class="slpt-ca-1"></canvas>
   </div>
</div>
```

### < Script > ###
< body >内にスクリプトの記述を行います。
$(document).readyイベントから_Start()関数を呼び、更にpopulateContents()を呼ぶ作りにしています。
populateContents()関数の中で、Chart.jsの棒グラフを描画します。

先ず、棒グラフに表示するデータを準備。Sharperlightでクエリを作成し、ここでのデータソースとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d6241ce3-dc40-e1f5-b48f-cbcb890f3673.png)
Sharperlightサービスを利用して呼び出すので、URLはこのようになります。
```
http://{your server name}/mdService1Rest/DataSource/?query=PresentationDS.VBarChartTypeA&dfmt=jsonarray&dcat=UseNames
```
コード内で、このURLを指定する場所は、URL：gURL_DS001　この部分です。
```
try{
   var jsonData = $.ajax({
       url: gURL_DS001,
       dataType: 'json',
       }).done(
           function (results) {
```
ここでは、gURL_DS001変数がそのURLを保持しています。
URLをここに直接記述してもいいのですが、URLが、つまりデータセットが固定になってしまうので、このカスタムレポートのパラメータを利用して自由にデータセットのURLを生成できるようにします。
パラメータには、データセットを供給するSharperlightクエリの名前のみを渡し、その名前を使用してURLを作成しクエリ結果として出力します。出力されたURLは、このようなタグ "{*Row.dsURLChart.text}" で、このコードに渡されます。
この部分です。
```
var gURL_DS001 = "{*Row.dsURLChart.text}";
```
実行時はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/377c8024-dc80-c3f6-2a12-3b9e9dfd08b5.png)
ajaxコールで取得したデータセットの各列の値は、データ供給クエリの出力名で参照できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6b956a3c-4ca2-59d3-ac65-3e25f4b2063b.png)
このようにして、Sharperlightクエリでデータセットをデザインし、カスタムレポートとし作成したレポートにデータを供給し、お好みのJavaScriptフレームワークのグラフ等を利用することができます。





以下に、全コードを貼り付けておきます。
```
<html>
   <head> 
        <title>Sharperlight Presentation Tiles - VerticalBarChartTypeA</title> 
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <link rel="stylesheet" type="text/css" href="{*Url.Root}Resources/Chart.js/Chart.min.css" />
        <script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.js"></script>
    	<script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.min.js"></script>
    	<script type="text/javascript" src="{*Url.Root}Resources/jquery/jquery.min.js"></script>

        <style>
            body{
                overflow: hidden;
                width: 450px;
                height: 200px;
            }
            canvas {
                -moz-user-select: none;
                -webkit-user-select: none;
                -ms-user-select: none;
            }
            .slpt-title{
                position: absolute;
                top: 10px;
                left: 15px;
                font-size: 20px;
                font-family: Arial;
            }
            .slpt-ca-1 {
                display: block;
                /* width: 100%;
                height: 100%; */
                margin-top: 12px;
            }
            .slpt-ca-2 {
                display: block;
                width: 100%;
                height: 100%;
            }
            .slpt-row {
                clear: both;
                width: 100%;
                height: 100%;
                margin: 0px;
                padding: 0px;
            }
            .slpt-leftCell {
                float: left;
                margin-top: 20px;
                border: 0px;
                height: 210px;
                width: 250px;
            }
            .slpt-rightCell {
                float: left;
                margin-left: -130px;
                margin-top: 12px;
                border: 0px;
                height: 150px;
                width: 250px;
            }

        </style>
   </head> 
   <body> 
        <div class="slpt-row">
            <div class="slpt-title"></div>
            <div class="slpt-leftCell">
                <canvas id="chart-area1" class="slpt-ca-1"></canvas>
            </div>
        </div>
        
        <script>
            var gDsSomething;       //Data Source
            var gURL_DS001 = "{*Row.dsURLChart.text}";
            var gConfig;

            $(document).ready(function(e) { _Start(e) });


            function _Start(e){
                try { 
                    populateContents();
                }catch(err){
                    console.log(err.name, 'Error in _Start(): ' + err.message);
                }
            }

            function populateContents(){
                try{
                    var jsonData = $.ajax({
                        url: gURL_DS001,
                        dataType: 'json',
                        }).done(
                            function (results) {
                                try{
                                    // Split timestamp and data into separate arrays
                                    var labels = [], data=[]; color=[];
                                    var chartTitle = '';
                                    var tileTitle = '';
                                    var centreValue = '0';
                                    results.forEach(function(packet) {
                                        try{
                                            chartTitle = packet.dsChartTitle;
                                            tileTitle = packet.dsTileTitle;
                                            if (typeof packet.dsCentreValue === 'number') {
                                                centreValue = parseFloat(packet.dsCentreValue);
                                            }else{
                                                centreValue = packet.dsCentreValue;
                                            }
                                            labels.push(packet.dsLabel);
                                            data.push(parseFloat(packet.dsValue));
                                            color.push(packet.dsColor);
                                        }catch (err){
                                            console.log(err.name, 'populateContents_Core() Chart-> ajax:forEach: ' + err.message);
                                        }
                                    });

                                    $(".slpt-title").text(tileTitle);

                                    //Populate Config
                                    gConfig = {
                                        type: 'horizontalBar',
                                        data: {
                                            datasets: [{
                                                axis: 'y',
                                                data: data,
                                                backgroundColor: color,
                                                borderWidth: 1,
                                                barThickness: 6
                                            }],
                                            labels: labels
                                        },
                                        options: {
                                            //indexAxis: 'y',
                                            maintainAspectRatio: false,
                                            responsive: true,
                                            scales: {   // For Chart.js version 3.x
                                                x: {
                                                    beginAtZero: true
                                                }
                                            },
                                            scales: {   // For Chart.js version 2.x 
                                                xAxes: [{
                                                    ticks: {
                                                        beginAtZero: true
                                                    }
                                                }]
                                            },
                                            title: {
                                                display: true,
                                                position: 'bottom',
                                                text: chartTitle
                                            },
                                            legend: {
                                                display: false
                                            }
                                        }
                                    };
                                    
                                    var ctx = document.getElementById("chart-area1").getContext("2d");
                                    window.myDoughnut = new Chart(ctx, gConfig);
                                
                                }catch (err){
                                    console.log(err.name, 'populateContents_Core() Chart-> ajax: ' + err.message);
                                }
                            }
                        );
        
                    }catch (err){
                        console.log(err.name, 'populateContents_Core(): ' + err.message);
                    }
            };
        </script>  
    </body>
</html>
```