前置き
ポップアップメニューは便利なんだけど、作るとなると同じ様な記述を何度も何度も繰り返さなきゃならない。それだけで何十行、そこに処理の分岐が加わり、それでいて処理自体は数行だったり、変数作ってもIDしか要らなかったりってのが何となく気に障る。そういうわけでいっそその辺を関数にして自動的に作成してしまおうという話。手を抜く為に手をかける。
ダウンロード
StructPopupMenu
仕様
PopupMenuオブジェクトの構造は簡単だから、配列に情報を入れて関数に送る。配列はこんな感じ。
argument=[MenuItem,MenuItem...]
MenuItem=[caption,id,function,[MenuItem...]]
MenuItemは子メニューとなるMenuItemオブジェクトの情報。
MenuItemのcaption・idはメニューの各項目。functionは選択した時に実行する処理。関数そのものでも文字列でもいい。4番目のMenuItemは子メニュー(つまり孫メニュー)の配列。構造は同じ。どの項目も省略可だけど、空の配列だとセパレータとみなす。
これを関数に送って実行すると、関数は次の様な配列を返す。
return=[PopupMenu,funcList]
funcList={ID:function...}
PopupMenuはPopupMenuオブジェクトそのもの。funcListはIDとそれに対応する関数からなるオブジェクト。よってreturn[0]を実行してIDを取得、そのIDでreturn[1][ID]を実行するだけでいいので、処理の分岐を書かなくて済む。
実例
例えばこんなメニューを作るとする。

一番上のメニューがa・bの2つ。その間にセパレータがある。aの子にc・dがあって、cの子にeがある。そしてb・d・eを選択した時にはalert()でダイアログを表示する事にする。これを普通に書けばこうなる。
var pop=App.NewObject("PopupMenu");
var a=pop.Add();
a.Caption="a";
a.Id=1;
pop.Add().Id=0;
var b=pop.Add();
b.Caption="b";
b.Id=2;
var c=a.Add();
c.Caption="c";
c.Id=3;
var d=a.Add();
d.Caption="d";
d.Id=4;
var e=c.Add();
e.Caption="e";
e.Id=5;
switch(pop.Execute()){
case 2:
alert("parent");
break;
case 4:
alert("child");
break;
case 5:
alert("grandchild");
break;
}
これをStructPopupMenu()を使う場合、メニューは次の様な配列で表される。
[["a",1,,[["c",3,,[["e",5,"alert(grandchild)"]]],["d",4,"alert(child)"]]],[],["b",2,"alert(parent)"]]
注意が要るのは"[["e",5,"alert(grandchild)"]]"の様に、子メニューが一つだけでも配列の中に入れなければいけないという事。これを関数に送ると、
[PopupMenu,{2:'alert(parent)',4:'alert(child)',5:'alert(grandchild)'}]
という配列が返ってくるので、[0]を実行してIDを取得。[1]からそのIDをキーとするプロパティを取り出せばいい。実際のコードはこんな感じ。
var menu=[["a",1,,[["c",3,,[["e",5,"alert(grandchild)"]]],["d",4,"alert(child)"]]],[],["b",2,"alert(parent)"]];
var t=StructPopupMenu(menu);
var id=t[0].Execute();
if(id>0){eval(t[1][id]);}
最後のeval()は、処理を文字列で指定してるから。関数で指定していれば"t[1][id]()"となる。
StructPM
仕様・実例
StructPopupMenuはIDを指定する。一方こちらはIDを自動的に割り振る。パラメータでIDを渡すみたいに、外部からIDを知られなくてもいい場合にはこちらでいい。配列は殆ど同じで、ただMenuItemからidを省いただけ。返り値も同じ。
argument=[MenuItem,MenuItem...]
MenuItem=[caption,function,[MenuItem...]]
return=[PopupMenu,funcList]
funcList={ID:function...}
実際のコードも少し簡単になる。
var menu=[["a",,[["c",,[["e","alert(grandchild)"]]],["d","alert(child)"]]],[],["b","alert(parent)"]];
var t=StructPopupMenu(menu);
var id=t[0].Execute();
if(id>0){eval(t[1][id]);}