dojo.connect がうまくできなかった。
javascriptって難しいよねー。
実行されるタイミングを意識してProgrammingしないと痛い目にあう。
以下のソースでは
phpで動的生成した2つのボタンにonclickイベントをそれぞれ登録する
っていうjavascript文。
うまく動くと思っているのに、実行結果は
どっちのボタンを押しても、2つ目のボタンの処理が走っている。
どこが原因なのでしょうか?
<script type="text/javascript"> dojo.addOnLoad(function (){ var tournaments = eval(<?php echo $tournaments_json; ?>); console.log("tournamets.length: " + tournaments.length); for(var key in tournaments){ console.log("key : " + key); console.log(tournaments[key].cup + " " + tournaments[key].tournament); var divId = tournaments[key].cup + tournaments[key].tournament; var div = dojo.byId(divId); debugger; dojo.connect(div, "onclick", null, function(context){ console.log("base_usl is " + "<?php echo base_url() ?>"); var baseurl = "<?php echo base_url() ?>"; console.log("url = " + "../tournament/open/" + tournaments[key].cup + '/' + tournaments[key].tournament); dojo.xhrGet({ // たぶんGETではurlで引数を送れない!? url:"../tournament/open/" + tournaments[key].cup + '/' + tournaments[key].tournament, handleAs: "text", content : { "cup" : tournaments[key].cup , "tournament" : tournaments[key].tournament , "ajax" : "true" }, load: function(data){ console.log("res=", data); debugger; var itemdata = data.chart.rows; var structure = data.chart.columns; var chart = new dojo.data.ItemFileReadStore( {data :{ items : itemdata }}); var grid = dojox.grid.DataGrid({ id : 'myDataGrid' , store : chart , structure : structure }); //var grid = dijit.byId("myDataGrid"); //grid.setStore(chart); //grid.setStructure(structure); //grid.autoWidth = true; //grid.autoHeight = true; grid.startup(); //debugger; }, error: function(error) { debugger; console.warn(new Error().stack); } }); }); } }); </script>
原因は
dojo.xhrGetのコールバック関数loadで
url:"../tournament/open/" + tournaments[key].cup + '/' + tournaments[key].tournament,
tournaments[key].cup とkeyを指定している箇所。
(これを書いている段階ではまだ、これを推測にすぎない。
ただ、そうとうな自信はある、っていうかこれが合ってなかったら
相当ヘコむ、なぜなら既に数時間もこれに費やしているから。)
dojo.connectを設定するこの文が処理されるのはページがloadされてdoucmunetがreadyになった時、
そして、コールバック関数loadが実行されるのは
ボタンが押された、レスポンスが帰ってきた時。
この時のkeyの値はdojo.connectを設定していた時のloopの最後の
値がはいってしまったいるのだ。
loadでtournament[key]としてもその値をその時保持してくれる訳
ではないようだ。
それではこれから検証します。
tournament[key]はだめだから、
divにnameを埋め込んでおいて、
var div = dojo.byId(divId);
とした所で、
div.nameとしてみたら、どうか。以下がソース
<script type="text/javascript"> dojo.addOnLoad(function (){ var tournaments = eval(<?php echo $tournaments_json; ?>); for(var key in tournaments){ var divId = tournaments[key].cup + tournaments[key].tournament; var div = dojo.byId(divId); dojo.connect(div, "onclick", params, function(context){ dojo.xhrGet({ url:"../tournament/open/" + div.name handleAs: "json", content : { "cup" : tournaments[key].cup , "tournament" : tournaments[key].tournament , "ajax" : "true" , "divId" : context.divId }, load: function(data){ console.log("res=", data); }, error: function(error) { console.warn(new Error().stack); } }); }); } }); </script>
結果は一緒でダメでした。
dojo.connectにdivを渡しているので、
クリックが発生した時にはconnectを設定した時のdivが
渡されるでしょ、って思ったんだけど、
ダメでしたね。
うん、これもtournament[key]と同じで、
実行時、最後にインスタンス化されたdivがそのまま使われるんだんね。
ってことで、マウスから手離し、天井を仰ぎ、考える。
そんで、dojo.connect(,,, でcontextが渡せることを思いつく)
そして、これがやっとこさ、
やっとこさ思い道理にうごいたスクリプト。
var params = { "cup" : tournaments[key].cup , "tournament" : tournaments[key].tournament } dojo.connect(div, "onclick", params, function(context){ dojo.xhrGet({ url:"../tournament/open/" + this.cup + "/" + this.tournament,
dojo.connectの第三引数はcontext