Google chart API(グラフ描画ツール)とkintoneの連携

初めまして。
これから宜しくお願いします。
さて、現在、日付をX軸、金額をY軸として、金額の累計グラフを作成したいのですが、kintoneの標準機能ではそれがありませんので、Google chart APIを利用し実装しています。
処理概要としてはkintone.api(‘/k/v1/records’, ‘GET’, param, function(resp) {});で検索した結果を配列に詰めて、
グラフ表示処理google.setOnLoadCallback(function(){});でその配列の中身を表示するというものです。
グラフが表示されることもあるのですが、描画処理が先に走り、データ取得の前にしないまま、画面表示されてしまうことがあります。

Google chart API連携をしたことがあり心当たりがある方がいらっしゃればお教えください。
以上、宜しくお願いします。

清水祐介さん
cstapの落合です。

Google chart APIとkintoneを同時に使った開発をしたわけではないですが、参考になればと思います。

google.setOnLoadCallbackは、google.loadに対するcallbackのセットなので、kintone.apiのcallbackが呼ばれる前にgoogle.loadするようなコードになっているのだと思います。

kintone.apiのcallbackで、google.visualization.DataTable()とgoogle.visualization.LineChartを使って描画する感じで実装することはできますでしょうか?

ご回答ありがとうございます。
google.apiの中でgoogle chart APIのグラフ描画処理を入れてみたのですが、
google.setOnLoadCallbackを読み込まずに処理終了してしまいました。

以下がソースです。。。

/*
* カスタマイズビューのサンプルプログラム
* Copyright (c) 2014 Cybozu
*
* Licensed under the MIT License
*/

kintone.events.on(['app.record.index.show'], function(event){
    if (document.getElementById( "linechart" ) != null){
        var appId = kintone.app.getId(); //実績管理アプリID
        var app_yosan = 54; //予算管理アプリID

        //テーブルの作成
        var data = [];
        var param={
            "app":app_yosan,
            "query":'order by 日付'
        };

        kintone.api('/k/v1/records', 'GET', param, function(resp) {
            var records = resp['records'];
            var key0,key1,key2,key3;
            var chkPush = 0;
            var nn = 0;

            var reqUri;
            var xmlHttp;

            for(var i = 0; i < records.length; i++){
                chkPush = 0;chkPush = 0;
                key0 = records[i]['氏名']['value'];
                key0 = key0.replace(/</g, "&lt;").replace(/>/g, "&gt;");
                key1 = records[i]['日付']['value'];
                key2 = records[i]['金額']['value'];

                // 同期リクエストを行う
                reqUri = kintone.api.url('/k/v1/records') + '?app='+ appId + '&query=' + encodeURI("氏名 = \"" + key0 + "\"");
                xmlHttp = new XMLHttpRequest();
                xmlHttp.open("GET", reqUri, false);
                xmlHttp.setRequestHeader('X-Requested-With','XMLHttpRequest');
                xmlHttp.send(null);

                if (xmlHttp.status == 200){
                    if(window.JSON){
                        key3 = 0;
                        var obj = JSON.parse(xmlHttp.responseText);
                        // 実績DB、予算DBともに登録してある場合
                        //if (obj['records'].length != 0){
                            for(var j = 0; j < obj['records'].length; j++){
                                key3 += parseInt(obj['records'][j]['金額']['value']);
                            }
                            preData=data.length;
                            while (chkPush == 0){
                                preData=data.length;
                                data.push({segment:key1,budget:key2,results:key3});
                                // なぜか処理が重いので…
                                if (preData == data.length){
                                    chkPush = 0;
                                } else {
                                    chkPush = 1;
                                }
                            }
                        //}
                    }
                }    
            }



                        //---------------------google chart APIの処理------------------------
            //描写用ライブラリの読み込み
            google.load("visualization", "1", {packages:["corechart"]});

            //ライブラリの読み込み後に実行する関数
            google.setOnLoadCallback(function(){

                //Google Chartのインスタンスを作成する
                var elment = document.getElementById("linechart");
                if (elment == null) {
                   return;
                }
                var chart = new google.visualization.AreaChart(elment);

                //データのインスタンスを作成する
                var dataSum = new google.visualization.DataTable();

                //カラムの設定
                dataSum.addColumn("date","日付");
                dataSum.addColumn("number","実行金額");
                dataSum.addColumn("number","予定金額");
                var sumBudget = 0;
                var sumResults = 0;
                for (var i = 0; i < data.length; i++){
                    sumBudget += parseInt(data[i]['budget']);
                    sumResults += parseInt(data[i]['results']);
                    //データの挿入
                    dataSum.addRow([new Date(data[i]['segment']), sumBudget, sumResults]);
                }

                //オプション要素
                var option = {
                    'title':'予実績累計グラフ',

                    'pointSize': 5,
                    'backgroundColor':'black',

                    'hAxis': {
                        'title':'日付',
                        'titleTextStyle': { fontSize: 15 },
                        'baselineColor':'green',
                        'gridlines':{
                            color:'green',
                            'count':8
                        },
                        titleTextStyle: {color: 'red'},
                        textStyle: {color: 'red'}

                    },
                    'vAxis': {
                        'title': '金額',
                        'titleTextStyle': { fontSize: 15 },
                        'baselineColor':'green',
                        'gridlines':{
                            color:'green',
                            'count':8
                        },
                        titleTextStyle: {color: 'red'},
                        textStyle: {color: 'red'}

                    },
                    'legend': {
                        position:'top',
                        textStyle:{
                            color:'white'
                        }
                    }

                };

                //グラフの描画
                chart.draw(dataSum, option);
            });  

        });

    }
    return event;
});

callbackがよくわかっていない状況です。。。

清水さん

こんにちは。
大内@cstapです。
上記のcallbackとは違う話になってしまいますが、「住所から地図を表示する」のサンプルではGoogle APIとkintone APIのデータ読み込みの前後関係を別の方法で解決しています。
https://cybozudev.zendesk.com/hc/ja/articles/202640950-%E4%BD%8F%E6%89%80%E3%81%8B%E3%82%89%E5%9C%B0%E5%9B%B3%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B

こちら、Google Map APIになりますが参考にご一読されてみてはいかがでしょうか。

清水さん

たびたびすみません。
callbackについてよくお分かりでないとの事ですが、「はじめよう kintone JavaScript API」の第10回でkintone.apiでのcallbackの使い方について軽く触れていますので、よろしければ参考になさってください。
https://cybozudev.zendesk.com/hc/ja/articles/203727120-%E7%AC%AC10%E5%9B%9E-REST-API%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E5%8F%96%E5%BE%97

大内貴志さん
有益な情報ありがとうございます。
callbackについての理解が少し深まりました。

しかし描画処理をkintoneAPIの成功したときのcallback処理の中に置くと動かないのがやっぱりわからないです。。。

大内貴志さん
確かに可読性が悪いですね。
試行錯誤してるうちにこんな感じになってしまいました。

ソースの方はpredataが定義されていなかったのでvarで定義しました。
デバッグしてみました。
google.loadまでは私の希望通りの動きでしたが、
google.setOnLoadCallbackの中でブレークポイントを張ったのですが通りませんでした。

よくわからないのですが、そもそもcallbackがセットされていないということなのでしょうか。