- ベストアンサー
jqplotによる変動グラフを作成する方法
- jqplotによる変動グラフを作成する方法を教えてください。セレクトボックスの値を変更するたびに、その値に基づいたグラフを作成したいです。
- セレクトボックスの値をJqueryからCGIに渡し、WEB上のDBから値を取得し、グラフプロットのデータに加工します。しかし、CGIからの結果を直接プロットデータに入れるとグラフが表示されません。生データをコピーして入れると表示されます。
- グラフのプロットデータとしてはコードは合っていると思われますが、CGIからの変数データをそのまま組み込む方法がわかりません。質問内容の詳細について教えてください。
- みんなの回答 (13)
- 専門家の回答
質問者が選んだベストアンサー
JSONデータは ・シングルクォートは使えません ・objectオブジェクトのプロパティも文字列として設定します(ダブルクォートで囲む)。 ・文字コードは「UTF-8」 というルールです。 こちらの実験として、 CGIでの、Content-Type: application/json; charset=utf-8 を出力しないように して JavaScriptのsuccess: function()内を alert("path=1:"+result); var gdata = $.parseJSON(result); alert("path=2:" + gdata); var plot = $.jqplot('Graph', gdata, options).replot(); alert("path=3"); としてから 1)CGI側の出力をキーをダブルクォートのままだと alertのボックスにはそれぞれ path=1:[[["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17],["d",45]]] path=2:a,1,b,4,c,7,d,11,a,45,b,33,c,14,d,37,a,45,b,24,c,17,d,45 path=3 とどれも表示されて、 "path=2:~"のアラートの後にグラフ描画(縦積の棒グラフで実験)もできました。 2)CGI側の出力をシングルクォートに修正してみると alertボックスでは、 path=1:[[['a',1],['b',4],['c',7],['d',11]],[['a',45],['b',33],['c',14],['d',37]],[['a',45],['b',24],['c',17],['d',45]]] のみで、次の$.parseJSON(result)で止まりました。 このとき、ブラウザのデバッグツール(私は FireFoxのブラウザコンソールのJSで確認)では SyntaxError: JSON.parse: unexpected character at line 1 column 4 of the JSON data とエラー表示されていました(4文字目が違反文字) なので、 >キーの部分を、’ ’ で囲んで、全体を” ”で囲んで、Perlから送ると、グラフ描画のところで止まって、グラフは表示しないのですが、 >キーの部分を、” ”で囲って、全体を’ ’で囲んで、Perlから送ると、$.parseJSON(result); のところで止まって、その先に進みません。 という現象は、反対ではないですか?(キーを' 'で囲むと$parseJSON()で止まるということでは?)
その他の回答 (12)
- superside0
- ベストアンサー率64% (461/711)
$.ajax({ type: 'POST', cache: false, url: 'CGI.cgi', data: 'data=' +セレクトボックスからの値 , datatype: 'json', success: function(result){ if (result != ''){ var gdata =$.parseJSON(result); var plot = $.jqplot('Graph', gdata , { ....................... }).replot(); } } }); この部分ですが、 このサイトでは、空白でインデント(字下げ)しても詰めて表示されてしまうので あえて 全角空白で書いています。 よっって、これをコピペするときは、字下げに使っている全角の空白を 半角の(ASCII文字の) 空白に書き換えて頂く必要がありますが そのあたり大丈夫ですか?
お礼
superside0さん 何度もコメントをありがとうございます。 はい、もちろん大丈夫です! 全角空白は使っていないです。 では表示されるはず、ということですね。。 なぜ~。。(泣) もうちょっと試行錯誤してみます。 ありがとうございます。
- superside0
- ベストアンサー率64% (461/711)
print "[[["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17].["d",45]]]"; これじゃぁ、" " のなかに "が入ってしまっていますね。失礼しました。 print '[[["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17].["d",45]]]'; と同様になるように・・・ ということです。
お礼
superside0さん いろいろ試していて、ちょっと気になったことがあるのですが、 JSONは、配列のキーの部分(名前)は” ”で囲まないといけないと、いろんなサイトに書いてありますが、 キーの部分を、’ ’ で囲んで、全体を” ”で囲んで、Perlから送ると、グラフ描画のところで止まって、グラフは表示しないのですが、 キーの部分を、” ”で囲って、全体を’ ’で囲んで、Perlから送ると、$.parseJSON(result); のところで止まって、その先に進みません。 これって何か関係があるのでしょうか。 もし何かお気づきのことがありましたら教えて下さい!
- superside0
- ベストアンサー率64% (461/711)
perl でも問題ありませんよ。 データが正しくJavaScriptの多次元配列に引き渡しできればよいだけです。 > CGI(Perl)で下記のデータプロットデータを渡してもダメなんですね。。 > [[a,1],[b,4],[c,7],[d,11]],[[a,45],[b,33],[c,14],[d,37]],[[a,45],[b,24],[c,17],[d,45]],,,,, これでもよいのですが、 このままだと受け取ったJavascript側でこの文字列を解析して 配列に代入する処理を作るのが面倒です。 つまり、 $.ajaxのsuccess: functionの引数には、そういう文字列として、resultに入っただけですが $.jqplot()には、多次元の配列で引き渡しするのですから、このままだと gdata = "[[a,1],~"という文字列を gdata = [ [ "a", 1] ,... という多次元配列に格納しなおす必要があります。 #CGIで受け取っても、JavaScript内にハードコーディングしても #alert()したら同じになったと言われましたが、 #文字列と配列ではまったく異なりますので、 #たぶん、このあたりが正しく理解できていないのではないでしょうか。 JSONを使うとこれが簡単になります。 perlで行うなら まず、a,b,cというのは数値でなく文字なので " "で囲みます。 それと、全体を さらに、1つの [ ]で括って下さい。 つまり、 print "[[["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17].["d",45]]]"; と同様になるように、データを作ります。 さらに perlの先頭で(なにかprintする前に)、 これを出力するときは print "Content-Type: application/json; charset=utf-8\n\n"; を入れます。 (これを入れることで、success: function(result)のresultが 文字列でなく配列になってくれます。 もし、これを入れられない事情があるなら、後述の$.ajax内で gdata = $.parseJSON(result); のようにして文字列からの 配列への変換が必要です) JavaScirptの$.ajaxには、 datatype: 'json', も追加して下さい。 これで $.ajax({ type: 'POST', cache: false, data: 'graphdata=' + なんちゃら, url: 'なんちゃら', datatype: 'json', success: function(result){ if (result != ''){ var gdata = result; //gdata = $.parseJSON(result); //ヘッダがjsonでないととき用 var plot = $.jqplot('Graph', gdata, options).replot(); } } }); でブラフの描画が可能です。 >これは、JSON用の別ファイルにしなくてもいいんですよね? >CGIからそのままJSON形式にして?Ajaxにデータを渡してもいいのでしょうか。 もちろんです。
お礼
superside0さん 何度も何度もありがとうございます! ご丁寧に教えてくださって、ありがとうございます。 これでやっとグラフ表示ができる!!! と思いましたが、、、表示されませんでした。。(泣) 本当に泣きそうです。。 確かに、文字列で渡して、配列にしないといけないというのが、よくわかっていなかったのかもしれないです。 ご指摘ありがとうございます! CGI(Perl)で、 print '[[["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17].["d",45]]]'; 送りたい配列の全体をかっこでくくっています。 で、Ajaxで、 $.ajax({ type: 'POST', cache: false, url: 'CGI.cgi', data: 'data=' +セレクトボックスからの値 , datatype: 'json', success: function(result){ if (result != ''){ var gdata =$.parseJSON(result); var plot = $.jqplot('Graph', gdata , { ....................... }).replot(); } } }); と、設定してみましたが、表示されないです。 $.parseJSONを使うのに別の設定がいるのでしょうか?? print "Content-Type: application/json; charset=utf-8\n\n"; ↑これを設定してみてもダメでした。。 なにがおかしいのかわからず、お手上げ状態です。(泣) もしお気づきのことがありましたら教えて下さい。 お忙しい中、本当に申し訳ございません。 よろしくお願いします。
- superside0
- ベストアンサー率64% (461/711)
なんども訂正ごめんさない。 CGI側でヘッダとして Content-Type: text/javascript; charset=utf-8 でなく Content-Type: application/json; charset=utf-8 のようにしておくと これを受け取ったJavascriptの$.ajax側では gdata = $.parseJSON(result); のようにして文字列からオブジェクトに変換する必要はなく gdata = result; とするだけでした。 (というか、resultをそのまま$.jqplot()に引き渡すだけ)
- superside0
- ベストアンサー率64% (461/711)
すいません。コピペのミスで、success: functionがちゃんと閉じていなかったです。 function onselect_event (){ var options = { title : '折れ線グラフ' }; $.ajax({ type: 'POST', cache: false, data: 'graphdata=' + 'aaa', url: 'jqplot.php', datatype: 'json', success: function(result){ if (result != ''){ gdata = $.parseJSON(result); plot = $.jqplot('Graph', gdata, options).replot(); } }, error: function(XMLHttpRequest, textStatus, errorThrown){ エラー処理(略) } }); } で実験しました。 要点は ・Ajaxは非同期通信なので、$.ajax()の外では値が更新されてないことを考慮する。 ・JSONで値を取り込むのなら、CGIの出力の文字列を配列に変換しないとだめ。 ・再描画するなら ~.replot()が必要 ということになるでしょう。
- superside0
- ベストアンサー率64% (461/711)
あ、すいません。訂正です。 plot = $.jqplot('Graph', gdata, options); ↓ plot = $.jqplot('Graph', gdata, options).replot();
- superside0
- ベストアンサー率64% (461/711)
私のほうの実験では、CGIはjson形式で 適当にでっち上げただけです。 <?php if ( intval(date("s")) % 2 == 1 ) { $user[0] = array(1,2,3,4,5,6,7); $user[1] = array(5,4,3,2,1,2,3); } else { $user[0] = array(5,4,3,2,1,2,3); $user[1] = array(1,2,3,4,5,6,7); $user[2] = array(3,4,5,6,7,8,9); $user[3] = array(2,2,2,2,2,2,2); } $json_value= json_encode( $user ); header( 'Content-Type: text/javascript; charset=utf-8' ); echo $json_value; ?> これを呼び出すJavaScript は function onselect_event (){ var options = { title : '折れ線グラフ' }; $.ajax({ type: 'POST', cache: false, data: 'graphdata=' + 'aaa', url: 'jqplot.php', datatype: 'json', success: function(result){ if (result != ''){ gdata = $.parseJSON(result); plot = $.jqplot('Graph', gdata, options); }, error: function(XMLHttpRequest, textStatus, errorThrown){ エラー処理(略) } }); } って感じにしました。 ちなみに、CGIの戻り値をJSON形式にしたので、gdataへの代入は $.parseJSON()を使っています。 #このサイト 空白文字が詰められて表示されるので、 #インデントに全角空白を使いましたが実際は半角空白です。
お礼
superside0さん 何度もコメントをありがとうございます。 お返事が遅くなってしまってすみません。 私も色々と調べて、JSONがいいのかなあと思いましたが、PHPもJSONも使ったことがなく、どうしようかと悩んでおりました。。 CGIはPerlを使っておりますので、どうにかPerlで値を渡して、JSONでJqueryに渡したいと思うのですが、 Ajax受け取り側で、 datatype: 'json', を追加して、 CGI(Perl)で下記のデータプロットデータを渡してもダメなんですね。。 [[a,1],[b,4],[c,7],[d,11]],[[a,45],[b,33],[c,14],[d,37]],[[a,45],[b,24],[c,17],[d,45]],,,,, JSON形式をどんな感じにしたらいいか調べてみます。 これは、JSON用の別ファイルにしなくてもいいんですよね? CGIからそのままJSON形式にして?Ajaxにデータを渡してもいいのでしょうか。 またわからなくなりましたら教えて下さい! 色々とご丁寧にありがとうございます!
- superside0
- ベストアンサー率64% (461/711)
私のほうでは、Ajaxの結果で jqplotを動的に描画する実績はあります。 ただ、コーディングスタイルというか、アルゴリズムがかなり違うので 手探りになってしまって申し訳ないです。 そこで、#1の御返信にありましたようなスタイルで私のほうで、実験してみました。 $.ajaxのsuccess: function内で gdata=result;するだけの状態で $.ajax();行の次の行で、plot = $.jqplot( ...としても、 たしかに、そのデータでは再描画してくれませんでした。 これは。Ajaxは非同期通信処理なので、コーディングした順番で 実行してくれる訳ではないということに関係していると考えられます。 (パラレル実行されていると、考えたほうが分かりやすいですかね) そこで、試しに、$.ajaxのsuccess: function内の gadata= result;の次の行に plot = $.jqplot(... を入れてみたところ、きちんと描画してくれましたよ。 #CGIの内容までわからないので、適当にでっち上げましたが。
お礼
superside0さん 何度もコメントとお忙しい中テストをして頂いてありがとうございます。 $.ajaxのsuccess: function内の gadata= result;の次の行にplot = $.jqplot(... を入れてみましたが、ダメでした。。(泣) なにが違うんでしょう、、 もしよろしかったら、superside0さんがテストされた環境で CGIからどのような形式のデータを返したか教えていただけませんでしょうか。 どう違うのか検証させていただけたらと思います。 よろしくお願いします。
- superside0
- ベストアンサー率64% (461/711)
Ajaxって非同期なので、gdataに値がセットされる前に $.grplotしてしまっているということはないでしょうか? $.when() で通信を待ってからとか、 Ajaxの戻りの処理で描画をキックするとかしてみてはどうでしょう。
お礼
superside0さん コメントありがとうございます。 今のところテストをしている状態なので、gdataに値がセットされたらAlert();で、値の確認をしています。 その後にグラフを描画するようにしていますので、値がセットされる前にグラフ描画をしているということはないと思うのですが、Alert();のタイミングが良くわからないので、Alert();がでている裏で動いているかはわからないのですが、このような確認でも大丈夫でしょうか。 でもsuperside0さんの見解では、CGIからのデータをそのままグラフプロットデータ部分に変数として当てはめてもちゃんと動くはずということでよろしいでしょうか。 このやり方自体が間違っているのでしたら他のやり方を考えないといけないと思うのですが、このやり方でもあっているということでしたら、またいろいろ検討してみます。 また引き続き、アドバイスが有りましたらどうぞよろしくお願い致します。
- superside0
- ベストアンサー率64% (461/711)
一度、 var plot = $.jqplot('Graph',[ gdata], { で描画していて、それをデータを替えて再描画させているということですよね。 もしかして、 plot = $.jqplot('Graph', [gdata], {略} ).replot(); のような感じで、" .replot()" を つけてみるとか plot = ... のあとで plot.replot(); とかしてみてはどうでしょう?
お礼
superside0さん コメントありがとうございます。 いえ、最初からCGIから来たデータを変数でプロットデータとしていれようとしているのですが、うまく表示されなくて、試しに、生データを入れてみるとちゃんと表示されています。 生データというのは、CGIから来たデータを書出して、そのままコピーして入れているので、変数と同じ値のはずなのですが、、、 セレクトボックスの値を元にグラフを切り替えたいので、最初から変数でグラフ表示したいのです。 はい、最後に plot.replot();と入れてあります。。(泣) でもダメなのです。。
- 1
- 2
お礼
superside0さん できました!!!!!(泣)(泣)(泣) ご丁寧にAlertの値を出してくださってありがとうございます!!! それと同じように、Alertを出すようにして、値をチェックして修正したら、、、 出てきました~!!!!!(泣) わー!! もうほんとに数週間悩んでいたのですが、今日は素敵な夢を見ることができそうです!!!! ここまでお付き合いくださって、本当に本当にありがとうございました。 うまくできなかった原因は、CGIから送るときに、配列全体を ’ ’ または、” ” で囲って送ってテストをしていました。。。 print ' "[ [['a',1],['b',4],['c',7],['d',11]],[['a',45],['b',33],['c',14],['d',37]],[['a',45],['b',24],['c',17],['d',45]]]" '; 先ほど書いた件も、間違い(反対)ではなく、その現象が出ていたのですが、このせいでおかしくなっていたみたいです。(それと、今まで、キーを ' ' で囲っていました。。 ” ” に変えたりしてテストをしていたのですが、上記のせいで、先述の現象が出て、うまくできていませんでした。) print ' [ [['a',1],['b',4],['c',7],['d',11]],[['a',45],['b',33],['c',14],['d',37]],[['a',45],['b',24],['c',17],['d',45]]] '; これにして、個々の配列データのキーの値を、” ” で囲ったら、、、出てきました!! print ' [ [["a",1],["b",4],["c",7],["d",11]],[["a",45],["b",33],["c",14],["d",37]],[["a",45],["b",24],["c",17],["d",45]]] '; ↑これで出てきました!! JSONデータの仕様もわかりました! 本当に本当に本当にありがとうございました。 これで、もう少し使いやすいように修正して、提出できます!!! ほんとにsuperside0さんに見放されたら、一人ではできませんでした! ありがとうございました。 また困ったことがありましたら教えて下さい♪